1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-11-04 08:17:17 -05:00
elinks/src/document/xml/tags.c
2022-01-28 16:05:35 +01:00

4723 lines
138 KiB
C

/* General element handlers */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifndef _GNU_SOURCE
#define _GNU_SOURCE /* strcasestr() */
#endif
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "elinks.h"
#include "config/options.h"
#include "bfu/listmenu.h"
#include "bookmarks/bookmarks.h"
#include "document/css/apply.h"
#include "document/html/frames.h"
#include "document/html/parser/link.h"
#include "document/html/parser/stack.h"
#include "document/html/parser.h"
#include "document/html/renderer.h"
#include "document/html/tables.h"
#include "document/options.h"
#include "document/xml/tables.h"
#include "document/xml/tags.h"
#include "globhist/globhist.h"
#include "intl/charsets.h"
#include "protocol/uri.h"
#include "terminal/draw.h"
#include "util/align.h"
#include "util/box.h"
#include "util/color.h"
#include "util/conv.h"
#include "util/error.h"
#include "util/memdebug.h"
#include "util/memory.h"
#include "util/string.h"
/* Unsafe macros */
#include "document/html/internal.h"
#include <stdio.h>
#include <libxml++/libxml++.h>
static struct {
int n;
unsigned char *s;
} roman_tbl[] = {
{1000, "m"},
{999, "im"},
{990, "xm"},
{900, "cm"},
{500, "d"},
{499, "id"},
{490, "xd"},
{400, "cd"},
{100, "c"},
{99, "ic"},
{90, "xc"},
{50, "l"},
{49, "il"},
{40, "xl"},
{10, "x"},
{9, "ix"},
{5, "v"},
{4, "iv"},
{1, "i"},
{0, NULL}
};
enum hlink_type {
LT_UNKNOWN = 0,
LT_START,
LT_PARENT,
LT_NEXT,
LT_PREV,
LT_CONTENTS,
LT_INDEX,
LT_GLOSSARY,
LT_CHAPTER,
LT_SECTION,
LT_SUBSECTION,
LT_APPENDIX,
LT_HELP,
LT_SEARCH,
LT_BOOKMARK,
LT_COPYRIGHT,
LT_AUTHOR,
LT_ICON,
LT_ALTERNATE,
LT_ALTERNATE_LANG,
LT_ALTERNATE_MEDIA,
LT_ALTERNATE_STYLESHEET,
LT_STYLESHEET,
};
enum hlink_direction {
LD_UNKNOWN = 0,
LD_REV,
LD_REL,
};
struct hlink {
enum hlink_type type;
enum hlink_direction direction;
unsigned char *content_type;
unsigned char *media;
unsigned char *href;
unsigned char *hreflang;
unsigned char *title;
unsigned char *lang;
unsigned char *name;
/* Not implemented yet.
unsigned char *charset;
unsigned char *target;
unsigned char *id;
unsigned char *class_;
unsigned char *dir;
*/
};
struct lt_default_name {
enum hlink_type type;
unsigned char *str;
};
/* TODO: i18n */
/* XXX: Keep the (really really ;) default name first */
static struct lt_default_name lt_names[] = {
{ LT_START, "start" },
{ LT_START, "top" },
{ LT_START, "home" },
{ LT_PARENT, "parent" },
{ LT_PARENT, "up" },
{ LT_NEXT, "next" },
{ LT_PREV, "previous" },
{ LT_PREV, "prev" },
{ LT_CONTENTS, "contents" },
{ LT_CONTENTS, "toc" },
{ LT_INDEX, "index" },
{ LT_GLOSSARY, "glossary" },
{ LT_CHAPTER, "chapter" },
{ LT_SECTION, "section" },
{ LT_SUBSECTION, "subsection" },
{ LT_SUBSECTION, "child" },
{ LT_SUBSECTION, "sibling" },
{ LT_APPENDIX, "appendix" },
{ LT_HELP, "help" },
{ LT_SEARCH, "search" },
{ LT_BOOKMARK, "bookmark" },
{ LT_ALTERNATE_LANG, "alt. language" },
{ LT_ALTERNATE_MEDIA, "alt. media" },
{ LT_ALTERNATE_STYLESHEET, "alt. stylesheet" },
{ LT_STYLESHEET, "stylesheet" },
{ LT_ALTERNATE, "alternate" },
{ LT_COPYRIGHT, "copyright" },
{ LT_AUTHOR, "author" },
{ LT_AUTHOR, "made" },
{ LT_AUTHOR, "owner" },
{ LT_ICON, "icon" },
{ LT_UNKNOWN, NULL }
};
static void
roman(struct string *p, unsigned n)
{
int i = 0;
if (n >= 4000) {
add_to_string(p, "---");
return;
}
if (!n) {
add_to_string(p, "o");
return;
}
while (n) {
while (roman_tbl[i].n <= n) {
n -= roman_tbl[i].n;
add_to_string(p, roman_tbl[i].s);
}
i++;
assertm(!(n && !roman_tbl[i].n),
"BUG in roman number converter");
if_assert_failed break;
}
}
static int
tags_get_form_mode(struct html_context *html_context, void *node)
{
xmlpp::Element *el = node;
xmlpp::Attribute *attr;
attr = el->get_attribute("disabled");
if (attr) {
return FORM_MODE_DISABLED;
}
attr = el->get_attribute("readonly");
if (attr) {
return FORM_MODE_READONLY;
}
return FORM_MODE_NORMAL;
}
static struct el_form_control *
tags_init_form_control(enum form_type type, void *node,
struct html_context *html_context)
{
struct el_form_control *fc;
fc = (struct el_form_control *)mem_calloc(1, sizeof(*fc));
if (!fc) return NULL;
fc->type = type;
fc->position = ++html_context->ff;
// fc->position = attr - html_context->startf;
fc->mode = tags_get_form_mode(html_context, node);
return fc;
}
#if 0
static void
html_apply_canvas_bgcolor(struct source_renderer *rendererer)
{
struct html_context *html_context = rendererer->html_context;
#ifdef CONFIG_CSS
/* If there are any CSS twaks regarding bgcolor, make sure we will get
* it _and_ prefer it over bgcolor attribute. */
if (html_context->options->css_enable)
css_apply(html_context, html_top, &html_context->css_styles,
&html_context->stack);
#endif
if (par_elformat.color.background != elformat.style.color.background) {
/* Modify the root HTML element - format_html_part() will take
* this from there. */
struct html_element *e = html_bottom;
html_context->was_body_background = 1;
e->parattr.color.background = e->attr.style.color.background = par_elformat.color.background = elformat.style.color.background;
}
if (html_context->has_link_lines
&& par_elformat.color.background != html_context->options->default_style.color.background
&& !search_html_stack(html_context, DOM_HTML_ELEMENT_TYPE_BODY)) {
html_context->special_f(html_context, SP_COLOR_LINK_LINES);
}
}
#endif
static void tags_html_linebrk(struct source_renderer *renderer, unsigned char *al);
static void tags_html_h(int h, void *node, unsigned char *a,
format_align_T default_align, struct source_renderer *renderer,
unsigned char *html, unsigned char *eof, unsigned char **end);
static void
tags_set_fragment_identifier(struct html_context *html_context,
unsigned char *id_attr)
{
if (id_attr) {
html_context->special_f(html_context, SP_TAG, id_attr);
mem_free(id_attr);
}
}
#if 0
static void
tags_add_fragment_identifier(struct html_context *html_context,
struct part *part, unsigned char *attr)
{
struct part *saved_part = html_context->part;
html_context->part = part;
html_context->special_f(html_context, SP_TAG, attr);
html_context->part = saved_part;
}
#endif
void
tags_html_focusable(struct source_renderer *renderer, void *node)
{
struct html_context *html_context = renderer->html_context;
int32_t tabindex;
elformat.accesskey = 0;
elformat.tabindex = 0x80000000;
xmlpp::Element *el = node;
xmlpp::ustring accesskey_value = el->get_attribute_value("accesskey");
if (accesskey_value != "") {
elformat.accesskey = accesskey_string_to_unicode(accesskey_value.c_str());
}
xmlpp::ustring tabindex_value = el->get_attribute_value("tabindex");
if (tabindex_value != "") {
tabindex = atoi(tabindex_value.c_str());
if (0 < tabindex && tabindex < 32767) {
elformat.tabindex = (tabindex & 0x7fff) << 16;
}
}
xmlpp::ustring string_value = el->get_attribute_value("onclick");
char *value = NULL;
if (string_value != "") {
value = memacpy(string_value.c_str(), string_value.size());
}
mem_free_set(&elformat.onclick, value);
string_value = el->get_attribute_value("ondblclick");
value = NULL;
if (string_value != "") {
value = memacpy(string_value.c_str(), string_value.size());
}
mem_free_set(&elformat.ondblclick, value);
string_value = el->get_attribute_value("onmouseover");
value = NULL;
if (string_value != "") {
value = memacpy(string_value.c_str(), string_value.size());
}
mem_free_set(&elformat.onmouseover, value);
string_value = el->get_attribute_value("onhover");
value = NULL;
if (string_value != "") {
value = memacpy(string_value.c_str(), string_value.size());
}
mem_free_set(&elformat.onhover, value);
string_value = el->get_attribute_value("onfocus");
value = NULL;
if (string_value != "") {
value = memacpy(string_value.c_str(), string_value.size());
}
mem_free_set(&elformat.onfocus, value);
string_value = el->get_attribute_value("onmouseout");
value = NULL;
if (string_value != "") {
value = memacpy(string_value.c_str(), string_value.size());
}
mem_free_set(&elformat.onmouseout, value);
string_value = el->get_attribute_value("onblur");
value = NULL;
if (string_value != "") {
value = memacpy(string_value.c_str(), string_value.size());
}
mem_free_set(&elformat.onblur, value);
}
void
tags_html_a(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
struct html_context *html_context = renderer->html_context;
unsigned char *href;
xmlpp::Element *anchor = node;
xmlpp::ustring href_value = anchor->get_attribute_value("href");
if (href_value == "") {
return;
}
href = memacpy(href_value.c_str(), href_value.size());
if (href) {
unsigned char *target = NULL;
unsigned char *title = NULL;
mem_free_set(&elformat.link,
join_urls(html_context->base_href,
trim_chars(href, ' ', 0)));
mem_free(href);
xmlpp::ustring target_value = anchor->get_attribute_value("target");
if (target_value != "") {
target = memacpy(target_value.c_str(), target_value.size());
}
if (target) {
mem_free_set(&elformat.target, target);
} else {
mem_free_set(&elformat.target, stracpy(html_context->base_target));
}
if (0) {
; /* Shut up compiler */
#ifdef CONFIG_GLOBHIST
} else if (get_global_history_item(elformat.link)) {
elformat.style.color.foreground = elformat.color.vlink;
html_top->pseudo_class &= ~ELEMENT_LINK;
html_top->pseudo_class |= ELEMENT_VISITED;
#endif
#ifdef CONFIG_BOOKMARKS
} else if (get_bookmark(elformat.link)) {
elformat.style.color.foreground = elformat.color.bookmark_link;
html_top->pseudo_class &= ~ELEMENT_VISITED;
/* XXX: Really set ELEMENT_LINK? --pasky */
html_top->pseudo_class |= ELEMENT_LINK;
#endif
} else {
elformat.style.color.foreground = elformat.color.clink;
html_top->pseudo_class &= ~ELEMENT_VISITED;
html_top->pseudo_class |= ELEMENT_LINK;
}
xmlpp::ustring title_value = anchor->get_attribute_value("title");
if (title_value != "") {
title = memacpy(title_value.c_str(), title_value.size());
}
mem_free_set(&elformat.title, title);
tags_html_focusable(renderer, (void *)anchor);
} else {
pop_html_element(html_context);
}
xmlpp::ustring name_value = anchor->get_attribute_value("name");
if (name_value != "") {
unsigned char *name = memacpy(name_value.c_str(), name_value.size());
tags_set_fragment_identifier(html_context, name);
}
}
void
tags_html_a_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_abbr(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_abbr_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_address(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
struct html_context *html_context = renderer->html_context;
par_elformat.leftmargin++;
par_elformat.align = ALIGN_LEFT;
}
void
tags_html_address_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_applet(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_applet_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_area(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_area_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_article(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_article_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_aside(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_aside_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_audio(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_audio_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_b(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
struct html_context *html_context = renderer->html_context;
elformat.style.attr |= AT_BOLD;
}
void
tags_html_b_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_base(struct source_renderer *renderer, void *no, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
struct html_context *html_context = renderer->html_context;
xmlpp::Element *element = no;
unsigned char *al;
xmlpp::ustring href_value = element->get_attribute_value("href");
if (href_value != "") {
al = memacpy(href_value.c_str(), href_value.size());
if (al) {
unsigned char *base = join_urls(html_context->base_href, al);
struct uri *uri = base ? get_uri(base, URI_NONE) : NULL;
mem_free(al);
mem_free_if(base);
if (uri) {
done_uri(html_context->base_href);
html_context->base_href = uri;
}
}
}
xmlpp::ustring target_value = element->get_attribute_value("target");
if (target_value != "") {
al = memacpy(target_value.c_str(), target_value.size());
if (al) mem_free_set(&html_context->base_target, al);
}
}
void
tags_html_base_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_basefont(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_basefont_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_bdi(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_bdi_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_bdo(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_bdo_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_blockquote(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
struct html_context *html_context = renderer->html_context;
par_elformat.align = ALIGN_LEFT;
if (par_elformat.blockquote_level == 0) {
par_elformat.orig_leftmargin = par_elformat.leftmargin;
par_elformat.blockquote_level++;
}
par_elformat.blockquote_level++;
}
void
tags_html_blockquote_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
struct html_context *html_context = renderer->html_context;
if (par_elformat.blockquote_level == 2) par_elformat.blockquote_level--;
if (par_elformat.blockquote_level > 0) par_elformat.blockquote_level--;
}
void
tags_html_apply_canvas_bgcolor(struct source_renderer *renderer)
{
struct html_context *html_context = renderer->html_context;
#ifdef CONFIG_CSS
/* If there are any CSS twaks regarding bgcolor, make sure we will get
* it _and_ prefer it over bgcolor attribute. */
if (html_context->options->css_enable)
css_apply(html_context, html_top, &html_context->css_styles,
&html_context->stack);
#endif
if (par_elformat.color.background != elformat.style.color.background) {
/* Modify the root HTML element - format_html_part() will take
* this from there. */
struct html_element *e = html_bottom;
html_context->was_body_background = 1;
e->parattr.color.background = e->attr.style.color.background = par_elformat.color.background = elformat.style.color.background;
}
if (html_context->has_link_lines
&& par_elformat.color.background != html_context->options->default_style.color.background
&& !search_html_stack(html_context, "body")) {
html_context->special_f(html_context, SP_COLOR_LINK_LINES);
}
}
void
tags_html_body(struct source_renderer *renderer, void *no, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
struct html_context *html_context = renderer->html_context;
xmlpp::Element *node = no;
xmlpp::ustring text_value = node->get_attribute_value("text");
get_color2(html_context, text_value.c_str(), &elformat.style.color.foreground);
xmlpp::ustring link_value = node->get_attribute_value("link");
get_color2(html_context, link_value.c_str(), &elformat.color.clink);
xmlpp::ustring vlink_value = node->get_attribute_value("vlink");
get_color2(html_context, vlink_value.c_str(), &elformat.color.vlink);
xmlpp::ustring bgcolor_value = node->get_attribute_value("bgcolor");
int v = get_color2(html_context, bgcolor_value.c_str(), &elformat.style.color.background);
if (-1 != v) {
html_context->was_body_background = 1;
}
html_context->was_body = 1; /* this will be used by "meta inside body" */
tags_html_apply_canvas_bgcolor(renderer);
}
void
tags_html_body_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_br(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *html, unsigned char *eof, unsigned char **end)
{
struct html_context *html_context = renderer->html_context;
//html_linebrk(html_context, a, html, eof, end);
if (html_context->was_br)
ln_break(html_context, 2);
else
html_context->was_br = 1;
}
void
tags_html_br_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_button(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
struct html_context *html_context = renderer->html_context;
unsigned char *al = NULL;
struct el_form_control *fc;
enum form_type type = FC_SUBMIT;
xmlpp::Element *button = node;
tags_html_focusable(renderer, node);
xmlpp::ustring type_value = button->get_attribute_value("type");
if (type_value != "") {
al = memacpy(type_value.c_str(), type_value.size());
}
// al = get_attr_val(a, "type", cp);
if (!al) goto no_type_attr;
if (!c_strcasecmp(al, "button")) {
type = FC_BUTTON;
} else if (!c_strcasecmp(al, "reset")) {
type = FC_RESET;
} else if (c_strcasecmp(al, "submit")) {
/* unknown type */
mem_free(al);
return;
}
mem_free(al);
no_type_attr:
fc = tags_init_form_control(type, node, html_context);
if (!fc) return;
xmlpp::ustring disabled = button->get_attribute_value("disabled");
if (disabled == "true" || disabled == "1" || disabled == "disabled") {
fc->mode = FORM_MODE_DISABLED;
}
xmlpp::ustring id_value = button->get_attribute_value("id");
if (id_value != "") {
fc->id = memacpy(id_value.c_str(), id_value.size());
}
//fc->id = get_attr_val(a, "id", cp);
xmlpp::ustring name_value = button->get_attribute_value("name");
if (name_value != "") {
fc->name = memacpy(name_value.c_str(), name_value.size());
}
//fc->name = get_attr_val(a, "name", cp);
xmlpp::ustring value_value = button->get_attribute_value("value");
if (true) {
fc->default_value = memacpy(value_value.c_str(), value_value.size());
}
//fc->default_value = get_attr_val(a, "value", cp);
if (!fc->default_value) {
if (fc->type == FC_SUBMIT)
fc->default_value = stracpy("Submit");
else if (fc->type == FC_RESET)
fc->default_value = stracpy("Reset");
else if (fc->type == FC_BUTTON)
fc->default_value = stracpy("Button");
}
if (!fc->default_value)
fc->default_value = stracpy("");
html_context->special_f(html_context, SP_CONTROL, fc);
elformat.form = fc;
elformat.style.attr |= AT_BOLD;
}
void
tags_html_button_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_canvas(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_canvas_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_caption(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_caption_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_center(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
struct html_context *html_context = renderer->html_context;
par_elformat.align = ALIGN_CENTER;
if (!html_context->table_level)
par_elformat.leftmargin = par_elformat.rightmargin = 0;
}
void
tags_html_center_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_cite(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_cite_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_code(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_code_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_col(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_col_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_colgroup(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_colgroup_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_data(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_data_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_datalist(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_datalist_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_dd(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
struct html_context *html_context = renderer->html_context;
kill_html_stack_until(html_context, 0, "", "DL", NULL);
par_elformat.leftmargin = par_elformat.dd_margin + 3;
if (!html_context->table_level) {
par_elformat.leftmargin += 5;
int_upper_bound(&par_elformat.leftmargin, par_elformat.width / 2);
}
par_elformat.align = ALIGN_LEFT;
}
void
tags_html_dd_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_del(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_del_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_details(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_details_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_dfn(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_dfn_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_dialog(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_dialog_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_dir(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_dir_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_div(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_div_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_dl(struct source_renderer *renderer, void *no, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
struct html_context *html_context = renderer->html_context;
xmlpp::Element *node = no;
xmlpp::ustring compact = node->get_attribute_value("compact");
par_elformat.flags &= ~P_COMPACT;
if (compact != "") {
par_elformat.flags |= P_COMPACT;
}
if (par_elformat.list_level) par_elformat.leftmargin += 5;
par_elformat.list_level++;
par_elformat.list_number = 0;
par_elformat.align = ALIGN_LEFT;
par_elformat.dd_margin = par_elformat.leftmargin;
html_top->type = ELEMENT_DONT_KILL;
if (!(par_elformat.flags & P_COMPACT)) {
ln_break(html_context, 2);
html_top->linebreak = 2;
}
}
void
tags_html_dl_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_dt(struct source_renderer *renderer, void *no, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
struct html_context *html_context = renderer->html_context;
xmlpp::Element *node = no;
xmlpp::ustring compact = node->get_attribute_value("compact");
kill_html_stack_until(html_context, 0, "", "DL", NULL);
par_elformat.align = ALIGN_LEFT;
par_elformat.leftmargin = par_elformat.dd_margin;
if (!(par_elformat.flags & P_COMPACT) && (compact == ""))
ln_break(html_context, 2);
}
void
tags_html_dt_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_em(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_em_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_embed(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_embed_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_fieldset(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_fieldset_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_figcaption(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_figcaption_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_figure(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_figure_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_font(struct source_renderer *renderer, void *no, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
struct html_context *html_context = renderer->html_context;
xmlpp::Element *node = no;
xmlpp::ustring size_value = node->get_attribute_value("size");
if (size_value != "") {
unsigned char *al = memacpy(size_value.c_str(), size_value.size());
if (al) {
int p = 0;
unsigned s;
unsigned char *nn = al;
unsigned char *end;
if (*al == '+') p = 1, nn++;
else if (*al == '-') p = -1, nn++;
errno = 0;
s = strtoul(nn, (char **) &end, 10);
if (!errno && *nn && !*end) {
if (s > 7) s = 7;
if (!p) elformat.fontsize = s;
else elformat.fontsize += p * s;
if (elformat.fontsize < 1) elformat.fontsize = 1;
else if (elformat.fontsize > 7) elformat.fontsize = 7;
}
mem_free(al);
}
}
xmlpp::ustring color_value = node->get_attribute_value("color");
get_color2(html_context, color_value.c_str(), &elformat.style.color.foreground);
}
void
tags_html_font_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_footer(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_footer_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_form(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
struct html_context *html_context = renderer->html_context;
unsigned char *al=NULL;
struct form *form;
xmlpp::Element *form_node = node;
html_context->was_br = 1;
form = init_form();
if (!form) return;
form->method = FORM_METHOD_GET;
form->form_num = ++html_context->ff;
// form->form_num = a - html_context->startf;
xmlpp::ustring method_value = form_node->get_attribute_value("method");
if (method_value != "") {
al = memacpy(method_value.c_str(), method_value.size());
}
//al = get_attr_val(a, "method", html_context->doc_cp);
if (al) {
if (!c_strcasecmp(al, "post")) {
xmlpp::ustring enctype_value = form_node->get_attribute_value("enctype");
if (enctype_value != "") {
unsigned char *enctype = memacpy(enctype_value.c_str(), enctype_value.size());
// enctype = get_attr_val(a, "enctype",
// html_context->doc_cp);
form->method = FORM_METHOD_POST;
if (enctype) {
if (!c_strcasecmp(enctype, "multipart/form-data"))
form->method = FORM_METHOD_POST_MP;
else if (!c_strcasecmp(enctype, "text/plain"))
form->method = FORM_METHOD_POST_TEXT_PLAIN;
mem_free(enctype);
}
}
}
mem_free(al);
}
xmlpp::ustring onsubmit_value = form_node->get_attribute_value("onsubmit");
if (onsubmit_value != "") {
form->onsubmit = memacpy(onsubmit_value.c_str(), onsubmit_value.size());
}
xmlpp::ustring name_value = form_node->get_attribute_value("name");
//form->onsubmit = get_attr_val(a, "onsubmit", html_context->doc_cp);
if (name_value != "") {
form->name = memacpy(name_value.c_str(), name_value.size());
}
//al = get_attr_val(a, "name", html_context->doc_cp);
//if (al) form->name = al;
xmlpp::ustring action_value = form_node->get_attribute_value("action");
if (action_value != "") {
al = memacpy(action_value.c_str(), action_value.size());
// al = get_attr_val(a, "action", html_context->doc_cp);
/* The HTML specification at
* http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.3 states
* that the behavior of an empty action attribute should be undefined.
* Mozilla handles action="" as action="<current-URI>" which seems
* reasonable. (bug 615) */
if (al && *al) {
form->action = join_urls(html_context->base_href, trim_chars(al, ' ', NULL));
mem_free(al);
} else {
uri_component_T components = URI_ORIGINAL;
mem_free_if(al);
/* We have to do following for GET method, because we would end
* up with two '?' otherwise. */
if (form->method == FORM_METHOD_GET) {
components = URI_FORM_GET;
}
form->action = get_uri_string(html_context->base_href, components);
/* No action URI should contain post data */
assert(!form->action || !strchr(form->action, POST_CHAR));
/* GET method URIs should not have '?'. */
assert(!form->action
|| form->method != FORM_METHOD_GET
|| !strchr(form->action, '?'));
}
}
al = NULL;
xmlpp::ustring target_value = form_node->get_attribute_value("target");
if (target_value != "") {
al = memacpy(target_value.c_str(), target_value.size());
}
//al = get_target(html_context->options, a);
form->target = al ? al : stracpy(html_context->base_target);
html_context->special_f(html_context, SP_FORM, form);
}
void
tags_html_form_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_frame(struct source_renderer *renderer, void *no, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
struct html_context *html_context = renderer->html_context;
xmlpp::Element *node = no;
xmlpp::ustring src_value = node->get_attribute_value("src");
unsigned char *src = NULL, *name = NULL, *url;
if (src_value != "") {
src = memacpy(src_value.c_str(), src_value.size());
}
if (!src) {
url = stracpy("about:blank");
} else {
url = join_urls(html_context->base_href, src);
mem_free(src);
}
if (!url) return;
xmlpp::ustring name_value = node->get_attribute_value("name");
if (name_value != "") {
name = memacpy(name_value.c_str(), name_value.size());
}
if (!name) {
name = stracpy(url);
} else if (!name[0]) {
/* When name doesn't have a value */
mem_free(name);
name = stracpy(url);
}
if (!name) {
mem_free_if(url);
return;
}
if (!html_context->options->frames || !html_top->frameset) {
tags_html_focusable(renderer, no);
put_link_line("Frame: ", name, url, "", html_context);
} else {
if (html_context->special_f(html_context, SP_USED, NULL)) {
html_context->special_f(html_context, SP_FRAME,
html_top->frameset, name, url);
}
}
mem_free(name);
mem_free(url);
}
void
tags_html_frame_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_frameset(struct source_renderer *renderer, void *no, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
struct html_context *html_context = renderer->html_context;
xmlpp::Element *node = no;
struct frameset_param fp;
unsigned char *cols = NULL, *rows = NULL;
int width, height;
/* XXX: This is still not 100% correct. We should also ignore the
* frameset when we encountered anything 3v1l (read as: non-whitespace
* text/element/anything) in the document outside of <head>. Well, this
* is still better than nothing and it should heal up the security
* concerns at least because sane sites should enclose the documents in
* <body> elements ;-). See also bug 171. --pasky */
if (search_html_stack(html_context, "body")
|| !html_context->options->frames
|| !html_context->special_f(html_context, SP_USED, NULL))
return;
xmlpp::ustring cols_value = node->get_attribute_value("cols");
if (cols_value != "") {
cols = memacpy(cols_value.c_str(), cols_value.size());
}
if (!cols) {
cols = stracpy("100%");
if (!cols) return;
}
xmlpp::ustring rows_value = node->get_attribute_value("rows");
if (rows_value != "") {
rows = memacpy(rows_value.c_str(), rows_value.size());
}
if (!rows) {
rows = stracpy("100%");
if (!rows) {
mem_free(cols);
return;
}
}
if (!html_top->frameset) {
width = html_context->options->document_width;
height = html_context->options->box.height;
html_context->options->needs_height = 1;
} else {
struct frameset_desc *frameset_desc = html_top->frameset;
int offset;
if (frameset_desc->box.y >= frameset_desc->box.height)
goto free_and_return;
offset = frameset_desc->box.x
+ frameset_desc->box.y * frameset_desc->box.width;
width = frameset_desc->frame_desc[offset].width;
height = frameset_desc->frame_desc[offset].height;
}
fp.width = fp.height = NULL;
parse_frame_widths(cols, width, HTML_FRAME_CHAR_WIDTH,
&fp.width, &fp.x);
parse_frame_widths(rows, height, HTML_FRAME_CHAR_HEIGHT,
&fp.height, &fp.y);
fp.parent = html_top->frameset;
if (fp.x && fp.y) {
html_top->frameset = html_context->special_f(html_context, SP_FRAMESET, &fp);
}
mem_free_if(fp.width);
mem_free_if(fp.height);
free_and_return:
mem_free(cols);
mem_free(rows);
}
void
tags_html_frameset_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_h1(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *html, unsigned char *eof, unsigned char **end)
{
struct html_context *html_context = renderer->html_context;
elformat.style.attr |= AT_BOLD;
tags_html_h(1, node, a, ALIGN_CENTER, renderer, html, eof, end);
}
void
tags_html_h1_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_h2(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *html, unsigned char *eof, unsigned char **end)
{
tags_html_h(2, node, a, ALIGN_LEFT, renderer, html, eof, end);
}
void
tags_html_h2_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_h3(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *html, unsigned char *eof, unsigned char **end)
{
tags_html_h(3, node, a, ALIGN_LEFT, renderer, html, eof, end);
}
void
tags_html_h3_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_h4(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *html, unsigned char *eof, unsigned char **end)
{
tags_html_h(4, node, a, ALIGN_LEFT, renderer, html, eof, end);
}
void
tags_html_h4_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_h5(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *html, unsigned char *eof, unsigned char **end)
{
tags_html_h(5, node, a, ALIGN_LEFT, renderer, html, eof, end);
}
void
tags_html_h5_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_h6(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *html, unsigned char *eof, unsigned char **end)
{
tags_html_h(6, node, a, ALIGN_LEFT, renderer, html, eof, end);
}
void
tags_html_h6_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_head(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
/* This makes sure it gets to the stack and helps tame down unclosed
* <title>. */
renderer->html_context->skip_html = 1;
}
void
tags_html_head_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
renderer->html_context->skip_html = 0;
}
void
tags_html_header(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_header_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_hgroup(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_hgroup_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_hr(struct source_renderer *renderer, void *no, unsigned char *a,
unsigned char *html, unsigned char *eof, unsigned char **end)
{
struct html_context *html_context = renderer->html_context;
int i = -1/* = par_elformat.width - 10*/;
unsigned char r = (unsigned char) BORDER_DHLINE;
xmlpp::Element *node = no;
unsigned char *al = NULL;
int q = -1;
//dom_long q = 0;
xmlpp::ustring size_value = node->get_attribute_value("size");
if (size_value != "") {
al = memacpy(size_value.c_str(), size_value.size());
q = get_num2(al);
}
if (q >= 0 && q < 2) r = (unsigned char) BORDER_SHLINE;
html_stack_dup(html_context, ELEMENT_KILLABLE);
par_elformat.align = ALIGN_CENTER;
mem_free_set(&elformat.link, NULL);
elformat.form = NULL;
xmlpp::ustring align_value = node->get_attribute_value("align");
if (align_value != "") {
al = memacpy(align_value.c_str(), align_value.size());
tags_html_linebrk(renderer, al);
}
if (par_elformat.align == ALIGN_JUSTIFY) par_elformat.align = ALIGN_CENTER;
par_elformat.leftmargin = par_elformat.rightmargin = html_context->margin;
xmlpp::ustring width_value = node->get_attribute_value("width");
if (width_value != "") {
al = memacpy(width_value.c_str(), width_value.size());
i = get_width2(al, 1, html_context);
}
if (i == -1) i = get_html_max_width();
elformat.style.attr = AT_GRAPHICS;
html_context->special_f(html_context, SP_NOWRAP, 1);
while (i-- > 0) {
put_chrs(html_context, &r, 1);
}
html_context->special_f(html_context, SP_NOWRAP, 0);
ln_break(html_context, 2);
pop_html_element(html_context);
}
void
tags_html_hr_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_html(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
struct html_context *html_context = renderer->html_context;
/* This is here just to get CSS stuff applied. */
/* Modify the root HTML element - format_html_part() will take
* this from there. */
struct html_element *e = html_bottom;
if (par_elformat.color.background != elformat.style.color.background)
e->parattr.color.background = e->attr.style.color.background = par_elformat.color.background = elformat.style.color.background;
}
void
tags_html_html_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
struct html_context *html_context = renderer->html_context;
if (html_top->type >= ELEMENT_KILLABLE
&& !html_context->was_body_background) {
tags_html_apply_canvas_bgcolor(renderer);
}
}
void
tags_html_i(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
struct html_context *html_context = renderer->html_context;
elformat.style.attr |= AT_ITALIC;
}
void
tags_html_i_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_iframe(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_iframe_close(struct source_renderer *renderer, void *node, unsigned char *a,
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 = (unsigned char *)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(struct source_renderer *renderer, void *node, unsigned char *label)
{
struct html_context *html_context = renderer->html_context;
color_T saved_foreground;
text_style_format_T saved_attr;
/* This is not 100% appropriate for <img>, but well, accepting
* accesskey and tabindex near <img> is just our little
* extension to the standard. After all, it makes sense. */
tags_html_focusable(renderer, node);
saved_foreground = elformat.style.color.foreground;
saved_attr = elformat.style.attr;
elformat.style.color.foreground = elformat.color.image_link;
elformat.style.attr |= AT_NO_ENTITIES;
put_chrs(html_context, label, strlen(label));
elformat.style.color.foreground = saved_foreground;
elformat.style.attr = saved_attr;
}
static void
tags_html_img_do(struct source_renderer *renderer, void *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;
xmlpp::Element *img_element = node;
/* 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 */
xmlpp::ustring usemap_value = img_element->get_attribute_value("usemap");
if (usemap_value != "") {
usemap_attr = memacpy(usemap_value.c_str(), usemap_value.size());
} 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(&elformat.link, map_url);
elformat.form = NULL;
elformat.style.attr |= AT_BOLD;
usemap = 1;
}
xmlpp::ustring ismap_value = img_element->get_attribute_value("ismap");
ismap = elformat.link && (ismap_value != "") && !usemap;
// ismap = elformat.link
// && has_attr(a, "ismap", html_context->doc_cp)
// && !usemap;
if (display_style == 2 || display_style == 3) {
xmlpp::ustring alt_value = img_element->get_attribute_value("alt");
if (alt_value != "") {
label = memacpy(alt_value.c_str(), alt_value.size());
}
//label = get_attr_val(a, "alt", html_context->doc_cp);
if (!label) {
xmlpp::ustring title_value = img_element->get_attribute_value("title");
if (title_value != "") {
label = memacpy(title_value.c_str(), title_value.size());
}
//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) {
xmlpp::ustring src_value = img_element->get_attribute_value("src");
if (src_value != "") {
src = memacpy(src_value.c_str(), src_value.size());
}
//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 && !elformat.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(&elformat.image, NULL);
mem_free_set(&elformat.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(renderer, node, label);
} else {
if (src) {
elformat.image = join_urls(html_context->base_href, src);
}
xmlpp::ustring title_value = img_element->get_attribute_value("title");
if (title_value != "") {
elformat.title = memacpy(title_value.c_str(), title_value.size());
}
//elformat.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(elformat.link, "?0,0", (unsigned char *) NULL);
if (new_link) {
mem_free_set(&elformat.link, new_link);
}
}
put_image_label(renderer, node, label);
if (ismap) pop_html_element(html_context);
mem_free_set(&elformat.image, NULL);
mem_free_set(&elformat.title, NULL);
}
mem_free(label);
}
mem_free_if(src);
if (usemap) pop_html_element(html_context);
}
void
tags_html_img(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
tags_html_img_do(renderer, node, a, NULL);
}
void
tags_html_img_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
static void
tags_html_input_format(struct source_renderer *renderer, void *node, unsigned char *a,
struct el_form_control *fc)
{
struct html_context *html_context = renderer->html_context;
put_chrs(html_context, " ", 1);
html_stack_dup(html_context, ELEMENT_KILLABLE);
tags_html_focusable(renderer, node);
elformat.form = fc;
mem_free_if(elformat.title);
xmlpp::Element *input = node;
xmlpp::ustring title_value = input->get_attribute_value("title");
if (title_value != "") {
elformat.title = memacpy(title_value.c_str(), title_value.size());
}
//elformat.title = get_attr_val(a, "title", html_context->doc_cp);
switch (fc->type) {
case FC_TEXT:
case FC_PASSWORD:
case FC_FILE:
{
int i;
elformat.style.attr |= AT_BOLD;
for (i = 0; i < fc->size; i++)
put_chrs(html_context, "_", 1);
break;
}
case FC_CHECKBOX:
elformat.style.attr |= AT_BOLD;
put_chrs(html_context, "[&nbsp;]", 8);
break;
case FC_RADIO:
elformat.style.attr |= AT_BOLD;
put_chrs(html_context, "(&nbsp;)", 8);
break;
case FC_IMAGE:
{
unsigned char *al = NULL;
mem_free_set(&elformat.image, NULL);
xmlpp::ustring src_value = input->get_attribute_value("src");
if (src_value != "") {
al = memacpy(src_value.c_str(), src_value.size());
}
//al = get_url_val(a, "src", html_context->doc_cp);
#if 0
if (!al) {
al = get_url_val(a, "dynsrc",
html_context->doc_cp);
}
#endif
if (al) {
elformat.image = join_urls(html_context->base_href, al);
mem_free(al);
}
elformat.style.attr |= AT_BOLD;
put_chrs(html_context, "[&nbsp;", 7);
elformat.style.attr |= AT_NO_ENTITIES;
if (fc->alt)
put_chrs(html_context, fc->alt, strlen(fc->alt));
else if (fc->name)
put_chrs(html_context, fc->name, strlen(fc->name));
else
put_chrs(html_context, "Submit", 6);
elformat.style.attr &= ~AT_NO_ENTITIES;
put_chrs(html_context, "&nbsp;]", 7);
break;
}
case FC_SUBMIT:
case FC_RESET:
case FC_BUTTON:
elformat.style.attr |= AT_BOLD;
put_chrs(html_context, "[&nbsp;", 7);
if (fc->default_value) {
elformat.style.attr |= AT_NO_ENTITIES;
put_chrs(html_context, fc->default_value, strlen(fc->default_value));
elformat.style.attr &= ~AT_NO_ENTITIES;
}
put_chrs(html_context, "&nbsp;]", 7);
break;
case FC_TEXTAREA:
case FC_SELECT:
case FC_HIDDEN:
INTERNAL("bad control type");
}
pop_html_element(html_context);
put_chrs(html_context, " ", 1);
}
void
tags_html_input(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
struct html_context *html_context = renderer->html_context;
unsigned char *al = NULL;
struct el_form_control *fc;
xmlpp::Element *input = node;
unsigned int size = 0;
fc = tags_init_form_control(FC_TEXT, node, html_context);
if (!fc) return;
xmlpp::ustring disabled = input->get_attribute_value("disabled");
if (disabled == "disabled" || disabled == "true" || disabled == "1") {
fc->mode = FORM_MODE_DISABLED;
}
if (disabled == "") {
xmlpp::ustring readonly = input->get_attribute_value("readonly");
if (readonly == "readonly" || readonly == "true" || readonly == "1") {
fc->mode = FORM_MODE_READONLY;
}
}
xmlpp::ustring type_value = input->get_attribute_value("type");
if (type_value != "") {
al = memacpy(type_value.c_str(), type_value.size());
}
// al = get_attr_val(a, "type", cp);
if (al) {
if (!c_strcasecmp(al, "text")) fc->type = FC_TEXT;
else if (!c_strcasecmp(al, "hidden")) fc->type = FC_HIDDEN;
else if (!c_strcasecmp(al, "button")) fc->type = FC_BUTTON;
else if (!c_strcasecmp(al, "checkbox")) fc->type = FC_CHECKBOX;
else if (!c_strcasecmp(al, "radio")) fc->type = FC_RADIO;
else if (!c_strcasecmp(al, "password")) fc->type = FC_PASSWORD;
else if (!c_strcasecmp(al, "submit")) fc->type = FC_SUBMIT;
else if (!c_strcasecmp(al, "reset")) fc->type = FC_RESET;
else if (!c_strcasecmp(al, "file")) fc->type = FC_FILE;
else if (!c_strcasecmp(al, "image")) fc->type = FC_IMAGE;
/* else unknown type, let it default to FC_TEXT. */
mem_free(al);
}
xmlpp::ustring value_value = input->get_attribute_value("value");
if (true) {
if (fc->type == FC_HIDDEN) {
fc->default_value = memacpy(value_value.c_str(), value_value.size());
} else if (fc->type != FC_FILE) {
fc->default_value = memacpy(value_value.c_str(), value_value.size());
}
}
// if (fc->type == FC_HIDDEN)
// fc->default_value = get_lit_attr_val(a, "value", cp);
// else if (fc->type != FC_FILE)
// fc->default_value = get_attr_val(a, "value", cp);
if (!fc->default_value) {
if (fc->type == FC_CHECKBOX)
fc->default_value = stracpy("on");
else if (fc->type == FC_SUBMIT)
fc->default_value = stracpy("Submit");
else if (fc->type == FC_RESET)
fc->default_value = stracpy("Reset");
else if (fc->type == FC_BUTTON)
fc->default_value = stracpy("Button");
}
if (!fc->default_value)
fc->default_value = stracpy("");
xmlpp::ustring id_value = input->get_attribute_value("id");
if (id_value != "") {
fc->id = memacpy(id_value.c_str(), id_value.size());
}
//fc->id = get_attr_val(a, "id", cp);
xmlpp::ustring name_value = input->get_attribute_value("name");
if (name_value != "") {
fc->name = memacpy(name_value.c_str(), name_value.size());
}
//fc->name = get_attr_val(a, "name", cp);
xmlpp::ustring size_value = input->get_attribute_value("size");
if (size_value != "") {
fc->size = atoi(size_value.c_str());
}
//fc->size = get_num(a, "size", cp);
if (fc->size <= 0)
fc->size = html_context->options->default_form_input_size;
fc->size++;
if (fc->size > html_context->options->document_width)
fc->size = html_context->options->document_width;
xmlpp::ustring maxlength_value = input->get_attribute_value("maxlength");
if (maxlength_value != "") {
fc->maxlength = atoi(maxlength_value.c_str());
}
//fc->maxlength = get_num(a, "maxlength", cp);
if (fc->maxlength == -1) fc->maxlength = INT_MAX;
if (fc->type == FC_CHECKBOX || fc->type == FC_RADIO) {
xmlpp::ustring checked_value = input->get_attribute_value("checked");
bool checked = (checked_value == "checked" || checked_value == "true" || checked_value == "1");
//fc->default_state = has_attr(a, "checked", cp);
fc->default_state = checked;
}
if (fc->type == FC_IMAGE) {
xmlpp::ustring alt_value = input->get_attribute_value("alt");
if (alt_value != "") {
fc->alt = memacpy(alt_value.c_str(), alt_value.size());
}
// fc->alt = get_attr_val(a, "alt", cp);
}
if (fc->type != FC_HIDDEN) {
tags_html_input_format(renderer, node, a, fc);
}
html_context->special_f(html_context, SP_CONTROL, fc);
}
void
tags_html_input_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_ins(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_ins_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_isindex(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_isindex_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_kbd(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_kbd_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_keygen(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_keygen_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_label(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_label_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_legend(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_legend_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
void
tags_html_li(struct source_renderer *renderer, void *no, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
struct html_context *html_context = renderer->html_context;
xmlpp::Element *node = no;
int t = par_elformat.flags & P_LISTMASK;
/* When handling the code <li><li> @was_li will be 1 and it means we
* have to insert a line break since no list item content has done it
* for us. */
if (html_context->was_li) {
html_context->line_breax = 0;
ln_break(html_context, 1);
}
/*kill_html_stack_until(html_context, 0
"", "UL", "OL", NULL);*/
if (t == P_NO_BULLET) {
/* Print nothing. */
} else if (!par_elformat.list_number) {
if (t == P_O) /* Print U+25E6 WHITE BULLET. */
put_chrs(html_context, "&#9702;", 7);
else if (t == P_SQUARE) /* Print U+25AA BLACK SMALL SQUARE. */
put_chrs(html_context, "&#9642;", 7);
else /* Print U+2022 BULLET. */
put_chrs(html_context, "&#8226;", 7);
put_chrs(html_context, "&nbsp;", 6);
par_elformat.leftmargin += 2;
par_elformat.align = ALIGN_LEFT;
} else {
long s = -1;
unsigned char c = 0;
int nlen;
int t = par_elformat.flags & P_LISTMASK;
struct string n;
xmlpp::ustring s_value = node->get_attribute_value("value");
if (s_value != "") {
s = atol(s_value.c_str());
}
if (!init_string(&n)) return;
if (s != -1) par_elformat.list_number = s;
if (t == P_ALPHA || t == P_alpha) {
unsigned char n0;
put_chrs(html_context, "&nbsp;", 6);
c = 1;
n0 = par_elformat.list_number
? (par_elformat.list_number - 1) % 26
+ (t == P_ALPHA ? 'A' : 'a')
: 0;
if (n0) add_char_to_string(&n, n0);
} else if (t == P_ROMAN || t == P_roman) {
roman(&n, par_elformat.list_number);
if (t == P_ROMAN) {
unsigned char *x;
for (x = n.source; *x; x++) *x = c_toupper(*x);
}
} else {
unsigned char n0[64];
if (par_elformat.list_number < 10) {
put_chrs(html_context, "&nbsp;", 6);
c = 1;
}
ulongcat(n0, NULL, par_elformat.list_number, (sizeof(n) - 1), 0);
add_to_string(&n, n0);
}
nlen = n.length;
put_chrs(html_context, n.source, nlen);
put_chrs(html_context, ".&nbsp;", 7);
par_elformat.leftmargin += nlen + c + 2;
par_elformat.align = ALIGN_LEFT;
done_string(&n);
{
struct html_element *element;
element = search_html_stack(html_context, "ol");
if (element)
element->parattr.list_number = par_elformat.list_number + 1;
}
par_elformat.list_number = 0;
}
html_context->putsp = HTML_SPACE_SUPPRESS;
html_context->line_breax = 2;
html_context->was_li = 1;
}
void
tags_html_li_close(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
}
/* Search for default name for this link according to its type. */
static unsigned char *
get_lt_default_name(struct hlink *link)
{
struct lt_default_name *entry = lt_names;
assert(link);
while (entry && entry->str) {
if (entry->type == link->type) return entry->str;
entry++;
}
return "unknown";
}
static void
tags_html_link_clear(struct hlink *link)
{
assert(link);
mem_free_if(link->content_type);
mem_free_if(link->media);
mem_free_if(link->href);
mem_free_if(link->hreflang);
mem_free_if(link->title);
mem_free_if(link->lang);
mem_free_if(link->name);
memset(link, 0, sizeof(*link));
}
/* Parse a link and return results in @link.
* It tries to identify known types. */
static int
tags_html_link_parse(struct source_renderer *renderer, void *node, unsigned char *a,
struct hlink *link)
{
//struct html_context *html_context = renderer->html_context;
xmlpp::Element *link_element = node;
int i;
assert(/*a &&*/ link);
memset(link, 0, sizeof(*link));
xmlpp::ustring href_value = link_element->get_attribute_value("href");
if (href_value != "") {
link->href = memacpy(href_value.c_str(), href_value.size());
}
// link->href = get_url_val(a, "href", html_context->doc_cp);
if (!link->href) return 0;
xmlpp::ustring lang_value = link_element->get_attribute_value("lang");
if (lang_value != "") {
link->lang = memacpy(lang_value.c_str(), lang_value.size());
}
//link->lang = get_attr_val(a, "lang", html_context->doc_cp);
xmlpp::ustring hreflang_value = link_element->get_attribute_value("hreflang");
if (hreflang_value != "") {
link->hreflang = memacpy(hreflang_value.c_str(), hreflang_value.size());
}
// link->hreflang = get_attr_val(a, "hreflang", html_context->doc_cp);
xmlpp::ustring title_value = link_element->get_attribute_value("title");
if (title_value != "") {
link->title = memacpy(title_value.c_str(), title_value.size());
}
// link->title = get_attr_val(a, "title", html_context->doc_cp);
xmlpp::ustring type_value = link_element->get_attribute_value("type");
if (type_value != "") {
link->content_type = memacpy(type_value.c_str(), type_value.size());
}
//link->content_type = get_attr_val(a, "type", html_context->doc_cp);
xmlpp::ustring media_value = link_element->get_attribute_value("media");
if (media_value != "") {
link->media = memacpy(media_value.c_str(), media_value.size());
}
//link->media = get_attr_val(a, "media", html_context->doc_cp);
xmlpp::ustring rel_value = link_element->get_attribute_value("rel");
if (rel_value != "") {
link->name = memacpy(rel_value.c_str(), rel_value.size());
}
//link->name = get_attr_val(a, "rel", html_context->doc_cp);
if (link->name) {
link->direction = LD_REL;
} else {
xmlpp::ustring rev_value = link_element->get_attribute_value("rev");
if (rev_value != "") {
link->name = memacpy(rev_value.c_str(), rev_value.size());
}
//link->name = get_attr_val(a, "rev", html_context->doc_cp);
if (link->name) link->direction = LD_REV;
}
if (!link->name) return 1;
/* TODO: fastfind */
for (i = 0; lt_names[i].str; i++)
if (!c_strcasecmp(link->name, lt_names[i].str)) {
link->type = lt_names[i].type;
return 1;
}
if (c_strcasestr((const char *)link->name, "icon") ||
(link->content_type && c_strcasestr((const char *)link->content_type, "icon"))) {
link->type = LT_ICON;
} else if (c_strcasestr((const char *)link->name, "alternate")) {
link->type = LT_ALTERNATE;
if (link->lang)
link->type = LT_ALTERNATE_LANG;
else if (c_strcasestr((const char *)link->name, "stylesheet") ||
(link->content_type && c_strcasestr((const char *)link->content_type, "css")))
link->type = LT_ALTERNATE_STYLESHEET;
else if (link->media)
link->type = LT_ALTERNATE_MEDIA;
} else if (link->content_type && c_strcasestr((const char *)link->content_type, "css")) {
link->type = LT_STYLESHEET;
}
return 1;
}
void
tags_html_link(struct source_renderer *renderer, void *node, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
struct html_context *html_context = renderer->html_context;
int link_display = html_context->options->meta_link_display;
unsigned char *name;
struct hlink link;
struct string text;
int name_neq_title = 0;
int first = 1;
#ifndef CONFIG_CSS
if (!link_display) return;
#endif
if (!tags_html_link_parse(renderer, node, a, &link)) return;
if (!link.href) goto free_and_return;
#ifdef CONFIG_CSS
if (link.type == LT_STYLESHEET
&& supports_html_media_attr(link.media)) {
int len = strlen(link.href);
import_css_stylesheet(&html_context->css_styles,
html_context->base_href, link.href, len);
}
if (!link_display) goto free_and_return;
#endif
/* Ignore few annoying links.. */
if (link_display < 5 &&
(link.type == LT_ICON ||
link.type == LT_AUTHOR ||
link.type == LT_STYLESHEET ||
link.type == LT_ALTERNATE_STYLESHEET)) goto free_and_return;
if (!link.name || link.type != LT_UNKNOWN)
/* Give preference to our default names for known types. */
name = get_lt_default_name(&link);
else
name = link.name;
if (!name) goto free_and_return;
if (!init_string(&text)) goto free_and_return;
tags_html_focusable(renderer, node);
if (link.title) {
add_to_string(&text, link.title);
name_neq_title = strcmp(link.title, name);
} else
add_to_string(&text, name);
if (link_display == 1) goto put_link_line; /* Only title */
#define APPEND(what) do { \
add_to_string(&text, first ? " (" : ", "); \
add_to_string(&text, (what)); \
first = 0; \
} while (0)
if (name_neq_title) {
APPEND(name);
}
if (link_display >= 3 && link.hreflang) {
APPEND(link.hreflang);
}
if (link_display >= 4 && link.content_type) {
APPEND(link