1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-09-28 03:06:20 -04:00

Merge branch 'master' of ssh://pasky.or.cz/srv/git/elinks

Conflicts:

	src/document/options.c
This commit is contained in:
Miciah Dashiel Butler Masters 2007-08-30 21:13:43 +00:00 committed by Miciah Dashiel Butler Masters
commit 0e0bacf0d3
35 changed files with 1249 additions and 1051 deletions

View File

@ -184,10 +184,6 @@ MAKE_COLOR = @MAKE_COLOR@
LIB_O_NAME = lib.o
# Reverse a CONFIG_* string
# Usage $(call not,$(CONFIG_FOO))
not = $(if $(findstring yes,$(1)),no,yes)
### This is here because Makefile.config is usually the first thing
### we get and sometimes the all rule can be implicit, yet we want
### it always as the default one. So this should make sure it always

View File

@ -74,11 +74,11 @@ quiet_cmd_uninstall = " [$(UNINSTALL_COLOR)UNINSTALL$(END_COLOR)] $(3)/$(n
#############################################################################
# Special handling of conditional variables
SUBDIRS += $(SUBDIRS-yes)
OBJS += $(OBJS-yes)
SUBDIRS += $(SUBDIRS-yes) $(SUBDIRS-unlessno) $(SUBDIRS-unless)
OBJS += $(OBJS-yes) $(OBJS-unlessno) $(OBJS-unless)
ALTDIRS = $(SUBDIRS-no) $(SUBDIRS-)
ALTOBJS = $(OBJS-no) $(OBJS-)
ALTDIRS = $(SUBDIRS-no) $(SUBDIRS-) $(SUBDIRS-unlessyes)
ALTOBJS = $(OBJS-no) $(OBJS-) $(OBJS-unlessyes)
ifneq ($(findstring cleanall,$(MAKECMDGOALS)),)
INCLUDE_ALL=1
@ -191,8 +191,7 @@ test-default:
ifdef TEST_PROGS
TESTDEPS-$(CONFIG_DEBUG) += $(top_builddir)/src/util/memdebug.o
TESTDEPS-$(call not,$(CONFIG_SMALL)) += \
$(top_builddir)/src/util/fastfind.o \
TESTDEPS-unless$(CONFIG_SMALL) += $(top_builddir)/src/util/fastfind.o
# Add most of the basic utility library to the test dependencies.
TESTDEPS += \
@ -206,7 +205,7 @@ TESTDEPS += \
$(top_builddir)/src/util/string.o \
$(top_builddir)/src/util/time.o
TESTDEPS += $(TESTDEPS-yes)
TESTDEPS += $(TESTDEPS-yes) $(TESTDEPS-unlessno)
TEST_LIB=$(top_srcdir)/test/libtest.sh
export TEST_LIB

View File

@ -6,6 +6,6 @@ SUBDIRS-$(CONFIG_DOM) += dom
SUBDIRS = html plain
OBJS = docdata.o document.o forms.o options.o refresh.o renderer.o
OBJS = docdata.o document.o format.o forms.o options.o refresh.o renderer.o
include $(top_srcdir)/Makefile.lib

View File

@ -21,6 +21,7 @@
#include "document/css/property.h"
#include "document/css/scanner.h"
#include "document/css/stylesheet.h"
#include "document/format.h"
#include "document/html/parser/parse.h"
#include "document/options.h"
#include "util/align.h"

View File

@ -15,7 +15,6 @@
#include "document/css/scanner.h"
#include "document/css/stylesheet.h"
#include "document/css/value.h"
#include "document/html/parser.h"
#include "util/color.h"
#include "util/lists.h"
#include "util/error.h"

View File

@ -2,7 +2,8 @@
#ifndef EL__DOCUMENT_CSS_PROPERTY_H
#define EL__DOCUMENT_CSS_PROPERTY_H
#include "document/html/parser.h"
#include "document/format.h"
#include "util/align.h"
#include "util/color.h"
#include "util/lists.h"
@ -48,7 +49,7 @@ struct css_property {
CSS_DISP_BLOCK,
} display;
struct {
enum format_attr add, rem;
enum text_style_format add, rem;
} font_attribute;
enum format_align text_align;
/* TODO:

View File

@ -2,6 +2,7 @@
#ifndef EL__DOCUMENT_CSS_STYLESHEET_H
#define EL__DOCUMENT_CSS_STYLESHEET_H
#include "protocol/uri.h"
#include "util/lists.h"
/* #define DEBUG_CSS */

View File

@ -13,7 +13,6 @@
#include "document/css/property.h"
#include "document/css/scanner.h"
#include "document/css/value.h"
#include "document/html/parser.h"
#include "util/color.h"
#include "util/error.h"
#include "util/memory.h"

View File

@ -1,6 +1,6 @@
top_builddir=../../..
include $(top_builddir)/Makefile.config
OBJS = renderer.o
OBJS = renderer.o rss.o source.o util.o
include $(top_srcdir)/Makefile.lib

2
src/document/dom/README Normal file
View File

@ -0,0 +1,2 @@
This is DOM document renderer. The DOM "engine" itself (parsers, selectors,
...) lives directly in src/dom/.

View File

