diff --git a/src/document/libdom/tags.c b/src/document/libdom/tags.c index b8434341..2b01246c 100644 --- a/src/document/libdom/tags.c +++ b/src/document/libdom/tags.c @@ -1756,11 +1756,315 @@ tags_html_iframe_close(struct source_renderer *renderer, dom_node *node, unsigne unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5) { } +/* Returns an allocated string made after @label + * but limited to @max_len length, by truncating + * the middle of @label string, which is replaced + * by an asterisk ('*'). + * If @max_len < 0 it returns NULL. + * If @max_len == 0 it returns an unmodified copy + * of @label string. + * In either case, it may return NULL if a memory + * allocation failure occurs. + * Example: + * truncate_label("some_string", 5) => "so*ng" */ +static unsigned char * +truncate_label(unsigned char *label, int max_len) +{ + unsigned char *new_label; + int len = strlen(label); + int left_part_len; + int right_part_len; + + if (max_len < 0) return NULL; + if (max_len == 0 || len <= max_len) + return stracpy(label); + + right_part_len = left_part_len = max_len / 2; + + if (left_part_len + right_part_len + 1 > max_len) + right_part_len--; + + new_label = mem_alloc(max_len + 1); + if (!new_label) return NULL; + + if (left_part_len) + memcpy(new_label, label, left_part_len); + + new_label[left_part_len] = '*'; + + if (right_part_len) + memcpy(new_label + left_part_len + 1, + label + len - right_part_len, right_part_len); + + new_label[max_len] = '\0'; + + return new_label; +} + +/* Get image filename from its src attribute. */ +static unsigned char * +get_image_filename_from_src(int max_len, unsigned char *src) +{ + unsigned char *text = NULL; + unsigned char *start, *filename; + int len; + + if (!src) return NULL; + /* We can display image as [foo.gif]. */ + + len = strcspn(src, "?"); + + for (start = src + len; start > src; start--) + if (dir_sep(start[-1])) { + break; + } + + len -= start - src; + + filename = memacpy(start, len); + if (filename) { + /* XXX: Due to a compatibility alias (added: 2004-12-15 in + * 0.10pre3.CVS for document.browse.images.file_tags) this can + * return a negative @max_len. */ + text = truncate_label(filename, max_len); + mem_free(filename); + } + + return text; +} + + +/* Returns an allocated string containing formatted @label. */ +static unsigned char * +get_image_label(int max_len, unsigned char *label) +{ + unsigned char *formatted_label; + + if (!label) return NULL; + + formatted_label = truncate_label(label, max_len); + mem_free(label); + + return formatted_label; +} + +static void +put_image_label(unsigned char *a, unsigned char *label, + struct html_context *html_context) +{ + color_T saved_foreground; + enum text_style_format saved_attr; + + /* This is not 100% appropriate for , but well, accepting + * accesskey and tabindex near is just our little + * extension to the standard. After all, it makes sense. */ + html_focusable(html_context, a); + + saved_foreground = format.style.color.foreground; + saved_attr = format.style.attr; + format.style.color.foreground = format.color.image_link; + format.style.attr |= AT_NO_ENTITIES; + put_chrs(html_context, label, strlen(label)); + format.style.color.foreground = saved_foreground; + format.style.attr = saved_attr; +} + +static void +tags_html_img_do(struct source_renderer *renderer, dom_node *node, unsigned char *a, unsigned char *object_src) +{ + struct html_context *html_context = renderer->html_context; + int ismap, usemap = 0; + bool ismap_b = 0; + int add_brackets = 0; + unsigned char *src = NULL; + unsigned char *label = NULL; + unsigned char *usemap_attr; + struct document_options *options = html_context->options; + int display_style = options->image_link.display_style; + dom_exception exc; + dom_html_image_element *img_element = (dom_html_image_element *)node; + dom_string *usemap_value; + dom_string *title_value = NULL; + + /* Note about display_style: + * 0 means always display IMG + * 1 means always display filename + * 2 means display alt/title attribute if possible, IMG if not + * 3 means display alt/title attribute if possible, filename if not */ + + exc = dom_html_image_element_get_use_map(img_element, &usemap_value); + if (DOM_NO_ERR == exc && usemap_value) { + usemap_attr = memacpy(dom_string_data(usemap_value), dom_string_byte_length(usemap_value)); + dom_string_unref(usemap_value); + } else { + usemap_attr = NULL; + } + + //usemap_attr = get_attr_val(a, "usemap", html_context->doc_cp); + if (usemap_attr) { + unsigned char *joined_urls = join_urls(html_context->base_href, + usemap_attr); + unsigned char *map_url; + + mem_free(usemap_attr); + if (!joined_urls) return; + map_url = straconcat("MAP@", joined_urls, + (unsigned char *) NULL); + mem_free(joined_urls); + if (!map_url) return; + + html_stack_dup(html_context, ELEMENT_KILLABLE); + mem_free_set(&format.link, map_url); +//fprintf(stderr, "html_img_do: format.link=%s\n", format.link); + format.form = NULL; + format.style.attr |= AT_BOLD; + usemap = 1; + } + + exc = dom_html_image_element_get_is_map(img_element, &ismap_b); + + ismap = format.link && ismap_b && !usemap; +// ismap = format.link +// && has_attr(a, "ismap", html_context->doc_cp) +// && !usemap; + + if (display_style == 2 || display_style == 3) { + dom_string *alt_value = NULL; + + exc = dom_html_image_element_get_alt(img_element, &alt_value); + if (DOM_NO_ERR == exc && alt_value) { + label = memacpy(dom_string_data(alt_value), dom_string_byte_length(alt_value)); + dom_string_unref(alt_value); + } + + //label = get_attr_val(a, "alt", html_context->doc_cp); + if (!label) { + dom_string *title_value = NULL; + + exc = dom_html_element_get_title((dom_html_element *)node, &title_value); + if (DOM_NO_ERR == exc && title_value) { + label = memacpy(dom_string_data(title_value), dom_string_byte_length(title_value)); + dom_string_unref(title_value); + } + + //label = get_attr_val(a, "title", html_context->doc_cp); + } + + /* Little hack to preserve rendering of [ ], in directory listings, + * but we still want to drop extra spaces in alt or title attribute + * to limit display width on certain websites. --Zas */ + if (label && strlen(label) > 5) clr_spaces(label); + } + + src = null_or_stracpy(object_src); + if (!src) { + dom_string *src_value = NULL; + + exc = dom_html_image_element_get_src(img_element, &src_value); + if (DOM_NO_ERR == exc && src_value) { + src = memacpy(dom_string_data(src_value), dom_string_byte_length(src_value)); + dom_string_unref(src_value); + } + //src = get_url_val(a, "src", html_context->doc_cp); + } +// if (!src) src = get_url_val(a, "dynsrc", html_context->doc_cp); + + /* If we have no label yet (no title or alt), so + * just use default ones, or image filename. */ + if (!label || !*label) { + mem_free_set(&label, NULL); + /* Do we want to display images with no alt/title and with no + * link on them ? + * If not, just exit now. */ + if (!options->images && !format.link) { + mem_free_if(src); + if (usemap) pop_html_element(html_context); + return; + } + + add_brackets = 1; + + if (usemap) { + label = stracpy("USEMAP"); + } else if (ismap) { + label = stracpy("ISMAP"); + } else { + if (display_style == 3) + label = get_image_filename_from_src(options->image_link.filename_maxlen, src); + } + + } else { + label = get_image_label(options->image_link.label_maxlen, label); + } + + if (!label || !*label) { + mem_free_set(&label, NULL); + add_brackets = 1; + if (display_style == 1) + label = get_image_filename_from_src(options->image_link.filename_maxlen, src); + if (!label || !*label) + mem_free_set(&label, stracpy("IMG")); + } + + mem_free_set(&format.image, NULL); + mem_free_set(&format.title, NULL); + + if (label) { + int img_link_tag = options->image_link.tagging; + + if (img_link_tag && (img_link_tag == 2 || add_brackets)) { + unsigned char *img_link_prefix = options->image_link.prefix; + unsigned char *img_link_suffix = options->image_link.suffix; + unsigned char *new_label = straconcat(img_link_prefix, label, img_link_suffix, (unsigned char *) NULL); + + if (new_label) mem_free_set(&label, new_label); + } + + if (!options->image_link.show_any_as_links) { + put_image_label(a, label, html_context); + + } else { + if (src) { + format.image = join_urls(html_context->base_href, src); + } + + exc = dom_html_element_get_title((dom_html_element *)node, &title_value); + if (DOM_NO_ERR == exc && title_value) { + format.title = memacpy(dom_string_data(title_value), dom_string_byte_length(title_value)); + dom_string_unref(title_value); + } + //format.title = get_attr_val(a, "title", html_context->doc_cp); + + if (ismap) { + unsigned char *new_link; + + html_stack_dup(html_context, ELEMENT_KILLABLE); + new_link = straconcat(format.link, "?0,0", (unsigned char *) NULL); + if (new_link) { + mem_free_set(&format.link, new_link); + //fprintf(stderr, "new_link: format.link=%s\n", format.link); + } + } + + put_image_label(a, label, html_context); + + if (ismap) pop_html_element(html_context); + mem_free_set(&format.image, NULL); + mem_free_set(&format.title, NULL); + } + + mem_free(label); + } + + mem_free_if(src); + if (usemap) pop_html_element(html_context); +} void tags_html_img(struct source_renderer *renderer, dom_node *node, unsigned char *a, unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5) { + tags_html_img_do(renderer, node, a, NULL); } void