1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-12-04 14:46:47 -05:00
This commit is contained in:
Kalle Olavi Niemitalo 2006-01-10 21:02:21 +02:00 committed by Kalle Olavi Niemitalo
commit 9deceafa0b
24 changed files with 513 additions and 277 deletions

View File

@ -294,7 +294,7 @@ b.Xi ISOgrk4 0x039E # GREEK CAPITAL LETTER XI
b.alpha ISOgrk4 0x03B1 # GREEK SMALL LETTER ALPHA
b.beta ISOgrk4 0x03B2 # GREEK SMALL LETTER BETA
b.chi ISOgrk4 0x03C7 # GREEK SMALL LETTER CHI
b.delta ? 0x03B3 # GREEK SMALL LETTER GAMMA
b.delta ISOgrk4 0x03B4 # GREEK SMALL LETTER DELTA
b.epsi ISOgrk4 0x03B5 # GREEK SMALL LETTER EPSILON
b.epsis ISOgrk4 0x03B5 # GREEK SMALL LETTER EPSILON
b.epsiv ISOgrk4 0x03B5 # GREEK SMALL LETTER EPSILON

View File

@ -49,6 +49,11 @@ ELINKS = $(top_builddir)/src/elinks
KBDBIND = $(top_srcdir)/src/config/kbdbind.c
FEATURES = $(top_srcdir)/features.conf
### Locale env vars to override system one to ensure commands
# using elinks binary will generate texts in english
#
LOCALES = LC_ALL=C LANGUAGE=en
### Scripts
#
@ -59,7 +64,7 @@ MAKE_ELINKS_MANPAGE = $(top_srcdir)/doc/tools/make-elinks-manpage
MAKE_ELINKSKEYS_MANPAGE = $(top_srcdir)/doc/tools/make-elinkskeys-manpage
HTML_DOCS-$(CONFIG_ASCIIDOC) += \
api/dom-sgml-parser.html \
api/dom.html \
elinks.1.html \
elinkskeys.5.html \
hacking.html \
@ -109,10 +114,10 @@ $(TXT_DIR)/import-features.conf.txt: $(FEATURES) $(IMPORT_FEATURES_CONF)
$(IMPORT_FEATURES_CONF) > $@
$(TXT_DIR)/elinks.1.%.txt: $(MAKE_ELINKS_MANPAGE) $(ELINKS)
$(MAKE_ELINKS_MANPAGE) $@ $(ELINKS) $(HELP2DOC) > $@
$(LOCALES) $(MAKE_ELINKS_MANPAGE) $@ $(ELINKS) $(HELP2DOC) > $@
$(TXT_DIR)/elinkskeys.5.%.txt: $(MAKE_ELINKSKEYS_MANPAGE) $(KBDBIND)
$(MAKE_ELINKSKEYS_MANPAGE) $@ $(KBDBIND) > $@
$(LOCALES) $(MAKE_ELINKSKEYS_MANPAGE) $@ $(KBDBIND) > $@
# Man Pages
@ -122,15 +127,19 @@ $(XML_DIR)/%.man.xml: $(TXT_DIR)/%.man.txt
$(MAN_DIR)/man1/elinks.1.in: $(XML_DIR)/elinks.1.man.xml
$(XMLTO) -o $(MAN_DIR)/man1 man $<
mv $(MAN_DIR)/man1/elinks.1 $@
sed 's/^\.TH "ELINKS" 1 .*/.TH "ELINKS" 1 "The ELinks text-browser" "$(shell date -I)" "The ELinks text-browser"/' \
< $(MAN_DIR)/man1/elinks.1 > $@
rm $(MAN_DIR)/man1/elinks.1
$(MAN_DIR)/man5/elinkskeys.5: $(XML_DIR)/elinkskeys.5.man.xml
$(XMLTO) -o $(MAN_DIR)/man5 man $<
sed -e 's/\\fI\\fR'\''/\\fI\\'\''\\fR/' < $@ > $@.tmp
mv $@.tmp $@
sed 's/^\.TH "ELINKSKEYS" 5 .*/.TH "ELINKSKEYS" 5 "ELinks keybindings" "$(shell date -I)" "ELinks keybindings"/' \
< $@.tmp > $@
rm $@.tmp
$(MAN_DIR)/man5/elinks.conf.5: $(ELINKS)
$(HELP2DOC) --elinks=$(ELINKS) --elinksconf > $@
$(LOCALES) $(HELP2DOC) --elinks=$(ELINKS) --elinksconf > $@
# XHTML/CSS Man Pages
@ -171,7 +180,12 @@ $(HTML_DIR)/perl-hooks.html: $(top_srcdir)/contrib/perl/hooks.pl
## API Docs
#
$(HTML_DIR)/api/dom-sgml-parser.html: $(top_srcdir)/src/dom/sgml/parser.h
$(CODE2DOC) $< | $(ASCIIDOC) -f code2doc.conf -b xhtml11 -d book -o $@ -n -
DOM_API = \
$(top_srcdir)/src/dom/scanner.h \
$(top_srcdir)/src/dom/stack.h \
$(top_srcdir)/src/dom/sgml/parser.h
$(HTML_DIR)/api/dom.html: $(DOM_API)
$(CODE2DOC) $(DOM_API) | $(ASCIIDOC) -f code2doc.conf -b xhtml11 -d book -o $@ -n -
include $(top_srcdir)/Makefile.lib

View File

@ -6,16 +6,19 @@ monospacedwords=\basciidoc\(1\)
<a id="{0}" href="#{0}">{0}</a>
[enum-inlinemacro]
<a id="{0}" href="#{0}">enum {0}</a>
<a id="{target}">enum {target}: {0}</a>
[func-inlinemacro]
<a id="{0}" href="#{0}">{0}()</a>
<a id="{target}">{target}(): {0}</a>
[struct-inlinemacro]
<a id="{0}" href="#{0}">struct {0}</a>
<a id="{target}">struct {target}: {0}</a>
[callback-inlinemacro]
<a id="{0}" href="#{0}">callback {0}</a>
[macro-inlinemacro]
<a id="{target}">struct {target}: {0}</a>
[typedef-inlinemacro]
<a id="{target}">typedef {target}: {0}</a>
[ref-inlinemacro]
<a href="{target}#{0}">{0}</a>

View File

@ -17,7 +17,7 @@
.el .ne 3
.IP "\\$1" \\$2
..
.TH "ELINKS" 1 "" "" ""
.TH "ELINKS" 1 "The ELinks text-browser" "2006-01-10" "The ELinks text-browser"
.SH NAME
elinks \- lynx-like alternative character mode WWW browser
.SH "SYNOPSIS"

View File

