mirror of
https://github.com/rkd77/elinks.git
synced 2024-11-04 08:17:17 -05:00
4723 lines
138 KiB
C
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, "[ ]", 8);
|
|
break;
|
|
case FC_RADIO:
|
|
elformat.style.attr |= AT_BOLD;
|
|
put_chrs(html_context, "( )", 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, "[ ", 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, " ]", 7);
|
|
break;
|
|
}
|
|
case FC_SUBMIT:
|
|
case FC_RESET:
|
|
case FC_BUTTON:
|
|
elformat.style.attr |= AT_BOLD;
|
|
put_chrs(html_context, "[ ", 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, " ]", 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, "◦", 7);
|
|
else if (t == P_SQUARE) /* Print U+25AA BLACK SMALL SQUARE. */
|
|
put_chrs(html_context, "▪", 7);
|
|
else /* Print U+2022 BULLET. */
|
|
put_chrs(html_context, "•", 7);
|
|
put_chrs(html_context, " ", 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, " ", 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, " ", 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, ". ", 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 |