diff options
Diffstat (limited to 'render')
-rw-r--r-- | render/form.c | 748 | ||||
-rw-r--r-- | render/form.h | 8 | ||||
-rw-r--r-- | render/html.c | 41 | ||||
-rw-r--r-- | render/html_interaction.c | 60 | ||||
-rw-r--r-- | render/html_object.c | 26 |
5 files changed, 574 insertions, 309 deletions
diff --git a/render/form.c b/render/form.c index fe18e4336..761fc4c69 100644 --- a/render/form.c +++ b/render/form.c @@ -88,7 +88,7 @@ static plot_font_style_t plot_fstyle_entry = { }; static char *form_acceptable_charset(struct form *form); -static char *form_encode_item(const char *item, const char *charset, +static char *form_encode_item(const char *item, uint32_t len, const char *charset, const char *fallback); static void form_select_menu_clicked(struct form_control *control, int x, int y); @@ -321,7 +321,7 @@ bool form_add_option(struct form_control *control, char *value, char *text, /** - * Identify 'successful' controls. + * Identify 'successful' controls via the DOM. * * All text strings in the successful controls list will be in the charset most * appropriate for submission. Therefore, no utf8_to_* processing should be @@ -338,337 +338,498 @@ bool form_add_option(struct form_control *control, char *value, char *text, * * See HTML 4.01 section 17.13.2. */ -bool form_successful_controls(struct form *form, - struct form_control *submit_button, - struct fetch_multipart_data **successful_controls) +bool form_successful_controls_dom(struct form *_form, + struct form_control *_submit_button, + struct fetch_multipart_data **successful_controls) { - struct form_control *control; - struct form_option *option; + dom_html_form_element *form = _form->node; + dom_html_element *submit_button = (_submit_button != NULL) ? _submit_button->node : NULL; + dom_html_collection *form_elements = NULL; + dom_html_options_collection *options = NULL; + dom_node *form_element = NULL, *option_element = NULL; + dom_exception err; + dom_string *nodename = NULL, *inputname = NULL, *inputvalue = NULL, *inputtype = NULL; struct fetch_multipart_data sentinel, *last_success, *success_new; - char *value = NULL; - bool had_submit = false; - char *charset, *rawfile_temp; + bool had_submit = false, element_disabled; + char *charset, *rawfile_temp = NULL, *basename; + uint32_t index, element_count; + struct image_input_coords *coords; last_success = &sentinel; sentinel.next = NULL; - - charset = form_acceptable_charset(form); - if (charset == NULL) + + LOG(("XYZZY: Yay, let's look for a form")); + + /** \todo Replace this call with something DOMish */ + charset = form_acceptable_charset(_form); + if (charset == NULL) { + LOG(("failed to find charset")); return false; + } -#define ENCODE_ITEM(i) form_encode_item((i), charset, form->document_charset) - - for (control = form->controls; control; control = control->next) { - /* ignore disabled controls */ - if (control->disabled) +#define ENCODE_ITEM(i) (((i) == NULL) ? ( \ + form_encode_item("", 0, charset, _form->document_charset) \ + ):( \ + form_encode_item(dom_string_data(i), dom_string_byte_length(i), \ + charset, _form->document_charset) \ + )) + + err = dom_html_form_element_get_elements(form, &form_elements); + + if (err != DOM_NO_ERR) { + LOG(("Could not get form elements")); + goto dom_no_memory; + } + + LOG(("Reffed %p", form_elements)); + + err = dom_html_collection_get_length(form_elements, &element_count); + + if (err != DOM_NO_ERR) { + LOG(("Could not get form element count")); + goto dom_no_memory; + } + + for (index = 0; index < element_count; index++) { + if (form_element != NULL) { + LOG(("Unreffed %p", form_element)); + dom_node_unref(form_element); + form_element = NULL; + } + if (nodename != NULL) { + dom_string_unref(nodename); + nodename = NULL; + } + if (inputname != NULL) { + dom_string_unref(inputname); + inputname = NULL; + } + if (inputvalue != NULL) { + dom_string_unref(inputvalue); + inputvalue = NULL; + } + if (inputtype != NULL) { + dom_string_unref(inputtype); + inputtype = NULL; + } + if (options != NULL) { + dom_html_options_collection_unref(options); + options = NULL; + } + err = dom_html_collection_item(form_elements, + index, &form_element); + if (err != DOM_NO_ERR) { + LOG(("Could not retrieve form element %d", index)); + goto dom_no_memory; + } + LOG(("Reffed %p", form_element)); + /* Form elements are one of: + * HTMLInputElement + * HTMLTextAreaElement + * HTMLSelectElement + */ + err = dom_node_get_node_name(form_element, &nodename); + if (err != DOM_NO_ERR) { + LOG(("Could not get node name")); + goto dom_no_memory; + } + LOG(("Found a node(%p): `%*s`", nodename, + dom_string_byte_length(nodename), + dom_string_data(nodename))); + if (dom_string_isequal(nodename, corestring_dom_TEXTAREA)) { + err = dom_html_text_area_element_get_disabled( + (dom_html_text_area_element *)form_element, + &element_disabled); + if (err != DOM_NO_ERR) { + LOG(("Could not get text area disabled property")); + goto dom_no_memory; + } + err = dom_html_text_area_element_get_name( + (dom_html_text_area_element *)form_element, + &inputname); + if (err != DOM_NO_ERR) { + LOG(("Could not get text area name property")); + goto dom_no_memory; + } + } else if (dom_string_isequal(nodename, corestring_dom_SELECT)) { + err = dom_html_select_element_get_disabled( + (dom_html_select_element *)form_element, + &element_disabled); + if (err != DOM_NO_ERR) { + LOG(("Could not get select disabled property")); + goto dom_no_memory; + } + err = dom_html_select_element_get_name( + (dom_html_select_element *)form_element, + &inputname); + if (err != DOM_NO_ERR) { + LOG(("Could not get select name property")); + goto dom_no_memory; + } + } else if (dom_string_isequal(nodename, corestring_dom_INPUT)) { + err = dom_html_input_element_get_disabled( + (dom_html_input_element *)form_element, + &element_disabled); + if (err != DOM_NO_ERR) { + LOG(("Could not get input disabled property")); + goto dom_no_memory; + } + err = dom_html_input_element_get_name( + (dom_html_input_element *)form_element, + &inputname); + if (err != DOM_NO_ERR) { + LOG(("Could not get input name property")); + goto dom_no_memory; + } + } else if (dom_string_isequal(nodename, corestring_dom_BUTTON)) { + /* It was a button, no fair */ continue; - - /* ignore controls with no name */ - if (!control->name) + } else { + /* Unknown element type came through! */ + LOG(("Unknown element type: %*s", + dom_string_byte_length(nodename), + dom_string_data(nodename))); + goto dom_no_memory; + } + if (element_disabled) continue; - - switch (control->type) { - case GADGET_HIDDEN: - if (control->value) - value = ENCODE_ITEM(control->value); - else - value = ENCODE_ITEM(""); - if (!value) { - LOG(("failed to duplicate value" - "'%s' for control %s", - control->value, - control->name)); - goto no_memory; + if (inputname == NULL) + continue; + + if (dom_string_isequal(nodename, corestring_dom_TEXTAREA)) { + err = dom_html_text_area_element_get_value( + (dom_html_text_area_element *)form_element, + &inputvalue); + if (err != DOM_NO_ERR) { + LOG(("Could not get text area content")); + goto dom_no_memory; + } + } else if (dom_string_isequal(nodename, corestring_dom_SELECT)) { + uint32_t options_count, option_index; + err = dom_html_select_element_get_options( + (dom_html_select_element *)form_element, + &options); + if (err != DOM_NO_ERR) { + LOG(("Could not get select options collection")); + goto dom_no_memory; + } + err = dom_html_options_collection_get_length( + options, &options_count); + if (err != DOM_NO_ERR) { + LOG(("Could not get select options collection length")); + goto dom_no_memory; + } + for(option_index = 0; option_index < options_count; + ++option_index) { + bool selected; + if (option_element != NULL) { + dom_node_unref(option_element); + option_element = NULL; } - break; - - case GADGET_RADIO: - case GADGET_CHECKBOX: - /* ignore checkboxes and radio buttons which - * aren't selected */ - if (!control->selected) - continue; - if (control->value) - value = ENCODE_ITEM(control->value); - else - value = ENCODE_ITEM("on"); - if (!value) { - LOG(("failed to duplicate" - "value '%s' for" - "control %s", - control->value, - control->name)); - goto no_memory; + if (inputvalue != NULL) { + dom_string_unref(inputvalue); + inputvalue = NULL; } - break; - - case GADGET_SELECT: - /* select */ - for (option = control->data.select.items; - option != NULL; - option = option->next) { - if (!option->selected) - continue; - success_new = - malloc(sizeof(*success_new)); - if (!success_new) { - LOG(("malloc failed")); - goto no_memory; - } - success_new->file = false; - success_new->name = - ENCODE_ITEM(control->name); - success_new->value = - ENCODE_ITEM(option->value); - success_new->next = NULL; - last_success->next = success_new; - last_success = success_new; - if (!success_new->name || - !success_new->value) { - LOG(("strdup failed")); - goto no_memory; - } + err = dom_html_options_collection_item( + options, option_index, &option_element); + if (err != DOM_NO_ERR) { + LOG(("Could not get options item %d", option_index)); + goto dom_no_memory; } - - continue; - break; - - case GADGET_TEXTBOX: - case GADGET_PASSWORD: - case GADGET_TEXTAREA: - { - char *v2; - int ta_len = textarea_get_text( - control->data.text.ta, - NULL, 0); - - value = malloc(ta_len); - if (!value) { - LOG(("failed handling textarea")); - goto no_memory; + err = dom_html_option_element_get_selected( + (dom_html_option_element *)option_element, + &selected); + if (err != DOM_NO_ERR) { + LOG(("Could not get option selected property")); + goto dom_no_memory; } - textarea_get_text(control->data.text.ta, - value, ta_len); - - if (control->type == GADGET_TEXTAREA && - value[0] == '\0') { - /* Textarea not submitted if empty */ - free(value); + if (!selected) continue; + err = dom_html_option_element_get_value( + (dom_html_option_element *)option_element, + &inputvalue); + if (err != DOM_NO_ERR) { + LOG(("Could not get option value")); + goto dom_no_memory; } - - v2 = ENCODE_ITEM(value); - if (!v2) { - LOG(("failed handling textarea")); - free(value); - goto no_memory; - } - - free(value); - value = v2; - } - break; - - case GADGET_IMAGE: { - /* image */ - size_t len; - char *name; - - if (control != submit_button) - /* only the activated submit button - * is successful */ - continue; - - name = ENCODE_ITEM(control->name); - if (name == NULL) - goto no_memory; - - len = strlen(name) + 3; - - /* x */ - success_new = malloc(sizeof(*success_new)); - if (!success_new) { - free(name); - LOG(("malloc failed")); - goto no_memory; + + success_new = calloc(1, sizeof(*success_new)); + if (success_new == NULL) { + LOG(("Could not allocate data for option")); + goto dom_no_memory; } - success_new->file = false; - success_new->name = malloc(len); - success_new->value = malloc(20); - if (!success_new->name || - !success_new->value) { - free(success_new->name); - free(success_new->value); - free(success_new); - free(name); - LOG(("malloc failed")); - goto no_memory; - } - sprintf(success_new->name, "%s.x", name); - sprintf(success_new->value, "%i", - control->data.image.mx); - success_new->next = 0; + last_success->next = success_new; last_success = success_new; - - /* y */ - success_new = malloc(sizeof(*success_new)); - if (!success_new) { - free(name); - LOG(("malloc failed")); - goto no_memory; + + success_new->name = ENCODE_ITEM(inputname); + if (success_new->name == NULL) { + LOG(("Could not encode name for option")); + goto dom_no_memory; } - success_new->file = false; - success_new->name = malloc(len); - success_new->value = malloc(20); - if (!success_new->name || - !success_new->value) { - free(success_new->name); - free(success_new->value); - free(success_new); - free(name); - LOG(("malloc failed")); - goto no_memory; + success_new->value = ENCODE_ITEM(inputvalue); + if (success_new->value == NULL) { + LOG(("Could not encode value for option")); + goto dom_no_memory; } - sprintf(success_new->name, "%s.y", name); - sprintf(success_new->value, "%i", - control->data.image.my); - success_new->next = 0; - last_success->next = success_new; - last_success = success_new; - - free(name); - - continue; - break; } - - case GADGET_SUBMIT: - if (!submit_button && !had_submit) - /* no submit button specified, so - * use first declared in form */ + continue; + } else if (dom_string_isequal(nodename, corestring_dom_INPUT)) { + /* Things to consider here */ + /* Buttons -- only if the successful control */ + /* radio and checkbox -- only if selected */ + /* file -- also get the rawfile */ + /* everything else -- just value */ + err = dom_html_input_element_get_type( + (dom_html_input_element *) form_element, + &inputtype); + if (err != DOM_NO_ERR) { + LOG(("Could not get input element type")); + goto dom_no_memory; + } + if (dom_string_caseless_isequal( + inputtype, corestring_dom_submit)) { + LOG(("Examining submit button")); + if (submit_button == NULL && !had_submit) + /* no button used, and first submit + * node found, so use it + */ had_submit = true; - else if (control != submit_button) - /* only the activated submit button - * is successful */ + else if ((dom_node *)submit_button != + (dom_node *)form_element) continue; - if (control->value) - value = ENCODE_ITEM(control->value); - else - value = ENCODE_ITEM(""); - if (!value) { - LOG(("failed to duplicate value" - "'%s' for control %s", - control->value, - control->name)); - goto no_memory; + err = dom_html_input_element_get_value( + (dom_html_input_element *)form_element, + &inputvalue); + if (err != DOM_NO_ERR) { + LOG(("Could not get submit button value")); + goto dom_no_memory; } - break; - - case GADGET_RESET: - /* ignore reset */ - continue; - break; - - case GADGET_FILE: - /* file */ - /* Handling of blank file entries is - * implementation defined - we're perfectly - * within our rights to treat it as an - * unsuccessful control. Unfortunately, every - * other browser submits the field with - * a blank filename and no content. So, - * that's what we have to do, too. + /* Drop through to report the successful button */ + } else if (dom_string_caseless_isequal( + inputtype, corestring_dom_image)) { + /* We *ONLY* use an image input if it was the + * thing which activated us */ - success_new = malloc(sizeof(*success_new)); - if (!success_new) { - LOG(("malloc failed")); - goto no_memory; + LOG(("Examining image button")); + if ((dom_node *)submit_button != + (dom_node *)form_element) + continue; + + err = dom_node_get_user_data( + form_element, + corestring_dom___ns_key_image_coords_node_data, + &coords); + if (err != DOM_NO_ERR) { + LOG(("Could not get image XY data")); + goto dom_no_memory; + } + if (coords == NULL) { + LOG(("No XY data on the image input")); + goto dom_no_memory; + } + + basename = ENCODE_ITEM(inputname); + + success_new = calloc(1, sizeof(*success_new)); + if (success_new == NULL) { + free(basename); + LOG(("Could not allocate data for image.x")); + goto dom_no_memory; + } + + last_success->next = success_new; + last_success = success_new; + + success_new->name = malloc(strlen(basename) + 3); + if (success_new->name == NULL) { + free(basename); + LOG(("Could not allocate name for image.x")); + goto dom_no_memory; + } + success_new->value = malloc(20); + if (success_new->value == NULL) { + free(basename); + LOG(("Could not allocate value for image.x")); + goto dom_no_memory; + } + sprintf(success_new->name, "%s.x", basename); + sprintf(success_new->value, "%d", coords->x); + + success_new = calloc(1, sizeof(*success_new)); + if (success_new == NULL) { + free(basename); + LOG(("Could not allocate data for image.y")); + goto dom_no_memory; + } + + last_success->next = success_new; + last_success = success_new; + + success_new->name = malloc(strlen(basename) + 3); + if (success_new->name == NULL) { + free(basename); + LOG(("Could not allocate name for image.y")); + goto dom_no_memory; + } + success_new->value = malloc(20); + if (success_new->value == NULL) { + free(basename); + LOG(("Could not allocate value for image.y")); + goto dom_no_memory; + } + sprintf(success_new->name, "%s.y", basename); + sprintf(success_new->value, "%d", coords->y); + free(basename); + continue; + } else if (dom_string_caseless_isequal( + inputtype, corestring_dom_radio) || + dom_string_caseless_isequal( + inputtype, corestring_dom_checkbox)) { + LOG(("Examining radio or checkbox")); + err = dom_html_input_element_get_value( + (dom_html_input_element *)form_element, + &inputvalue); + if (err != DOM_NO_ERR) { + LOG(("Could not get input element value")); + goto dom_no_memory; } - success_new->file = true; - success_new->name = ENCODE_ITEM(control->name); - success_new->value = - ENCODE_ITEM(control->value ? - control->value : ""); - success_new->rawfile = NULL; - /* Retrieve the filename from the DOM annotation */ - LOG(("XYZZY: Attempting to retrieve data")); - if (dom_node_get_user_data( - control->node, - corestring_dom___ns_key_file_name_node_data, - &rawfile_temp) != DOM_NO_ERR) { - LOG(("XYZZY: unable to get rawfile")); - goto no_memory; + if (inputvalue == NULL) + inputvalue = dom_string_ref( + corestring_dom_on); + /* Fall through to simple allocation */ + } else if (dom_string_caseless_isequal( + inputtype, corestring_dom_file)) { + LOG(("Examining file input")); + err = dom_html_input_element_get_value( + (dom_html_input_element *)form_element, + &inputvalue); + if (err != DOM_NO_ERR) { + LOG(("Could not get file value")); + goto dom_no_memory; } - LOG(("XYZZY: Got raw filename: %s", rawfile_temp)); - if (rawfile_temp == NULL) { - /* No annotation means the file was not - */ - success_new->rawfile = strdup(""); - } else { - success_new->rawfile = strdup(rawfile_temp); - } - - if (success_new->rawfile == NULL) { - LOG(("strdup failed")); - goto no_memory; + err = dom_node_get_user_data( + form_element, + corestring_dom___ns_key_file_name_node_data, + &rawfile_temp); + if (err != DOM_NO_ERR) { + LOG(("Could not get file rawname")); + goto dom_no_memory; } - - success_new->next = 0; - last_success->next = success_new; - last_success = success_new; - if (!success_new->name || - !success_new->value) { - LOG(("strdup failed")); - goto no_memory; + rawfile_temp = strdup(rawfile_temp != NULL ? + rawfile_temp : + ""); + if (rawfile_temp == NULL) { + LOG(("Could not copy file rawname")); + goto dom_no_memory; } - - continue; - break; - - case GADGET_BUTTON: - /* Ignore it */ + /* Fall out to the allocation */ + } else if (dom_string_caseless_isequal( + inputtype, corestring_dom_reset) || + dom_string_caseless_isequal( + inputtype, corestring_dom_button)) { + /* Skip these */ + LOG(("Skipping RESET and BUTTON")); continue; - break; - - default: - assert(0); - break; + } else { + /* Everything else is treated as text values */ + LOG(("Retrieving generic input text")); + err = dom_html_input_element_get_value( + (dom_html_input_element *)form_element, + &inputvalue); + if (err != DOM_NO_ERR) { + LOG(("Could not get input value")); + goto dom_no_memory; + } + /* Fall out to the allocation */ + } } - - success_new = malloc(sizeof(*success_new)); - if (!success_new) { - LOG(("malloc failed")); - free(value); - goto no_memory; + + success_new = calloc(1, sizeof(*success_new)); + if (success_new == NULL) { + LOG(("Could not allocate data for generic")); + goto dom_no_memory; } - success_new->file = false; - success_new->name = ENCODE_ITEM(control->name); - success_new->value = value; - success_new->next = NULL; + last_success->next = success_new; last_success = success_new; - if (!success_new->name) { - LOG(("failed to duplicate name '%s'", - control->name)); - goto no_memory; + + success_new->name = ENCODE_ITEM(inputname); + if (success_new->name == NULL) { + LOG(("Could not encode name for generic")); + goto dom_no_memory; + } + success_new->value = ENCODE_ITEM(inputvalue); + if (success_new->value == NULL) { + LOG(("Could not encode value for generic")); + goto dom_no_memory; + } + if (rawfile_temp != NULL) { + success_new->file = true; + success_new->rawfile = rawfile_temp; + rawfile_temp = NULL; } } - + free(charset); - + if (form_element != NULL) { + LOG(("Unreffed %p", form_element)); + dom_node_unref(form_element); + } + if (form_elements != NULL) { + LOG(("Unreffed %p", form_elements)); + dom_html_collection_unref(form_elements); + } + if (nodename != NULL) + dom_string_unref(nodename); + if (inputname != NULL) + dom_string_unref(inputname); + if (inputvalue != NULL) + dom_string_unref(inputvalue); + if (options != NULL) + dom_html_options_collection_unref(options); + if (option_element != NULL) + dom_node_unref(option_element); + if (inputtype != NULL) + dom_string_unref(inputtype); + if (rawfile_temp != NULL) + free(rawfile_temp); *successful_controls = sentinel.next; + + for (success_new = *successful_controls; success_new != NULL; + success_new = success_new->next) { + LOG(("%p -> %s=%s", success_new, success_new->name, success_new->value)); + LOG(("%p -> file=%s rawfile=%s", success_new, + success_new->file ? "yes" : "no", success_new->rawfile)); + } return true; - -no_memory: - warn_user("NoMemory", 0); + +dom_no_memory: free(charset); fetch_multipart_data_destroy(sentinel.next); + + if (form_elements != NULL) + dom_html_collection_unref(form_elements); + if (form_element != NULL) + dom_node_unref(form_element); + if (nodename != NULL) + dom_string_unref(nodename); + if (inputname != NULL) + dom_string_unref(inputname); + if (inputvalue != NULL) + dom_string_unref(inputvalue); + if (options != NULL) + dom_html_options_collection_unref(options); + if (option_element != NULL) + dom_node_unref(option_element); + if (inputtype != NULL) + dom_string_unref(inputtype); + if (rawfile_temp != NULL) + free(rawfile_temp); + return false; - -#undef ENCODE_ITEM } - +#undef ENCODE_ITEM /** * Encode controls using application/x-www-form-urlencoded. @@ -813,12 +974,13 @@ char *form_acceptable_charset(struct form *form) * \todo Return charset used? * * \param item String to convert + * \param len Length of string to convert * \param charset Destination charset * \param fallback Fallback charset (may be NULL), * used iff converting to charset fails * \return Pointer to converted string (on heap, caller frees), or NULL */ -char *form_encode_item(const char *item, const char *charset, +char *form_encode_item(const char *item, uint32_t len, const char *charset, const char *fallback) { utf8_convert_ret err; @@ -834,7 +996,7 @@ char *form_encode_item(const char *item, const char *charset, if (err == UTF8_CONVERT_BADENC) { /* charset not understood, try without transliteration */ snprintf(cset, sizeof cset, "%s", charset); - err = utf8_to_enc(item, cset, 0, &ret); + err = utf8_to_enc(item, cset, len, &ret); if (err == UTF8_CONVERT_BADENC) { /* nope, try fallback charset (if any) */ @@ -1491,7 +1653,7 @@ void form_submit(nsurl *page_url, struct browser_window *target, assert(form != NULL); - if (form_successful_controls(form, submit_button, &success) == false) { + if (form_successful_controls_dom(form, submit_button, &success) == false) { warn_user("NoMemory", 0); return; } diff --git a/render/form.h b/render/form.h index b538c3b33..78211ee19 100644 --- a/render/form.h +++ b/render/form.h @@ -134,6 +134,11 @@ struct form_option { struct form_option* next; }; +struct image_input_coords { + int x; + int y; +}; + /** * Called by the select menu when it wants an area to be redrawn. The * coordinates are menu origin relative. @@ -159,6 +164,9 @@ bool form_add_option(struct form_control *control, char *value, char *text, bool form_successful_controls(struct form *form, struct form_control *submit_button, struct fetch_multipart_data **successful_controls); +bool form_successful_controls_dom(struct form *form, + struct form_control *submit_button, + struct fetch_multipart_data **successful_controls); bool form_open_select_menu(void *client_data, struct form_control *control, diff --git a/render/html.c b/render/html.c index 103dec14f..e10f1e930 100644 --- a/render/html.c +++ b/render/html.c @@ -507,6 +507,37 @@ static nserror html_meta_refresh_process_element(html_content *c, dom_node *n) return error; } +static bool html_process_img(html_content *c, dom_node *node) +{ + dom_string *src; + nsurl *url; + nserror err; + dom_exception exc; + bool success; + + /* Do nothing if foreground images are disabled */ + if (nsoption_bool(foreground_images) == false) { + return true; + } + + exc = dom_element_get_attribute(node, corestring_dom_src, &src); + if (exc != DOM_NO_ERR || src == NULL) { + return true; + } + + err = nsurl_join(c->base_url, dom_string_data(src), &url); + if (err != NSERROR_OK) { + dom_string_unref(src); + return false; + } + dom_string_unref(src); + + /* Speculatively fetch the image */ + success = html_fetch_object(c, url, NULL, CONTENT_IMAGE, 0, 0, false); + nsurl_unref(url); + + return success; +} /** * Complete conversion of an HTML document @@ -608,6 +639,10 @@ dom_default_action_DOMNodeInserted_cb(struct dom_event *evt, void *pw) name, corestring_lwc_title) && htmlc->title == NULL) { htmlc->title = dom_node_ref(node); + } else if (dom_string_caseless_lwc_isequal( + name, corestring_lwc_img)) { + html_process_img(htmlc, + (dom_node *) node); } dom_string_unref(name); @@ -1697,14 +1732,13 @@ static void html__dom_user_data_handler(dom_node_operation operation, char *oldfile; char *data = (char *)_data; - if (!dom_string_isequal(corestring_dom___ns_key_libcss_node_data, + if (!dom_string_isequal(corestring_dom___ns_key_file_name_node_data, key) || data == NULL) { return; } switch (operation) { case DOM_NODE_CLONED: - LOG(("XYZZY: Cloned, so copying to the new location")); if (dom_node_set_user_data(dst, corestring_dom___ns_key_file_name_node_data, strdup(data), html__dom_user_data_handler, @@ -1720,7 +1754,6 @@ static void html__dom_user_data_handler(dom_node_operation operation, break; case DOM_NODE_DELETED: - LOG(("XYZZY: Freeing data due to node deletion")); free(data); break; default: @@ -1748,12 +1781,10 @@ static void html__set_file_gadget_filename(struct content *c, form_gadget_update_value(html, gadget, utf8_fn); /* corestring_dom___ns_key_file_name_node_data */ - LOG(("XYZZY: Setting userdata to %s", fn)); if (dom_node_set_user_data((dom_node *)file_box->gadget->node, corestring_dom___ns_key_file_name_node_data, strdup(fn), html__dom_user_data_handler, &oldfile) == DOM_NO_ERR) { - LOG(("XYZZY: Userdata used to be %s", oldfile)); if (oldfile != NULL) free(oldfile); } diff --git a/render/html_interaction.c b/render/html_interaction.c index b04d42586..84c64ca20 100644 --- a/render/html_interaction.c +++ b/render/html_interaction.c @@ -45,8 +45,10 @@ #include "render/imagemap.h" #include "render/search.h" #include "javascript/js.h" +#include "utils/corestrings.h" #include "utils/messages.h" #include "utils/utils.h" +#include "utils/log.h" /** @@ -228,6 +230,47 @@ void html_mouse_track(struct content *c, struct browser_window *bw, html_mouse_action(c, bw, mouse, x, y); } +/** Helper for file gadgets to store their filename unencoded on the + * dom node associated with the gadget. + * + * \todo Get rid of this crap eventually + */ +static void html__image_coords_dom_user_data_handler(dom_node_operation operation, + dom_string *key, void *_data, struct dom_node *src, + struct dom_node *dst) +{ + struct image_input_coords *oldcoords, *coords = _data, *newcoords; + + if (!dom_string_isequal(corestring_dom___ns_key_image_coords_node_data, + key) || coords == NULL) { + return; + } + + switch (operation) { + case DOM_NODE_CLONED: + newcoords = calloc(1, sizeof(*newcoords)); + *newcoords = *coords; + if (dom_node_set_user_data(dst, + corestring_dom___ns_key_image_coords_node_data, + newcoords, html__image_coords_dom_user_data_handler, + &oldcoords) == DOM_NO_ERR) { + free(oldcoords); + } + break; + + case DOM_NODE_RENAMED: + case DOM_NODE_IMPORTED: + case DOM_NODE_ADOPTED: + break; + + case DOM_NODE_DELETED: + free(coords); + break; + default: + LOG(("User data operation not handled.")); + assert(0); + } +} /** * Handle mouse clicks and movements in an HTML content window. @@ -630,8 +673,21 @@ void html_mouse_action(struct content *c, struct browser_window *bw, break; case GADGET_IMAGE: if (mouse & BROWSER_MOUSE_CLICK_1) { - gadget->data.image.mx = x - gadget_box_x; - gadget->data.image.my = y - gadget_box_y; + struct image_input_coords *coords, *oldcoords; + /** \todo Find a way to not ignore errors */ + coords = calloc(1, sizeof(*coords)); + if (coords == NULL) { + return; + } + coords->x = x - gadget_box_x; + coords->y = y - gadget_box_y; + if (dom_node_set_user_data( + gadget->node, + corestring_dom___ns_key_image_coords_node_data, + coords, html__image_coords_dom_user_data_handler, + &oldcoords) != DOM_NO_ERR) + return; + free(oldcoords); } /* drop through */ case GADGET_SUBMIT: diff --git a/render/html_object.c b/render/html_object.c index 15ca7ed3b..e76919dd4 100644 --- a/render/html_object.c +++ b/render/html_object.c @@ -123,6 +123,9 @@ html_object_callback(hlcache_handle *object, assert(c->base.status != CONTENT_STATUS_ERROR); box = o->box; + if (box == NULL && event->type != CONTENT_MSG_ERROR) { + return NSERROR_OK; + } switch (event->type) { case CONTENT_MSG_LOADING: @@ -181,11 +184,13 @@ html_object_callback(hlcache_handle *object, o->content = NULL; - c->base.active--; - LOG(("%d fetches active", c->base.active)); + if (box != NULL) { + c->base.active--; + LOG(("%d fetches active", c->base.active)); - content_add_error(&c->base, "?", 0); - html_object_failed(box, c, o->background); + content_add_error(&c->base, "?", 0); + html_object_failed(box, c, o->background); + } break; case CONTENT_MSG_STATUS: @@ -461,7 +466,7 @@ html_object_callback(hlcache_handle *object, * then reformat the page to display newly fetched objects */ else if (nsoption_bool(incremental_reflow) && event->type == CONTENT_MSG_DONE && - !(box->flags & REPLACE_DIM) && + box != NULL && !(box->flags & REPLACE_DIM) && (c->base.status == CONTENT_STATUS_READY || c->base.status == CONTENT_STATUS_DONE) && (wallclock() > c->base.reformat_time)) { @@ -488,6 +493,7 @@ static bool html_replace_object(struct content_html_object *object, nsurl *url) nserror error; assert(object != NULL); + assert(object->box != NULL); c = (html_content *) object->parent; @@ -559,7 +565,7 @@ nserror html_object_open_objects(html_content *html, struct browser_window *bw) for (object = html->object_list; object != NULL; object = next) { next = object->next; - if (object->content == NULL) + if (object->content == NULL || object->box == NULL) continue; if (content_get_type(object->content) == CONTENT_NONE) @@ -618,7 +624,7 @@ nserror html_object_close_objects(html_content *html) for (object = html->object_list; object != NULL; object = next) { next = object->next; - if (object->content == NULL) + if (object->content == NULL || object->box == NULL) continue; if (content_get_type(object->content) == CONTENT_NONE) @@ -698,8 +704,10 @@ bool html_fetch_object(html_content *c, nsurl *url, struct box *box, c->object_list = object; c->num_objects++; - c->base.active++; - LOG(("%d fetches active", c->base.active)); + if (box != NULL) { + c->base.active++; + LOG(("%d fetches active", c->base.active)); + } return true; } |