@ -1,6 +1,6 @@
.\" elinks.conf.5
.\"
.\" Generated by help2doc (Revision: 1.19) on 03 January 06 using output from ELinks version 0.12.GIT.
.\" Generated by help2doc (Revision: 1.19) on 2006-01-10 using output from ELinks version 0.12.GIT.
.\"
.\" Copyleft (c) 2002-2004 The ELinks project
.\"
@ -8,7 +8,7 @@
.\" General Public License. <www.gnu.org/licenses/gpl.html>
.\"
.\" Process this file with groff -man -Tascii elinks.conf.5
.TH ELINKS.CONF 5 \"03 January 06\"
.TH ELINKS.CONF 5 "ELinks configuration file" "2006-01-10" "ELinks configuration file"
.SH NAME
elinks.conf \- ELinks configuration file
@ -50,7 +50,7 @@ set document.browse.margin_width = 3
# Default document codepage.
set document.codepage.assume = "ISO-8859-1"
# User defined protocol handlers
set protocol.user.mailto.unix = "mutt %h -s \"%s\""
set protocol.user.mailto.unix = "mutt %h -s \e\*(lq%s\e\*(rq"
.SH OPTIONS
.SS Bookmarks (bookmarks)
@ -784,8 +784,6 @@ in dump output.
.TP
\f3document.dump.separator\f2 <str>\f1 (document.dump.separator <str> (default: ")
.TP
\f3String\f2 Swhich\f1 (String which separates two dumps.)
.TP
\f3document.dump.width\f2 <num>\f1 (default: 80)
Width of screen in characters when dumping documents.
.PD
@ -2162,8 +2160,6 @@ Keep the session active even if the last terminal exits.
Automatically save a snapshot of all tabs periodically.
This will periodically bookmark the tabs of each terminal in a separate folder
for recovery after a crash.
.TP
\f3This\f2 Tfeature\f1 (This feature requires bookmark support.)
.SS Window tabs (ui.tabs)
Window tabs settings.
.TP
@ -2246,7 +2242,7 @@ in an xterm-like terminal. This way the document's title is
shown on the window titlebar.
.SH "DOCUMENT INFO"
.PP
Generated by help2doc (Revision: 1.19) on 03 January 06 using output from ELinks version 0.12.GIT.
Generated by help2doc (Revision: 1.19) on 2006-01-10 using output from ELinks version 0.12.GIT.
help2doc is distributed with ELinks under the terms of the GPL.
.SH "SEE ALSO"
.BR elinks (1),

View File

@ -17,7 +17,7 @@
.el .ne 3
.IP "\\$1" \\$2
..
.TH "ELINKSKEYS" 5 "" "" ""
.TH "ELINKSKEYS" 5 "ELinks keybindings" "2006-01-10" "ELinks keybindings"
.SH NAME
elinkskeys \- keybindings for ELinks
.SH "SYNOPSIS"

View File

@ -2,45 +2,111 @@
use strict;
use warnings;
use diagnostics;
use Getopt::Std;
print "Usage: $0 [FILE]\n\tParses [FILE], outputing the result to stdout.\n"
and exit if not @ARGV;
my $HELP = "Usage: $0 [FILE]...
Parses [FILE], outputing the result to stdout.";
my ($input) = @ARGV;
my ($found, $start, $first, $gotone, $idpath);
print "Copyleft© 2006, Russ Rowan (See `COPYING')\n" and exit if $input eq '-v';
open FILEIN, "<$input" or print "File `$input' was not found.\n" and exit;
$idpath = '';
while (<FILEIN>)
{
if ($found)
{
if ($_ =~ /^\s+\*\s$/) { next if $first; $_ =~ s/\s\*// if not $first; }
if ($_ =~ /^\s\*+\/$/ or $_ !~ /^\s/) { $found = undef; next; }
$_ =~ s/^(\s*)\s\*\s/$1/;
$found = 'sorta' if $_ =~ s/\s*\*\/$/\n/; $first = undef;
}
elsif ($_ =~ /^\s*\/\*\*\s(.*)/)
{
$_ = $1; $first = 1;
print STDOUT "\n\n" if $start;
if ($_ =~ s/\s*\*\/$//) { $found = 'sorta'; } else { $found = $.; }
if ($_ =~ /struct:[[]([^\]]+)[\]]/) { $idpath = "$1."; } else { $idpath = ''; }
if ($_ =~ /::/) { $_ = "$_\n\n"; }
else
{
my $dash; for (my $x = 0; $x < length($_); $x++) { $dash .= '-'; }
$_ = "$_\n$dash\n\n";
}
}
elsif ($_ =~ /^(\s|[^\s=]+)*[\s*]([A-Za-z0-9_]+)(\s+=\s+[^,;]+)?[,;]\s*\/\*::\s*(.*)\s+\*\/$/)
{
print STDOUT "\n" if $gotone;
$_ = "\nid:[$idpath$2]::\n\t$4\n";
$found = 'sorta'; $gotone = $.;
}
print STDOUT "\n" and $gotone = undef if $gotone and $gotone < $.;
next if not $found; $found = undef if $found eq 'sorta';
print STDOUT $_ and $start = 1;
sub usage {
print "@_\n";
exit;
}
our($opt_h, $opt_v, $title, $body, $indent, $idpath, $inblock);
getopts("hv") or usage($HELP);
$opt_v and usage("Copyleft (c) 2006, Russ Rowan (See `COPYING')");
usage($HELP) if $opt_h or @ARGV < 1;
sub put_section {
if ($title) {
print "\n$title\n";
$_ = $title;
s/[^-]/-/g;
print "$_\n" if not $indent;
}
if ($body) {
$_ = $body;
s/#newline#/$indent/g;
print "$_\n";
}
$title = $body = undef;
}
$idpath = $title = $body = "";
while (<>)
{
my $end = s/\s*\*+\//\n/ ? 'yes' : undef;
if ($end and /[^=]*[\s*](\w+)[\s:,;].*\/\*:\s*(.*)/) {
# Implicit id for enum values and struct members.
print "\nid:[$idpath$1]::\n\t$2\n";
} elsif ($inblock) {
# Redo the indentation, preserve empty lines.
s/^(\s|\*)*//;
s/^$/\n/;
$body .= "#newline#" . $_;
} elsif (s/\s*\/\*\*+\s*(.*)/$1/) {
# Found magic header; flush, record title and set indentation.
put_section;
$title = "$1";
$indent = /::/ ? "\t" : "";
} else {
next if not ($title or $body) or /^\s$/;
my $orig_title = $title;
if (not /^#define\s/) {
while (not /(struct|enum|typedef|[^=])*[\s*](\w+).*[\[:,;{]/) {
$_ .= <>;
}
}
if (/struct\s+(\w+)\s*{/) {
$title = "struct:$1" . "[$title]";
$idpath = "$1.";
} elsif (/enum\s+(\w+)\s*{/) {
$title = "enum:$1" . "[$title]";
$idpath = "";
} elsif (/#define\s+(\w+)[(]/) {
$title = "func:$1" . "[$title]";
$idpath = "";
} elsif (/#define\s+(\w+)/) {
$title = "macro:$1" . "[$title]";
$idpath = "";
} else {
if (/typedef/) {
if (/.*\(\*(\w+)\)\(/) {
$title = "typedef:$1" . "[$title]";
} elsif (/typedef.*\s(\w+);/) {
$title = "typedef:$1" . "[$title]";
}
$idpath = "";
} else {
if (/.*[\s*](\w+)\(/) {
$title = "func:$1" . "[$title]";
$idpath = "";
} elsif (/.*\(\*(\w+)\)\(/) {
$body = "#newline#" . $title if not $body;
$title = "id:[$idpath$1]::";
$indent = "\t";
} elsif (/[^=]*[\s*](\w+)[\[\s,:;]/) {
$body = "#newline#" . $title if not $body;
$title = "id:[$idpath$1]::";
$indent = "\t";
}
}
}
put_section if $orig_title ne $title;
next;
}
$inblock = $end ? undef : 'yes';
}
close FILEIN;

View File

@ -67,7 +67,7 @@ then
usage "No backend defined"
fi
date_string=`date +"%d %B %y"`
date_string=`date -I`
script_version=`echo "\\$Revision: 1.19 $" | sed -e 's/\\$\(.*\) \\$/\1/'`
elinks_version="`$elinks -version | head -n 1 | sed -e 's/ELinks \([0-9][^ ]*\).*/\1/'`"
script_info="Generated by `basename $0` ($script_version) on $date_string"
@ -171,7 +171,7 @@ print_elinksconf_header()
.\" General Public License. <www.gnu.org/licenses/gpl.html>
.\"
.\" Process this file with groff -man -Tascii elinks.conf.5
.TH ELINKS.CONF 5 \"$date_string\"
.TH ELINKS.CONF 5 "ELinks configuration file" "$date_string" "ELinks configuration file"
.SH NAME
elinks.conf \- ELinks configuration file
@ -213,7 +213,7 @@ set document.browse.margin_width = 3
# Default document codepage.
set document.codepage.assume = "ISO-8859-1"
# User defined protocol handlers
set protocol.user.mailto.unix = "mutt %h -s \"%s\""
set protocol.user.mailto.unix = "mutt %h -s \e\*(lq%s\e\*(rq"
.SH OPTIONS
__END__

View File

@ -855,6 +855,16 @@ render_rss_item(struct dom_renderer *renderer, struct dom_node *item)
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);
}

View File

@ -114,9 +114,10 @@ struct html_context {
void *(*special_f)(struct html_context *, enum html_special_type, ...);
};
#define format (((struct html_element *) html_context->stack.next)->attr)
#define par_format (((struct html_element *) html_context->stack.next)->parattr)
#define html_top (*(struct html_element *) html_context->stack.next)
#define html_top ((struct html_element *) html_context->stack.next)
#define html_bottom ((struct html_element *) html_context->stack.prev)
#define format (html_top->attr)
#define par_format (html_top->parattr)
#define html_is_preformatted() (format.style.attr & AT_PREFORMATTED)

View File

@ -93,7 +93,7 @@ get_target(struct document_options *options, unsigned char *a)
void
ln_break(struct html_context *html_context, int n)
{
if (!n || html_top.invisible) return;
if (!n || html_top->invisible) return;
while (n > html_context->line_breax) {
html_context->line_breax++;
html_context->line_break_f(html_context);
@ -108,7 +108,7 @@ put_chrs(struct html_context *html_context, unsigned char *start, int len)
if (html_is_preformatted())
html_context->putsp = HTML_SPACE_NORMAL;
if (!len || html_top.invisible)
if (!len || html_top->invisible)
return;
switch (html_context->putsp) {
@ -258,8 +258,8 @@ html_focusable(struct html_context *html_context, unsigned char *a)
void
html_skip(struct html_context *html_context, unsigned char *a)
{
html_top.invisible = 1;
html_top.type = ELEMENT_DONT_KILL;
html_top->invisible = 1;
html_top->type = ELEMENT_DONT_KILL;
}
void
@ -663,10 +663,7 @@ init_html_parser_state(struct html_context *html_context,
enum html_element_type type,
int align, int margin, int width)
{
struct html_element *element;
html_stack_dup(html_context, type);
element = &html_top;
par_format.align = align;
@ -677,10 +674,10 @@ init_html_parser_state(struct html_context *html_context,
par_format.list_level = 0;
par_format.list_number = 0;
par_format.dd_margin = 0;
html_top.namelen = 0;
html_top->namelen = 0;
}
return element;
return html_top;
}
@ -691,20 +688,20 @@ done_html_parser_state(struct html_context *html_context,
{
html_context->line_breax = 1;
while (&html_top != element) {
kill_html_stack_item(html_context, &html_top);
while (html_top != element) {
pop_html_element(html_context);
#if 0
/* I've preserved this bit to show an example of the Old Code
* of the Mikulas days (I _HOPE_ it's by Mikulas, at least ;-).
* I think this assert() can never fail, for one. --pasky */
assertm(&html_top && (void *) &html_top != (void *) &html_stack,
assertm(html_top && (void *) html_top != (void *) &html_stack,
"html stack trashed");
if_assert_failed break;
#endif
}
html_top.type = ELEMENT_KILLABLE;
kill_html_stack_item(html_context, &html_top);
html_top->type = ELEMENT_KILLABLE;
pop_html_element(html_context);
}
@ -777,12 +774,12 @@ init_html_parser(struct uri *uri, struct document_options *options,
par_format.bgcolor = options->default_bg;
html_top.invisible = 0;
html_top.name = NULL;
html_top.namelen = 0;
html_top.options = NULL;
html_top.linebreak = 1;
html_top.type = ELEMENT_DONT_KILL;
html_top->invisible = 0;
html_top->name = NULL;
html_top->namelen = 0;
html_top->options = NULL;
html_top->linebreak = 1;
html_top->type = ELEMENT_DONT_KILL;
html_context->has_link_lines = 0;
html_context->table_level = 0;

View File

@ -254,7 +254,7 @@ html_input_format(struct html_context *html_context, unsigned char *a,
case FC_HIDDEN:
INTERNAL("bad control type");
}
kill_html_stack_item(html_context, &html_top);
pop_html_element(html_context);
put_chrs(html_context, " ", 1);
}
@ -498,7 +498,7 @@ end_parse:
for (i = 0; i < max_width; i++)
put_chrs(html_context, "_", 1);
kill_html_stack_item(html_context, &html_top);
pop_html_element(html_context);
put_chrs(html_context, "]", 1);
html_context->special_f(html_context, SP_CONTROL, fc);
}
@ -513,7 +513,7 @@ do_html_select_multiple(struct html_context *html_context, unsigned char *a,
if (!al) return;
html_focusable(html_context, a);
html_top.type = ELEMENT_DONT_KILL;
html_top->type = ELEMENT_DONT_KILL;
mem_free_set(&format.select, al);
format.select_disabled = has_attr(a, "disabled", html_context->options)
? FORM_MODE_DISABLED
@ -603,7 +603,7 @@ end_parse:
format.form = fc;
format.style.attr |= AT_BOLD;
put_chrs(html_context, "[ ]", 3);
kill_html_stack_item(html_context, &html_top);
pop_html_element(html_context);
put_chrs(html_context, " ", 1);
html_context->special_f(html_context, SP_CONTROL, fc);
}
@ -709,7 +709,7 @@ pp:
ln_break(html_context, 1);
}
kill_html_stack_item(html_context, &html_top);
pop_html_element(html_context);
if (rows > 1)
ln_break(html_context, 1);
else

View File

@ -141,14 +141,14 @@ html_apply_canvas_bgcolor(struct html_context *html_context)
/* 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,
css_apply(html_context, html_top, &html_context->css_styles,
&html_context->stack);
#endif
if (par_format.bgcolor != format.style.bg) {
/* Modify the root HTML element - format_html_part() will take
* this from there. */
struct html_element *e = html_context->stack.prev;
struct html_element *e = html_bottom;
html_context->was_body_background = 1;
e->parattr.bgcolor = e->attr.style.bg = par_format.bgcolor = format.style.bg;
@ -195,7 +195,7 @@ html_script(struct html_context *html_context, unsigned char *a,
mem_free(type);
not_processed:
/* Permit nested scripts and retreat. */
html_top.invisible++;
html_top->invisible++;
return;
}
@ -364,7 +364,7 @@ html_html(struct html_context *html_context, unsigned char *a,
/* Modify the root HTML element - format_html_part() will take
* this from there. */
struct html_element *e = html_context->stack.prev;
struct html_element *e = html_bottom;
if (par_format.bgcolor != format.style.bg)
e->parattr.bgcolor = e->attr.style.bg = par_format.bgcolor = format.style.bg;
@ -403,8 +403,8 @@ void
html_title(struct html_context *html_context, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
html_top.invisible = 1;
html_top.type = ELEMENT_WEAK;
html_top->invisible = 1;
html_top->type = ELEMENT_WEAK;
}
void
@ -586,7 +586,7 @@ html_hr(struct html_context *html_context, unsigned char *a,
}
html_context->special_f(html_context, SP_NOWRAP, 0);
ln_break(html_context, 2);
kill_html_stack_item(html_context, &html_top);
pop_html_element(html_context);
}
void
@ -690,7 +690,7 @@ html_ul(struct html_context *html_context, unsigned char *a,
int_upper_bound(&par_format.leftmargin, par_format.width / 2);
par_format.align = ALIGN_LEFT;
html_top.type = ELEMENT_DONT_KILL;
html_top->type = ELEMENT_DONT_KILL;
}
void
@ -725,7 +725,7 @@ html_ol(struct html_context *html_context, unsigned char *a,
int_upper_bound(&par_format.leftmargin, par_format.width / 2);
par_format.align = ALIGN_LEFT;
html_top.type = ELEMENT_DONT_KILL;
html_top->type = ELEMENT_DONT_KILL;
}
static struct {
@ -873,10 +873,10 @@ html_dl(struct html_context *html_context, unsigned char *a,
par_format.list_number = 0;
par_format.align = ALIGN_LEFT;
par_format.dd_margin = par_format.leftmargin;
html_top.type = ELEMENT_DONT_KILL;
html_top->type = ELEMENT_DONT_KILL;
if (!(par_format.flags & P_COMPACT)) {
ln_break(html_context, 2);
html_top.linebreak = 2;
html_top->linebreak = 2;
}
}
@ -948,14 +948,14 @@ html_frame(struct html_context *html_context, unsigned char *a,
}
if (!name) return;
if (!html_context->options->frames || !html_top.frameset) {
if (!html_context->options->frames || !html_top->frameset) {
html_focusable(html_context, a);
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);
html_top->frameset, name, url);
}
}
@ -997,12 +997,12 @@ html_frameset(struct html_context *html_context, unsigned char *a,
}
}
if (!html_top.frameset) {
if (!html_top->frameset) {
width = html_context->options->box.width;
height = html_context->options->box.height;
html_context->options->needs_height = 1;
} else {
struct frameset_desc *frameset_desc = html_top.frameset;
struct frameset_desc *frameset_desc = html_top->frameset;
int offset;
if (frameset_desc->box.y >= frameset_desc->box.height)
@ -1020,9 +1020,9 @@ html_frameset(struct html_context *html_context, unsigned char *a,
parse_frame_widths(rows, height, HTML_FRAME_CHAR_HEIGHT,
&fp.height, &fp.y);
fp.parent = html_top.frameset;
fp.parent = html_top->frameset;
if (fp.x && fp.y) {
html_top.frameset = html_context->special_f(html_context, SP_FRAMESET, &fp);
html_top->frameset = html_context->special_f(html_context, SP_FRAMESET, &fp);
}
mem_free_if(fp.width);
mem_free_if(fp.height);

View File

@ -67,20 +67,20 @@ html_a(struct html_context *html_context, unsigned char *a,
#ifdef CONFIG_GLOBHIST
} else if (get_global_history_item(format.link)) {
format.style.fg = format.vlink;
html_top.pseudo_class &= ~ELEMENT_LINK;
html_top.pseudo_class |= ELEMENT_VISITED;
html_top->pseudo_class &= ~ELEMENT_LINK;
html_top->pseudo_class |= ELEMENT_VISITED;
#endif
#ifdef CONFIG_BOOKMARKS
} else if (get_bookmark(format.link)) {
format.style.fg = format.bookmark_link;
html_top.pseudo_class &= ~ELEMENT_VISITED;
html_top->pseudo_class &= ~ELEMENT_VISITED;
/* XXX: Really set ELEMENT_LINK? --pasky */
html_top.pseudo_class |= ELEMENT_LINK;
html_top->pseudo_class |= ELEMENT_LINK;
#endif
} else {
format.style.fg = format.clink;
html_top.pseudo_class &= ~ELEMENT_VISITED;
html_top.pseudo_class |= ELEMENT_LINK;
html_top->pseudo_class &= ~ELEMENT_VISITED;
html_top->pseudo_class |= ELEMENT_LINK;
}
mem_free_set(&format.title,
@ -89,7 +89,7 @@ html_a(struct html_context *html_context, unsigned char *a,
html_focusable(html_context, a);
} else {
kill_html_stack_item(html_context, &html_top);
pop_html_element(html_context);
}
set_fragment_identifier(html_context, a, "name");
@ -269,7 +269,7 @@ html_img_do(unsigned char *a, unsigned char *object_src,
* If not, just exit now. */
if (!options->images && !format.link) {
mem_free_if(src);
if (usemap) kill_html_stack_item(html_context, &html_top);
if (usemap) pop_html_element(html_context);
return;
}
@ -332,7 +332,7 @@ html_img_do(unsigned char *a, unsigned char *object_src,
put_image_label(a, label, html_context);
if (ismap) kill_html_stack_item(html_context, &html_top);
if (ismap) pop_html_element(html_context);
mem_free_set(&format.image, NULL);
mem_free_set(&format.title, NULL);
}
@ -341,7 +341,7 @@ html_img_do(unsigned char *a, unsigned char *object_src,
}
mem_free_if(src);
if (usemap) kill_html_stack_item(html_context, &html_top);
if (usemap) pop_html_element(html_context);
}
void
@ -369,7 +369,7 @@ put_link_line(unsigned char *prefix, unsigned char *linkname,
format.style.fg = format.clink;
put_chrs(html_context, linkname, strlen(linkname));
ln_break(html_context, 1);
kill_html_stack_item(html_context, &html_top);
pop_html_element(html_context);
}

View File

@ -714,7 +714,7 @@ next_break:
element:
endingtag = *name == '/'; name += endingtag; namelen -= endingtag;
if (!endingtag && html_context->putsp == HTML_SPACE_ADD && !html_top.invisible)
if (!endingtag && html_context->putsp == HTML_SPACE_ADD && !html_top->invisible)
put_chrs(html_context, " ", 1);
put_chrs(html_context, base_pos, html - base_pos);
if (!html_is_preformatted() && !endingtag && html_context->putsp == HTML_SPACE_NORMAL) {
@ -766,14 +766,14 @@ start_element(struct element_info *ei,
struct css_selector *selector = NULL;
#endif
if (html_top.type == ELEMENT_WEAK) {
kill_html_stack_item(html_context, &html_top);
if (html_top->type == ELEMENT_WEAK) {
pop_html_element(html_context);
}
/* We try to process nested <script> if we didn't process the parent
* one. */
if (html_top.invisible
&& (ei->func != html_script || html_top.invisible < 2)) {
if (html_top->invisible
&& (ei->func != html_script || html_top->invisible < 2)) {
ELEMENT_RENDER_PROLOGUE
return html;
}
@ -803,11 +803,14 @@ start_element(struct element_info *ei,
if (e->type < ELEMENT_KILLABLE) break;
if (is_block_element(e) || is_inline_element(ei)) break;
}
} else foreach (e, html_context->stack) {
if (is_block_element(e) && is_inline_element(ei)) break;
if (e->type < ELEMENT_KILLABLE) break;
if (!strlcasecmp(e->name, e->namelen, name, namelen)) break;
} else {
foreach (e, html_context->stack) {
if (is_block_element(e) && is_inline_element(ei)) break;
if (e->type < ELEMENT_KILLABLE) break;
if (!strlcasecmp(e->name, e->namelen, name, namelen)) break;
}
}
if (!strlcasecmp(e->name, e->namelen, name, namelen)) {
while (e->prev != (void *) &html_context->stack)
kill_html_stack_item(html_context, e->prev);
@ -819,10 +822,10 @@ start_element(struct element_info *ei,
if (ei->type != ELEMENT_TYPE_NON_PAIRABLE) {
html_stack_dup(html_context, ELEMENT_KILLABLE);
html_top.name = name;
html_top.namelen = namelen;
html_top.options = attr;
html_top.linebreak = ei->linebreak;
html_top->name = name;
html_top->namelen = namelen;
html_top->options = attr;
html_top->linebreak = ei->linebreak;
#ifdef CONFIG_ECMASCRIPT
if (has_attr(attr, "onClick", html_context->options)) {
@ -830,7 +833,7 @@ start_element(struct element_info *ei,
mem_free_set(&format.link, stracpy("javascript:void(0);"));
mem_free_set(&format.target, stracpy(html_context->base_target));
format.style.fg = format.clink;
html_top.pseudo_class = ELEMENT_LINK;
html_top->pseudo_class = ELEMENT_LINK;
mem_free_set(&format.title, stracpy("onClick placeholder"));
/* Er. I know. Well, double html_focusable()s shouldn't
* really hurt. */
@ -840,7 +843,7 @@ start_element(struct element_info *ei,
}
#ifdef CONFIG_CSS
if (html_top.options && html_context->options->css_enable) {
if (html_top->options && html_context->options->css_enable) {
/* XXX: We should apply CSS otherwise as well, but that'll need
* some deeper changes in order to have options filled etc.
* Probably just applying CSS from more places, since we
@ -852,12 +855,12 @@ start_element(struct element_info *ei,
/* FIXME: The caching of the CSS selector is broken, since t can
* lead to wrong styles being applied to following elements, so
* disabled for now. */
selector = get_css_selector_for_element(html_context, &html_top,
selector = get_css_selector_for_element(html_context, html_top,
&html_context->css_styles,
&html_context->stack);
if (selector) {
apply_css_selector_style(html_context, &html_top, selector);
apply_css_selector_style(html_context, html_top, selector);
done_css_selector(selector);
}
}
@ -868,14 +871,14 @@ start_element(struct element_info *ei,
ELEMENT_RENDER_PROLOGUE
if (ei->func) ei->func(html_context, attr, html, eof, &html);
#ifdef CONFIG_CSS
if (selector && html_top.options) {
if (selector && html_top->options) {
/* Call it now to override default colors of the elements. */
selector = get_css_selector_for_element(html_context, &html_top,
selector = get_css_selector_for_element(html_context, html_top,
&html_context->css_styles,
&html_context->stack);
if (selector) {
apply_css_selector_style(html_context, &html_top, selector);
apply_css_selector_style(html_context, html_top, selector);
done_css_selector(selector);
}
}
@ -909,7 +912,7 @@ end_element(struct element_info *ei,
/* Apply background color from the <HTML> element. (bug 696) */
if (ei->func == html_html
&& html_top.type >= ELEMENT_KILLABLE
&& html_top->type >= ELEMENT_KILLABLE
&& !html_context->was_body_background)
html_apply_canvas_bgcolor(html_context);

View File

@ -60,7 +60,7 @@ search_html_stack(struct html_context *html_context, unsigned char *name)
#endif
foreach (element, html_context->stack) {
if (element == &html_top)
if (element == html_top)
continue; /* skip the top element */
if (strlcasecmp(element->name, element->namelen, name, namelen))
continue;
@ -189,7 +189,7 @@ kill_element(struct html_context *html_context, int ls, struct html_element *e)
void
kill_html_stack_until(struct html_context *html_context, int ls, ...)
{
struct html_element *e = &html_top;
struct html_element *e = html_top;
if (ls) e = e->next;

View File

@ -14,6 +14,8 @@ void html_stack_dup(struct html_context *html_context,
void kill_html_stack_item(struct html_context *html_context,
struct html_element *e);
#define pop_html_element(html_context) \
kill_html_stack_item(html_context, html_top)
void kill_html_stack_until(struct html_context *html_context, int ls, ...);
/* void dump_html_stack(struct html_context *html_context); */

View File

@ -7,30 +7,32 @@
/* Define if you want a talking scanner */
/* #define DEBUG_DOM_SCANNER */
/* The {struct dom_scanner_token} describes one scanner state. There are two
* kinds of tokens: char and non-char tokens. Char tokens contains only one
* char and simply have their char value as type. They are tokens having
* special control meaning in the code, like ':', ';', '{', '}' and '*'. Non
* char tokens has one or more chars and contain stuff like number or
* indentifier strings. */
/** DOM scanner token
*
* This struct describes one scanner state. There are two kinds of tokens: char
* and non-char tokens. Char tokens contains only one char and simply have
* their char value as type. They are tokens having special control meaning in
* the code, like ':', ';', '{', '}' and '*'. Non-char tokens have one or more
* chars and contain stuff like number or indentifier strings. */
struct dom_scanner_token {
/* The type the token */
/** The type the token. */
int type;
/* Some precedence value */
/** Some precedence value. */
int precedence;
/* The line number; used for error tokens */
/** The line number; used for error tokens. */
unsigned int lineno;
/* The start of the token string and the token length */
/** The start of the token string and the token length. */
struct dom_string string;
};
/** Skip the first charector of a token */
#define skip_dom_scanner_token_char(token) \
do { (token)->string.string++; (token)->string.length--; } while (0)
/* Compare the string of @token with the "static" string in @str. */
/** Compare the token string to a "static" string */
#define dom_scanner_token_contains(token, str) \
((token)->string.length == (sizeof(str) - 1) \
&& !strncasecmp((token)->string.string, str, sizeof(str) - 1))
@ -70,55 +72,72 @@ struct dom_scanner_string_mapping {
struct dom_scanner;
/** DOM scanner info
*
* Backend-specific information used during the actual scanning and
* by the front end to fill the token table on-demand, etc.
*/
struct dom_scanner_info {
/* Table containing how to map strings to token types */
/** Table containing how to map strings to token types */
const struct dom_scanner_string_mapping *mappings;
/* Information for how to initialize the scanner table */
/** Information for how to initialize the scanner table */
const struct dom_scan_table_info *scan_table_info;
/* Fills the scanner with tokens. Already scanned tokens which have not
/**
* Fills the scanner with tokens. Already scanned tokens which have not
* been requested remain and are moved to the start of the scanners
* token table. */
/* Returns the current token or NULL if there are none. */
* token table. Returns the current token or NULL if there are none. */
struct dom_scanner_token *(*scan)(struct dom_scanner *scanner);
/* The scanner table */
/* Contains bitmaps for the various characters groups.
* Idea sync'ed from mozilla browser. */
/**
* The scanner table. Contains bitmaps for the various characters
* groups. Idea sync'ed from mozilla browser. */
int scan_table[DOM_SCAN_TABLE_SIZE];
/* Has the scanner info been initialized? */
/** Has the scanner info been initialized? */
unsigned int initialized:1;
};
/* Initializes the scanner. */
/** Initializes a DOM scanner
*
* See struct ref:[dom_scanner] for a description of the `int` flags. */
void init_dom_scanner(struct dom_scanner *scanner, struct dom_scanner_info *scanner_info,
struct dom_string *string, int state, int count_lines, int complete,
int check_complete, int detect_error);
/* The number of tokens in the scanners token table:
/** The number of tokens in the scanners token table
*
* At best it should be big enough to contain properties with space separated
* values and function calls with up to 3 variables like rgb(). At worst it
* should be no less than 2 in order to be able to peek at the next token in
* the scanner. */
#define DOM_SCANNER_TOKENS 10
/* The {struct dom_scanner} describes the current state of the scanner. */
/** DOM scanner
*
* Holds the current state of the scanner. */
struct dom_scanner {
/* The very start of the scanned string, the position in the string
* where to scan next and the end of the string. If position is NULL it
* means that no more tokens can be retrieved from the string. */
unsigned char *string, *position, *end;
/** The start of the scanned string. */
unsigned char *string;
/** The end of the scanned string. */
unsigned char *end;
/**
* The position in the string where to scan next and the end of the
* string. If position is NULL it means that no more tokens can be
* retrieved from the string. */
unsigned char *position;
/* The current token and number of scanned tokens in the table.
* If the number of scanned tokens is less than DOM_SCANNER_TOKENS it
* is because there are no more tokens in the string. */
/**
* The current token. If the number of scanned tokens is less than
* ref:[DOM_SCANNER_TOKENS] it is because there are no more tokens in
* the string. */
struct dom_scanner_token *current;
/** The number of scanned tokens left in the table. */
int tokens;
/* The 'meta' scanner information */
/** The 'meta' scanner information */
struct dom_scanner_info *info;
#ifdef DEBUG_SCANNER
@ -130,25 +149,27 @@ struct dom_scanner {
/* The following two flags are used when parsing is incremental and
* the scanner must ensure that only tokens that are complete are
* generated. */
unsigned int check_complete:1; /* Only generate complete tokens */
unsigned int incomplete:1; /* The scanned string is incomplete */
unsigned int check_complete:1; /*: Only generate complete tokens */
unsigned int incomplete:1; /*: The scanned string is incomplete */
unsigned int detect_errors:1; /* Check for markup errors */
unsigned int found_error; /* Did we already report this error? */
unsigned int detect_errors:1; /*: Check for markup errors */
unsigned int found_error; /*: Did we already report this error? */
unsigned int count_lines:1; /* Is line counting enbaled? */
unsigned int lineno; /* Line # of the last scanned token */
unsigned int count_lines:1; /*: Is line counting enbaled? */
unsigned int lineno; /*: Line # of the last scanned token */
/* Some state indicator only meaningful to the scanner internals */
/** Some state indicator only meaningful to the scanner internals */
int state;
/* The table contain already scanned tokens. It is maintained in
/**
* The table contain already scanned tokens. It is maintained in
* order to optimize the scanning a bit and make it possible to look
* ahead at the next token. You should always use the accessors
* (defined below) for getting tokens from the scanner. */
struct dom_scanner_token table[DOM_SCANNER_TOKENS];
};
/** Check if there are more tokens */
#define dom_scanner_has_tokens(scanner) \
((scanner)->tokens > 0 && (scanner)->current < (scanner)->table + (scanner)->tokens)
@ -162,22 +183,24 @@ struct dom_scanner {
/* Scanner table accessors and mutators */
/* Checks the type of the next token */
/** Check the type of the next token */
#define check_next_dom_scanner_token(scanner, token_type) \
(scanner_has_tokens(scanner) \
&& ((scanner)->current + 1 < (scanner)->table + (scanner)->tokens) \
&& (scanner)->current[1].type == (token_type))
/* Access current and next token. Getting the next token might cause
* a rescan so any token pointers that has been stored in a local variable
* might not be valid after the call. */
/** Get the current token */
static inline struct dom_scanner_token *
get_dom_scanner_token(struct dom_scanner *scanner)
{
return dom_scanner_has_tokens(scanner) ? scanner->current : NULL;
}
/* Do a scanning if we do not have also have access to next token. */
/** Get the next token
*
* Getting the next token might cause a rescan so any token pointers that has
* been stored in a local variable might not be valid after the call. */
/* Do a scanning if we do not also have access to next token. */
static inline struct dom_scanner_token *
get_next_dom_scanner_token(struct dom_scanner *scanner)
{
@ -186,16 +209,20 @@ get_next_dom_scanner_token(struct dom_scanner *scanner)
? scanner->info->scan(scanner) : get_dom_scanner_token(scanner));
}
/* This should just make the code more understandable .. hopefully */
/** Skip the current token */
#define skip_dom_scanner_token(scanner) get_next_dom_scanner_token(scanner)
/* Removes tokens from the scanner until it meets a token of the given type.
/** Conditionally skip tokens
*
* Removes tokens from the scanner until it meets a token of the given type.
* This token will then also be skipped. */
struct dom_scanner_token *
skip_dom_scanner_tokens(struct dom_scanner *scanner, int skipto, int precedence);
/* Looks up the string from @ident to @end to in the scanners string mapping
* table */
/** Map a string to internal ID
*
* Looks up the string from @ident to @end to in the scanners string mapping
* table. */
int
map_dom_scanner_string(struct dom_scanner *scanner,
unsigned char *ident, unsigned char *end, int base_type);

View File

@ -11,12 +11,12 @@ struct sgml_parser;
struct string;
struct uri;
/** enum:[sgml_parser_type]: SGML parser type
/** SGML parser type
*
* There are two kinds of parser types: One that optimises one-time access to
* the DOM tree and one that creates a persistent DOM tree. */
enum sgml_parser_type {
/** id:[SGML_PARSER_STREAM]::
/**
* The first one will simply push nodes on the stack, not building a
* DOM tree. This interface is similar to that of SAX (Simple API for
* XML) where events are fired when nodes are entered and exited. It is
@ -24,7 +24,7 @@ enum sgml_parser_type {
* do all processing in a stream-like manner, such as when highlighting
* HTML code. */
SGML_PARSER_STREAM,
/** id:[SGML_PARSER_TREE]::
/**
* The second one is a DOM tree builder, that builds a persistent DOM
* tree. When using this type, it is possible to do even more
* (pre)processing than for parser streams. For example you can sort
@ -33,49 +33,48 @@ enum sgml_parser_type {
SGML_PARSER_TREE,
};
/** enum:[sgml_parser_flag]: SGML parser flags
/** SGML parser flags
*
* These flags control how the parser behaves.
*/
enum sgml_parser_flag {
SGML_PARSER_COUNT_LINES = 1, /*:: Make line numbers available. */
SGML_PARSER_COMPLETE = 2, /*:: Used internally when incremental. */
SGML_PARSER_INCREMENTAL = 4, /*:: Parse chunks of input. */
SGML_PARSER_DETECT_ERRORS = 8, /*:: Report errors. */
SGML_PARSER_COUNT_LINES = 1, /*: Make line numbers available. */
SGML_PARSER_COMPLETE = 2, /*: Used internally when incremental. */
SGML_PARSER_INCREMENTAL = 4, /*: Parse chunks of input. */
SGML_PARSER_DETECT_ERRORS = 8, /*: Report errors. */
};
/** struct:[sgml_parser_state]: SGML parser state
/** SGML parser state
*
* The SGML parser has only little state.
*/
struct sgml_parser_state {
/** id:[sgml_parser_state.info]::
/**
* Info about the properties of the node contained by state.
* This is only meaningful to element and attribute nodes. For
* unknown nodes it points to the common 'unknown node' info. */
struct sgml_node_info *info;
/** id:[sgml_parser_state.end_token]::
/**
* This is used by the DOM source renderer for highlighting the
* end-tag of an element. */
struct dom_scanner_token end_token;
};
/** enum:[sgml_parser_code]: (Error) codes for the SGML parser
/** (Error) codes for the SGML parser
*
* These enum values are used for return codes.
*/
enum sgml_parser_code {
SGML_PARSER_CODE_OK, /*:: The parsing was successful */
SGML_PARSER_CODE_INCOMPLETE, /*:: The parsing could not be completed */
SGML_PARSER_CODE_MEM_ALLOC, /*:: Failed to allocate memory */
/** id:[SGML_PARSER_CODE_ERROR]::
SGML_PARSER_CODE_OK, /*: The parsing was successful */
SGML_PARSER_CODE_INCOMPLETE, /*: The parsing could not be completed */
SGML_PARSER_CODE_MEM_ALLOC, /*: Failed to allocate memory */
/**
* FIXME: For when we will add support for requiring stricter parsing
* or even a validator. */
SGML_PARSER_CODE_ERROR,
};
/** callback:[sgml_error_T]: SGML error callback
/** SGML error callback
*
* Called by the SGML parser when a parsing error has occurred.
*
@ -85,28 +84,29 @@ typedef enum sgml_parser_code
(*sgml_error_T)(struct sgml_parser *, struct dom_string *, unsigned int);
/** struct:[sgml_parser]: The SGML parser
/** The SGML parser
*
* This struct hold info used while parsing SGML data.
*
* NOTE: The only variable the user should set is ref:[error_func]. */
* NOTE: The only variable the user should set is ref:[sgml_parser.error_func].
*/
struct sgml_parser {
enum sgml_parser_type type; /*:: Stream or tree */
enum sgml_parser_flag flags; /*:: Flags that control the behaviour */
enum sgml_parser_type type; /*: Stream or tree */
enum sgml_parser_flag flags; /*: Flags that control the behaviour */
struct sgml_info *info; /*:: Backend dependent info */
struct sgml_info *info; /*: Backend dependent info */
struct dom_string uri; /*:: The URI of the DOM document */
struct dom_node *root; /*:: The document root node */
struct dom_string uri; /*: The URI of the DOM document */
struct dom_node *root; /*: The document root node */
sgml_error_T error_func; /*:: Called for detected errors */
sgml_error_T error_func; /*: Called for detected errors */
struct dom_stack stack; /*:: A stack for tracking parsed nodes */
struct dom_stack parsing; /*:: Used for tracking parsing states */
struct dom_stack stack; /*: A stack for tracking parsed nodes */
struct dom_stack parsing; /*: Used for tracking parsing states */
};
/** func:[init_sgml_parser]: Initialise an SGML parser
/** Initialise an SGML parser
*
* Initialise an SGML parser with the given properties.
*
@ -121,7 +121,7 @@ struct sgml_parser *
init_sgml_parser(enum sgml_parser_type type, enum sgml_document_type doctype,
struct dom_string *uri, enum sgml_parser_flag flags);
/** func:[done_sgml_parser]: Release an SGML parser
/** Release an SGML parser
*
* Deallocates all resources, _expect_ the root node.
*
@ -129,7 +129,7 @@ init_sgml_parser(enum sgml_parser_type type, enum sgml_document_type doctype,
*/
void done_sgml_parser(struct sgml_parser *parser);
/** func:[parse_sgml]: Parse a chunk of SGML source
/** Parse a chunk of SGML source
*
* Parses the given `buffer`. For incremental rendering the last buffer can be
* signals through the `complete` parameter.
@ -144,12 +144,12 @@ void done_sgml_parser(struct sgml_parser *parser);
enum sgml_parser_code
parse_sgml(struct sgml_parser *parser, struct dom_string *buffer, int complete);
/** func:[get_sgml_parser_line_number]: Get the line position in the source
/** Get the line position in the source
*
* Returns what line number the parser is currently at or zero if there has
* been no parsing yet.
*
* NOTE: Line numbers are recoderded in the scanner tokens.
* NOTE: Line numbers are recorded in the scanner tokens.
*/
unsigned int get_sgml_parser_line_number(struct sgml_parser *parser);

View File

@ -7,75 +7,110 @@
struct dom_stack;
/** DOM stack callback
*
* Used by contexts, for 'hooking' into the node traversing. */
typedef void (*dom_stack_callback_T)(struct dom_stack *, struct dom_node *, void *);
#define DOM_STACK_MAX_DEPTH 4096
/** DOM stack state
*
* This state records what node and where it is placed. */
struct dom_stack_state {
/** The node assiciated with the state */
struct dom_node *node;
/* The depth of the state in the stack. This is amongst other things
/**
* The depth of the state in the stack. This is amongst other things
* used to get the state object data. */
unsigned int depth;
/* Wether this stack state can be popped with pop_dom_*() family. */
/** Whether this stack state can be popped with pop_dom_*() family. */
unsigned int immutable:1;
};
/** DOM stack context info
*
* To add a DOM stack context define this struct either statically or on the
* stack. */
struct dom_stack_context_info {
/* The @object_size member tells whether the stack should allocate
* objects for each state to be assigned to the state's @data member.
* Zero means no state data should be allocated. */
/**
* This member tells whether the stack should allocate objects for each
* state to be assigned to the state's @data member. Zero means no
* state data should be allocated. */
size_t object_size;
/* Callbacks to be called when pushing and popping nodes. */
/** Callbacks to be called when pushing nodes. */
dom_stack_callback_T push[DOM_NODES];
/** Callbacks to be called when popping nodes. */
dom_stack_callback_T pop[DOM_NODES];
};
/** DOM stack context
*
* This holds 'runtime' data for the stack context. */
struct dom_stack_context {
/* Data specific to the context. */
/** Data specific to the context. */
void *data;
/* This is one big array of context specific objects. */
/* For the SGML parser this holds DTD-oriented info about the node
* (recorded in struct sgml_node_info). E.g. whether an element node
* is optional. */
/**
* This is one big array of context specific objects. For the SGML
* parser this holds DTD-oriented info about the node (recorded in
* struct sgml_node_info). E.g. whether an element node is optional.
*/
unsigned char *state_objects;
/* Info about node callbacks and such. */
/** Info about node callbacks and such. */
struct dom_stack_context_info *info;
};
/** Flags for controlling the DOM stack */
enum dom_stack_flag {
/** No flag needed. */
DOM_STACK_FLAG_NONE = 0,
/* Free nodes when popping them by calling done_dom_node(). */
/** Free nodes when popping by calling ref:[done_dom_node]. */
DOM_STACK_FLAG_FREE_NODES = 1,
};
/* The DOM stack is a convenient way to traverse DOM trees. Also it
/** The DOM stack
*
* The DOM stack is a convenient way to traverse DOM trees. Also it
* maintains needed state info and is therefore also a holder of the current
* context since the stack is used to when the DOM tree is manipulated. */
struct dom_stack {
/* The stack of nodes */
/** The states currently on the stack. */
struct dom_stack_state *states;
/** The depth of the stack. */
size_t depth;
/** Flags given to ref:[init_dom_stack]. */
enum dom_stack_flag flags;
/* Contexts for the pushed and popped nodes. */
/** Contexts for the pushed and popped nodes. */
struct dom_stack_context **contexts;
/** The number of active contexts. */
size_t contexts_size;
/* The current context. */
/* XXX: Only meaningful within dom_stack_callback_T functions. */
/**
* The current context. Only meaningful within
* ref:[dom_stack_callback_T] functions. */
struct dom_stack_context *current;
};
/** Check whether stack is empty or not
*
* stack:: The stack to check.
*
* Returns non-zero if stack is empty. */
#define dom_stack_is_empty(stack) \
(!(stack)->states || (stack)->depth == 0)
/** Access state by offset from top
*
* stack:: The stack to fetch the state from.
* top_offset:: The offset from the stack top, zero is the top.
*
* Returns the requested state. */
static inline struct dom_stack_state *
get_dom_stack_state(struct dom_stack *stack, int top_offset)
{
@ -84,8 +119,24 @@ get_dom_stack_state(struct dom_stack *stack, int top_offset)
return &stack->states[stack->depth - 1 - top_offset];
}
#define get_dom_stack_top(stack) get_dom_stack_state(stack, 0)
/** Access the stack top
*
* stack:: The stack to get the top state from.
*
* Returns the top state. */
#define get_dom_stack_top(stack) \
get_dom_stack_state(stack, 0)
/** Access context specific state data
*
* Similar to ref:[get_dom_stack_state], this will fetch the data
* associated with the state for the given context.
*
* context:: The context to get data from.
* state:: The stack state to get data from.
*
* Returns the state data or NULL if ref:[dom_stack_context_info.object_size]
* was zero. */
static inline void *
get_dom_stack_state_data(struct dom_stack_context *context,
struct dom_stack_state *state)
@ -99,25 +150,36 @@ get_dom_stack_state_data(struct dom_stack_context *context,
return (void *) &context->state_objects[state->depth * object_size];
}
/* Define to have debug info about the nodes added printed to the log.
* Run as: ELINKS_LOG=/tmp/dom-dump.txt ./elinks -no-connect <url>
* to have the debug dumped into a file. */
/*#define DOM_STACK_TRACE*/
#ifdef DOM_STACK_TRACE
extern struct dom_stack_context_info dom_stack_trace_context_info;
/** Get debug info from the DOM stack
*
* Define `DOM_STACK_TRACE` to have debug info about the nodes added printed to
* the log. It will define add_dom_stack_tracer() to not be a no-op.
*
* Run as:
*
* ELINKS_LOG=/tmp/dom-dump.txt ./elinks -no-connect <url>
*
* to have the debug dumped into a file. */
#define add_dom_stack_tracer(stack, name) \
add_dom_stack_context(stack, name, &dom_stack_trace_context_info)
#else
#define add_dom_stack_tracer(stack, name) /* Nada */
#endif
/* The state iterators do not include the bottom state */
/** The state iterators
*
* To safely iterate through the stack state iterators. */
/** Iterate the stack from bottom to top. */
#define foreach_dom_stack_state(stack, state, pos) \
for ((pos) = 0; (pos) < (stack)->depth; (pos)++) \
if (((state) = &(stack)->states[(pos)]))
/** Iterate the stack from top to bottom. */
#define foreachback_dom_stack_state(stack, state, pos) \
for ((pos) = (stack)->depth - 1; (pos) >= 0; (pos)--) \
if (((state) = &(stack)->states[(pos)]))
@ -125,41 +187,96 @@ extern struct dom_stack_context_info dom_stack_trace_context_info;
/* Life cycle functions. */
/** Initialise a DOM stack
* stack:: Pointer to a (preallocated) stack.
* flags:: Any flags needed for controlling the behaviour of the stack.
*/
void init_dom_stack(struct dom_stack *stack, enum dom_stack_flag flags);
/** Release a DOM stack
*
* Free all resources collected by the stack.
*
* stack:: The stack to release. */
void done_dom_stack(struct dom_stack *stack);
/* Add a context to the stack. This is needed if either you want to have the
* stack allocated objects for created states and/or if you want to install
* callbacks for pushing or popping. . */
/** Add a context to the stack
*
* This is needed if either you want to have the stack allocated objects for
* created states and/or if you want to install callbacks for pushing or
* popping.
*
* stack:: The stack where the context should be created.
* data:: Private data to be stored in ref:[dom_stack_context.data].
* context_info:: Information about state objects and node callbacks.
*
* Returns a pointer to the newly created context or NULL. */
struct dom_stack_context *
add_dom_stack_context(struct dom_stack *stack, void *data,
struct dom_stack_context_info *context_info);
/* Unregister a stack @context. This should be done especially for temporary
* stack contexts (without any callbacks) so that they do not increasing the
* memory usage. */
/** Unregister a stack context
* This should be done especially for temporary stack contexts (without any
* callbacks) so that they do not increasing the memory usage. */
void done_dom_stack_context(struct dom_stack *stack, struct dom_stack_context *context);
/* Decends down to the given node making it the current parent */
/* If an error occurs the node is free()d and NULL is returned */
/** Push a node onto the stack
*
* Makes the pushed node the new top of the stack.
*
* stack:: The stack to push onto.
* node:: The node to push onto the stack.
*
* If an error occurs the node is released with ref:[done_dom_node] and NULL is
* returned. Else the pushed node is returned. */
struct dom_node *push_dom_node(struct dom_stack *stack, struct dom_node *node);
/* Ascends the stack to the current parent */
/** Pop the top stack state
*
* stack:: The stack to pop from. */
void pop_dom_node(struct dom_stack *stack);
/* Ascends the stack looking for specific parent */
/** Conditionally pop the stack states
*
* Searches the stack (using ref:[search_dom_stack]) for a specific node and
* pops all states until that particular state is met.
*
* NOTE: The popping is stopped if an immutable state is encountered. */
void pop_dom_nodes(struct dom_stack *stack, enum dom_node_type type,
struct dom_string *string);
/* Pop all stack states until a specific state is reached. */
/** Pop all states until target state
*
* Pop all stack states until a specific state is reached. The target state
* is also popped.
*
* stack:: The stack to pop from.
* target:: The state to pop until and including. */
void pop_dom_state(struct dom_stack *stack, struct dom_stack_state *target);
/* Dive through the stack states in search for the specified match. */
/** Search the stack states
*
* The string comparison is done against the ref:[dom_node.string] member of
* the of the state nodes.
*
* stack:: The stack to search in.
* type:: The type of node to match against.
* string:: The string to match against.
*
* Returns a state that matched the type and string or NULL. */
struct dom_stack_state *
search_dom_stack(struct dom_stack *stack, enum dom_node_type type,
struct dom_string *string);
/* Visit each node in the tree rooted at @root pre-order */
/** Walk all nodes reachable from a given node
*
* Visits each node in the DOM tree rooted at a given node, pre-order style.
*
* stack:: The stack to use for walking the nodes.
* root:: The root node to start from.
*
* It is assummed that the given stack has been initialised with
* ref:[init_dom_stack] and that the caller already added one or more
* context to the stack. */
void walk_dom_nodes(struct dom_stack *stack, struct dom_node *root);
#endif

View File

@ -259,7 +259,7 @@ struct entity { char *s; unicode_val_T c; } entities [1002] = {
{ "b.alpha", 0x03B1 }, /* GREEK SMALL LETTER ALPHA */
{ "b.beta", 0x03B2 }, /* GREEK SMALL LETTER BETA */
{ "b.chi", 0x03C7 }, /* GREEK SMALL LETTER CHI */
{ "b.delta", 0x03B3 }, /* GREEK SMALL LETTER GAMMA */
{ "b.delta", 0x03B4 }, /* GREEK SMALL LETTER DELTA */
{ "b.epsi", 0x03B5 }, /* GREEK SMALL LETTER EPSILON */
{ "b.epsis", 0x03B5 }, /* GREEK SMALL LETTER EPSILON */
{ "b.epsiv", 0x03B5 }, /* GREEK SMALL LETTER EPSILON */
@ -1005,4 +1005,4 @@ struct entity { char *s; unicode_val_T c; } entities [1002] = {
{ NULL, 0 }
};
#define N_ENTITIES 1001
#define N_ENTITIES 1001

View File

@ -110,7 +110,8 @@ init_response_digest(md5_digest_hex_T response, struct auth_entry *entry,
MD5_Init(&MD5Ctx);
MD5_Update(&MD5Ctx, ha1, sizeof(ha1));
MD5_Update(&MD5Ctx, ":", 1);
MD5_Update(&MD5Ctx, entry->nonce, strlen(entry->nonce));
if (entry->nonce)
MD5_Update(&MD5Ctx, entry->nonce, strlen(entry->nonce));
MD5_Update(&MD5Ctx, ":", 1);
MD5_Update(&MD5Ctx, "00000001", 8);
MD5_Update(&MD5Ctx, ":", 1);
@ -142,10 +143,12 @@ get_http_auth_digest_response(struct auth_entry *entry, struct uri *uri)
add_to_string(&string, entry->user);
add_to_string(&string, "\", ");
add_to_string(&string, "realm=\"");
add_to_string(&string, entry->realm);
if (entry->realm)
add_to_string(&string, entry->realm);
add_to_string(&string, "\", ");
add_to_string(&string, "nonce=\"");
add_to_string(&string, entry->nonce);
if (entry->nonce)
add_to_string(&string, entry->nonce);
add_to_string(&string, "\", ");
add_to_string(&string, "uri=\"/");
add_bytes_to_string(&string, uri->data, uri->datalen);

View File

@ -140,7 +140,7 @@ get_gopher_entity_info(enum gopher_entity type)
{
int entry;
for (entry = 0; entry < sizeof(gopher_entity_info) - 1; entry++)
for (entry = 0; entry < sizeof_array(gopher_entity_info) - 1; entry++)
if (gopher_entity_info[entry].type == type)
return &gopher_entity_info[entry];
@ -282,7 +282,7 @@ init_gopher_connection_info(struct connection *conn)
/* Get entity type, and selector string. */
/* Pick up gopher_entity */
if (selectorlen > 0) {
if (selectorlen > 1 && selector[1] == '/') {
entity = *selector++;
selectorlen--;
}
@ -296,7 +296,7 @@ init_gopher_connection_info(struct connection *conn)
* _after_ the Gopher entity. If the <entity-char> '/' combo is not
* found assume that the whole URI data part is the selector. */
entity_info = get_gopher_entity_info(entity);
if (entity_info->type == GOPHER_UNKNOWN) {
if (entity_info->type == GOPHER_UNKNOWN && entity != GOPHER_UNKNOWN) {
selector--;
selectorlen++;
}
@ -518,7 +518,8 @@ add_gopher_menu_line(struct string *buffer, unsigned char *line)
default:
{
struct string address;
unsigned char *format = *selector ? "%s://%s@%s/" : "%s://%s%s/";
unsigned char *format = selector && *selector
? "%s://%s@%s/" : "%s://%s%s/";
/* If port is defined it means that both @selector and @host
* was correctly parsed. */

View File

@ -10,10 +10,6 @@
* Ie. MIN(a+b, c+d) will do 3 additions...
* Please prefer to use int_min() and int_max() if possible. */
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h> /* MIN/MAX may be defined in this header. */
#endif
/* FreeBSD needs this. */
#ifdef MIN
#undef MIN