@ -4,23 +4,16 @@
#include "config.h"
#endif
#include <sys/types.h> /* FreeBSD needs this before regex.h */
#ifdef HAVE_REGEX_H
#include <regex.h>
#endif
#include <string.h>
#include "elinks.h"
#include "bookmarks/bookmarks.h" /* get_bookmark() */
#include "cache/cache.h"
#include "document/css/css.h"
#include "document/css/parser.h"
#include "document/css/property.h"
#include "document/css/stylesheet.h"
#include "document/docdata.h"
#include "document/document.h"
#include "document/dom/renderer.h"
#include "document/dom/rss.h"
#include "document/dom/source.h"
#include "document/dom/util.h"
#include "document/renderer.h"
#include "dom/configuration.h"
#include "dom/scanner.h"
@ -30,69 +23,16 @@
#include "dom/node.h"
#include "dom/stack.h"
#include "intl/charsets.h"
#include "globhist/globhist.h" /* get_global_history_item() */
#include "protocol/uri.h"
#include "terminal/draw.h"
#include "util/box.h"
#include "util/error.h"
#include "util/memory.h"
#include "util/snprintf.h"
#include "util/string.h"
struct dom_renderer {
enum sgml_document_type doctype;
struct document *document;
struct conv_table *convert_table;
enum convert_string_mode convert_mode;
struct uri *base_uri;
unsigned char *source;
unsigned char *end;
unsigned char *position;
int canvas_x, canvas_y;
#ifdef HAVE_REGEX_H
regex_t url_regex;
unsigned int find_url:1;
#endif
struct screen_char styles[DOM_NODES];
/* RSS renderer variables */
struct dom_node *channel;
struct dom_node_list *items;
struct dom_node *item;
struct dom_node *node;
struct dom_string text;
};
#define URL_REGEX "(file://|((f|ht|nt)tp(s)?|smb)://[[:alnum:]]+([-@:.]?[[:alnum:]])*\\.[[:alpha:]]{2,4}(:[[:digit:]]+)?)(/(%[[:xdigit:]]{2}|[-_~&=;?.a-z0-9])*)*"
#define URL_REGFLAGS (REG_ICASE | REG_EXTENDED)
static void
init_template(struct screen_char *template, struct document_options *options,
color_T background, color_T foreground, enum screen_char_attr attr)
{
struct color_pair colors = INIT_COLOR_PAIR(background, foreground);
template->attr = attr;
template->data = ' ';
set_term_color(template, &colors,
options->color_flags, options->color_mode);
}
/* Checks the user CSS for properties for each DOM node type name */
static inline void
init_dom_renderer(struct dom_renderer *renderer, struct document *document,
struct string *buffer, struct conv_table *convert_table)
{
enum dom_node_type type;
struct css_stylesheet *css = &default_stylesheet;
memset(renderer, 0, sizeof(*renderer));
renderer->document = document;
@ -102,894 +42,15 @@ init_dom_renderer(struct dom_renderer *renderer, struct document *document,
renderer->end = buffer->source + buffer->length;
renderer->position = renderer->source;
renderer->base_uri = get_uri_reference(document->uri);
#ifdef HAVE_REGEX_H
if (renderer->document->options.plain_display_links) {
if (regcomp(&renderer->url_regex, URL_REGEX, URL_REGFLAGS)) {
regfree(&renderer->url_regex);
} else {
renderer->find_url = 1;
}
}
#endif
for (type = 0; type < DOM_NODES; type++) {
struct screen_char *template = &renderer->styles[type];
color_T background = document->options.default_bg;
color_T foreground = document->options.default_fg;
enum screen_char_attr attr = 0;
static int i_want_struct_module_for_dom;
struct dom_string *name = get_dom_node_type_name(type);
struct css_selector *selector = NULL;
if (!i_want_struct_module_for_dom) {
static const unsigned char default_colors[] =
"document { color: yellow } "
"element { color: lightgreen } "
"entity-reference { color: red } "
"proc-instruction { color: red } "
"attribute { color: magenta } "
"comment { color: aqua } "
"cdata-section { color: orange2 } ";
unsigned char *styles = (unsigned char *) default_colors;
i_want_struct_module_for_dom = 1;
/* When someone will get here earlier than at 4am,
* this will be done in some init function, perhaps
* not overriding the user's default stylesheet. */
css_parse_stylesheet(css, NULL, styles, styles + sizeof(default_colors));
}
if (name)
if (is_dom_string_set(name))
selector = find_css_selector(&css->selectors,
CST_ELEMENT, CSR_ROOT,
name->string, name->length);
if (selector) {
struct css_property *property;
foreach (property, selector->properties) {
switch (property->type) {
case CSS_PT_BACKGROUND_COLOR:
case CSS_PT_BACKGROUND:
if (property->value_type == CSS_VT_COLOR)
background = property->value.color;
break;
case CSS_PT_COLOR:
foreground = property->value.color;
break;
case CSS_PT_FONT_WEIGHT:
if (property->value.font_attribute.add & AT_BOLD)
attr |= SCREEN_ATTR_BOLD;
break;
case CSS_PT_FONT_STYLE:
if (property->value.font_attribute.add & AT_UNDERLINE)
attr |= SCREEN_ATTR_UNDERLINE;
if (property->value.font_attribute.add & AT_ITALIC)
attr |= SCREEN_ATTR_ITALIC;
break;
case CSS_PT_TEXT_DECORATION:
if (property->value.font_attribute.add & AT_UNDERLINE)
attr |= SCREEN_ATTR_UNDERLINE;
break;
case CSS_PT_DISPLAY:
case CSS_PT_NONE:
case CSS_PT_TEXT_ALIGN:
case CSS_PT_WHITE_SPACE:
case CSS_PT_LAST:
break;
}
}
}
init_template(template, &document->options, background, foreground, attr);
}
}
static inline void
done_dom_renderer(struct dom_renderer *renderer)
{
#ifdef HAVE_REGEX_H
if (renderer->find_url)
regfree(&renderer->url_regex);
#endif
done_uri(renderer->base_uri);
}
/* Document maintainance */
static struct screen_char *
realloc_line(struct document *document, int x, int y)
{
struct line *line = realloc_lines(document, y);
if (!line) return NULL;
if (x > line->length) {
if (!ALIGN_LINE(&line->chars, line->length, x))
return NULL;
for (; line->length < x; line->length++) {
line->chars[line->length].data = ' ';
}
if (x > document->width) document->width = x;
}
return line->chars;
}
static struct node *
add_search_node(struct dom_renderer *renderer, int width)
{
struct node *node = mem_alloc(sizeof(*node));
if (node) {
set_box(&node->box, renderer->canvas_x, renderer->canvas_y,
width, 1);
add_to_list(renderer->document->nodes, node);
}
return node;
}
#define X(renderer) ((renderer)->canvas_x)
#define Y(renderer) ((renderer)->canvas_y)
#define POS(renderer) (&(renderer)->document->data[Y(renderer)].chars[X(renderer)])
#define WIDTH(renderer, add) ((renderer)->canvas_x + (add))
static void
render_dom_line(struct dom_renderer *renderer, struct screen_char *template,
unsigned char *string, int length)
{
struct document *document = renderer->document;
struct conv_table *convert = renderer->convert_table;
enum convert_string_mode mode = renderer->convert_mode;
int x, charlen;
#ifdef CONFIG_UTF8
int utf8 = document->options.utf8;
unsigned char *end;
#endif /* CONFIG_UTF8 */
assert(renderer && template && string && length);
string = convert_string(convert, string, length, document->options.cp,
mode, &length, NULL, NULL);
if (!string) return;
if (!realloc_line(document, WIDTH(renderer, length), Y(renderer))) {
mem_free(string);
return;
}
add_search_node(renderer, length);
#ifdef CONFIG_UTF8
end = string + length;
#endif /* CONFIG_UTF8 */
for (x = 0, charlen = 1; x < length;x += charlen, renderer->canvas_x++) {
unsigned char *text = &string[x];
/* This is mostly to be able to break out so the indentation
* level won't get to high. */
switch (*text) {
case ASCII_TAB:
{
int tab_width = 7 - (X(renderer) & 7);
int width = WIDTH(renderer, length - x + tab_width);
template->data = ' ';
if (!realloc_line(document, width, Y(renderer)))
break;
/* Only loop over the expanded tab chars and let the
* ``main loop'' add the actual tab char. */
for (; tab_width-- > 0; renderer->canvas_x++)
copy_screen_chars(POS(renderer), template, 1);
charlen = 1;
break;
}
default:
#ifdef CONFIG_UTF8
if (utf8) {
unicode_val_T data;
charlen = utf8charlen(text);
data = utf8_to_unicode(&text, end);
template->data = (unicode_val_T)data;
if (unicode_to_cell(data) == 2) {
copy_screen_chars(POS(renderer),
template, 1);
X(renderer)++;
template->data = UCS_NO_CHAR;
}
} else
#endif /* CONFIG_UTF8 */
template->data = isscreensafe(*text) ? *text:'.';
}
copy_screen_chars(POS(renderer), template, 1);
}
mem_free(string);
}
static inline unsigned char *
split_dom_line(unsigned char *line, int length, int *linelen)
{
unsigned char *end = line + length;
unsigned char *pos;
/* End of line detection.
* We handle \r, \r\n and \n types here. */
for (pos = line; pos < end; pos++) {
int step = 0;
if (pos[step] == ASCII_CR)
step++;
if (pos[step] == ASCII_LF)
step++;
if (step) {
*linelen = pos - line;
return pos + step;
}
}
*linelen = length;
return NULL;
}
static void
render_dom_text(struct dom_renderer *renderer, struct screen_char *template,
unsigned char *string, int length)
{
int linelen;
for (; length > 0; string += linelen, length -= linelen) {
unsigned char *newline = split_dom_line(string, length, &linelen);
if (linelen)
render_dom_line(renderer, template, string, linelen);
if (newline) {
renderer->canvas_y++;
renderer->canvas_x = 0;
linelen = newline - string;
}
}
}
#define realloc_document_links(doc, size) \
ALIGN_LINK(&(doc)->links, (doc)->nlinks, size)
static inline struct link *
add_dom_link(struct dom_renderer *renderer, unsigned char *string, int length,
unsigned char *uristring, int urilength)
{
struct document *document = renderer->document;
int x = renderer->canvas_x;
int y = renderer->canvas_y;
unsigned char *where;
struct link *link;
struct point *point;
struct screen_char template;
color_T fgcolor;
if (!realloc_document_links(document, document->nlinks + 1))
return NULL;
link = &document->links[document->nlinks];
if (!realloc_points(link, length))
return NULL;
uristring = convert_string(renderer->convert_table,
uristring, urilength, document->options.cp,
CSM_DEFAULT, NULL, NULL, NULL);
if (!uristring) return NULL;
where = join_urls(renderer->base_uri, uristring);
mem_free(uristring);
if (!where)
return NULL;
#ifdef CONFIG_GLOBHIST
else if (get_global_history_item(where))
fgcolor = document->options.default_vlink;
#endif
#ifdef CONFIG_BOOKMARKS
else if (get_bookmark(where))
fgcolor = document->options.default_bookmark_link;
#endif
else
fgcolor = document->options.default_link;
link->npoints = length;
link->type = LINK_HYPERTEXT;
link->where = where;
link->color.background = document->options.default_bg;
link->color.foreground = fgcolor;
link->number = document->nlinks;
init_template(&template, &document->options,
link->color.background, link->color.foreground, 0);
render_dom_text(renderer, &template, string, length);
for (point = link->points; length > 0; length--, point++, x++) {
point->x = x;
point->y = y;
}
document->nlinks++;
document->links_sorted = 0;
return link;
}
/* DOM Source Renderer */
#define check_dom_node_source(renderer, str, len) \
((renderer)->source <= (str) && (str) + (len) <= (renderer)->end)
#define assert_source(renderer, str, len) \
assertm(check_dom_node_source(renderer, str, len), "renderer[%p : %p] str[%p : %p]", \
(renderer)->source, (renderer)->end, (str), (str) + (len))
static inline void
render_dom_flush(struct dom_renderer *renderer, unsigned char *string)
{
struct screen_char *template = &renderer->styles[DOM_NODE_TEXT];
int length = string - renderer->position;
assert_source(renderer, renderer->position, 0);
assert_source(renderer, string, 0);
if (length <= 0) return;
render_dom_text(renderer, template, renderer->position, length);
renderer->position = string;
assert_source(renderer, renderer->position, 0);
}
static inline void
render_dom_node_text(struct dom_renderer *renderer, struct screen_char *template,
struct dom_node *node)
{
unsigned char *string = node->string.string;
int length = node->string.length;
if (node->type == DOM_NODE_ENTITY_REFERENCE) {
string -= 1;
length += 2;
}
if (check_dom_node_source(renderer, string, length)) {
render_dom_flush(renderer, string);
renderer->position = string + length;
assert_source(renderer, renderer->position, 0);
}
render_dom_text(renderer, template, string, length);
}
#ifdef HAVE_REGEX_H
static inline void
render_dom_node_enhanced_text(struct dom_renderer *renderer, struct dom_node *node)
{
regex_t *regex = &renderer->url_regex;
regmatch_t regmatch;
unsigned char *string = node->string.string;
int length = node->string.length;
struct screen_char *template = &renderer->styles[node->type];
unsigned char *alloc_string;
if (check_dom_node_source(renderer, string, length)) {
render_dom_flush(renderer, string);
renderer->position = string + length;
assert_source(renderer, renderer->position, 0);
}
alloc_string = memacpy(string, length);
if (alloc_string)
string = alloc_string;
while (length > 0 && !regexec(regex, string, 1, &regmatch, 0)) {
int matchlen = regmatch.rm_eo - regmatch.rm_so;
int offset = regmatch.rm_so;
if (!matchlen || offset < 0 || regmatch.rm_eo > length)
break;
if (offset > 0)
render_dom_text(renderer, template, string, offset);
string += offset;
length -= offset;
add_dom_link(renderer, string, matchlen, string, matchlen);
length -= matchlen;
string += matchlen;
}
if (length > 0)
render_dom_text(renderer, template, string, length);
mem_free_if(alloc_string);
}
#endif
static enum dom_code
render_dom_node_source(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct dom_renderer *renderer = stack->current->data;
assert(node && renderer && renderer->document);
#ifdef HAVE_REGEX_H
if (renderer->find_url
&& (node->type == DOM_NODE_TEXT
|| node->type == DOM_NODE_CDATA_SECTION
|| node->type == DOM_NODE_COMMENT)) {
render_dom_node_enhanced_text(renderer, node);
} else
#endif
render_dom_node_text(renderer, &renderer->styles[node->type], node);
return DOM_CODE_OK;
}
/* This callback is also used for rendering processing instruction nodes. */
static enum dom_code
render_dom_element_source(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct dom_renderer *renderer = stack->current->data;
assert(node && renderer && renderer->document);
render_dom_node_text(renderer, &renderer->styles[node->type], node);
return DOM_CODE_OK;
}
enum dom_code
render_dom_element_end_source(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct dom_renderer *renderer = stack->current->data;
struct dom_stack_state *state = get_dom_stack_top(stack);
struct sgml_parser_state *pstate = get_dom_stack_state_data(stack->contexts[0], state);
struct dom_scanner_token *token = &pstate->end_token;
unsigned char *string = token->string.string;
int length = token->string.length;
assert(node && renderer && renderer->document);
if (!string || !length)
return DOM_CODE_OK;
if (check_dom_node_source(renderer, string, length)) {
render_dom_flush(renderer, string);
renderer->position = string + length;
assert_source(renderer, renderer->position, 0);
}
render_dom_text(renderer, &renderer->styles[node->type], string, length);
return DOM_CODE_OK;
}
static void
set_base_uri(struct dom_renderer *renderer, unsigned char *value, size_t valuelen)
{
unsigned char *href = memacpy(value, valuelen);
unsigned char *uristring;
struct uri *uri;
if (!href) return;
uristring = join_urls(renderer->base_uri, href);
mem_free(href);
if (!uristring) return;
uri = get_uri(uristring, 0);
mem_free(uristring);
if (!uri) return;
done_uri(renderer->base_uri);
renderer->base_uri = uri;
}
enum dom_code
render_dom_attribute_source(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct dom_renderer *renderer = stack->current->data;
struct screen_char *template = &renderer->styles[node->type];
assert(node && renderer->document);
render_dom_node_text(renderer, template, node);
if (is_dom_string_set(&node->data.attribute.value)) {
int quoted = node->data.attribute.quoted == 1;
unsigned char *value = node->data.attribute.value.string - quoted;
int valuelen = node->data.attribute.value.length + quoted * 2;
if (check_dom_node_source(renderer, value, 0)) {
render_dom_flush(renderer, value);
renderer->position = value + valuelen;
assert_source(renderer, renderer->position, 0);
}
if (node->data.attribute.reference
&& valuelen - quoted * 2 > 0) {
int skips;
/* Need to flush the first quoting delimiter and any
* leading whitespace so that the renderers x position
* is at the start of the value string. */
for (skips = 0; skips < valuelen; skips++) {
if ((quoted && skips == 0)
|| isspace(value[skips])
|| value[skips] < ' ')
continue;
break;
}
if (skips > 0) {
render_dom_text(renderer, template, value, skips);
value += skips;
valuelen -= skips;
}
/* Figure out what should be skipped after the actual
* link text. */
for (skips = 0; skips < valuelen; skips++) {
if ((quoted && skips == 0)
|| isspace(value[valuelen - skips - 1])
|| value[valuelen - skips - 1] < ' ')
continue;
break;
}
if (renderer->doctype == SGML_DOCTYPE_HTML
&& node->data.attribute.type == HTML_ATTRIBUTE_HREF
&& node->parent->data.element.type == HTML_ELEMENT_BASE) {
set_base_uri(renderer, value, valuelen - skips);
}
add_dom_link(renderer, value, valuelen - skips,
value, valuelen - skips);
if (skips > 0) {
value += valuelen - skips;
render_dom_text(renderer, template, value, skips);
}
} else {
render_dom_text(renderer, template, value, valuelen);
}
}
return DOM_CODE_OK;
}
enum dom_code
render_dom_cdata_source(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct dom_renderer *renderer = stack->current->data;
unsigned char *string = node->string.string;
assert(node && renderer && renderer->document);
/* Highlight the 'CDATA' part of <![CDATA[ if it is there. */
if (check_dom_node_source(renderer, string - 6, 6)) {
render_dom_flush(renderer, string - 6);
render_dom_text(renderer, &renderer->styles[DOM_NODE_ATTRIBUTE], string - 6, 5);
renderer->position = string - 1;
assert_source(renderer, renderer->position, 0);
}
render_dom_node_text(renderer, &renderer->styles[node->type], node);
return DOM_CODE_OK;
}
enum dom_code
render_dom_document_end(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct dom_renderer *renderer = stack->current->data;
/* If there are no non-element nodes after the last element node make
* sure that we flush to the end of the cache entry source including
* the '>' of the last element tag if it has one. (bug 519) */
if (check_dom_node_source(renderer, renderer->position, 0)) {
render_dom_flush(renderer, renderer->end);
}
return DOM_CODE_OK;
}
static struct dom_stack_context_info dom_source_renderer_context_info = {
/* Object size: */ 0,
/* Push: */
{
/* */ NULL,
/* DOM_NODE_ELEMENT */ render_dom_element_source,
/* DOM_NODE_ATTRIBUTE */ render_dom_attribute_source,
/* DOM_NODE_TEXT */ render_dom_node_source,
/* DOM_NODE_CDATA_SECTION */ render_dom_cdata_source,
/* DOM_NODE_ENTITY_REFERENCE */ render_dom_node_source,
/* DOM_NODE_ENTITY */ render_dom_node_source,
/* DOM_NODE_PROC_INSTRUCTION */ render_dom_element_source,
/* DOM_NODE_COMMENT */ render_dom_node_source,
/* DOM_NODE_DOCUMENT */ NULL,
/* DOM_NODE_DOCUMENT_TYPE */ render_dom_node_source,
/* DOM_NODE_DOCUMENT_FRAGMENT */ render_dom_node_source,
/* DOM_NODE_NOTATION */ render_dom_node_source,
},
/* Pop: */
{
/* */ NULL,
/* DOM_NODE_ELEMENT */ render_dom_element_end_source,
/* DOM_NODE_ATTRIBUTE */ NULL,
/* DOM_NODE_TEXT */ NULL,
/* DOM_NODE_CDATA_SECTION */ NULL,
/* DOM_NODE_ENTITY_REFERENCE */ NULL,
/* DOM_NODE_ENTITY */ NULL,
/* DOM_NODE_PROC_INSTRUCTION */ NULL,
/* DOM_NODE_COMMENT */ NULL,
/* DOM_NODE_DOCUMENT */ render_dom_document_end,
/* DOM_NODE_DOCUMENT_TYPE */ NULL,
/* DOM_NODE_DOCUMENT_FRAGMENT */ NULL,
/* DOM_NODE_NOTATION */ NULL,
}
};
/* DOM RSS Renderer */
#define RSS_CONFIG_FLAGS \
(DOM_CONFIG_NORMALIZE_WHITESPACE | DOM_CONFIG_NORMALIZE_CHARACTERS)
enum dom_code
dom_rss_push_element(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct dom_renderer *renderer = stack->current->data;
assert(node && renderer && renderer->document);
switch (node->data.element.type) {
case RSS_ELEMENT_CHANNEL:
/* The stack should have: #document * channel */
if (stack->depth != 3)
break;
if (!renderer->channel) {
renderer->channel = node;
}
break;
case RSS_ELEMENT_ITEM:
/* The stack should have: #document * channel item */
#if 0
/* Don't be so strict ... */
if (stack->depth != 4)
break;
#endif
/* ... but be exclusive. */
if (renderer->item)
break;
add_to_dom_node_list(&renderer->items, node, -1);
renderer->item = node;
break;
case RSS_ELEMENT_LINK:
case RSS_ELEMENT_DESCRIPTION:
case RSS_ELEMENT_TITLE:
case RSS_ELEMENT_AUTHOR:
case RSS_ELEMENT_PUBDATE:
if (!node->parent || renderer->node != node->parent)
break;
renderer->node = node;
}
return DOM_CODE_OK;
}
enum dom_code
dom_rss_pop_element(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct dom_renderer *renderer = stack->current->data;
struct dom_node_list **list;
assert(node && renderer && renderer->document);
switch (node->data.element.type) {
case RSS_ELEMENT_ITEM:
if (is_dom_string_set(&renderer->text))
done_dom_string(&renderer->text);
renderer->item = NULL;
break;
case RSS_ELEMENT_LINK:
case RSS_ELEMENT_DESCRIPTION:
case RSS_ELEMENT_TITLE:
case RSS_ELEMENT_AUTHOR:
case RSS_ELEMENT_PUBDATE:
if (!is_dom_string_set(&renderer->text)
|| !node->parent
|| renderer->item != node->parent
|| renderer->node != node)
break;
/* Replace any child nodes with the normalized text node. */
list = get_dom_node_list(node->parent, node);
done_dom_node_list(*list);
if (is_dom_string_set(&renderer->text)) {
if (!add_dom_node(node, DOM_NODE_TEXT, &renderer->text))
done_dom_string(&renderer->text);
}
renderer->node = NULL;
break;
default:
break;
}
return DOM_CODE_OK;
}
static struct dom_string *
get_rss_text(struct dom_node *node, enum rss_element_type type)
{
node = get_dom_node_child(node, DOM_NODE_ELEMENT, type);
if (!node) return NULL;
node = get_dom_node_child(node, DOM_NODE_TEXT, 0);
return node ? &node->string: NULL;
}
static void
render_rss_item(struct dom_renderer *renderer, struct dom_node *item)
{
struct dom_string *title = get_rss_text(item, RSS_ELEMENT_TITLE);
struct dom_string *link = get_rss_text(item, RSS_ELEMENT_LINK);
struct dom_string *author = get_rss_text(item, RSS_ELEMENT_AUTHOR);
struct dom_string *date = get_rss_text(item, RSS_ELEMENT_PUBDATE);
if (title && is_dom_string_set(title)) {
if (item == renderer->channel) {
unsigned char *str;
str = convert_string(renderer->convert_table,
title->string, title->length,
renderer->document->options.cp,
CSM_DEFAULT, NULL, NULL, NULL);
if (str)
renderer->document->title = str;
}
render_dom_text(renderer, &renderer->styles[DOM_NODE_ELEMENT],
title->string, title->length);
}
if (link && is_dom_string_set(link)) {
X(renderer)++;
add_dom_link(renderer, "[link]", 6, link->string, link->length);
}
/* New line, and indent */
Y(renderer)++;
X(renderer) = 0;
if (author && is_dom_string_set(author)) {
render_dom_text(renderer, &renderer->styles[DOM_NODE_COMMENT],
author->string, author->length);
}
if (date && is_dom_string_set(date)) {
if (author && is_dom_string_set(author)) {
render_dom_text(renderer, &renderer->styles[DOM_NODE_COMMENT],
" - ", 3);
}
render_dom_text(renderer, &renderer->styles[DOM_NODE_COMMENT],
date->string, date->length);
}
if ((author && is_dom_string_set(author))
|| (date && is_dom_string_set(date))) {
/* New line, and indent */
Y(renderer)++;
X(renderer) = 0;
}
}
enum dom_code
dom_rss_pop_document(struct dom_stack *stack, struct dom_node *root, void *data)
{
struct dom_renderer *renderer = stack->current->data;
if (!renderer->channel)
return DOM_CODE_OK;
render_rss_item(renderer, renderer->channel);
if (renderer->items) {
struct dom_node *node;
int index;
foreach_dom_node (renderer->items, node, index) {
Y(renderer)++;
X(renderer) = 0;
render_rss_item(renderer, node);
}
}
if (is_dom_string_set(&renderer->text))
done_dom_string(&renderer->text);
mem_free_if(renderer->items);
done_dom_node(root);
return DOM_CODE_OK;
}
static struct dom_stack_context_info dom_rss_renderer_context_info = {
/* Object size: */ 0,
/* Push: */
{
/* */ NULL,
/* DOM_NODE_ELEMENT */ dom_rss_push_element,
/* DOM_NODE_ATTRIBUTE */ NULL,
/* DOM_NODE_TEXT */ NULL,
/* DOM_NODE_CDATA_SECTION */ NULL,
/* DOM_NODE_ENTITY_REFERENCE */ NULL,
/* DOM_NODE_ENTITY */ NULL,
/* DOM_NODE_PROC_INSTRUCTION */ NULL,
/* DOM_NODE_COMMENT */ NULL,
/* DOM_NODE_DOCUMENT */ NULL,
/* DOM_NODE_DOCUMENT_TYPE */ NULL,
/* DOM_NODE_DOCUMENT_FRAGMENT */ NULL,
/* DOM_NODE_NOTATION */ NULL,
},
/* Pop: */
{
/* */ NULL,
/* DOM_NODE_ELEMENT */ dom_rss_pop_element,
/* DOM_NODE_ATTRIBUTE */ NULL,
/* DOM_NODE_TEXT */ NULL,
/* DOM_NODE_CDATA_SECTION */ NULL,
/* DOM_NODE_ENTITY_REFERENCE */ NULL,
/* DOM_NODE_ENTITY */ NULL,
/* DOM_NODE_PROC_INSTRUCTION */ NULL,
/* DOM_NODE_COMMENT */ NULL,
/* DOM_NODE_DOCUMENT */ dom_rss_pop_document,
/* DOM_NODE_DOCUMENT_TYPE */ NULL,
/* DOM_NODE_DOCUMENT_FRAGMENT */ NULL,
/* DOM_NODE_NOTATION */ NULL,
}
};
static void
get_doctype(struct dom_renderer *renderer, struct cache_entry *cached)
{
@ -1038,7 +99,7 @@ render_dom_document(struct cache_entry *cached, struct document *document,
init_dom_renderer(&renderer, document, buffer, convert_table);
document->bgcolor = document->options.default_bg;
document->bgcolor = document->options.default_style.bg;
#ifdef CONFIG_UTF8
document->options.utf8 = is_cp_utf8(document->options.cp);
#endif /* CONFIG_UTF8 */

262
src/document/dom/rss.c Normal file
View File

@ -0,0 +1,262 @@
/* DOM-based RSS renderer */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "elinks.h"
#include "document/css/css.h"
#include "document/css/parser.h"
#include "document/css/stylesheet.h"
#include "document/document.h"
#include "document/dom/util.h"
#include "document/dom/rss.h"
#include "dom/sgml/rss/rss.h"
#include "dom/node.h"
#include "dom/stack.h"
#include "intl/charsets.h"
#include "util/error.h"
#include "util/memory.h"
enum rss_style {
RSS_STYLE_TITLE,
RSS_STYLE_AUTHOR,
RSS_STYLE_AUTHOR_DATE_SEP,
RSS_STYLE_DATE,
RSS_STYLES,
};
struct rss_renderer {
/* The current item being processed; can be either a channel or
* item element. */
struct dom_node *item;
/* One style per node type. */
struct screen_char styles[RSS_STYLES];
};
static struct dom_string *
get_rss_text(struct dom_node *node, enum rss_element_type type)
{
node = get_dom_node_child(node, DOM_NODE_ELEMENT, type);
if (!node) return NULL;
node = get_dom_node_child(node, DOM_NODE_TEXT, 0);
return node ? &node->string: NULL;
}
static void
render_rss_item(struct dom_renderer *renderer, struct dom_node *item)
{
struct rss_renderer *rss = renderer->data;
struct dom_string *title = get_rss_text(item, RSS_ELEMENT_TITLE);
struct dom_string *link = get_rss_text(item, RSS_ELEMENT_LINK);
struct dom_string *author = get_rss_text(item, RSS_ELEMENT_AUTHOR);
struct dom_string *date = get_rss_text(item, RSS_ELEMENT_PUBDATE);
if (item->data.element.type == RSS_ELEMENT_ITEM) {
Y(renderer)++;
X(renderer) = 0;
}
if (title && is_dom_string_set(title)) {
if (item->data.element.type == RSS_ELEMENT_CHANNEL) {
unsigned char *str;
str = convert_string(renderer->convert_table,
title->string, title->length,
renderer->document->options.cp,
CSM_DEFAULT, NULL, NULL, NULL);
if (str)
renderer->document->title = str;
}
render_dom_text(renderer, &rss->styles[RSS_STYLE_TITLE],
title->string, title->length);
}
if (link && is_dom_string_set(link)) {
X(renderer)++;
add_dom_link(renderer, "[link]", 6, link->string, link->length);
}
/* New line, and indent */
Y(renderer)++;
X(renderer) = 0;
if (author && is_dom_string_set(author)) {
render_dom_text(renderer, &rss->styles[RSS_STYLE_AUTHOR],
author->string, author->length);
}
if (date && is_dom_string_set(date)) {
if (author && is_dom_string_set(author)) {
render_dom_text(renderer, &rss->styles[RSS_STYLE_AUTHOR_DATE_SEP],
" - ", 3);
}
render_dom_text(renderer, &rss->styles[RSS_STYLE_DATE],
date->string, date->length);
}
if ((author && is_dom_string_set(author))
|| (date && is_dom_string_set(date))) {
/* New line, and indent */
Y(renderer)++;
X(renderer) = 0;
}
}
static void
flush_rss_item(struct dom_renderer *renderer, struct rss_renderer *rss)
{
if (rss->item) {
render_rss_item(renderer, rss->item);
rss->item = NULL;
}
}
static enum dom_code
dom_rss_push_element(struct dom_stack *stack, struct dom_node *node, void *xxx)
{
struct dom_renderer *renderer = stack->current->data;
struct rss_renderer *rss = renderer->data;
assert(node && node->parent && renderer && renderer->document);
switch (node->data.element.type) {
case RSS_ELEMENT_CHANNEL:
/* The stack should have: #document * channel */
if (stack->depth == 3)
rss->item = node;
break;
case RSS_ELEMENT_ITEM:
flush_rss_item(renderer, rss);
rss->item = node;
}
return DOM_CODE_OK;
}
static enum dom_code
dom_rss_pop_element(struct dom_stack *stack, struct dom_node *node, void *xxx)
{
struct dom_renderer *renderer = stack->current->data;
struct rss_renderer *rss = renderer->data;
assert(node && node->parent && renderer && renderer->document);
switch (node->data.element.type) {
case RSS_ELEMENT_CHANNEL:
flush_rss_item(renderer, rss);
break;
}
return DOM_CODE_OK;
}
static enum dom_code
dom_rss_push_document(struct dom_stack *stack, struct dom_node *root, void *xxx)
{
struct dom_renderer *renderer = stack->current->data;
struct document *document = renderer->document;
struct rss_renderer *rss;
enum rss_style type;
struct css_stylesheet *css = &default_stylesheet;
{
static int i_want_struct_module_for_dom;
if (!i_want_struct_module_for_dom) {
static const unsigned char default_colors[] =
"title { color: lightgreen } "
"author { color: aqua }"
"author-date-sep{ color: aqua }"
"date { color: aqua }";
unsigned char *styles = (unsigned char *) default_colors;
i_want_struct_module_for_dom = 1;
/* When someone will get here earlier than at 4am,
* this will be done in some init function, perhaps
* not overriding the user's default stylesheet. */
css_parse_stylesheet(css, NULL, styles, styles + sizeof(default_colors));
}
}
rss = renderer->data = mem_calloc(1, sizeof(*rss));
if (rss)
return DOM_CODE_ALLOC_ERR;
/* Initialize styles. */
for (type = 0; type < RSS_STYLES; type++) {
struct screen_char *template = &rss->styles[type];
static const unsigned char *names[RSS_STYLES] =
{ "title", "author", "author-date-sep", "date" };
struct css_selector *selector = NULL;
selector = find_css_selector(&css->selectors,
CST_ELEMENT, CSR_ROOT,
names[type], strlen(names[type]));
init_template_by_style(template, &document->options,
selector ? &selector->properties : NULL);
}
return DOM_CODE_OK;
}
static enum dom_code
dom_rss_pop_document(struct dom_stack *stack, struct dom_node *root, void *xxx)
{
struct dom_renderer *renderer = stack->current->data;
struct rss_renderer *rss = renderer->data;
done_dom_node(root);
mem_free(rss);
return DOM_CODE_OK;
}
struct dom_stack_context_info dom_rss_renderer_context_info = {
/* Object size: */ 0,
/* Push: */
{
/* */ NULL,
/* DOM_NODE_ELEMENT */ dom_rss_push_element,
/* DOM_NODE_ATTRIBUTE */ NULL,
/* DOM_NODE_TEXT */ NULL,
/* DOM_NODE_CDATA_SECTION */ NULL,
/* DOM_NODE_ENTITY_REFERENCE */ NULL,
/* DOM_NODE_ENTITY */ NULL,
/* DOM_NODE_PROC_INSTRUCTION */ NULL,
/* DOM_NODE_COMMENT */ NULL,
/* DOM_NODE_DOCUMENT */ dom_rss_push_document,
/* DOM_NODE_DOCUMENT_TYPE */ NULL,
/* DOM_NODE_DOCUMENT_FRAGMENT */ NULL,
/* DOM_NODE_NOTATION */ NULL,
},
/* Pop: */
{
/* */ NULL,
/* DOM_NODE_ELEMENT */ dom_rss_pop_element,
/* DOM_NODE_ATTRIBUTE */ NULL,
/* DOM_NODE_TEXT */ NULL,
/* DOM_NODE_CDATA_SECTION */ NULL,
/* DOM_NODE_ENTITY_REFERENCE */ NULL,
/* DOM_NODE_ENTITY */ NULL,
/* DOM_NODE_PROC_INSTRUCTION */ NULL,
/* DOM_NODE_COMMENT */ NULL,
/* DOM_NODE_DOCUMENT */ dom_rss_pop_document,
/* DOM_NODE_DOCUMENT_TYPE */ NULL,
/* DOM_NODE_DOCUMENT_FRAGMENT */ NULL,
/* DOM_NODE_NOTATION */ NULL,
}
};

13
src/document/dom/rss.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef EL__DOCUMENT_DOM_RSS_H
#define EL__DOCUMENT_DOM_RSS_H
#include "dom/stack.h"
#define RSS_CONFIG_FLAGS \
(DOM_CONFIG_NORMALIZE_WHITESPACE | DOM_CONFIG_NORMALIZE_CHARACTERS)
extern struct dom_stack_context_info dom_rss_renderer_context_info;
#endif

450
src/document/dom/source.c Normal file
View File

@ -0,0 +1,450 @@
/* DOM-based SGML (HTML) source view renderer (just syntax highlighting :-) */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <sys/types.h> /* FreeBSD needs this before regex.h */
#ifdef HAVE_REGEX_H
#include <regex.h>
#endif
#include "elinks.h"
#include "cache/cache.h"
#include "document/css/css.h"
#include "document/css/parser.h"
#include "document/css/property.h"
#include "document/css/stylesheet.h"
#include "document/document.h"
#include "document/dom/renderer.h"
#include "document/dom/util.h"
#include "document/dom/rss.h"
#include "document/renderer.h"
#include "dom/configuration.h"
#include "dom/scanner.h"
#include "dom/sgml/parser.h"
#include "dom/sgml/html/html.h"
#include "dom/sgml/rss/rss.h"
#include "dom/node.h"
#include "dom/stack.h"
#include "intl/charsets.h"
#include "protocol/uri.h"
#include "terminal/draw.h"
#include "util/error.h"
#include "util/memory.h"
#include "util/string.h"
#define check_dom_node_source(renderer, str, len) \
((renderer)->source <= (str) && (str) + (len) <= (renderer)->end)
#define assert_source(renderer, str, len) \
assertm(check_dom_node_source(renderer, str, len), "renderer[%p : %p] str[%p : %p]", \
(renderer)->source, (renderer)->end, (str), (str) + (len))
#define URL_REGEX "(file://|((f|ht|nt)tp(s)?|smb)://[[:alnum:]]+([-@:.]?[[:alnum:]])*\\.[[:alpha:]]{2,4}(:[[:digit:]]+)?)(/(%[[:xdigit:]]{2}|[-_~&=;?.a-z0-9])*)*"
#define URL_REGFLAGS (REG_ICASE | REG_EXTENDED)
struct source_renderer {
#ifdef HAVE_REGEX_H
regex_t url_regex;
unsigned int find_url:1;
#endif
/* One style per node type. */
struct screen_char styles[DOM_NODES];
};
static inline void
render_dom_flush(struct dom_renderer *renderer, unsigned char *string)
{
struct source_renderer *data = renderer->data;
struct screen_char *template = &data->styles[DOM_NODE_TEXT];
int length = string - renderer->position;
assert_source(renderer, renderer->position, 0);
assert_source(renderer, string, 0);
if (length <= 0) return;
render_dom_text(renderer, template, renderer->position, length);
renderer->position = string;
assert_source(renderer, renderer->position, 0);
}
static inline void
render_dom_node_text(struct dom_renderer *renderer, struct screen_char *template,
struct dom_node *node)
{
unsigned char *string = node->string.string;
int length = node->string.length;
if (node->type == DOM_NODE_ENTITY_REFERENCE) {
string -= 1;
length += 2;
}
if (check_dom_node_source(renderer, string, length)) {
render_dom_flush(renderer, string);
renderer->position = string + length;
assert_source(renderer, renderer->position, 0);
}
render_dom_text(renderer, template, string, length);
}
#ifdef HAVE_REGEX_H
static inline void
render_dom_node_enhanced_text(struct dom_renderer *renderer, struct dom_node *node)
{
struct source_renderer *data = renderer->data;
regex_t *regex = &data->url_regex;
regmatch_t regmatch;
unsigned char *string = node->string.string;
int length = node->string.length;
struct screen_char *template = &data->styles[node->type];
unsigned char *alloc_string;
if (check_dom_node_source(renderer, string, length)) {
render_dom_flush(renderer, string);
renderer->position = string + length;
assert_source(renderer, renderer->position, 0);
}
alloc_string = memacpy(string, length);
if (alloc_string)
string = alloc_string;
while (length > 0 && !regexec(regex, string, 1, &regmatch, 0)) {
int matchlen = regmatch.rm_eo - regmatch.rm_so;
int offset = regmatch.rm_so;
if (!matchlen || offset < 0 || regmatch.rm_eo > length)
break;
if (offset > 0)
render_dom_text(renderer, template, string, offset);
string += offset;
length -= offset;
add_dom_link(renderer, string, matchlen, string, matchlen);
length -= matchlen;
string += matchlen;
}
if (length > 0)
render_dom_text(renderer, template, string, length);
mem_free_if(alloc_string);
}
#endif
static enum dom_code
render_dom_node_source(struct dom_stack *stack, struct dom_node *node, void *xxx)
{
struct dom_renderer *renderer = stack->current->data;
struct source_renderer *data = renderer->data;
assert(node && renderer && renderer->document);
#ifdef HAVE_REGEX_H
if (data->find_url
&& (node->type == DOM_NODE_TEXT
|| node->type == DOM_NODE_CDATA_SECTION
|| node->type == DOM_NODE_COMMENT)) {
render_dom_node_enhanced_text(renderer, node);
} else
#endif
render_dom_node_text(renderer, &data->styles[node->type], node);
return DOM_CODE_OK;
}
/* This callback is also used for rendering processing instruction nodes. */
static enum dom_code
render_dom_element_source(struct dom_stack *stack, struct dom_node *node, void *xxx)
{
struct dom_renderer *renderer = stack->current->data;
struct source_renderer *data = renderer->data;
assert(node && renderer && renderer->document);
render_dom_node_text(renderer, &data->styles[node->type], node);
return DOM_CODE_OK;
}
static enum dom_code
render_dom_element_end_source(struct dom_stack *stack, struct dom_node *node, void *xxx)
{
struct dom_renderer *renderer = stack->current->data;
struct source_renderer *data = renderer->data;
struct dom_stack_state *state = get_dom_stack_top(stack);
struct sgml_parser_state *pstate = get_dom_stack_state_data(stack->contexts[0], state);
struct dom_scanner_token *token = &pstate->end_token;
unsigned char *string = token->string.string;
int length = token->string.length;
assert(node && renderer && renderer->document);
if (!string || !length)
return DOM_CODE_OK;
if (check_dom_node_source(renderer, string, length)) {
render_dom_flush(renderer, string);
renderer->position = string + length;
assert_source(renderer, renderer->position, 0);
}
render_dom_text(renderer, &data->styles[node->type], string, length);
return DOM_CODE_OK;
}
static void
set_base_uri(struct dom_renderer *renderer, unsigned char *value, size_t valuelen)
{
unsigned char *href = memacpy(value, valuelen);
unsigned char *uristring;
struct uri *uri;
if (!href) return;
uristring = join_urls(renderer->base_uri, href);
mem_free(href);
if (!uristring) return;
uri = get_uri(uristring, 0);
mem_free(uristring);
if (!uri) return;
done_uri(renderer->base_uri);
renderer->base_uri = uri;
}
static enum dom_code
render_dom_attribute_source(struct dom_stack *stack, struct dom_node *node, void *xxx)
{
struct dom_renderer *renderer = stack->current->data;
struct source_renderer *data = renderer->data;
struct screen_char *template = &data->styles[node->type];
assert(node && renderer->document);
render_dom_node_text(renderer, template, node);
if (is_dom_string_set(&node->data.attribute.value)) {
int quoted = node->data.attribute.quoted == 1;
unsigned char *value = node->data.attribute.value.string - quoted;
int valuelen = node->data.attribute.value.length + quoted * 2;
if (check_dom_node_source(renderer, value, 0)) {
render_dom_flush(renderer, value);
renderer->position = value + valuelen;
assert_source(renderer, renderer->position, 0);
}
if (node->data.attribute.reference
&& valuelen - quoted * 2 > 0) {
int skips;
/* Need to flush the first quoting delimiter and any
* leading whitespace so that the renderers x position
* is at the start of the value string. */
for (skips = 0; skips < valuelen; skips++) {
if ((quoted && skips == 0)
|| isspace(value[skips])
|| value[skips] < ' ')
continue;
break;
}
if (skips > 0) {
render_dom_text(renderer, template, value, skips);
value += skips;
valuelen -= skips;
}
/* Figure out what should be skipped after the actual
* link text. */
for (skips = 0; skips < valuelen; skips++) {
if ((quoted && skips == 0)
|| isspace(value[valuelen - skips - 1])
|| value[valuelen - skips - 1] < ' ')
continue;
break;
}
if (renderer->doctype == SGML_DOCTYPE_HTML
&& node->data.attribute.type == HTML_ATTRIBUTE_HREF
&& node->parent->data.element.type == HTML_ELEMENT_BASE) {
set_base_uri(renderer, value, valuelen - skips);
}
add_dom_link(renderer, value, valuelen - skips,
value, valuelen - skips);
if (skips > 0) {
value += valuelen - skips;
render_dom_text(renderer, template, value, skips);
}
} else {
render_dom_text(renderer, template, value, valuelen);
}
}
return DOM_CODE_OK;
}
static enum dom_code
render_dom_cdata_source(struct dom_stack *stack, struct dom_node *node, void *xxx)
{
struct dom_renderer *renderer = stack->current->data;
struct source_renderer *data = renderer->data;
unsigned char *string = node->string.string;
assert(node && renderer && renderer->document);
/* Highlight the 'CDATA' part of <![CDATA[ if it is there. */
if (check_dom_node_source(renderer, string - 6, 6)) {
render_dom_flush(renderer, string - 6);
render_dom_text(renderer, &data->styles[DOM_NODE_ATTRIBUTE], string - 6, 5);
renderer->position = string - 1;
assert_source(renderer, renderer->position, 0);
}
render_dom_node_text(renderer, &data->styles[node->type], node);
return DOM_CODE_OK;
}
static enum dom_code
render_dom_document_start(struct dom_stack *stack, struct dom_node *node, void *xxx)
{
struct dom_renderer *renderer = stack->current->data;
struct document *document = renderer->document;
struct source_renderer *data;
enum dom_node_type type;
struct css_stylesheet *css = &default_stylesheet;
{
static int i_want_struct_module_for_dom;
if (!i_want_struct_module_for_dom) {
static const unsigned char default_colors[] =
"document { color: yellow } "
"element { color: lightgreen } "
"entity-reference { color: red } "
"proc-instruction { color: red } "
"attribute { color: magenta } "
"comment { color: aqua } "
"cdata-section { color: orange2 } ";
unsigned char *styles = (unsigned char *) default_colors;
i_want_struct_module_for_dom = 1;
/* When someone will get here earlier than at 4am,
* this will be done in some init function, perhaps
* not overriding the user's default stylesheet. */
css_parse_stylesheet(css, NULL, styles, styles + sizeof(default_colors));
}
}
data = renderer->data = mem_calloc(1, sizeof(*data));
/* Initialize styles for all the DOM node types. */
for (type = 0; type < DOM_NODES; type++) {
struct screen_char *template = &data->styles[type];
struct dom_string *name = get_dom_node_type_name(type);
struct css_selector *selector = NULL;
if (name && is_dom_string_set(name))
selector = find_css_selector(&css->selectors,
CST_ELEMENT, CSR_ROOT,
name->string, name->length);
init_template_by_style(template, &document->options,
selector ? &selector->properties : NULL);
}
#ifdef HAVE_REGEX_H
if (document->options.plain_display_links) {
if (regcomp(&data->url_regex, URL_REGEX, URL_REGFLAGS)) {
regfree(&data->url_regex);
} else {
data->find_url = 1;
}
}
#endif
return DOM_CODE_OK;
}
static enum dom_code
render_dom_document_end(struct dom_stack *stack, struct dom_node *node, void *xxx)
{
struct dom_renderer *renderer = stack->current->data;
struct source_renderer *data = renderer->data;
/* If there are no non-element nodes after the last element node make
* sure that we flush to the end of the cache entry source including
* the '>' of the last element tag if it has one. (bug 519) */
if (check_dom_node_source(renderer, renderer->position, 0)) {
render_dom_flush(renderer, renderer->end);
}
#ifdef HAVE_REGEX_H
if (data->find_url)
regfree(&data->url_regex);
#endif
mem_free(data);
return DOM_CODE_OK;
}
struct dom_stack_context_info dom_source_renderer_context_info = {
/* Object size: */ 0,
/* Push: */
{
/* */ NULL,
/* DOM_NODE_ELEMENT */ render_dom_element_source,
/* DOM_NODE_ATTRIBUTE */ render_dom_attribute_source,
/* DOM_NODE_TEXT */ render_dom_node_source,
/* DOM_NODE_CDATA_SECTION */ render_dom_cdata_source,
/* DOM_NODE_ENTITY_REFERENCE */ render_dom_node_source,
/* DOM_NODE_ENTITY */ render_dom_node_source,
/* DOM_NODE_PROC_INSTRUCTION */ render_dom_element_source,
/* DOM_NODE_COMMENT */ render_dom_node_source,
/* DOM_NODE_DOCUMENT */ render_dom_document_start,
/* DOM_NODE_DOCUMENT_TYPE */ render_dom_node_source,
/* DOM_NODE_DOCUMENT_FRAGMENT */ render_dom_node_source,
/* DOM_NODE_NOTATION */ render_dom_node_source,
},
/* Pop: */
{
/* */ NULL,
/* DOM_NODE_ELEMENT */ render_dom_element_end_source,
/* DOM_NODE_ATTRIBUTE */ NULL,
/* DOM_NODE_TEXT */ NULL,
/* DOM_NODE_CDATA_SECTION */ NULL,
/* DOM_NODE_ENTITY_REFERENCE */ NULL,
/* DOM_NODE_ENTITY */ NULL,
/* DOM_NODE_PROC_INSTRUCTION */ NULL,
/* DOM_NODE_COMMENT */ NULL,
/* DOM_NODE_DOCUMENT */ render_dom_document_end,
/* DOM_NODE_DOCUMENT_TYPE */ NULL,
/* DOM_NODE_DOCUMENT_FRAGMENT */ NULL,
/* DOM_NODE_NOTATION */ NULL,
}
};

10
src/document/dom/source.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef EL__DOCUMENT_DOM_SOURCE_H
#define EL__DOCUMENT_DOM_SOURCE_H
#include "dom/stack.h"
extern struct dom_stack_context_info dom_source_renderer_context_info;
#endif

313
src/document/dom/util.c Normal file
View File

@ -0,0 +1,313 @@
/* Utilities for rendering document bits */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <sys/types.h> /* FreeBSD needs this before regex.h */
#ifdef HAVE_REGEX_H
#include <regex.h>
#endif
#include <string.h>
#include "elinks.h"
#include "bookmarks/bookmarks.h" /* get_bookmark() */
#include "document/css/property.h"
#include "document/docdata.h"
#include "document/document.h"
#include "document/dom/util.h"
#include "document/format.h"
#include "intl/charsets.h"
#include "globhist/globhist.h" /* get_global_history_item() */
#include "protocol/uri.h"
#include "terminal/draw.h"
#include "util/error.h"
#include "util/memory.h"
#include "util/box.h"
static inline void
init_template(struct screen_char *template, struct document_options *options,
enum screen_char_attr attr, color_T foreground, color_T background)
{
struct text_style style = { attr, foreground, background };
get_screen_char_template(template, options, style);
}
void
init_template_by_style(struct screen_char *template, struct document_options *options,
LIST_OF(struct css_property) *properties)
{
struct text_style style = options->default_style;
struct css_property *property;
if (properties) {
/* TODO: Use the CSS appliers. */
foreach (property, *properties) {
switch (property->type) {
case CSS_PT_BACKGROUND_COLOR:
case CSS_PT_BACKGROUND:
if (property->value_type == CSS_VT_COLOR)
style.bg = property->value.color;
break;
case CSS_PT_COLOR:
style.fg = property->value.color;
break;
case CSS_PT_FONT_WEIGHT:
style.attr |= property->value.font_attribute.add;
break;
case CSS_PT_FONT_STYLE:
style.attr |= property->value.font_attribute.add;
break;
case CSS_PT_TEXT_DECORATION:
style.attr |= property->value.font_attribute.add;
break;
case CSS_PT_DISPLAY:
case CSS_PT_NONE:
case CSS_PT_TEXT_ALIGN:
case CSS_PT_WHITE_SPACE:
case CSS_PT_LAST:
break;
}
}
}
get_screen_char_template(template, options, style);
}
static struct screen_char *
realloc_line(struct document *document, int x, int y)
{
struct line *line = realloc_lines(document, y);
if (!line) return NULL;
if (x > line->length) {
if (!ALIGN_LINE(&line->chars, line->length, x))
return NULL;
for (; line->length < x; line->length++) {
line->chars[line->length].data = ' ';
}
if (x > document->width) document->width = x;
}
return line->chars;
}
static struct node *
add_search_node(struct dom_renderer *renderer, int width)
{
struct node *node = mem_alloc(sizeof(*node));
if (node) {
set_box(&node->box, renderer->canvas_x, renderer->canvas_y,
width, 1);
add_to_list(renderer->document->nodes, node);
}
return node;
}
#define POS(renderer) (&(renderer)->document->data[Y(renderer)].chars[X(renderer)])
#define WIDTH(renderer, add) ((renderer)->canvas_x + (add))
static void
render_dom_line(struct dom_renderer *renderer, struct screen_char *template,
unsigned char *string, int length)
{
struct document *document = renderer->document;
struct conv_table *convert = renderer->convert_table;
enum convert_string_mode mode = renderer->convert_mode;
int x, charlen;
#ifdef CONFIG_UTF8
int utf8 = document->options.utf8;
unsigned char *end;
#endif /* CONFIG_UTF8 */
assert(renderer && template && string && length);
string = convert_string(convert, string, length, document->options.cp,
mode, &length, NULL, NULL);
if (!string) return;
if (!realloc_line(document, WIDTH(renderer, length), Y(renderer))) {
mem_free(string);
return;
}
add_search_node(renderer, length);
#ifdef CONFIG_UTF8
end = string + length;
#endif /* CONFIG_UTF8 */
for (x = 0, charlen = 1; x < length;x += charlen, renderer->canvas_x++) {
unsigned char *text = &string[x];
/* This is mostly to be able to break out so the indentation
* level won't get to high. */
switch (*text) {
case ASCII_TAB:
{
int tab_width = 7 - (X(renderer) & 7);
int width = WIDTH(renderer, length - x + tab_width);
template->data = ' ';
if (!realloc_line(document, width, Y(renderer)))
break;
/* Only loop over the expanded tab chars and let the
* ``main loop'' add the actual tab char. */
for (; tab_width-- > 0; renderer->canvas_x++)
copy_screen_chars(POS(renderer), template, 1);
charlen = 1;
break;
}
default:
#ifdef CONFIG_UTF8
if (utf8) {
unicode_val_T data;
charlen = utf8charlen(text);
data = utf8_to_unicode(&text, end);
template->data = (unicode_val_T)data;
if (unicode_to_cell(data) == 2) {
copy_screen_chars(POS(renderer),
template, 1);
X(renderer)++;
template->data = UCS_NO_CHAR;
}
} else
#endif /* CONFIG_UTF8 */
template->data = isscreensafe(*text) ? *text:'.';
}
copy_screen_chars(POS(renderer), template, 1);
}
mem_free(string);
}
static inline unsigned char *
split_dom_line(unsigned char *line, int length, int *linelen)
{
unsigned char *end = line + length;
unsigned char *pos;
/* End of line detection.
* We handle \r, \r\n and \n types here. */
for (pos = line; pos < end; pos++) {
int step = 0;
if (pos[step] == ASCII_CR)
step++;
if (pos[step] == ASCII_LF)
step++;
if (step) {
*linelen = pos - line;
return pos + step;
}
}
*linelen = length;
return NULL;
}
void
render_dom_text(struct dom_renderer *renderer, struct screen_char *template,
unsigned char *string, int length)
{
int linelen;
for (; length > 0; string += linelen, length -= linelen) {
unsigned char *newline = split_dom_line(string, length, &linelen);
if (linelen)
render_dom_line(renderer, template, string, linelen);
if (newline) {
renderer->canvas_y++;
renderer->canvas_x = 0;
linelen = newline - string;
}
}
}
#define realloc_document_links(doc, size) \
ALIGN_LINK(&(doc)->links, (doc)->nlinks, size)
inline struct link *
add_dom_link(struct dom_renderer *renderer, unsigned char *string, int length,
unsigned char *uristring, int urilength)
{
struct document *document = renderer->document;
int x = renderer->canvas_x;
int y = renderer->canvas_y;
unsigned char *where;
struct link *link;
struct point *point;
struct screen_char template;
color_T fgcolor;
if (!realloc_document_links(document, document->nlinks + 1))
return NULL;
link = &document->links[document->nlinks];
if (!realloc_points(link, length))
return NULL;
uristring = convert_string(renderer->convert_table,
uristring, urilength, document->options.cp,
CSM_DEFAULT, NULL, NULL, NULL);
if (!uristring) return NULL;
where = join_urls(renderer->base_uri, uristring);
mem_free(uristring);
if (!where)
return NULL;
#ifdef CONFIG_GLOBHIST
else if (get_global_history_item(where))
fgcolor = document->options.default_vlink;
#endif
#ifdef CONFIG_BOOKMARKS
else if (get_bookmark(where))
fgcolor = document->options.default_bookmark_link;
#endif
else
fgcolor = document->options.default_link;
link->npoints = length;
link->type = LINK_HYPERTEXT;
link->where = where;
link->color.background = document->options.default_style.bg;
link->color.foreground = fgcolor;
link->number = document->nlinks;
init_template(&template, &document->options,
0, link->color.foreground, link->color.background);
render_dom_text(renderer, &template, string, length);
for (point = link->points; length > 0; length--, point++, x++) {
point->x = x;
point->y = y;
}
document->nlinks++;
document->links_sorted = 0;
return link;
}

54
src/document/dom/util.h Normal file
View File

@ -0,0 +1,54 @@
#ifndef EL__DOCUMENT_DOM_UTIL_H
#define EL__DOCUMENT_DOM_UTIL_H
/* This header is meant to be used only amongst the DOM renderers. */
#include <sys/types.h> /* FreeBSD needs this before regex.h */
#ifdef HAVE_REGEX_H
#include <regex.h>
#endif
#include "dom/sgml/sgml.h"
#include "intl/charsets.h"
#include "terminal/draw.h"
struct document;
struct uri;
struct dom_node;
struct dom_node_list;
struct dom_string;
struct dom_renderer {
enum sgml_document_type doctype;
struct document *document;
struct conv_table *convert_table;
enum convert_string_mode convert_mode;
struct uri *base_uri;
unsigned char *source;
unsigned char *end;
unsigned char *position;
int canvas_x, canvas_y;
/* Renderer-specific data */
void *data;
};
#define X(renderer) ((renderer)->canvas_x)
#define Y(renderer) ((renderer)->canvas_y)
void init_template_by_style(struct screen_char *template,
struct document_options *options,
LIST_OF(struct css_property) *properties);
void render_dom_text(struct dom_renderer *renderer, struct screen_char *template,
unsigned char *string, int length);
struct link *add_dom_link(struct dom_renderer *renderer, unsigned char *string,
int length, unsigned char *uristring, int urilength);
#endif

46
src/document/format.c Normal file
View File

@ -0,0 +1,46 @@
/** Format attributes utilities
* @file */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "elinks.h"
#include "document/format.h"
#include "document/options.h"
#include "terminal/draw.h"
#include "util/color.h"
void
get_screen_char_template(struct screen_char *template,
struct document_options *options,
struct text_style style)
{
template->attr = 0;
template->data = ' ';
if (style.attr) {
if (style.attr & AT_UNDERLINE) {
template->attr |= SCREEN_ATTR_UNDERLINE;
}
if (style.attr & AT_BOLD) {
template->attr |= SCREEN_ATTR_BOLD;
}
if (style.attr & AT_ITALIC) {
template->attr |= SCREEN_ATTR_ITALIC;
}
if (style.attr & AT_GRAPHICS) {
template->attr |= SCREEN_ATTR_FRAME;
}
}
{
struct color_pair colors = INIT_COLOR_PAIR(style.bg, style.fg);
set_term_color(template, &colors, options->color_flags, options->color_mode);
}
}

28
src/document/format.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef EL__DOCUMENT_FORMAT_H
#define EL__DOCUMENT_FORMAT_H
#include "util/color.h"
struct document_options;
struct screen_char;
enum text_style_format {
AT_BOLD = 1,
AT_ITALIC = 2,
AT_UNDERLINE = 4,
AT_FIXED = 8,
AT_GRAPHICS = 16,
AT_PREFORMATTED = 32,
};
struct text_style {
enum text_style_format attr;
color_T fg;
color_T bg;
};
void get_screen_char_template(struct screen_char *template, struct document_options *options, struct text_style style);
#endif

View File

@ -702,7 +702,7 @@ get_image_map(unsigned char *head, unsigned char *pos, unsigned char *eof,
struct html_element *
void *
init_html_parser_state(struct html_context *html_context,
enum html_element_mortality_type type,
int align, int margin, int width)
@ -728,8 +728,10 @@ init_html_parser_state(struct html_context *html_context,
void
done_html_parser_state(struct html_context *html_context,
struct html_element *element)
void *state)
{
struct html_element *element = state;
html_context->line_breax = 1;
while (html_top != element) {
@ -801,8 +803,7 @@ init_html_parser(struct uri *uri, struct document_options *options,
format.form = NULL;
format.title = NULL;
format.style.fg = options->default_fg;
format.style.bg = options->default_bg;
format.style = options->default_style;
format.clink = options->default_link;
format.vlink = options->default_vlink;
#ifdef CONFIG_BOOKMARKS
@ -819,7 +820,7 @@ init_html_parser(struct uri *uri, struct document_options *options,
par_format.dd_margin = options->margin;
par_format.flags = P_NONE;
par_format.bgcolor = options->default_bg;
par_format.bgcolor = options->default_style.bg;
html_top->invisible = 0;
html_top->name = NULL;

View File

@ -2,6 +2,7 @@
#ifndef EL__DOCUMENT_HTML_PARSER_H
#define EL__DOCUMENT_HTML_PARSER_H
#include "document/format.h"
#include "intl/charsets.h" /* unicode_val_T */
#include "util/align.h"
#include "util/color.h"
@ -16,28 +17,14 @@ struct menu_item;
struct part;
struct string;
struct uri;
enum html_special_type;
/* XXX: This is just terible - this interface is from 75% only for other HTML
* files - there's lack of any well defined interface and it's all randomly
* mixed up :/. */
enum format_attr {
AT_BOLD = 1,
AT_ITALIC = 2,
AT_UNDERLINE = 4,
AT_FIXED = 8,
AT_GRAPHICS = 16,
AT_PREFORMATTED = 32,
};
struct text_attrib_style {
enum format_attr attr;
color_T fg;
color_T bg;
};
struct text_attrib {
struct text_attrib_style style;
struct text_style style;
int fontsize;
unsigned char *link;
@ -150,23 +137,6 @@ struct html_element {
#define is_inline_element(e) (e->linebreak == 0)
#define is_block_element(e) (e->linebreak > 0)
enum html_special_type {
SP_TAG,
SP_FORM,
SP_CONTROL,
SP_TABLE,
SP_USED,
SP_FRAMESET,
SP_FRAME,
SP_NOWRAP,
SP_CACHE_CONTROL,
SP_CACHE_EXPIRES,
SP_REFRESH,
SP_STYLESHEET,
SP_COLOR_LINK_LINES,
SP_SCRIPT,
};
/* Interface for the renderer */
struct html_context *
@ -177,11 +147,10 @@ init_html_parser(struct uri *uri, struct document_options *options,
void (*line_break)(struct html_context *),
void *(*special)(struct html_context *, enum html_special_type,
...));
void done_html_parser(struct html_context *html_context);
struct html_element *init_html_parser_state(struct html_context *html_context, enum html_element_mortality_type type, int align, int margin, int width);
void done_html_parser_state(struct html_context *html_context,
struct html_element *element);
void *init_html_parser_state(struct html_context *html_context, enum html_element_mortality_type type, int align, int margin, int width);
void done_html_parser_state(struct html_context *html_context, void *state);
/* Interface for the table handling */

View File

@ -197,7 +197,7 @@ html_apply_canvas_bgcolor(struct html_context *html_context)
}
if (html_context->has_link_lines
&& par_format.bgcolor != html_context->options->default_bg
&& par_format.bgcolor != html_context->options->default_style.bg
&& !search_html_stack(html_context, "BODY")) {
html_context->special_f(html_context, SP_COLOR_LINK_LINES);
}

View File

@ -20,6 +20,7 @@
#include "document/html/parser/parse.h"
#include "document/html/parser/stack.h"
#include "document/html/parser.h"
#include "document/html/renderer.h"
#include "document/options.h"
#include "intl/charsets.h"
#include "util/conv.h"

View File

@ -340,39 +340,19 @@ static inline struct screen_char *
get_format_screen_char(struct html_context *html_context,
enum link_state link_state)
{
static struct text_attrib_style ta_cache = { -1, 0x0, 0x0 };
static struct text_style ta_cache = { -1, 0x0, 0x0 };
static struct screen_char schar_cache;
if (memcmp(&ta_cache, &format.style, sizeof(ta_cache))) {
copy_struct(&ta_cache, &format.style);
schar_cache.attr = 0;
if (format.style.attr) {
if (format.style.attr & AT_UNDERLINE) {
schar_cache.attr |= SCREEN_ATTR_UNDERLINE;
}
if (format.style.attr & AT_BOLD) {
schar_cache.attr |= SCREEN_ATTR_BOLD;
}
if (format.style.attr & AT_ITALIC) {
schar_cache.attr |= SCREEN_ATTR_ITALIC;
}
if (format.style.attr & AT_GRAPHICS) {
schar_cache.attr |= SCREEN_ATTR_FRAME;
}
}
struct text_style final_style = format.style;
if (link_state != LINK_STATE_NONE
&& html_context->options->underline_links) {
schar_cache.attr |= SCREEN_ATTR_UNDERLINE;
final_style.attr |= AT_UNDERLINE;
}
set_screen_char_color(&schar_cache, format.style.bg, format.style.fg,
html_context->options->color_flags,
html_context->options->color_mode);
get_screen_char_template(&schar_cache, html_context->options, final_style);
}
if (!!(schar_cache.attr & SCREEN_ATTR_UNSEARCHABLE)
@ -2094,7 +2074,7 @@ format_html_part(struct html_context *html_context,
int link_num)
{
struct part *part;
struct html_element *html_state;
void *html_state;
int llm = renderer_context.last_link_to_move;
struct tag *ltm = renderer_context.last_tag_to_move;
int ef = renderer_context.empty_format;

View File

@ -12,6 +12,27 @@ struct string;
void render_html_document(struct cache_entry *cached, struct document *document, struct string *buffer);
/* Interface with parser.c */
enum html_special_type {
SP_TAG,
SP_FORM,
SP_CONTROL,
SP_TABLE,
SP_USED,
SP_FRAMESET,
SP_FRAME,
SP_NOWRAP,
SP_CACHE_CONTROL,
SP_CACHE_EXPIRES,
SP_REFRESH,
SP_STYLESHEET,
SP_COLOR_LINK_LINES,
SP_SCRIPT,
};
/* Interface with tables.c */
/* This holds some context about what we're currently rendering. We only need

View File

@ -37,8 +37,8 @@ init_document_options(struct session *ses, struct document_options *doo)
doo->default_form_input_size = get_opt_int("document.browse.forms.input_size", ses);
/* Color options. */
doo->default_fg = get_opt_color("document.colors.text", ses);
doo->default_bg = get_opt_color("document.colors.background", ses);
doo->default_style.fg = get_opt_color("document.colors.text", ses);
doo->default_style.bg = get_opt_color("document.colors.background", ses);
doo->default_link = get_opt_color("document.colors.link", ses);
doo->default_vlink = get_opt_color("document.colors.vlink", ses);
#ifdef CONFIG_BOOKMARKS

View File

@ -1,6 +1,7 @@
#ifndef EL__DOCUMENT_OPTIONS_H
#define EL__DOCUMENT_OPTIONS_H
#include "document/format.h"
#include "terminal/color.h"
#include "util/color.h"
#include "util/box.h"
@ -34,8 +35,7 @@ struct document_options {
/** @name The default (fallback) colors.
* @{ */
color_T default_fg;
color_T default_bg;
struct text_style default_style;
color_T default_link;
color_T default_vlink;
#ifdef CONFIG_BOOKMARKS

View File

@ -14,6 +14,7 @@
#include "config/options.h"
#include "document/docdata.h"
#include "document/document.h"
#include "document/format.h"
#include "document/options.h"
#include "document/plain/renderer.h"
#include "document/renderer.h"
@ -92,7 +93,7 @@ add_document_link(struct document *document, unsigned char *uri, int length,
link->npoints = length;
link->type = LINK_HYPERTEXT;
link->where = uri;
link->color.background = document->options.default_bg;
link->color.background = document->options.default_style.bg;
link->color.foreground = document->options.default_link;
link->number = document->nlinks;
@ -213,7 +214,7 @@ print_document_link(struct plain_renderer *renderer, int lineno,
line[link_end] = saved_char;
new_link->color.background = doc_opts->default_bg;
new_link->color.background = doc_opts->default_style.bg;
set_term_color(&template, &new_link->color,
doc_opts->color_flags, doc_opts->color_mode);
@ -478,14 +479,7 @@ next:
static void
init_template(struct screen_char *template, struct document_options *options)
{
color_T background = options->default_bg;
color_T foreground = options->default_fg;
struct color_pair colors = INIT_COLOR_PAIR(background, foreground);
template->attr = 0;
template->data = ' ';
set_term_color(template, &colors,
options->color_flags, options->color_mode);
get_screen_char_template(template, options, options->default_style);
}
static struct node *
@ -643,7 +637,7 @@ render_plain_document(struct cache_entry *cached, struct document *document,
renderer.max_width = document->options.wrap ? document->options.box.width
: INT_MAX;
document->bgcolor = document->options.default_bg;
document->bgcolor = document->options.default_style.bg;
document->width = 0;
#ifdef CONFIG_UTF8
document->options.utf8 = is_cp_utf8(document->options.cp);

View File

@ -1,4 +1,4 @@
/** HTML renderer
/** Generic renderer multiplexer
* @file */
#ifdef HAVE_CONFIG_H

View File

@ -8,6 +8,7 @@ struct document_options;
struct document_view;
struct session;
struct view_state;
struct screen_char;
void render_document(struct view_state *, struct document_view *, struct document_options *);
void render_document_frames(struct session *ses, int no_cache);

View File

@ -19,7 +19,6 @@
#include "dialogs/menu.h"
#include "dialogs/status.h"
#include "document/html/frames.h"
#include "document/html/parser.h"
#include "document/html/renderer.h"
#include "document/refresh.h"
#include "document/view.h"

View File

@ -3,7 +3,7 @@ include $(top_builddir)/Makefile.config
INCLUDES += $(GNUTLS_CFLAGS) $(OPENSSL_CFLAGS)
OBJS-$(call not,$(CONFIG_SMALL)) += fastfind.o
OBJS-unless$(CONFIG_SMALL) += fastfind.o
OBJS-$(CONFIG_CSS) += scanner.o
OBJS-$(CONFIG_DEBUG) += memdebug.o
OBJS-$(CONFIG_DOM) += scanner.o
@ -12,14 +12,14 @@ OBJS-$(CONFIG_DOM) += scanner.o
# (either the real thing or GNUTLS compat wrappers).
OBJS-$(CONFIG_OWN_LIBC) += md5.o
ifeq ($(CONFIG_GNUTLS_OPENSSL_COMPAT),no)
OBJS-$(call not,$(CONFIG_OPENSSL)) += md5.o
OBJS-unless$(CONFIG_OPENSSL) += md5.o
endif
ifeq ($(CONFIG_BITTORRENT),yes)
# BitTorrent is the only user. Compile in SHA1 if testing libc or
# there is no OpenSSL. The GNUTLS OpenSSL wrappers doesn't have it.
OBJS-$(CONFIG_OWN_LIBC) += sha1.o
OBJS-$(call not,$(CONFIG_OPENSSL)) += sha1.o
OBJS-unless$(CONFIG_OPENSSL) += sha1.o
endif
OBJS = \

View File

@ -29,7 +29,6 @@
#include "dialogs/menu.h"
#include "document/document.h"
#include "document/forms.h"
#include "document/html/parser.h"
#include "document/view.h"
#include "intl/gettext/libintl.h"
#include "formhist/formhist.h"

View File

@ -16,7 +16,6 @@
#include "dialogs/status.h"
#include "document/document.h"
#include "document/forms.h"
#include "document/html/parser.h"
#include "document/html/renderer.h"
#include "document/options.h"
#include "document/view.h"

View File

@ -21,7 +21,6 @@
#include "bfu/dialog.h"
#include "document/document.h"
#include "document/forms.h"
#include "document/html/parser.h"
#include "document/html/renderer.h"
#include "document/view.h"
#include "intl/gettext/libintl.h"