mirror of
https://github.com/rkd77/elinks.git
synced 2025-02-02 15:09:23 -05:00
Merge with git+ssh://pasky.or.cz/srv/git/elinks.git
This commit is contained in:
commit
f15c0a2677
@ -48,6 +48,9 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
|
||||
TEST_LIB=$(top_srcdir)/test/libtest.sh
|
||||
export TEST_LIB
|
||||
|
||||
host = @host@
|
||||
|
||||
ASCIIDOC = @ASCIIDOC@
|
||||
@ -139,6 +142,7 @@ CONFIG_RISCOS = @CONFIG_RISCOS@
|
||||
CONFIG_RUBY = @CONFIG_RUBY@
|
||||
CONFIG_SCANNER = @CONFIG_SCANNER@
|
||||
CONFIG_SCRIPTING = @CONFIG_SCRIPTING@
|
||||
CONFIG_SEE = @CONFIG_SEE@
|
||||
CONFIG_SHA1 = @CONFIG_SHA1@
|
||||
CONFIG_SMALL = @CONFIG_SMALL@
|
||||
CONFIG_SMB = @CONFIG_SMB@
|
||||
|
83
Makefile.lib
83
Makefile.lib
@ -33,8 +33,8 @@ mcmd = @$(if $($(mquiet)cmd_$(1)),echo $($(mquiet)cmd_$(1)) &&) $(cmd_$(1))
|
||||
ecmd = @$(if $($(mquiet)cmd_$(1)),printf "%-38s " $($(mquiet)cmd_$(1)) &&) $(cmd_$(1))
|
||||
|
||||
quiet_cmd_compile = ' [$(CC_COLOR)CC$(END_COLOR)] $(RELPATH)$@'
|
||||
masq_cmd_compile = $(COMPILE) -c $<
|
||||
cmd_compile = $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
|
||||
masq_cmd_compile = $(COMPILE) -o $(@) -c $< $(2)
|
||||
cmd_compile = $(COMPILE) -o $(@) -Wp,-MD,.deps/$(*F).pp -c $< $(2)
|
||||
|
||||
# Rule to compile a set of .o files into one .o file
|
||||
quiet_cmd_ld_objs = " [$(LD_COLOR)LD$(END_COLOR)] $(RELPATH)$@"
|
||||
@ -43,7 +43,7 @@ quiet_cmd_ld_objs = " [$(LD_COLOR)LD$(END_COLOR)] $(RELPATH)$@"
|
||||
`test -e $(subdir)/lib.o && echo $(subdir)/lib.o`)
|
||||
|
||||
quiet_cmd_link = ' [$(LINK_COLOR)LINK$(END_COLOR)] $(RELPATH)$@'
|
||||
cmd_link = $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||
cmd_link = $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(2) $(LIBS)
|
||||
|
||||
quiet_cmd_sparse = ' [SPARSE] $(RELPATH)$(2)'
|
||||
cmd_sparse = $(SPARSE) $(DEFS) $(INCLUDES) $(AM_CFLAGS) $(CFLAGS) $(SPARSE_FLAGS) $(2)
|
||||
@ -125,12 +125,15 @@ CLEAN += $(PROG)
|
||||
|
||||
all-default: $(LIB_O) $(PROGS) $(MAN1) $(MAN5)
|
||||
|
||||
# Ensure that Makefiles in subdirs are created before we recursive into them
|
||||
init-recursive: init-default
|
||||
|
||||
init-default:
|
||||
@$(foreach subdir,$(sort $(SUBDIRS)), \
|
||||
$(MKINSTALLDIRS) $(subdir) >/dev/null; \
|
||||
echo 'include $(SRC)/$(RELPATH)/$(subdir)/Makefile' > $(subdir)/Makefile;)
|
||||
|
||||
clean-default:
|
||||
clean-default: clean-test
|
||||
@-test -z "$(CLEAN)" || $(RM) $(CLEAN)
|
||||
|
||||
cleanall-default: clean-default
|
||||
@ -141,6 +144,40 @@ ifneq ($(SPARSE),)
|
||||
$(call ncmd,sparse,$(file));)
|
||||
endif
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Auto-testing infrastructure
|
||||
#
|
||||
|
||||
clean-test:
|
||||
test-default:
|
||||
|
||||
ifdef TEST_PROGS
|
||||
TESTDEPS-$(CONFIG_DEBUG) += $(top_builddir)/src/util/memdebug.o
|
||||
TESTDEPS += $(TESTDEPS-yes)
|
||||
|
||||
TESTS = $(wildcard $(srcdir)test-*)
|
||||
|
||||
$(TEST_PROGS): $(TESTDEPS)
|
||||
$(call cmd,link,$@.o)
|
||||
|
||||
# We cannot use $$@.o in the rule above so ensure that all test programs are
|
||||
# built before linking.
|
||||
$(TESTS): $(addsuffix .o,$(TEST_PROGS)) $(TEST_PROGS)
|
||||
@echo "*** $(notdir $@) ***"; \
|
||||
$(call shellquote,$(SHELL)) $@ $(TEST_OPTS)
|
||||
|
||||
test-default: $(TESTS)
|
||||
|
||||
clean-test:
|
||||
@rm -fr trash
|
||||
|
||||
CLEAN += $(TEST_PROGS) $(addsuffix .o,$(TEST_PROGS))
|
||||
endif
|
||||
|
||||
.PHONY: $(TESTS)
|
||||
.NOPARALLEL:
|
||||
|
||||
# sparse is architecture-neutral, which means that we need to tell it
|
||||
# explicitly what architecture to check for. Fix this up for yours..
|
||||
SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
|
||||
@ -163,29 +200,41 @@ endif
|
||||
|
||||
# Recursion:
|
||||
|
||||
.PHONY: all-recursive install-recursive clean-recursive cleanall-recursive init-recursive check-recursive
|
||||
RULES = all install clean cleanall init check test
|
||||
RECRULES = $(addsuffix -recursive,$(RULES))
|
||||
|
||||
all-recursive install-recursive clean-recursive cleanall-recursive init-recursive check-recursive:
|
||||
.PHONY: $(RECRULES)
|
||||
|
||||
# The -recursive rules decend all subdirs.
|
||||
$(RECRULES):
|
||||
ifdef SUBDIRS
|
||||
@$(foreach subdir,$(sort $(SUBDIRS)), \
|
||||
$(call ncmd,recmake,$(subdir),$(subst -recursive,,$@)) || exit 1;)
|
||||
endif
|
||||
|
||||
all: all-recursive all-default all-local
|
||||
install: install-recursive install-default install-local
|
||||
check: check-recursive check-default check-local
|
||||
clean: clean-recursive clean-default clean-local
|
||||
# Setup the default sub commands dependency. First decend subdirs then do all
|
||||
# the default stuff and finally do any local hooks.
|
||||
recdeps = $1-recursive $1-default $1-local
|
||||
all: $(call recdeps,all)
|
||||
check: $(call recdeps,check)
|
||||
cleanall: $(call recdeps,cleanall)
|
||||
clean: $(call recdeps,clean)
|
||||
init: $(call recdeps,init)
|
||||
install: $(call recdeps,install)
|
||||
test: $(call recdeps,test)
|
||||
|
||||
cleanall: cleanall-recursive cleanall-default
|
||||
init: init-default init-recursive
|
||||
|
||||
all-local:
|
||||
install-local:
|
||||
clean-local:
|
||||
check-local:
|
||||
# Dummy rules for local hooks
|
||||
$(addsuffix -local,$(RULES)):
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
|
||||
# Shell quote;
|
||||
# Result of this needs to be placed inside ''
|
||||
# XXX: Placed here because Vim cannot highlight things right afterwards
|
||||
shq = $(subst ','\'',$(1))
|
||||
# This has surrounding ''
|
||||
shellquote = '$(call shq,$(1))'
|
||||
|
||||
# vim:syntax=make
|
||||
|
1102
Unicode/entities.lnx
1102
Unicode/entities.lnx
File diff suppressed because it is too large
Load Diff
1060
Unicode/entities.txt
Normal file
1060
Unicode/entities.txt
Normal file
File diff suppressed because it is too large
Load Diff
@ -2,18 +2,27 @@
|
||||
|
||||
echo
|
||||
echo Generating entity table.
|
||||
(
|
||||
cat entities.lnx | grep '^[ ]*{"' | sort >tmp
|
||||
|
||||
sed -n '/^[^#]/,$p' < entities.txt | while read line; do \
|
||||
name=$(echo "$line" | cut -f 1); \
|
||||
code=$(echo "$line" | cut -f 3); \
|
||||
desc=$(echo "$line" | cut -f 4 | sed 's/# //'); \
|
||||
test "$code" = "0x????" && continue
|
||||
printf "\t{ %-12s %s }, /* %-46s */\n" \
|
||||
"\"$name\"," "$code" "$desc"; \
|
||||
done | LC_ALL=C sort > tmp
|
||||
N=`cat tmp | wc -l`
|
||||
echo '/* Automatically generated by gen-ent */'
|
||||
echo
|
||||
echo 'struct entity { char *s; unicode_val_T c; } entities ['`expr $N + 1`'] = {'
|
||||
cat tmp
|
||||
echo ' {NULL, 0}'
|
||||
echo '};'
|
||||
echo
|
||||
echo '#define N_ENTITIES' $N
|
||||
) > ../src/intl/entity.inc
|
||||
|
||||
cat > ../src/intl/entity.inc <<EOF
|
||||
/* Automatically generated by gen-ent */
|
||||
|
||||
struct entity { char *s; unicode_val_T c; } entities [$(expr $N + 1)] = {
|
||||
$(cat tmp)
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
#define N_ENTITIES $N
|
||||
EOF
|
||||
rm -f tmp
|
||||
echo Done.
|
||||
echo
|
||||
|
51
configure.in
51
configure.in
@ -496,6 +496,55 @@ if test "$CONFIG_WIN32" = yes; then
|
||||
EL_CONFIG_WIN32
|
||||
fi
|
||||
|
||||
dnl ===================================================================
|
||||
dnl Check for SEE (Simple Ecmascript Engine)
|
||||
dnl ===================================================================
|
||||
AC_ARG_WITH(see, [ --with-see enable Simple Ecmascript Engine (SEE) support],
|
||||
[ if test "x$withval" != xno; then enable_see=yes; fi ])
|
||||
|
||||
# The following is probably bad, ugly and so on. Stolen from Guile's (1.4)
|
||||
# SEE_FLAGS but I really don't want to require people to have Guile in order
|
||||
# to compile CVS. Also, the macro seems to be really stupid regarding searching
|
||||
# for Guile in $PATH etc. --pasky
|
||||
|
||||
AC_MSG_CHECKING([for SEE])
|
||||
|
||||
if test "$enable_see" = "yes"; then
|
||||
AC_MSG_RESULT(yes);
|
||||
## Based on the SEE_FLAGS macro.
|
||||
|
||||
if test -d "$withval"; then
|
||||
SEE_PATH="$withval:$PATH"
|
||||
else
|
||||
SEE_PATH="$PATH"
|
||||
fi
|
||||
|
||||
AC_PATH_PROG(SEE_CONFIG, libsee-config, no, $SEE_PATH)
|
||||
|
||||
## First, let's just see if we can find Guile at all.
|
||||
if test "$SEE_CONFIG" != no; then
|
||||
cf_result="yes";
|
||||
|
||||
SEE_LIBS="`$SEE_CONFIG --libs`"
|
||||
SEE_CFLAGS="`$SEE_CONFIG --cppflags`"
|
||||
LIBS="$SEE_LIBS $LIBS"
|
||||
CPPFLAGS="$CPPFLAGS $SEE_CFLAGS"
|
||||
EL_CONFIG(CONFIG_SEE, [SEE])
|
||||
AC_SUBST(SEE_CFLAGS)
|
||||
AC_SUBST(CONFIG_SEE)
|
||||
disable_spidermonkey=yes
|
||||
else
|
||||
if test -n "$withval" && test "x$withval" != xno; then
|
||||
AC_MSG_ERROR([SEE not found])
|
||||
else
|
||||
AC_MSG_WARN([SEE support disabled])
|
||||
fi
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT(no);
|
||||
fi
|
||||
|
||||
|
||||
dnl ===================================================================
|
||||
dnl Check for SpiderMonkey, optional even if installed.
|
||||
dnl ===================================================================
|
||||
@ -550,7 +599,7 @@ fi
|
||||
|
||||
AC_SUBST(CONFIG_SPIDERMONKEY)
|
||||
|
||||
EL_CONFIG_DEPENDS(CONFIG_ECMASCRIPT, [CONFIG_SPIDERMONKEY], [ECMAScript (JavaScript)])
|
||||
EL_CONFIG_DEPENDS(CONFIG_ECMASCRIPT, [CONFIG_SEE CONFIG_SPIDERMONKEY], [ECMAScript (JavaScript)])
|
||||
|
||||
|
||||
dnl ===================================================================
|
||||
|
@ -934,8 +934,6 @@ B<dia> <I<dialect>> <I<URL>> (or current url)
|
||||
|
||||
Dialects: I<redneck>, I<jive>, I<cockney>, I<fudd>, I<bork>, I<moron>, I<piglatin>, or I<hacker>
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
############################################################################
|
||||
# the Dialectizer (dia <dialect> <url>)
|
||||
@ -1070,6 +1068,8 @@ using the search engine defined by the 'search' configuration option if
|
||||
}
|
||||
|
||||
|
||||
=back
|
||||
|
||||
|
||||
=head1 FOLLOW URL HOOK
|
||||
|
||||
@ -1081,8 +1081,6 @@ I<Developer's usage>: The function I<follow_url_hook> is called when the hook
|
||||
is triggered, taking the target URL as its only argument. It returns the final
|
||||
target URL.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
################################################################################
|
||||
### follow_url_hook ############################################################
|
||||
@ -1133,6 +1131,8 @@ Translates any I<nntp:> or I<news:> URLs to Google Groups HTTP URLs.
|
||||
}
|
||||
|
||||
|
||||
=back
|
||||
|
||||
|
||||
=head1 PRE FORMAT HTML HOOK
|
||||
|
||||
@ -1151,8 +1151,6 @@ I<Developer's usage>: The function I<pre_format_html_hook> is called when the
|
||||
hook is triggered, taking the document's URL and the HTML source as its two
|
||||
arguments. It returns the rewritten HTML code.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
################################################################################
|
||||
### pre_format_html_hook #######################################################
|
||||
@ -1242,6 +1240,8 @@ content-type:text/html.
|
||||
}
|
||||
|
||||
|
||||
=back
|
||||
|
||||
|
||||
=head1 PROXY FOR HOOK
|
||||
|
||||
@ -1256,8 +1256,6 @@ I<Developer's usage>: The function I<proxy_for_hook> is called when the hook is
|
||||
triggered, taking the target URL as its only argument. It returns the proxy
|
||||
URL, empty string to use no proxy or I<undef> to use the default proxy URL.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
################################################################################
|
||||
### proxy_for_hook #############################################################
|
||||
@ -1281,6 +1279,8 @@ Prevents proxy usage for local files and C<http://localhost>.
|
||||
}
|
||||
|
||||
|
||||
=back
|
||||
|
||||
|
||||
=head1 QUIT HOOK
|
||||
|
||||
@ -1294,8 +1294,6 @@ I<Developer's usage>: The function I<quit_hook> is called when the hook is
|
||||
triggered, taking no arguments nor returning anything. ('cause, you know, what
|
||||
would be the point?)
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
################################################################################
|
||||
### quit_hook ##################################################################
|
||||
@ -1367,6 +1365,8 @@ A few words of wisdom from ELinks the Sage.
|
||||
}
|
||||
|
||||
|
||||
=back
|
||||
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
|
146
doc/Makefile
146
doc/Makefile
@ -14,6 +14,7 @@ TXT_DIR = $(top_srcdir)/doc/txt
|
||||
|
||||
DOC_DIRS = \
|
||||
$(HTML_DIR) \
|
||||
$(HTML_DIR)/api \
|
||||
$(MAN_DIR)/man1 \
|
||||
$(MAN_DIR)/man5 \
|
||||
$(TXT_DIR) \
|
||||
@ -48,77 +49,51 @@ 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
|
||||
#
|
||||
|
||||
CODE2DOC = $(top_srcdir)/doc/tools/code2doc
|
||||
HELP2DOC = $(top_srcdir)/doc/tools/help2doc
|
||||
IMPORT_FEATURES_CONF = $(top_srcdir)/doc/tools/import-features.conf
|
||||
MAKE_ELINKS_MANPAGE = $(top_srcdir)/doc/tools/make-elinks-manpage
|
||||
MAKE_ELINKSKEYS_MANPAGE = $(top_srcdir)/doc/tools/make-elinkskeys-manpage
|
||||
|
||||
ifeq ($(CONFIG_ASCIIDOC),yes)
|
||||
HTML_DOCS_WITH_ASCIIDOC = \
|
||||
$(HTML_DIR)/elinks.1.html \
|
||||
$(HTML_DIR)/elinkskeys.5.html \
|
||||
$(HTML_DIR)/hacking.html \
|
||||
$(HTML_DIR)/manual.html
|
||||
endif
|
||||
HTML_DOCS-$(CONFIG_ASCIIDOC) += \
|
||||
api/dom.html \
|
||||
elinks.1.html \
|
||||
elinkskeys.5.html \
|
||||
hacking.html \
|
||||
manual.html
|
||||
|
||||
HTML_DOCS-$(CONFIG_XMLTO) += \
|
||||
manual.html-chunked
|
||||
|
||||
HTML_DOCS-$(CONFIG_POD2HTML) += \
|
||||
perl.html \
|
||||
perl-hooks.html
|
||||
|
||||
MAN_DOCS-$(CONFIG_XMLTO) += \
|
||||
man1/elinks.1.in \
|
||||
man5/elinkskeys.5
|
||||
|
||||
# Only jw is used for generating PDF.
|
||||
ifeq ($(CONFIG_XMLTO),yes)
|
||||
HTML_DOCS_WITH_XMLTO = \
|
||||
$(HTML_DIR)/manual.html-chunked
|
||||
PDF_DOCS-$(CONFIG_JW) += \
|
||||
manual.pdf
|
||||
|
||||
MAN_DOCS_WITH_XMLTO = \
|
||||
$(MAN_DIR)/man1/elinks.1.in \
|
||||
$(MAN_DIR)/man5/elinkskeys.5
|
||||
endif
|
||||
MAN_DOCS += man5/elinks.conf.5
|
||||
|
||||
# Only jw is used for generating PDF.
|
||||
ifeq ($(CONFIG_JW),yes)
|
||||
PDF_DOCS_WITH_JW = \
|
||||
$(PDF_DIR)/manual.pdf
|
||||
endif
|
||||
MAN_DOCS += $(MAN_DOCS-yes)
|
||||
HTML_DOCS += $(HTML_DOCS-yes)
|
||||
PDF_DOCS += $(PDF_DOCS-yes)
|
||||
|
||||
ifeq ($(CONFIG_POD2HTML),yes)
|
||||
HTML_DOCS_WITH_POD2HTML = \
|
||||
$(HTML_DIR)/perl.html \
|
||||
$(HTML_DIR)/perl-hooks.html
|
||||
endif
|
||||
|
||||
MAN_DOCS_WITH_SHELL = $(MAN_DIR)/man5/elinks.conf.5
|
||||
|
||||
MAN_DOCS = \
|
||||
$(MAN_DOCS_WITH_SHELL)
|
||||
$(MAN_DOCS_WITH_ASCIIDOC)
|
||||
|
||||
HTML_DOCS = \
|
||||
$(HTML_DOCS_WITH_ASCIIDOC) \
|
||||
$(HTML_DOCS_WITH_POD2HTML) \
|
||||
$(HTML_DOCS_WITH_JW)
|
||||
|
||||
PDF_DOCS = \
|
||||
$(PDF_DOCS_WITH_JW)
|
||||
|
||||
html-asciidoc-yes: doc-dirs $(HTML_DOCS_WITH_ASCIIDOC)
|
||||
html-asciidoc-no:
|
||||
|
||||
html-pod2html-yes: doc-dirs $(HTML_DOCS_WITH_POD2HTML)
|
||||
html-pod2html-no:
|
||||
|
||||
html-xmlto-yes: doc-dirs $(HTML_DOCS_WITH_XMLTO)
|
||||
html-xmlto-no:
|
||||
|
||||
man-xmlto-yes: doc-dirs $(MAN_DOCS_WITH_XMLTO)
|
||||
man-xmlto-no:
|
||||
|
||||
pdf-jw-yes: doc-dirs $(PDF_DOCS_WITH_JW)
|
||||
pdf-jw-no:
|
||||
|
||||
man-docs: man-xmlto-$(CONFIG_XMLTO) $(MAN_DOCS_WITH_SHELL)
|
||||
html-docs: html-asciidoc-$(CONFIG_ASCIIDOC) html-xmlto-$(CONFIG_XMLTO) html-pod2html-$(CONFIG_POD2HTML)
|
||||
pdf-docs: pdf-jw-$(CONFIG_JW)
|
||||
man-docs: doc-dirs $(addprefix $(MAN_DIR)/,$(MAN_DOCS))
|
||||
html-docs: doc-dirs $(addprefix $(HTML_DIR)/,$(HTML_DOCS))
|
||||
pdf-docs: doc-dirs $(addprefix $(PDF_DIR)/,$(PDF_DOCS))
|
||||
|
||||
all-docs: man-docs html-docs pdf-docs
|
||||
|
||||
@ -135,36 +110,40 @@ clean-local:
|
||||
|
||||
# Autogenerated asciidoc files.
|
||||
|
||||
$(TXT_DIR)/import-features.conf.txt: $(FEATURES) doc-dirs $(IMPORT_FEATURES_CONF)
|
||||
$(TXT_DIR)/import-features.conf.txt: $(FEATURES) $(IMPORT_FEATURES_CONF)
|
||||
$(IMPORT_FEATURES_CONF) > $@
|
||||
|
||||
$(TXT_DIR)/elinks.1.%.txt: $(MAKE_ELINKS_MANPAGE) doc-dirs $(ELINKS)
|
||||
$(MAKE_ELINKS_MANPAGE) $@ $(ELINKS) $(HELP2DOC) > $@
|
||||
$(TXT_DIR)/elinks.1.%.txt: $(MAKE_ELINKS_MANPAGE) $(ELINKS) $(HELP2DOC) Makefile
|
||||
$(LOCALES) $(MAKE_ELINKS_MANPAGE) $@ $(ELINKS) $(HELP2DOC) > $@
|
||||
|
||||
$(TXT_DIR)/elinkskeys.5.%.txt: $(MAKE_ELINKSKEYS_MANPAGE) doc-dirs $(KBDBIND)
|
||||
$(MAKE_ELINKSKEYS_MANPAGE) $@ $(KBDBIND) > $@
|
||||
$(TXT_DIR)/elinkskeys.5.%.txt: $(MAKE_ELINKSKEYS_MANPAGE) $(KBDBIND) Makefile
|
||||
$(LOCALES) $(MAKE_ELINKSKEYS_MANPAGE) $@ $(KBDBIND) > $@
|
||||
|
||||
|
||||
# Man Pages
|
||||
|
||||
$(XML_DIR)/%.man.xml: $(TXT_DIR)/%.man.txt doc-dirs
|
||||
$(XML_DIR)/%.man.xml: $(TXT_DIR)/%.man.txt
|
||||
$(ASCIIDOC) -b docbook -d manpage -o $@ $<
|
||||
|
||||
$(MAN_DIR)/man1/elinks.1.in: $(XML_DIR)/elinks.1.man.xml doc-dirs
|
||||
$(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 doc-dirs
|
||||
$(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: doc-dirs $(ELINKS)
|
||||
$(HELP2DOC) --elinks=$(ELINKS) --elinksconf > $@
|
||||
$(MAN_DIR)/man5/elinks.conf.5: $(ELINKS) $(HELP2DOC) Makefile
|
||||
$(LOCALES) $(HELP2DOC) --elinks=$(ELINKS) --elinksconf > $@
|
||||
|
||||
# XHTML/CSS Man Pages
|
||||
|
||||
$(HTML_DIR)/%.html: $(TXT_DIR)/%.html.txt doc-dirs
|
||||
$(HTML_DIR)/%.html: $(TXT_DIR)/%.html.txt
|
||||
$(ASCIIDOC) -b xhtml11 -d manpage -o $@ $<
|
||||
|
||||
# The Manual
|
||||
@ -174,28 +153,39 @@ MANUAL_EXTRA_FILES = \
|
||||
$(TXT_DIR)/elinks.1.html.txt \
|
||||
$(TXT_DIR)/elinkskeys.5.html.txt
|
||||
|
||||
$(HTML_DIR)/manual.html: $(MANUAL_FILES) doc-dirs $(MANUAL_EXTRA_FILES)
|
||||
$(HTML_DIR)/manual.html: $(MANUAL_FILES) $(MANUAL_EXTRA_FILES)
|
||||
$(ASCIIDOC) -b xhtml11 -d book -o $@ -n $<
|
||||
|
||||
$(HTML_DIR)/hacking.html: $(top_srcdir)/doc/hacking.txt doc-dirs
|
||||
$(HTML_DIR)/hacking.html: $(top_srcdir)/doc/hacking.txt
|
||||
$(ASCIIDOC) -b xhtml11 -d book -o $@ -n $<
|
||||
|
||||
$(HTML_DIR)/dev-intro.html: $(top_srcdir)/doc/dev-intro.txt doc-dirs
|
||||
$(HTML_DIR)/dev-intro.html: $(top_srcdir)/doc/dev-intro.txt
|
||||
$(ASCIIDOC) -b xhtml11 -d book -o $@ -n $<
|
||||
|
||||
$(XML_DIR)/manual.xml: $(MANUAL_FILES) doc-dirs $(MANUAL_EXTRA_FILES)
|
||||
$(XML_DIR)/manual.xml: $(MANUAL_FILES) $(MANUAL_EXTRA_FILES)
|
||||
$(ASCIIDOC) -b docbook -d book -o $@ $<
|
||||
|
||||
$(HTML_DIR)/manual.html-chunked: $(XML_DIR)/manual.xml doc-dirs
|
||||
$(HTML_DIR)/manual.html-chunked: $(XML_DIR)/manual.xml
|
||||
$(XMLTO) -o $@ html $<
|
||||
|
||||
$(PDF_DIR)/manual.pdf: $(XML_DIR)/manual.xml doc-dirs
|
||||
$(PDF_DIR)/manual.pdf: $(XML_DIR)/manual.xml
|
||||
$(JW) -o $(PDF_DIR) -b pdf $<
|
||||
|
||||
$(HTML_DIR)/perl.html: $(top_srcdir)/doc/perl.pod doc-dirs
|
||||
$(HTML_DIR)/perl.html: $(top_srcdir)/doc/perl.pod
|
||||
$(POD2HTML) --outfile=$@ < $<
|
||||
|
||||
$(HTML_DIR)/perl-hooks.html: $(top_srcdir)/contrib/perl/hooks.pl doc-dirs
|
||||
$(HTML_DIR)/perl-hooks.html: $(top_srcdir)/contrib/perl/hooks.pl
|
||||
$(POD2HTML) --outfile=$@ < $<
|
||||
|
||||
## API Docs
|
||||
#
|
||||
|
||||
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
|
||||
|
@ -220,6 +220,3 @@ in the future. So far, we have had no reports from our users that anyone wants
|
||||
to switch their bookmarks format frequently, so this is not too high on our
|
||||
TODO list. So be sure to tell us if you would like this process to be
|
||||
simplified rather sooner than later.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
55
doc/code2doc.conf
Normal file
55
doc/code2doc.conf
Normal file
@ -0,0 +1,55 @@
|
||||
[specialwords]
|
||||
emphasizedwords=\bAsciiDoc\b
|
||||
monospacedwords=\basciidoc\(1\)
|
||||
|
||||
[id-inlinemacro]
|
||||
<a id="{0}" href="#{0}">{0}</a>
|
||||
|
||||
[enum-inlinemacro]
|
||||
<a id="{target}">enum {target}: {0}</a>
|
||||
|
||||
[func-inlinemacro]
|
||||
<a id="{target}">{target}(): {0}</a>
|
||||
|
||||
[struct-inlinemacro]
|
||||
<a id="{target}">struct {target}: {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>
|
||||
|
||||
[replacements]
|
||||
(^|[^-])--($|[^-])=\1--\2
|
||||
|
||||
[tags]
|
||||
ilisttext=|
|
||||
olisttext=|
|
||||
vlisttext=|
|
||||
qlisttext=|
|
||||
colisttext=|
|
||||
|
||||
[tags]
|
||||
title1=<h1>|</h1>
|
||||
title2=<h2>|</h2>
|
||||
title3=<h3>|</h3>
|
||||
|
||||
[literalparagraph]
|
||||
<table border="1" class="code"><tr><td><pre>
|
||||
|
|
||||
</pre></td></tr></table>
|
||||
|
||||
[listingblock]
|
||||
<p><b>{title}</b></p>
|
||||
<table border="1" class="code"><tr><td><pre>
|
||||
|
|
||||
</pre></td></tr></table>
|
||||
|
||||
[noteblock]
|
||||
<div><p><b>{title}</b></p>
|
||||
|
|
||||
</div>
|
@ -120,6 +120,3 @@ that there are no SpiderMonkey references outside of
|
||||
ECMAScript backend, go ahead - you will just need to write an autoconf
|
||||
detection for it and tie it to `src/ecmascript/ecmascript.c`, which should be
|
||||
easy. We await your patches eagerly.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -99,6 +99,3 @@ Also, perhaps wider scale of commands should be implemented in ex-mode. The
|
||||
code is extremely flexible and it is very trivial to make another ex-mode
|
||||
command handler, it's just that no one has done it yet ;-). Also, more actions
|
||||
should be able to take arguments.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
12
doc/faq.txt
12
doc/faq.txt
@ -101,14 +101,6 @@ One mebibyte 1 MiB = 2^20 B = 1 048 576 B
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
[[Christmas]]
|
||||
Why are stable releases made at Christmas?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
It is suspected that this yearly present has become a tradition because pasky
|
||||
worships the Christmas spirit. ;-)
|
||||
|
||||
|
||||
[[get-256-colours]]
|
||||
How can I get 256 colors?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@ -150,7 +142,3 @@ The new ELinks versions (from 0.9.0 on) send:
|
||||
You should therefore check against something like /^ELinks[\/ ]/, since more
|
||||
fields can be added inside the parenthesis in subsequent versions. Note that
|
||||
users can change their User-Agent through the options system.
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -31,8 +31,3 @@ pizza, some close location of yourself recommended), we accept drinks, nice
|
||||
books, CDs with interesting things, computer equipment and accessories, PDAs,
|
||||
pens + pencils + erasers, and last but not least money. Contact the maintainer,
|
||||
he'll split the stuff properly amongst himself and other developers >:).
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -5,8 +5,6 @@ Welcome, mere mortal, to the realm of evil unindented code, heaps of one or
|
||||
two-letter variables, seas of gotos accompanied with 30-letters labels in Czech
|
||||
language with absolutely no meaning, welcome to the realm of ELinks code!
|
||||
|
||||
[We're going to extend this file slowly, basing on daily practice ;]
|
||||
|
||||
Don't take this file as a law. We may or may not be right in these issues.
|
||||
|
||||
Motto: I didn't expect someone to look at the source, so it's unreadable.
|
||||
@ -620,6 +618,22 @@ typedef int (some_func_T)(void *);
|
||||
typedef long long our_long_T;
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Please use mode_t and S_I???? macros instead of numeric modes
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.Use:
|
||||
-------------------------------------------------------------------------------
|
||||
mode_t mode = S_IRWXU | S_IRGRP | S_IROTH;
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
.Instead of:
|
||||
-------------------------------------------------------------------------------
|
||||
int mode = 0744;
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Note that S_IREAD, S_IWRITE and S_IEXEC are obsolete, you should use S_IRUSR,
|
||||
S_IWUSR, S_IXUSR instead.
|
||||
|
||||
|
||||
Patches
|
||||
~~~~~~~
|
||||
@ -681,6 +695,3 @@ to compile or execute in one of these modes, then rework it.
|
||||
|
||||
|
||||
Happy hacking!
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -74,6 +74,3 @@ include::ecmascript.txt[]
|
||||
include::txt/import-features.conf.txt[]
|
||||
|
||||
endif::installation-webpage[]
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -359,7 +359,3 @@ everything is marked TODO!
|
||||
- Insert mode in text-input form-fields.
|
||||
|
||||
- Menu searching.
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -559,6 +559,3 @@ More ideas
|
||||
- More things are possible, I'm sure. If you have an idea that requires
|
||||
another hook or function, contact me (Peter Wang) and I'll see what I can
|
||||
do.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -124,6 +124,3 @@ audio/mpeg; xmms '%s'; test=test -n "$DISPLAY";
|
||||
application/pdf; xpdf '%s'; test=test -n "$DISPLAY";
|
||||
application/postscript; ps2ascii %s ; copiousoutput
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -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"
|
||||
|
@ -1,6 +1,6 @@
|
||||
.\" elinks.conf.5
|
||||
.\"
|
||||
.\" Generated by help2doc (Revision: 1.19) on 09 August 05 using output from ELinks version 0.11.CVS.
|
||||
.\" 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 \"09 August 05\"
|
||||
.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)
|
||||
@ -313,8 +313,8 @@ are always inserted into a selected text field.
|
||||
\f3document.browse.forms.editor\f2 <str>\f1 (default: "")
|
||||
Path to the executable that ELinks should launch when the user
|
||||
requests to edit a textarea with an external editor.
|
||||
.TP
|
||||
\f3variable\f2 $EDITOR.\f1 (variable $EDITOR. If $EDITOR is empty or not set, ELinks will then)
|
||||
If this is blank, ELinks will use the value of the environmental
|
||||
variable $EDITOR. If $EDITOR is empty or not set, ELinks will then
|
||||
default to "vi".
|
||||
.TP
|
||||
\f3document.browse.forms.show_formhist\f2 [0|1]\f1 (default: 0)
|
||||
@ -459,6 +459,9 @@ The TABINDEX attribute in HTML elements specifies the order
|
||||
in which links should receive focus when using the keyboard
|
||||
to navigating the document.
|
||||
.TP
|
||||
\f3document.browse.links.missing_fragment\f2 [0|1]\f1 (default: 1)
|
||||
Open a message box when document has no tag with given id.
|
||||
.TP
|
||||
\f3document.browse.links.number_keys_select_link\f2 <num>\f1 (default: 1)
|
||||
Number keys select links rather than specify command prefixes. This
|
||||
is a tristate:
|
||||
@ -675,11 +678,10 @@ Default directory color.
|
||||
See document.browse.links.color_dirs option.
|
||||
.TP
|
||||
\f3document.colors.increase_contrast\f2 [0|1]\f1 (default: 1)
|
||||
Setting this option to 0 will increase the contrast
|
||||
between the foreground and background colors to ensure
|
||||
readability. For example it disallows dark colors on a
|
||||
black background. Note, this is different from ensuring
|
||||
the contrast with the ensure_contrast option.
|
||||
Increase the contrast between the foreground and background colors
|
||||
to ensure readability. For example it disallows dark colors on a
|
||||
black background. Note, this is different from ensuring the contrast
|
||||
with the ensure_contrast option.
|
||||
.TP
|
||||
\f3document.colors.ensure_contrast\f2 [0|1]\f1 (default: 1)
|
||||
Makes sure that the back- and foreground color are never equal.
|
||||
@ -877,6 +879,7 @@ A rule for passing URI to an external command.
|
||||
The format is:
|
||||
%c in the string means the current URL
|
||||
%% in the string means '%'
|
||||
Do _not_ put single- or double-quotes around %c.
|
||||
.SS ECMAScript (ecmascript)
|
||||
ECMAScript options.
|
||||
.TP
|
||||
@ -886,6 +889,10 @@ Whether to run those scripts inside of documents.
|
||||
\f3ecmascript.error_reporting\f2 [0|1]\f1 (default: 0)
|
||||
Open a message box when a script reports an error.
|
||||
.TP
|
||||
\f3ecmascript.ignore_noscript\f2 [0|1]\f1 (default: 0)
|
||||
Whether to ignore content enclosed by the <noscript> tag
|
||||
when ECMAScript is enabled.
|
||||
.TP
|
||||
\f3ecmascript.max_exec_time\f2 <num>\f1 (default: 5)
|
||||
Maximum execution time in seconds for a script.
|
||||
.PD
|
||||
@ -1045,6 +1052,13 @@ What IP address to report to the tracker. If set to ""
|
||||
no IP address will be sent and the tracker will automatically
|
||||
determine an appropriate IP address.
|
||||
.TP
|
||||
\f3protocol.bittorrent.tracker.key\f2 <str>\f1 (default: "")
|
||||
An additional identification that is not shared with any users.
|
||||
It is intended to allow a client to prove their identity should
|
||||
their IP address change. It is an optional parameter, but some
|
||||
trackers require this parameter. If set to "" no user key will
|
||||
be sent to the tracker.
|
||||
.TP
|
||||
\f3protocol.bittorrent.tracker.numwant\f2 <num>\f1 (default: 50)
|
||||
The maximum number of peers to request from the tracker.
|
||||
Set to 0 to use the server default.
|
||||
@ -1337,7 +1351,7 @@ disable use of the default template rewrite rule.
|
||||
Enable dumb prefixes - simple URI abbreviations which can
|
||||
be written to the Goto URL dialog instead of actual URIs - i.e.
|
||||
if you write 'elinks' there, you are directed to
|
||||
http://elinks.or.cz/.
|
||||
http://elinks.cz/.
|
||||
.TP
|
||||
\f3protocol.rewrite.enable-smart\f2 [0|1]\f1 (default: 1)
|
||||
Enable smart prefixes - URI templates triggered by writing
|
||||
@ -2139,6 +2153,9 @@ on the command line or when requested by the goto-url-home action.
|
||||
Set to "" if the environment variable WWW_HOME should be used
|
||||
as homepage URI instead.
|
||||
.TP
|
||||
\f3ui.sessions.keep_session_active\f2 [0|1]\f1 (default: 0)
|
||||
Keep the session active even if the last terminal exits.
|
||||
.TP
|
||||
\f3ui.sessions.snapshot\f2 [0|1]\f1 (default: 0)
|
||||
Automatically save a snapshot of all tabs periodically.
|
||||
This will periodically bookmark the tabs of each terminal in a separate folder
|
||||
@ -2225,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 09 August 05 using output from ELinks version 0.11.CVS.
|
||||
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),
|
||||
|
@ -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"
|
||||
@ -258,6 +258,10 @@ Follow the current link, forcing reload of the target\&.
|
||||
link\-menu
|
||||
Open the link context menu\&.
|
||||
|
||||
.TP
|
||||
link\-form\-menu
|
||||
Open the form fields menu\&.
|
||||
|
||||
.TP
|
||||
lua\-console
|
||||
Open a Lua console\&.
|
||||
|
@ -84,6 +84,3 @@ did not quit your ELinks _completely_ --- if you run multiple ELinks
|
||||
instances under a single user on a single system, they "join" together and
|
||||
you must quit (or kill) them all to get rid of the damn thing. But that's a
|
||||
different story.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -178,6 +178,3 @@ Just enter set mime.type.class.name = "handler", replacing class with the
|
||||
class for the mime type, name with the specific name within that class, and
|
||||
handler with the name for the handler you want to assign to the MIME type.
|
||||
E.g. you may want to have set mime.type.image.jpeg = "image_viewer".
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -83,6 +83,3 @@ example, by running:
|
||||
|
||||
new tabs containing `slashdot.org`, `freshmeat.net` and a Google search of elinks
|
||||
will be opened.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -90,6 +90,3 @@ Whow ! Around 200kb :)
|
||||
- it disables fastfind feature, reducing performance, but also reducing a lot
|
||||
memory usage, and a bit the executable size.
|
||||
==============================================================================
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -110,6 +110,3 @@ bookmark therein the currently displayed document of each tab:
|
||||
- As a mean of crash protection, tabs can periodically be saved so that it is
|
||||
later possible to reconstruct opened tabs. In case of a clean shutdown
|
||||
periodically saved tabs will be removed.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -163,6 +163,3 @@ GNU Screen is VT100-compatible, so select 'VT 100 frames'. GNU Screen also
|
||||
supports colors just fine, so select '16 colors', or, if you are running Screen
|
||||
within a terminal emulator that supports 256 colors and you have compiled both
|
||||
Screen and ELinks to support it, choose '256 colors'.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
112
doc/tools/code2doc
Executable file
112
doc/tools/code2doc
Executable file
@ -0,0 +1,112 @@
|
||||
#!/usr/bin/perl -w
|
||||
use strict;
|
||||
use warnings;
|
||||
use diagnostics;
|
||||
use Getopt::Std;
|
||||
|
||||
my $HELP = "Usage: $0 [FILE]...
|
||||
Parses [FILE], outputing the result to stdout.";
|
||||
|
||||
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';
|
||||
}
|
@ -27,6 +27,7 @@ END_OF_USAGE
|
||||
# Option handling {{{1
|
||||
|
||||
command=
|
||||
filter=cat
|
||||
prev_option=
|
||||
|
||||
for option
|
||||
@ -41,10 +42,12 @@ do
|
||||
case "$option" in
|
||||
--cmdoptions)
|
||||
command="$elinks -long-help"
|
||||
filter="sed 0,/^Options:/d"
|
||||
backend="cmdoptions"
|
||||
;;
|
||||
--elinksconf)
|
||||
command="$elinks -config-help"
|
||||
filter="sed 0,/^Configuration/d"
|
||||
backend="elinksconf"
|
||||
;;
|
||||
-)
|
||||
@ -64,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"
|
||||
@ -168,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
|
||||
@ -210,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__
|
||||
@ -227,7 +230,6 @@ print_elinksconf_footer()
|
||||
echo "$dist_info"
|
||||
echo ".SH \"SEE ALSO\""
|
||||
echo ".BR elinks (1),"
|
||||
echo ".BR elinksmanual (1),"
|
||||
echo ".BR elinkskeys (5)"
|
||||
}
|
||||
|
||||
@ -285,7 +287,7 @@ use_log=
|
||||
|
||||
$print_header
|
||||
|
||||
$command | while read line
|
||||
$command | $filter | while read line
|
||||
do
|
||||
if test -n "$parse_description"
|
||||
then
|
||||
@ -323,7 +325,7 @@ do
|
||||
case "$line" in
|
||||
Features:*)
|
||||
;;
|
||||
[A-Z]*:*[a-z]*)
|
||||
[A-Z]*:" ("*[a-z]*)
|
||||
parse_description=1
|
||||
title="`echo $line | sed -e 's/\([A-Z]*\):.*/\1/'`"
|
||||
path="`echo $line | sed -e 's/.*: (\([a-z_].*\))/\1/'`"
|
||||
|
@ -87,6 +87,3 @@ advanced CVSweb and Debian package database URI prefixes implemented in the
|
||||
sample Lua hooks file. The one disadvantage to this is that you must have Lua
|
||||
scripting enabled in order to make use of it, and many users don't have Lua
|
||||
installed.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -11,6 +11,8 @@ MSGMERGE = msgmerge
|
||||
# xgettext)
|
||||
POTFILES_ABS_LIST = potfiles.list
|
||||
|
||||
POTFILES_REL = $(shell find $(top_srcdir)/src/ -name '*.[ch]' -o -name options.inc -o -name 'actions-*.inc' | sort)
|
||||
|
||||
quiet_cmd_gmsgfmt = ' [$(PO_COLOR)GMSGFMT$(END_COLOR)] $(RELPATH)$(@)'
|
||||
cmd_gmsgfmt = rm -f -- "$@" && $(GMSGFMT) --statistics -o "$@" -- "$<"
|
||||
|
||||
@ -45,7 +47,7 @@ all-local: $(CATALOGS)
|
||||
# This pulls in _all_ .c and .h files in the src directory. Even files that has
|
||||
# not been added to the git repo. Beware of junk entries!
|
||||
|
||||
$(srcdir)$(POTFILES_ABS_LIST):
|
||||
$(srcdir)$(POTFILES_ABS_LIST): $(POTFILES_REL)
|
||||
@( cd $(top_srcdir); \
|
||||
find src/ -type f -name '*.[ch]' -o -name options.inc -o -name 'actions-*.inc' | sort ) \
|
||||
> $(srcdir)$(POTFILES_ABS_LIST)
|
||||
@ -67,7 +69,7 @@ $(srcdir)$(PACKAGE).pot: $(srcdir)$(POTFILES_ABS_LIST)
|
||||
# either <lang> or <lang>.po when calling make. Example: make update-po PO=is
|
||||
|
||||
update-po: Makefile $(srcdir)$(PACKAGE).pot
|
||||
@test -n "$(srcdir)" && cd $(srcdir)
|
||||
@test -z "$(srcdir)" || cd $(srcdir)
|
||||
@$(foreach lang,$(basename $(if $(strip $(PO)),$(PO),$(GMOFILES))), \
|
||||
echo -n "$(lang): "; \
|
||||
if $(MSGMERGE) $(srcdir)$(lang).po $(srcdir)$(PACKAGE).pot -o $(lang).new.po; then \
|
||||
|
144
po/fr.po
144
po/fr.po
@ -1,13 +1,13 @@
|
||||
# French ELinks translation.
|
||||
# Fabrice Haberer-Proust <fric@gmx.li>
|
||||
# Laurent Monin <zas@norz.org>, 2001 - 2005
|
||||
# Laurent Monin <zas@norz.org>, 2001 - 2006
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: ELinks 0.11.GIT\n"
|
||||
"Project-Id-Version: ELinks 0.12.GIT\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2006-01-01 17:49+0100\n"
|
||||
"PO-Revision-Date: 2006-01-01 17:50+0100\n"
|
||||
"POT-Creation-Date: 2006-01-10 23:00+0100\n"
|
||||
"PO-Revision-Date: 2006-01-10 23:01+0100\n"
|
||||
"Last-Translator: Laurent Monin <zas@norz.org>\n"
|
||||
"Language-Team: French <zas@norz.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -15,21 +15,21 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n>1;\n"
|
||||
|
||||
#: src/bfu/hierbox.c:329
|
||||
#: src/bfu/hierbox.c:338
|
||||
msgid "Close"
|
||||
msgstr "Fermer"
|
||||
|
||||
#. | MSGBOX_SCROLLABLE
|
||||
#: src/bfu/hierbox.c:425 src/bfu/hierbox.c:434 src/dialogs/document.c:43
|
||||
#: src/bfu/hierbox.c:434 src/bfu/hierbox.c:443 src/dialogs/document.c:43
|
||||
#: src/dialogs/document.c:240
|
||||
msgid "Info"
|
||||
msgstr "Info"
|
||||
|
||||
#: src/bfu/hierbox.c:426
|
||||
#: src/bfu/hierbox.c:435
|
||||
msgid "Press space to expand this folder."
|
||||
msgstr "Pressez espace pour déployer le dossier."
|
||||
|
||||
#: src/bfu/hierbox.c:437 src/bfu/inpfield.c:254 src/bfu/msgbox.c:172
|
||||
#: src/bfu/hierbox.c:446 src/bfu/inpfield.c:254 src/bfu/msgbox.c:172
|
||||
#: src/bfu/msgbox.c:189 src/config/dialogs.c:57 src/config/dialogs.c:391
|
||||
#: src/cookies/dialogs.c:354 src/dialogs/edit.c:97 src/dialogs/info.c:133
|
||||
#: src/dialogs/options.c:210 src/dialogs/options.c:290 src/mime/dialogs.c:129
|
||||
@ -40,57 +40,57 @@ msgid "~OK"
|
||||
msgstr "~OK"
|
||||
|
||||
#. cant_delete_item
|
||||
#: src/bfu/hierbox.c:548
|
||||
#: src/bfu/hierbox.c:557
|
||||
#, c-format
|
||||
msgid "Sorry, but the item \"%s\" cannot be deleted."
|
||||
msgstr "Désolé, mais l'item \"%s\" ne peut être supprimé."
|
||||
|
||||
#. cant_delete_used_item
|
||||
#: src/bfu/hierbox.c:551
|
||||
#: src/bfu/hierbox.c:560
|
||||
#, c-format
|
||||
msgid "Sorry, but the item \"%s\" is being used by something else."
|
||||
msgstr "Désolé, mais l'item \"%s\" est actuellement utilisé ailleurs."
|
||||
|
||||
#. cant_delete_folder
|
||||
#: src/bfu/hierbox.c:554 src/bookmarks/dialogs.c:119
|
||||
#: src/bfu/hierbox.c:563 src/bookmarks/dialogs.c:119
|
||||
#, c-format
|
||||
msgid "Sorry, but the folder \"%s\" cannot be deleted."
|
||||
msgstr "Désolé, mais le dossier \"%s\" ne peut être supprimé."
|
||||
|
||||
#. cant_delete_used_folder
|
||||
#: src/bfu/hierbox.c:557 src/bookmarks/dialogs.c:121
|
||||
#: src/bfu/hierbox.c:566 src/bookmarks/dialogs.c:121
|
||||
#, c-format
|
||||
msgid "Sorry, but the folder \"%s\" is being used by something else."
|
||||
msgstr "Désolé, mais le dossier \"%s\" est actuellement utilisé ailleurs."
|
||||
|
||||
#. delete_marked_items_title
|
||||
#: src/bfu/hierbox.c:560
|
||||
#: src/bfu/hierbox.c:569
|
||||
msgid "Delete marked items"
|
||||
msgstr "Supprimer les items marqués"
|
||||
|
||||
#. delete_marked_items
|
||||
#: src/bfu/hierbox.c:563
|
||||
#: src/bfu/hierbox.c:572
|
||||
msgid "Delete marked items?"
|
||||
msgstr "Supprimer les items marqués ?"
|
||||
|
||||
#. delete_folder_title
|
||||
#: src/bfu/hierbox.c:566 src/bookmarks/dialogs.c:127
|
||||
#: src/bfu/hierbox.c:575 src/bookmarks/dialogs.c:127
|
||||
msgid "Delete folder"
|
||||
msgstr "Supprimer un dossier"
|
||||
|
||||
#. delete_folder
|
||||
#: src/bfu/hierbox.c:569
|
||||
#: src/bfu/hierbox.c:578
|
||||
#, c-format
|
||||
msgid "Delete the folder \"%s\" and its content?"
|
||||
msgstr "Supprimer le dossier \"%s\" et son contenu ?"
|
||||
|
||||
#. delete_item_title
|
||||
#: src/bfu/hierbox.c:572
|
||||
#: src/bfu/hierbox.c:581
|
||||
msgid "Delete item"
|
||||
msgstr "Supprimer un item"
|
||||
|
||||
#. delete_item
|
||||
#: src/bfu/hierbox.c:575
|
||||
#: src/bfu/hierbox.c:584
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Delete \"%s\"?\n"
|
||||
@ -102,45 +102,45 @@ msgstr ""
|
||||
"%s"
|
||||
|
||||
#. clear_all_items_title
|
||||
#: src/bfu/hierbox.c:578
|
||||
#: src/bfu/hierbox.c:587
|
||||
msgid "Clear all items"
|
||||
msgstr "Effacer tous les items"
|
||||
|
||||
#. clear_all_items
|
||||
#: src/bfu/hierbox.c:581
|
||||
#: src/bfu/hierbox.c:590
|
||||
msgid "Do you really want to remove all items?"
|
||||
msgstr "Êtes-vous sûr de vouloir effacer tous les items ?"
|
||||
|
||||
#: src/bfu/hierbox.c:638
|
||||
#: src/bfu/hierbox.c:647
|
||||
msgid "Delete error"
|
||||
msgstr "Erreur de suppression"
|
||||
|
||||
#: src/bfu/hierbox.c:741 src/bfu/hierbox.c:770 src/bfu/hierbox.c:783
|
||||
#: src/bfu/hierbox.c:848 src/config/dialogs.c:832 src/dialogs/menu.c:126
|
||||
#: src/bfu/hierbox.c:750 src/bfu/hierbox.c:779 src/bfu/hierbox.c:792
|
||||
#: src/bfu/hierbox.c:857 src/config/dialogs.c:832 src/dialogs/menu.c:126
|
||||
#: src/formhist/formhist.c:418 src/mime/dialogs.c:69 src/session/task.c:272
|
||||
#: src/terminal/tab.c:191 src/terminal/tab.c:227
|
||||
msgid "~Yes"
|
||||
msgstr "~Oui"
|
||||
|
||||
#: src/bfu/hierbox.c:742 src/bfu/hierbox.c:771 src/bfu/hierbox.c:784
|
||||
#: src/bfu/hierbox.c:849 src/config/dialogs.c:833 src/dialogs/menu.c:127
|
||||
#: src/bfu/hierbox.c:751 src/bfu/hierbox.c:780 src/bfu/hierbox.c:793
|
||||
#: src/bfu/hierbox.c:858 src/config/dialogs.c:833 src/dialogs/menu.c:127
|
||||
#: src/formhist/formhist.c:419 src/mime/dialogs.c:70 src/session/task.c:273
|
||||
#: src/terminal/tab.c:192 src/terminal/tab.c:228
|
||||
msgid "~No"
|
||||
msgstr "~Non"
|
||||
|
||||
#: src/bfu/hierbox.c:917 src/bfu/hierbox.c:948 src/viewer/text/search.c:1013
|
||||
#: src/bfu/hierbox.c:926 src/bfu/hierbox.c:957 src/viewer/text/search.c:1013
|
||||
#: src/viewer/text/search.c:1021 src/viewer/text/search.c:1037
|
||||
#: src/viewer/text/search.c:1612
|
||||
msgid "Search"
|
||||
msgstr "Chercher"
|
||||
|
||||
#: src/bfu/hierbox.c:919 src/viewer/text/search.c:1014
|
||||
#: src/bfu/hierbox.c:928 src/viewer/text/search.c:1014
|
||||
#, c-format
|
||||
msgid "Search string '%s' not found"
|
||||
msgstr "Chaîne recherchée '%s' introuvable"
|
||||
|
||||
#: src/bfu/hierbox.c:948 src/config/dialogs.c:168 src/config/dialogs.c:357
|
||||
#: src/bfu/hierbox.c:957 src/config/dialogs.c:168 src/config/dialogs.c:357
|
||||
#: src/config/dialogs.c:504 src/cookies/dialogs.c:34 src/cookies/dialogs.c:348
|
||||
#: src/dialogs/edit.c:91 src/dialogs/edit.c:93 src/scripting/lua/core.c:373
|
||||
#: src/scripting/lua/core.c:374 src/scripting/lua/core.c:454
|
||||
@ -173,7 +173,7 @@ msgstr "Cha
|
||||
#: src/dialogs/options.c:291 src/mime/dialogs.c:130
|
||||
#: src/protocol/auth/dialogs.c:111 src/protocol/bittorrent/dialogs.c:801
|
||||
#: src/scripting/lua/core.c:378 src/scripting/lua/core.c:458
|
||||
#: src/session/download.c:544 src/session/download.c:1121
|
||||
#: src/session/download.c:544 src/session/download.c:1143
|
||||
#: src/viewer/text/search.c:1594
|
||||
msgid "~Cancel"
|
||||
msgstr "~Annuler"
|
||||
@ -187,7 +187,7 @@ msgid "Digital clock in the status bar."
|
||||
msgstr "Horloge digitale dans la barre de status."
|
||||
|
||||
#: src/bfu/leds.c:77 src/bfu/leds.c:94 src/config/options.inc:1118
|
||||
#: src/config/options.inc:1125 src/ecmascript/ecmascript.c:40
|
||||
#: src/config/options.inc:1125 src/ecmascript/ecmascript.c:39
|
||||
#: src/globhist/globhist.c:63 src/mime/backend/mailcap.c:93
|
||||
#: src/mime/backend/mimetypes.c:52 src/network/ssl/ssl.c:80
|
||||
msgid "Enable"
|
||||
@ -1837,7 +1837,7 @@ msgstr "Impossible d'ajouter une option ici."
|
||||
|
||||
#: src/config/dialogs.c:531 src/config/dialogs.c:943 src/cookies/dialogs.c:424
|
||||
#: src/dialogs/options.c:212 src/formhist/dialogs.c:213
|
||||
#: src/protocol/bittorrent/dialogs.c:788 src/session/download.c:1105
|
||||
#: src/protocol/bittorrent/dialogs.c:788 src/session/download.c:1127
|
||||
msgid "Sa~ve"
|
||||
msgstr "Enre~gistrer"
|
||||
|
||||
@ -2305,14 +2305,12 @@ msgstr "Editeur externe"
|
||||
msgid ""
|
||||
"Path to the executable that ELinks should launch when the user\n"
|
||||
"requests to edit a textarea with an external editor.\n"
|
||||
"\n"
|
||||
"If this is blank, ELinks will use the value of the environmental\n"
|
||||
"variable $EDITOR. If $EDITOR is empty or not set, ELinks will then\n"
|
||||
"default to \"vi\"."
|
||||
msgstr ""
|
||||
"Chemin du programme qu'ELinks doit lancer quand l'utilisateur\n"
|
||||
"demande à éditer un champ de texte avec un éditeur externe.\n"
|
||||
"\n"
|
||||
"Si vide, ELinks utilisera la valeur de la variable d'environnement\n"
|
||||
"$EDITOR. Si $EDITOR est vide ou non configurée, ELinks utilisera\n"
|
||||
"\"vi\" par défaut."
|
||||
@ -3357,15 +3355,13 @@ msgid ""
|
||||
"The format is:\n"
|
||||
"%c in the string means the current URL\n"
|
||||
"%% in the string means '%'\n"
|
||||
"\n"
|
||||
"Do _not_ put single- or double-quotes around %c."
|
||||
msgstr ""
|
||||
"Règle de passage d'URI à une commande externe.\n"
|
||||
"Le format est:\n"
|
||||
"%c dans la chaîne signifie URL courante\n"
|
||||
"%% dans la chaîne signifie '%'\n"
|
||||
"\n"
|
||||
"Ne mettez pas de simples ou doubles quotes autour de %c."
|
||||
"Ne mettez pas de simples ou doubles guillemets autour de %c."
|
||||
|
||||
#. Keep options in alphabetical order.
|
||||
#: src/config/options.inc:740
|
||||
@ -4674,7 +4670,7 @@ msgid ""
|
||||
"\n"
|
||||
"(C) 1999 - 2002 Mikulas Patocka\n"
|
||||
"(C) 2001 - 2004 Petr Baudis\n"
|
||||
"(C) 2002 - 2005 Jonas Fonseca\n"
|
||||
"(C) 2002 - 2006 Jonas Fonseca\n"
|
||||
"and others\n"
|
||||
"\n"
|
||||
"This program is free software; you can redistribute it and/or modify it "
|
||||
@ -4685,7 +4681,7 @@ msgstr ""
|
||||
"\n"
|
||||
"(C) 1999 - 2002 Mikulas Patocka\n"
|
||||
"(C) 2001 - 2004 Petr Baudis\n"
|
||||
"(C) 2002 - 2005 Jonas Fonseca\n"
|
||||
"(C) 2002 - 2006 Jonas Fonseca\n"
|
||||
"et d'autres\n"
|
||||
"\n"
|
||||
"Ce programme est un logiciel libre; vous pouvez le redistribuer et/ou le "
|
||||
@ -5362,31 +5358,31 @@ msgstr ""
|
||||
"Laisser à \"\" pour utiliser le style initial du document."
|
||||
|
||||
#. name:
|
||||
#: src/ecmascript/ecmascript.c:36 src/ecmascript/ecmascript.c:201
|
||||
#: src/ecmascript/ecmascript.c:35 src/ecmascript/ecmascript.c:137
|
||||
msgid "ECMAScript"
|
||||
msgstr "ECMAScript"
|
||||
|
||||
#: src/ecmascript/ecmascript.c:38
|
||||
#: src/ecmascript/ecmascript.c:37
|
||||
msgid "ECMAScript options."
|
||||
msgstr "Options d'ECMAScript."
|
||||
|
||||
#: src/ecmascript/ecmascript.c:42
|
||||
#: src/ecmascript/ecmascript.c:41
|
||||
msgid "Whether to run those scripts inside of documents."
|
||||
msgstr "Exécuter ou non ces scripts présents dans les documents."
|
||||
|
||||
#: src/ecmascript/ecmascript.c:44
|
||||
#: src/ecmascript/ecmascript.c:43
|
||||
msgid "Script error reporting"
|
||||
msgstr "Rapport d'erreur de script"
|
||||
|
||||
#: src/ecmascript/ecmascript.c:46
|
||||
#: src/ecmascript/ecmascript.c:45
|
||||
msgid "Open a message box when a script reports an error."
|
||||
msgstr "Ouvrir une boîte de message quand un script produit une erreur."
|
||||
|
||||
#: src/ecmascript/ecmascript.c:48
|
||||
#: src/ecmascript/ecmascript.c:47
|
||||
msgid "Ignore <noscript> content"
|
||||
msgstr "Ignorer le contenu de <noscript>"
|
||||
|
||||
#: src/ecmascript/ecmascript.c:50
|
||||
#: src/ecmascript/ecmascript.c:49
|
||||
msgid ""
|
||||
"Whether to ignore content enclosed by the <noscript> tag\n"
|
||||
"when ECMAScript is enabled."
|
||||
@ -5394,38 +5390,29 @@ msgstr ""
|
||||
"Ignorer ou non le contenu du tag <noscript> quand ECMAScript\n"
|
||||
"est actif."
|
||||
|
||||
#: src/ecmascript/ecmascript.c:53
|
||||
#: src/ecmascript/ecmascript.c:52
|
||||
msgid "Maximum execution time"
|
||||
msgstr "Temps maximal d'exécution"
|
||||
|
||||
#: src/ecmascript/ecmascript.c:55
|
||||
#: src/ecmascript/ecmascript.c:54
|
||||
msgid "Maximum execution time in seconds for a script."
|
||||
msgstr "Temps maximal pour l'exécution d'un script, en secondes."
|
||||
|
||||
#: src/ecmascript/ecmascript.c:57
|
||||
#: src/ecmascript/ecmascript.c:56
|
||||
msgid "Pop-up window blocking"
|
||||
msgstr "Blocage des fenêtres Javascript (popups)"
|
||||
|
||||
#: src/ecmascript/ecmascript.c:59
|
||||
#: src/ecmascript/ecmascript.c:58
|
||||
msgid "Whether to disallow scripts to open new windows or tabs."
|
||||
msgstr ""
|
||||
"Interdire ou non l'ouverture de fenêtres ou d'onglets\n"
|
||||
"par les scripts."
|
||||
|
||||
#: src/ecmascript/spidermonkey.c:92
|
||||
#, c-format
|
||||
msgid "A script embedded in the current document raised the following%s%s%s%s"
|
||||
msgstr "Un script contenu dans le document courant a provoqué%s%s%s%s"
|
||||
|
||||
#: src/ecmascript/spidermonkey.c:108
|
||||
msgid "JavaScript Error"
|
||||
msgstr "Erreur Javascript"
|
||||
|
||||
#: src/ecmascript/spidermonkey.c:127
|
||||
#: src/ecmascript/ecmascript.c:126
|
||||
msgid "JavaScript Emergency"
|
||||
msgstr "Alerte JavaScript"
|
||||
|
||||
#: src/ecmascript/spidermonkey.c:129
|
||||
#: src/ecmascript/ecmascript.c:128
|
||||
#, c-format
|
||||
msgid ""
|
||||
"A script embedded in the current document was running\n"
|
||||
@ -5438,10 +5425,19 @@ msgstr ""
|
||||
"qu'il y a un bogue dans ce script et que cela aurait pû\n"
|
||||
"bloquer ELinks, l'exécution du script a donc été interrompue."
|
||||
|
||||
#: src/ecmascript/spidermonkey/window.c:286
|
||||
#: src/ecmascript/see/window.c:242 src/ecmascript/spidermonkey/window.c:286
|
||||
msgid "JavaScript Alert"
|
||||
msgstr "Alerte JavaScript"
|
||||
|
||||
#: src/ecmascript/spidermonkey.c:162
|
||||
#, c-format
|
||||
msgid "A script embedded in the current document raised the following%s%s%s%s"
|
||||
msgstr "Un script contenu dans le document courant a provoqué%s%s%s%s"
|
||||
|
||||
#: src/ecmascript/spidermonkey.c:178
|
||||
msgid "JavaScript Error"
|
||||
msgstr "Erreur Javascript"
|
||||
|
||||
#: src/formhist/dialogs.c:67
|
||||
msgid "Forms are never saved for this URL."
|
||||
msgstr "Les formulaires ne sont jamais sauvés pour cette URL."
|
||||
@ -5983,12 +5979,12 @@ msgstr ""
|
||||
"ici à la place de '.')."
|
||||
|
||||
#. name:
|
||||
#: src/mime/backend/default.c:227
|
||||
#: src/mime/backend/default.c:228
|
||||
msgid "Option system"
|
||||
msgstr "Système de configuration"
|
||||
|
||||
#. name:
|
||||
#: src/mime/backend/mailcap.c:89 src/mime/backend/mailcap.c:668
|
||||
#: src/mime/backend/mailcap.c:89 src/mime/backend/mailcap.c:674
|
||||
msgid "Mailcap"
|
||||
msgstr "Mailcap"
|
||||
|
||||
@ -7128,7 +7124,7 @@ msgstr "Que voulez-vous faire avec le fichier '%s' ?"
|
||||
msgid "Information about the torrent"
|
||||
msgstr "Informations sur le torrent"
|
||||
|
||||
#: src/protocol/bittorrent/dialogs.c:763 src/session/download.c:1017
|
||||
#: src/protocol/bittorrent/dialogs.c:763 src/session/download.c:1039
|
||||
msgid "What to do?"
|
||||
msgstr "Que faire ?"
|
||||
|
||||
@ -7136,11 +7132,11 @@ msgstr "Que faire ?"
|
||||
msgid "Down~load"
|
||||
msgstr "Té~lécharger"
|
||||
|
||||
#: src/protocol/bittorrent/dialogs.c:791 src/session/download.c:1111
|
||||
#: src/protocol/bittorrent/dialogs.c:791 src/session/download.c:1133
|
||||
msgid "~Display"
|
||||
msgstr "A~fficher"
|
||||
|
||||
#: src/protocol/bittorrent/dialogs.c:795 src/session/download.c:1115
|
||||
#: src/protocol/bittorrent/dialogs.c:795 src/session/download.c:1137
|
||||
msgid "Show ~header"
|
||||
msgstr "~Montrer les en-têtes"
|
||||
|
||||
@ -7840,11 +7836,11 @@ msgid "Scripting"
|
||||
msgstr "Scripting"
|
||||
|
||||
#: src/session/download.c:234 src/session/download.c:331
|
||||
#: src/session/download.c:498 src/session/download.c:590
|
||||
#: src/session/download.c:498 src/session/download.c:593
|
||||
msgid "Download error"
|
||||
msgstr "Erreur de téléchargement"
|
||||
|
||||
#: src/session/download.c:235 src/session/download.c:591
|
||||
#: src/session/download.c:235 src/session/download.c:594
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Could not create file '%s':\n"
|
||||
@ -7900,30 +7896,30 @@ msgstr "Ecraser le fichier ~original"
|
||||
msgid "~Resume download of the original file"
|
||||
msgstr "~Reprendre le téléchargement du fichier original"
|
||||
|
||||
#: src/session/download.c:1020
|
||||
#: src/session/download.c:1042
|
||||
msgid "Unknown type"
|
||||
msgstr "Type inconnu"
|
||||
|
||||
#: src/session/download.c:1037
|
||||
#: src/session/download.c:1059
|
||||
#, c-format
|
||||
msgid "What would you like to do with the file '%s' (type: %s%s%s)?"
|
||||
msgstr "Que voulez-vous faire avec le fichier '%s' (type: %s%s%s) ?"
|
||||
|
||||
#: src/session/download.c:1067
|
||||
#: src/session/download.c:1089
|
||||
#, no-c-format
|
||||
msgid "Program ('%' will be replaced by the filename)"
|
||||
msgstr "Programme ('%' sera remplacé par le nom du fichier)"
|
||||
|
||||
#: src/session/download.c:1071
|
||||
#: src/session/download.c:1093
|
||||
msgid "Block the terminal"
|
||||
msgstr "Bloquer le terminal"
|
||||
|
||||
#: src/session/download.c:1077
|
||||
#: src/session/download.c:1099
|
||||
#, c-format
|
||||
msgid "The file will be opened with the program '%s'."
|
||||
msgstr "Le fichier sera ouvert avec le programme '%s'."
|
||||
|
||||
#: src/session/download.c:1098
|
||||
#: src/session/download.c:1120
|
||||
msgid "~Open"
|
||||
msgstr "~Ouvrir"
|
||||
|
||||
|
@ -157,13 +157,15 @@ hierbox_ev_kbd(struct dialog_data *dlg_data)
|
||||
selected = box->sel;
|
||||
action_id = kbd_action(KEYMAP_MENU, ev, NULL);
|
||||
|
||||
if (action_id == ACT_MENU_SELECT) {
|
||||
switch (action_id) {
|
||||
case ACT_MENU_SELECT:
|
||||
if (!selected) return EVENT_PROCESSED;
|
||||
if (selected->type != BI_FOLDER)
|
||||
return EVENT_NOT_PROCESSED;
|
||||
selected->expanded = !selected->expanded;
|
||||
break;
|
||||
|
||||
} else if (action_id == ACT_MENU_UNEXPAND) {
|
||||
case ACT_MENU_UNEXPAND:
|
||||
/* Recursively unexpand all folders */
|
||||
if (!selected) return EVENT_PROCESSED;
|
||||
|
||||
@ -173,8 +175,9 @@ hierbox_ev_kbd(struct dialog_data *dlg_data)
|
||||
* whole parent folder will be closed. */
|
||||
if (list_empty(selected->child)
|
||||
|| !selected->expanded) {
|
||||
struct listbox_item *root = box->ops->get_root(selected);
|
||||
struct listbox_item *root;
|
||||
|
||||
root = box->ops->get_root(selected);
|
||||
if (root) {
|
||||
listbox_sel(widget_data, root);
|
||||
}
|
||||
@ -182,23 +185,25 @@ hierbox_ev_kbd(struct dialog_data *dlg_data)
|
||||
} else if (selected->type == BI_FOLDER) {
|
||||
recursively_set_expanded(selected, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
} else if (action_id == ACT_MENU_EXPAND) {
|
||||
case ACT_MENU_EXPAND:
|
||||
/* Recursively expand all folders */
|
||||
|
||||
if (!selected || selected->type != BI_FOLDER)
|
||||
return EVENT_PROCESSED;
|
||||
|
||||
recursively_set_expanded(selected, 1);
|
||||
break;
|
||||
|
||||
} else if (action_id == ACT_MENU_SEARCH) {
|
||||
case ACT_MENU_SEARCH:
|
||||
if (!box->ops->match)
|
||||
return EVENT_NOT_PROCESSED;
|
||||
|
||||
push_hierbox_search_button(dlg_data, NULL);
|
||||
return EVENT_PROCESSED;
|
||||
|
||||
} else {
|
||||
default:
|
||||
return EVENT_NOT_PROCESSED;
|
||||
|
||||
}
|
||||
@ -230,7 +235,9 @@ hierbox_ev_init(struct dialog_data *dlg_data)
|
||||
litem->visible = 1;
|
||||
}
|
||||
|
||||
return EVENT_NOT_PROCESSED; /* FIXME: is this correct ? --Zas */
|
||||
/* Return this so that the generic dialog code will run and initialise
|
||||
* the widgets and stuff. */
|
||||
return EVENT_NOT_PROCESSED;
|
||||
}
|
||||
|
||||
static widget_handler_status_T
|
||||
@ -254,7 +261,9 @@ hierbox_ev_abort(struct dialog_data *dlg_data)
|
||||
}
|
||||
}
|
||||
|
||||
return EVENT_NOT_PROCESSED; /* FIXME: is this correct ? --Zas */
|
||||
/* Return this so that the generic dialog code will run and initialise
|
||||
* the widgets and stuff. */
|
||||
return EVENT_NOT_PROCESSED;
|
||||
}
|
||||
|
||||
|
||||
@ -312,7 +321,7 @@ hierbox_browser(struct hierbox_browser *browser, struct session *ses)
|
||||
dlg->udata = ses;
|
||||
dlg->udata2 = browser;
|
||||
|
||||
add_dlg_listbox(dlg, 12, listbox_data);
|
||||
add_dlg_listbox(dlg, listbox_data);
|
||||
|
||||
for (button = 0; button < browser->buttons_size; button++) {
|
||||
struct hierbox_browser_button *but = &browser->buttons[button];
|
||||
|
@ -121,52 +121,9 @@ refresh_hotkeys(struct terminal *term, struct menu *menu)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Returns true if key (upcased) matches one of the hotkeys in menu */
|
||||
static int
|
||||
is_hotkey(struct menu_item *item, unsigned char key, struct terminal *term)
|
||||
{
|
||||
unsigned char *text;
|
||||
int key_pos;
|
||||
|
||||
assert(item);
|
||||
if_assert_failed return 0;
|
||||
|
||||
if (!mi_has_left_text(item)) return 0;
|
||||
|
||||
text = item->text;
|
||||
if (mi_text_translate(item)) text = _(text, term);
|
||||
if (!text || !*text) return 0;
|
||||
|
||||
key_pos = item->hotkey_pos;
|
||||
|
||||
#ifdef CONFIG_DEBUG
|
||||
if (key_pos < 0) key_pos = -key_pos;
|
||||
#endif
|
||||
|
||||
return (key_pos && (toupper(text[key_pos]) == key));
|
||||
}
|
||||
|
||||
/* Returns true if key (upcased) matches first letter of menu item left text. */
|
||||
static int
|
||||
is_not_so_hotkey(struct menu_item *item, unsigned char key, struct terminal *term)
|
||||
{
|
||||
unsigned char *text;
|
||||
|
||||
assert(item);
|
||||
if_assert_failed return 0;
|
||||
|
||||
if (!mi_has_left_text(item)) return 0;
|
||||
|
||||
text = item->text;
|
||||
if (mi_text_translate(item)) text = _(text, term);
|
||||
if (!text || !*text) return 0;
|
||||
|
||||
return (toupper(*text) == key);
|
||||
}
|
||||
|
||||
static int
|
||||
check_hotkeys_common(struct menu *menu, unsigned char hotkey, struct terminal *term,
|
||||
int (*func)(struct menu_item *, unsigned char, struct terminal *))
|
||||
int check_mode)
|
||||
{
|
||||
unsigned char key = toupper(hotkey);
|
||||
int i = menu->selected;
|
||||
@ -179,9 +136,37 @@ check_hotkeys_common(struct menu *menu, unsigned char hotkey, struct terminal *t
|
||||
|
||||
start = i;
|
||||
do {
|
||||
struct menu_item *item;
|
||||
unsigned char *text;
|
||||
int found;
|
||||
|
||||
if (++i == menu->size) i = 0;
|
||||
|
||||
if (func(&menu->items[i], key, term)) {
|
||||
item = &menu->items[i];
|
||||
|
||||
if (!mi_has_left_text(item)) continue;
|
||||
|
||||
text = item->text;
|
||||
if (mi_text_translate(item)) text = _(text, term);
|
||||
if (!text || !*text) continue;
|
||||
|
||||
if (check_mode == 0) {
|
||||
/* Does the key (upcased) matches one of the
|
||||
* hotkeys in menu ? */
|
||||
int key_pos = item->hotkey_pos;
|
||||
|
||||
#ifdef CONFIG_DEBUG
|
||||
if (key_pos < 0) key_pos = -key_pos;
|
||||
#endif
|
||||
found = (key_pos && (toupper(text[key_pos]) == key));
|
||||
|
||||
} else {
|
||||
/* Does the key (upcased) matches first letter
|
||||
* of menu item left text ? */
|
||||
found = (toupper(*text) == key);
|
||||
}
|
||||
|
||||
if (found) {
|
||||
menu->selected = i;
|
||||
return 1;
|
||||
}
|
||||
@ -195,7 +180,7 @@ check_hotkeys_common(struct menu *menu, unsigned char hotkey, struct terminal *t
|
||||
int
|
||||
check_hotkeys(struct menu *menu, unsigned char key, struct terminal *term)
|
||||
{
|
||||
return check_hotkeys_common(menu, key, term, is_hotkey);
|
||||
return check_hotkeys_common(menu, key, term, 0);
|
||||
}
|
||||
|
||||
/* Search if first letter of an entry in menu matches the key (caseless comp.).
|
||||
@ -205,5 +190,5 @@ check_hotkeys(struct menu *menu, unsigned char key, struct terminal *term)
|
||||
int
|
||||
check_not_so_hot_keys(struct menu *menu, unsigned char key, struct terminal *term)
|
||||
{
|
||||
return check_hotkeys_common(menu, key, term, is_not_so_hotkey);
|
||||
return check_hotkeys_common(menu, key, term, 1);
|
||||
}
|
||||
|
@ -321,7 +321,7 @@ save_input_history(struct input_history *history, unsigned char *filename)
|
||||
history_file = straconcat(elinks_home, filename, NULL);
|
||||
if (!history_file) return -1;
|
||||
|
||||
ssi = secure_open(history_file, 0177);
|
||||
ssi = secure_open(history_file);
|
||||
mem_free(history_file);
|
||||
if (!ssi) return -1;
|
||||
|
||||
|
@ -24,14 +24,12 @@
|
||||
#define VERTICAL_LISTBOX_MARGIN 3
|
||||
|
||||
void
|
||||
add_dlg_listbox(struct dialog *dlg, int height, void *box_data)
|
||||
add_dlg_listbox(struct dialog *dlg, void *box_data)
|
||||
{
|
||||
struct widget *widget = &dlg->widgets[dlg->number_of_widgets++];
|
||||
|
||||
widget->type = WIDGET_LISTBOX;
|
||||
widget->data = box_data;
|
||||
|
||||
widget->info.listbox.height = height;
|
||||
}
|
||||
|
||||
struct listbox_data *
|
||||
|
@ -11,12 +11,8 @@ struct terminal;
|
||||
struct uri;
|
||||
struct widget_data;
|
||||
|
||||
struct widget_info_listbox {
|
||||
int height;
|
||||
};
|
||||
|
||||
|
||||
void add_dlg_listbox(struct dialog *dlg, int height, void *box_data);
|
||||
void add_dlg_listbox(struct dialog *dlg, void *box_data);
|
||||
|
||||
enum listbox_match {
|
||||
LISTBOX_MATCH_OK,
|
||||
|
@ -42,7 +42,6 @@ struct widget {
|
||||
union {
|
||||
struct widget_info_checkbox checkbox;
|
||||
struct widget_info_field field;
|
||||
struct widget_info_listbox listbox;
|
||||
struct widget_info_button button;
|
||||
struct widget_info_text text;
|
||||
} info;
|
||||
|
@ -94,7 +94,7 @@ bookmarks_write(struct list_head *bookmarks_list)
|
||||
file_name = straconcat(elinks_home, file_name, NULL);
|
||||
if (!file_name) return;
|
||||
|
||||
ssi = secure_open(file_name, 0177);
|
||||
ssi = secure_open(file_name);
|
||||
mem_free(file_name);
|
||||
if (!ssi) return;
|
||||
|
||||
|
@ -805,7 +805,7 @@ write_config_file(unsigned char *prefix, unsigned char *name,
|
||||
config_file = straconcat(prefix, slash, name, NULL);
|
||||
if (!config_file) goto free_cfg_str;
|
||||
|
||||
ssi = secure_open(config_file, 0177);
|
||||
ssi = secure_open(config_file);
|
||||
if (ssi) {
|
||||
secure_fputs(ssi, cfg_str);
|
||||
ret = secure_close(ssi);
|
||||
|
@ -193,7 +193,7 @@ static struct option_info config_options_info[] = {
|
||||
INIT_OPT_STRING("document.browse.forms", N_("External editor"),
|
||||
"editor", 0, "",
|
||||
N_("Path to the executable that ELinks should launch when the user\n"
|
||||
"requests to edit a textarea with an external editor.\n\n"
|
||||
"requests to edit a textarea with an external editor.\n"
|
||||
"If this is blank, ELinks will use the value of the environmental\n"
|
||||
"variable $EDITOR. If $EDITOR is empty or not set, ELinks will then\n"
|
||||
"default to \"vi\".")),
|
||||
@ -730,7 +730,7 @@ static struct option_info config_options_info[] = {
|
||||
N_("A rule for passing URI to an external command.\n"
|
||||
"The format is:\n"
|
||||
"%c in the string means the current URL\n"
|
||||
"%% in the string means '%'\n\n"
|
||||
"%% in the string means '%'\n"
|
||||
"Do _not_ put single- or double-quotes around %c.")),
|
||||
|
||||
/* Keep options in alphabetical order. */
|
||||
|
@ -775,7 +775,7 @@ save_cookies(void) {
|
||||
cookfile = straconcat(elinks_home, COOKIES_FILENAME, NULL);
|
||||
if (!cookfile) return;
|
||||
|
||||
ssi = secure_open(cookfile, 0177); /* rw for user only */
|
||||
ssi = secure_open(cookfile);
|
||||
mem_free(cookfile);
|
||||
if (!ssi) return;
|
||||
|
||||
|
@ -143,7 +143,7 @@ menu_copying(struct terminal *term, void *xxx, void *xxxx)
|
||||
"\n"
|
||||
"(C) 1999 - 2002 Mikulas Patocka\n"
|
||||
"(C) 2001 - 2004 Petr Baudis\n"
|
||||
"(C) 2002 - 2005 Jonas Fonseca\n"
|
||||
"(C) 2002 - 2006 Jonas Fonseca\n"
|
||||
"and others\n"
|
||||
"\n"
|
||||
"This program is free software; you can redistribute it "
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "document/renderer.h"
|
||||
#include "dom/scanner.h"
|
||||
#include "dom/sgml/parser.h"
|
||||
#include "dom/sgml/rss/rss.h"
|
||||
#include "dom/node.h"
|
||||
#include "dom/stack.h"
|
||||
#include "intl/charsets.h"
|
||||
@ -54,6 +55,13 @@ struct dom_renderer {
|
||||
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])*)*"
|
||||
@ -61,11 +69,11 @@ struct dom_renderer {
|
||||
|
||||
static void
|
||||
init_template(struct screen_char *template, struct document_options *options,
|
||||
color_T background, color_T foreground)
|
||||
color_T background, color_T foreground, enum screen_char_attr attr)
|
||||
{
|
||||
struct color_pair colors = INIT_COLOR_PAIR(background, foreground);
|
||||
|
||||
template->attr = 0;
|
||||
template->attr = attr;
|
||||
template->data = ' ';
|
||||
set_term_color(template, &colors,
|
||||
options->color_flags, options->color_mode);
|
||||
@ -115,6 +123,7 @@ init_dom_renderer(struct dom_renderer *renderer, struct document *document,
|
||||
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);
|
||||
@ -157,9 +166,31 @@ init_dom_renderer(struct dom_renderer *renderer, struct document *document,
|
||||
|
||||
property = get_css_property(properties, CSS_PT_COLOR);
|
||||
if (property) foreground = property->value.color;
|
||||
|
||||
property = get_css_property(properties, CSS_PT_FONT_WEIGHT);
|
||||
if (property) {
|
||||
if (property->value.font_attribute.add & AT_BOLD)
|
||||
attr |= SCREEN_ATTR_BOLD;
|
||||
}
|
||||
|
||||
property = get_css_property(properties, CSS_PT_FONT_STYLE);
|
||||
if (property) {
|
||||
if (property->value.font_attribute.add & AT_UNDERLINE)
|
||||
attr |= SCREEN_ATTR_UNDERLINE;
|
||||
|
||||
if (property->value.font_attribute.add & AT_ITALIC)
|
||||
attr |= SCREEN_ATTR_ITALIC;
|
||||
|
||||
}
|
||||
|
||||
property = get_css_property(properties, CSS_PT_TEXT_DECORATION);
|
||||
if (property) {
|
||||
if (property->value.font_attribute.add & AT_UNDERLINE)
|
||||
attr |= SCREEN_ATTR_UNDERLINE;
|
||||
}
|
||||
}
|
||||
|
||||
init_template(template, &document->options, background, foreground);
|
||||
init_template(template, &document->options, background, foreground, attr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -311,7 +342,8 @@ render_dom_text(struct dom_renderer *renderer, struct screen_char *template,
|
||||
ALIGN_LINK(&(doc)->links, (doc)->nlinks, size)
|
||||
|
||||
static inline struct link *
|
||||
add_dom_link(struct dom_renderer *renderer, unsigned char *string, int length)
|
||||
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;
|
||||
@ -320,7 +352,6 @@ add_dom_link(struct dom_renderer *renderer, unsigned char *string, int length)
|
||||
struct link *link;
|
||||
struct point *point;
|
||||
struct screen_char template;
|
||||
unsigned char *uristring;
|
||||
color_T fgcolor;
|
||||
|
||||
if (!realloc_document_links(document, document->nlinks + 1))
|
||||
@ -332,7 +363,7 @@ add_dom_link(struct dom_renderer *renderer, unsigned char *string, int length)
|
||||
return NULL;
|
||||
|
||||
uristring = convert_string(renderer->convert_table,
|
||||
string, length, document->options.cp,
|
||||
uristring, urilength, document->options.cp,
|
||||
CSM_DEFAULT, NULL, NULL, NULL);
|
||||
if (!uristring) return NULL;
|
||||
|
||||
@ -361,7 +392,7 @@ add_dom_link(struct dom_renderer *renderer, unsigned char *string, int length)
|
||||
link->number = document->nlinks;
|
||||
|
||||
init_template(&template, &document->options,
|
||||
link->color.background, link->color.foreground);
|
||||
link->color.background, link->color.foreground, 0);
|
||||
|
||||
render_dom_text(renderer, &template, string, length);
|
||||
|
||||
@ -456,7 +487,7 @@ render_dom_node_enhanced_text(struct dom_renderer *renderer, struct dom_node *no
|
||||
string += offset;
|
||||
length -= offset;
|
||||
|
||||
add_dom_link(renderer, string, matchlen);
|
||||
add_dom_link(renderer, string, matchlen, string, matchlen);
|
||||
|
||||
length -= matchlen;
|
||||
string += matchlen;
|
||||
@ -578,7 +609,8 @@ render_dom_attribute_source(struct dom_stack *stack, struct dom_node *node, void
|
||||
break;
|
||||
}
|
||||
|
||||
add_dom_link(renderer, value, valuelen - skips);
|
||||
add_dom_link(renderer, value, valuelen - skips,
|
||||
value, valuelen - skips);
|
||||
|
||||
if (skips > 0) {
|
||||
value += valuelen - skips;
|
||||
@ -659,23 +691,298 @@ static struct dom_stack_context_info dom_source_renderer_context_info = {
|
||||
};
|
||||
|
||||
|
||||
/* DOM RSS Renderer */
|
||||
|
||||
static void
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dom_rss_push_content(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct dom_renderer *renderer = stack->current->data;
|
||||
unsigned char *string = node->string.string;
|
||||
int length = node->string.length;
|
||||
|
||||
assert(node && renderer && renderer->document);
|
||||
|
||||
if (!renderer->node)
|
||||
return;
|
||||
|
||||
if (node->type == DOM_NODE_ENTITY_REFERENCE) {
|
||||
string -= 1;
|
||||
length += 2;
|
||||
}
|
||||
|
||||
if (!is_dom_string_set(&renderer->text)) {
|
||||
init_dom_string(&renderer->text, string, length);
|
||||
} else {
|
||||
add_to_dom_string(&renderer->text, string, length);
|
||||
}
|
||||
}
|
||||
|
||||
static struct dom_string *
|
||||
get_rss_node_text(struct dom_node *node)
|
||||
{
|
||||
struct dom_node *child;
|
||||
int index;
|
||||
|
||||
if (!node->data.element.children)
|
||||
return NULL;
|
||||
|
||||
foreach_dom_node (node->data.element.children, child, index) {
|
||||
if (child->type == DOM_NODE_TEXT)
|
||||
return &child->string;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct dom_node *
|
||||
get_rss_child(struct dom_node *parent, enum rss_element_type type)
|
||||
{
|
||||
struct dom_node *node;
|
||||
int index;
|
||||
|
||||
if (!parent->data.element.children)
|
||||
return NULL;
|
||||
|
||||
foreach_dom_node (parent->data.element.children, node, index) {
|
||||
if (node->type == DOM_NODE_ELEMENT
|
||||
&& type == node->data.element.type)
|
||||
return node;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static struct dom_string *
|
||||
get_rss_text(struct dom_node *node, enum rss_element_type type)
|
||||
{
|
||||
node = get_rss_child(node, type);
|
||||
|
||||
return node ? get_rss_node_text(node) : 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;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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 */ dom_rss_push_content,
|
||||
/* DOM_NODE_CDATA_SECTION */ dom_rss_push_content,
|
||||
/* DOM_NODE_ENTITY_REFERENCE */ dom_rss_push_content,
|
||||
/* 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,
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* Shared multiplexor between renderers */
|
||||
void
|
||||
render_dom_document(struct cache_entry *cached, struct document *document,
|
||||
struct string *buffer)
|
||||
{
|
||||
unsigned char *head = empty_string_or_(cached->head);
|
||||
struct dom_node *root;
|
||||
struct dom_renderer renderer;
|
||||
struct conv_table *convert_table;
|
||||
struct sgml_parser *parser;
|
||||
enum sgml_document_type doctype;
|
||||
enum sgml_parser_type parser_type;
|
||||
unsigned char *string = struri(cached->uri);
|
||||
size_t length = strlen(string);
|
||||
struct dom_string uri = INIT_DOM_STRING(string, length);
|
||||
struct dom_string source = INIT_DOM_STRING(buffer->source, buffer->length);
|
||||
|
||||
assert(document->options.plain);
|
||||
enum sgml_parser_code code;
|
||||
|
||||
convert_table = get_convert_table(head, document->options.cp,
|
||||
document->options.assume_cp,
|
||||
@ -687,6 +994,11 @@ render_dom_document(struct cache_entry *cached, struct document *document,
|
||||
|
||||
document->bgcolor = document->options.default_bg;
|
||||
|
||||
if (document->options.plain)
|
||||
parser_type = SGML_PARSER_STREAM;
|
||||
else
|
||||
parser_type = SGML_PARSER_TREE;
|
||||
|
||||
/* FIXME: Refactor the doctype lookup. */
|
||||
if (!strcasecmp("application/rss+xml", cached->content_type)) {
|
||||
doctype = SGML_DOCTYPE_RSS;
|
||||
@ -707,14 +1019,24 @@ render_dom_document(struct cache_entry *cached, struct document *document,
|
||||
doctype = SGML_DOCTYPE_HTML;
|
||||
}
|
||||
|
||||
parser = init_sgml_parser(SGML_PARSER_STREAM, doctype, &uri);
|
||||
if (!parser) return;
|
||||
parser = init_sgml_parser(parser_type, doctype, &uri, 0);
|
||||
if (!parser) return;
|
||||
|
||||
if (document->options.plain) {
|
||||
add_dom_stack_context(&parser->stack, &renderer,
|
||||
&dom_source_renderer_context_info);
|
||||
|
||||
add_dom_stack_context(&parser->stack, &renderer,
|
||||
&dom_source_renderer_context_info);
|
||||
} else if (doctype == SGML_DOCTYPE_RSS) {
|
||||
add_dom_stack_context(&parser->stack, &renderer,
|
||||
&dom_rss_renderer_context_info);
|
||||
}
|
||||
|
||||
root = parse_sgml(parser, &source);
|
||||
if (root) {
|
||||
/* FIXME: When rendering this way we don't really care about the code.
|
||||
* However, it will be useful when we will be able to also
|
||||
* incrementally parse new data. This will require the parser to live
|
||||
* during the fetching of data. */
|
||||
code = parse_sgml(parser, &source, 1);
|
||||
if (parser->root) {
|
||||
assert(parser->stack.depth == 1);
|
||||
|
||||
get_dom_stack_top(&parser->stack)->immutable = 0;
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
@ -574,10 +574,10 @@ sp:
|
||||
goto se;
|
||||
}
|
||||
if (parse_element(r, html_context->eoff, &name, &namelen, NULL, &p)) goto sp;
|
||||
|
||||
|
||||
if (namelen < 6) goto se;
|
||||
if (name[0] == '/') name++, namelen--;
|
||||
|
||||
|
||||
if (strlcasecmp(name, namelen, "OPTION", 6)
|
||||
&& strlcasecmp(name, namelen, "SELECT", 6)
|
||||
&& strlcasecmp(name, namelen, "OPTGROUP", 8))
|
||||
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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); */
|
||||
|
@ -254,7 +254,13 @@ render_encoded_document(struct cache_entry *cached, struct document *document)
|
||||
render_plain_document(cached, document, &buffer);
|
||||
|
||||
} else {
|
||||
render_html_document(cached, document, &buffer);
|
||||
#ifdef CONFIG_DOM
|
||||
if (cached->content_type
|
||||
&& (!strlcasecmp("application/rss+xml", 19, cached->content_type, -1)))
|
||||
render_dom_document(cached, document, &buffer);
|
||||
else
|
||||
#endif
|
||||
render_html_document(cached, document, &buffer);
|
||||
}
|
||||
|
||||
if (encoding != ENCODING_NONE) {
|
||||
|
@ -6,7 +6,4 @@ OBJS = node.o select.o stack.o scanner.o
|
||||
|
||||
SUBDIRS-$(CONFIG_DEBUG) += test
|
||||
|
||||
test: all
|
||||
make test -C test
|
||||
|
||||
include $(top_srcdir)/Makefile.lib
|
||||
|
@ -360,7 +360,7 @@ done_dom_node(struct dom_node *node)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
done_dom_node_data(node);
|
||||
}
|
||||
|
||||
|
@ -154,7 +154,8 @@ init_dom_scanner_info(struct dom_scanner_info *scanner_info)
|
||||
|
||||
void
|
||||
init_dom_scanner(struct dom_scanner *scanner, struct dom_scanner_info *scanner_info,
|
||||
struct dom_string *string, int state, int count_lines)
|
||||
struct dom_string *string, int state, int count_lines, int complete,
|
||||
int check_complete, int detect_errors)
|
||||
{
|
||||
if (!scanner_info->initialized) {
|
||||
init_dom_scanner_info(scanner_info);
|
||||
@ -170,6 +171,9 @@ init_dom_scanner(struct dom_scanner *scanner, struct dom_scanner_info *scanner_i
|
||||
scanner->info = scanner_info;
|
||||
scanner->state = state;
|
||||
scanner->count_lines = !!count_lines;
|
||||
scanner->incomplete = !complete;
|
||||
scanner->check_complete = !!check_complete;
|
||||
scanner->detect_errors = !!detect_errors;
|
||||
scanner->lineno = scanner->count_lines;
|
||||
scanner->info->scan(scanner);
|
||||
}
|
||||
|
@ -7,27 +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 start of the token string and the token length */
|
||||
/** The line number; used for error tokens. */
|
||||
unsigned int lineno;
|
||||
|
||||
/** 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))
|
||||
@ -67,54 +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);
|
||||
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
|
||||
@ -123,19 +146,30 @@ struct dom_scanner {
|
||||
int line;
|
||||
#endif
|
||||
|
||||
unsigned int count_lines:1;
|
||||
unsigned int lineno;
|
||||
/* 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 */
|
||||
|
||||
/* Some state indicator only meaningful to the scanner internals */
|
||||
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 */
|
||||
|
||||
/** 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)
|
||||
|
||||
@ -149,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)
|
||||
{
|
||||
@ -173,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);
|
||||
|
@ -158,13 +158,13 @@ parse_dom_select_attribute(struct dom_select_node *sel, struct dom_scanner *scan
|
||||
|
||||
/* Parse:
|
||||
*
|
||||
* 0n+1 / 1
|
||||
* 2n+0 / 2n
|
||||
* 2n+1
|
||||
* -0n+2
|
||||
* -0n+1 / -1
|
||||
* 1n+0 / n+0 / n
|
||||
* 0n+0
|
||||
* 0n+1 / 1
|
||||
* 2n+0 / 2n
|
||||
* 2n+1
|
||||
* -0n+2
|
||||
* -0n+1 / -1
|
||||
* 1n+0 / n+0 / n
|
||||
* 0n+0
|
||||
*/
|
||||
|
||||
/* FIXME: Move somewhere else? dom/scanner.h? */
|
||||
@ -391,7 +391,7 @@ parse_dom_select(struct dom_select *select, struct dom_stack *stack,
|
||||
struct dom_scanner scanner;
|
||||
struct dom_select_node sel;
|
||||
|
||||
init_dom_scanner(&scanner, &dom_css_scanner_info, string, 0, 0);
|
||||
init_dom_scanner(&scanner, &dom_css_scanner_info, string, 0, 0, 1, 0, 0);
|
||||
|
||||
memset(&sel, 0, sizeof(sel));
|
||||
|
||||
@ -441,8 +441,8 @@ parse_dom_select(struct dom_select *select, struct dom_stack *stack,
|
||||
|
||||
sel.node.type = DOM_NODE_ATTRIBUTE;
|
||||
sel.match.attribute |= DOM_SELECT_ATTRIBUTE_SPACE_LIST;
|
||||
set_dom_string(&sel.node.string, "class", -1);
|
||||
copy_dom_string(&sel.node.data.attribute.value, &token->string);
|
||||
set_dom_string(&sel.node.string, "class", -1);
|
||||
copy_dom_string(&sel.node.data.attribute.value, &token->string);
|
||||
break;
|
||||
|
||||
case ':':
|
||||
@ -530,7 +530,7 @@ init_dom_select(enum dom_select_syntax syntax, struct dom_string *string)
|
||||
struct dom_stack stack;
|
||||
enum dom_exception_code code;
|
||||
|
||||
init_dom_stack(&stack, DOM_STACK_KEEP_NODES);
|
||||
init_dom_stack(&stack, DOM_STACK_FLAG_NONE);
|
||||
add_dom_stack_tracer(&stack, "init-select: ");
|
||||
|
||||
code = parse_dom_select(select, &stack, string);
|
||||
@ -1060,12 +1060,12 @@ select_dom_nodes(struct dom_select *select, struct dom_node *root)
|
||||
|
||||
select_data.select = select;;
|
||||
|
||||
init_dom_stack(&stack, DOM_STACK_KEEP_NODES);
|
||||
init_dom_stack(&stack, DOM_STACK_FLAG_NONE);
|
||||
add_dom_stack_context(&stack, &select_data,
|
||||
&dom_select_context_info);
|
||||
add_dom_stack_tracer(&stack, "select-tree: ");
|
||||
|
||||
init_dom_stack(&select_data.stack, DOM_STACK_KEEP_NODES);
|
||||
init_dom_stack(&select_data.stack, DOM_STACK_FLAG_NONE);
|
||||
add_dom_stack_context(&select_data.stack, &select_data,
|
||||
&dom_select_data_context_info);
|
||||
add_dom_stack_tracer(&select_data.stack, "select-match: ");
|
||||
|
@ -154,7 +154,18 @@ add_sgml_node(struct dom_stack *stack, enum dom_node_type type, struct dom_scann
|
||||
|
||||
/* SGML parser main handling: */
|
||||
|
||||
static inline void
|
||||
static enum sgml_parser_code
|
||||
call_sgml_error_function(struct dom_stack *stack, struct dom_scanner_token *token)
|
||||
{
|
||||
struct sgml_parser *parser = get_sgml_parser(stack);
|
||||
unsigned int line = get_sgml_parser_line_number(parser);
|
||||
|
||||
assert(parser->error_func);
|
||||
|
||||
return parser->error_func(parser, &token->string, line);
|
||||
}
|
||||
|
||||
static inline enum sgml_parser_code
|
||||
parse_sgml_attributes(struct dom_stack *stack, struct dom_scanner *scanner)
|
||||
{
|
||||
struct dom_scanner_token name;
|
||||
@ -179,22 +190,30 @@ parse_sgml_attributes(struct dom_stack *stack, struct dom_scanner *scanner)
|
||||
case SGML_TOKEN_ELEMENT_BEGIN:
|
||||
case SGML_TOKEN_ELEMENT_END:
|
||||
case SGML_TOKEN_ELEMENT_EMPTY_END:
|
||||
return;
|
||||
return SGML_PARSER_CODE_OK;
|
||||
|
||||
case SGML_TOKEN_IDENT:
|
||||
copy_struct(&name, token);
|
||||
|
||||
/* Skip the attribute name token */
|
||||
token = get_next_dom_scanner_token(scanner);
|
||||
|
||||
if (token && token->type == '=') {
|
||||
/* If the token is not a valid value token
|
||||
* ignore it. */
|
||||
token = get_next_dom_scanner_token(scanner);
|
||||
if (token && token->type == SGML_TOKEN_INCOMPLETE)
|
||||
return SGML_PARSER_CODE_INCOMPLETE;
|
||||
|
||||
if (token
|
||||
&& token->type != SGML_TOKEN_IDENT
|
||||
&& token->type != SGML_TOKEN_ATTRIBUTE
|
||||
&& token->type != SGML_TOKEN_STRING)
|
||||
token = NULL;
|
||||
|
||||
} else if (token && token->type == SGML_TOKEN_INCOMPLETE) {
|
||||
return SGML_PARSER_CODE_INCOMPLETE;
|
||||
|
||||
} else {
|
||||
token = NULL;
|
||||
}
|
||||
@ -206,14 +225,29 @@ parse_sgml_attributes(struct dom_stack *stack, struct dom_scanner *scanner)
|
||||
skip_dom_scanner_token(scanner);
|
||||
break;
|
||||
|
||||
case SGML_TOKEN_INCOMPLETE:
|
||||
return SGML_PARSER_CODE_INCOMPLETE;
|
||||
|
||||
case SGML_TOKEN_ERROR:
|
||||
{
|
||||
enum sgml_parser_code code;
|
||||
|
||||
code = call_sgml_error_function(stack, token);
|
||||
if (code != SGML_PARSER_CODE_OK)
|
||||
return code;
|
||||
|
||||
skip_dom_scanner_token(scanner);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
skip_dom_scanner_token(scanner);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return SGML_PARSER_CODE_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
static enum sgml_parser_code
|
||||
parse_sgml_plain(struct dom_stack *stack, struct dom_scanner *scanner)
|
||||
{
|
||||
struct dom_scanner_token target;
|
||||
@ -235,7 +269,12 @@ parse_sgml_plain(struct dom_stack *stack, struct dom_scanner *scanner)
|
||||
}
|
||||
|
||||
if (token->type == SGML_TOKEN_ELEMENT_BEGIN) {
|
||||
parse_sgml_attributes(stack, scanner);
|
||||
enum sgml_parser_code code;
|
||||
|
||||
code = parse_sgml_attributes(stack, scanner);
|
||||
if (code != SGML_PARSER_CODE_OK)
|
||||
return code;
|
||||
|
||||
} else {
|
||||
skip_dom_scanner_token(scanner);
|
||||
}
|
||||
@ -294,10 +333,16 @@ parse_sgml_plain(struct dom_stack *stack, struct dom_scanner *scanner)
|
||||
|
||||
/* Skip the target token */
|
||||
token = get_next_dom_scanner_token(scanner);
|
||||
if (!token) break;
|
||||
if (!token || token->type == SGML_TOKEN_INCOMPLETE)
|
||||
return SGML_PARSER_CODE_INCOMPLETE;
|
||||
|
||||
if (token->type == SGML_TOKEN_ERROR)
|
||||
break;
|
||||
|
||||
assert(token->type == SGML_TOKEN_PROCESS_DATA);
|
||||
/* Fall-through */
|
||||
|
||||
case SGML_TOKEN_PROCESS_DATA:
|
||||
if (add_sgml_proc_instruction(stack, &target, token)
|
||||
&& (target.type == SGML_TOKEN_PROCESS_XML
|
||||
|| target.type == SGML_TOKEN_PROCESS_XML_STYLESHEET)
|
||||
@ -305,12 +350,19 @@ parse_sgml_plain(struct dom_stack *stack, struct dom_scanner *scanner)
|
||||
/* Parse the <?xml data="attributes"?>. */
|
||||
struct dom_scanner attr_scanner;
|
||||
|
||||
/* The attribute souce is complete. */
|
||||
init_dom_scanner(&attr_scanner, &sgml_scanner_info,
|
||||
&token->string, SGML_STATE_ELEMENT,
|
||||
scanner->count_lines);
|
||||
scanner->count_lines, 1, 0, 0);
|
||||
|
||||
if (dom_scanner_has_tokens(&attr_scanner))
|
||||
if (dom_scanner_has_tokens(&attr_scanner)) {
|
||||
/* Ignore parser codes from this
|
||||
* enhanced parsing of attributes. It
|
||||
* is really just a simple way to try
|
||||
* and support xml and xml-stylesheet
|
||||
* instructions. */
|
||||
parse_sgml_attributes(stack, &attr_scanner);
|
||||
}
|
||||
}
|
||||
|
||||
pop_dom_node(stack);
|
||||
@ -322,6 +374,20 @@ parse_sgml_plain(struct dom_stack *stack, struct dom_scanner *scanner)
|
||||
skip_dom_scanner_token(scanner);
|
||||
break;
|
||||
|
||||
case SGML_TOKEN_INCOMPLETE:
|
||||
return SGML_PARSER_CODE_INCOMPLETE;
|
||||
|
||||
case SGML_TOKEN_ERROR:
|
||||
{
|
||||
enum sgml_parser_code code;
|
||||
|
||||
code = call_sgml_error_function(stack, token);
|
||||
if (code != SGML_PARSER_CODE_OK)
|
||||
return code;
|
||||
|
||||
skip_dom_scanner_token(scanner);
|
||||
break;
|
||||
}
|
||||
case SGML_TOKEN_SPACE:
|
||||
case SGML_TOKEN_TEXT:
|
||||
default:
|
||||
@ -329,30 +395,34 @@ parse_sgml_plain(struct dom_stack *stack, struct dom_scanner *scanner)
|
||||
skip_dom_scanner_token(scanner);
|
||||
}
|
||||
}
|
||||
|
||||
return SGML_PARSER_CODE_OK;
|
||||
}
|
||||
|
||||
struct dom_node *
|
||||
parse_sgml(struct sgml_parser *parser, struct dom_string *buffer)
|
||||
enum sgml_parser_code
|
||||
parse_sgml(struct sgml_parser *parser, struct dom_string *buffer, int complete)
|
||||
{
|
||||
struct sgml_parsing_state *parsing;
|
||||
enum sgml_parser_code code;
|
||||
|
||||
if (complete)
|
||||
parser->flags |= SGML_PARSER_COMPLETE;
|
||||
|
||||
if (!parser->root) {
|
||||
parser->root = add_sgml_document(&parser->stack, &parser->uri);
|
||||
if (!parser->root)
|
||||
return NULL;
|
||||
return SGML_PARSER_CODE_MEM_ALLOC;
|
||||
get_dom_stack_top(&parser->stack)->immutable = 1;
|
||||
}
|
||||
|
||||
parsing = init_sgml_parsing_state(parser, buffer);
|
||||
if (!parsing) return NULL;
|
||||
if (!parsing) return SGML_PARSER_CODE_MEM_ALLOC;
|
||||
|
||||
/* FIXME: Make parse_sgml_plain() return something (error code or if
|
||||
* can be guarenteed a root node). */
|
||||
parse_sgml_plain(&parser->stack, &parsing->scanner);
|
||||
code = parse_sgml_plain(&parser->stack, &parsing->scanner);
|
||||
|
||||
pop_dom_node(&parser->parsing);
|
||||
|
||||
return parser->root;
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
@ -368,11 +438,16 @@ sgml_parsing_push(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct sgml_parser *parser = get_sgml_parser(stack);
|
||||
struct sgml_parsing_state *parsing = data;
|
||||
int count_lines = !!(parser->flags & SGML_PARSER_COUNT_LINES);
|
||||
int complete = !!(parser->flags & SGML_PARSER_COMPLETE);
|
||||
int incremental = !!(parser->flags & SGML_PARSER_INCREMENTAL);
|
||||
int detect_errors = !!(parser->flags & SGML_PARSER_DETECT_ERRORS);
|
||||
|
||||
parsing->depth = parser->stack.depth;
|
||||
get_dom_stack_top(&parser->stack)->immutable = 1;
|
||||
init_dom_scanner(&parsing->scanner, &sgml_scanner_info, &node->string,
|
||||
SGML_STATE_TEXT, 0);
|
||||
SGML_STATE_TEXT, count_lines, complete, incremental,
|
||||
detect_errors);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -443,6 +518,30 @@ init_sgml_parsing_state(struct sgml_parser *parser, struct dom_string *buffer)
|
||||
return get_dom_stack_state_data(parser->parsing.contexts[0], state);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
get_sgml_parser_line_number(struct sgml_parser *parser)
|
||||
{
|
||||
struct dom_stack_state *state;
|
||||
struct sgml_parsing_state *pstate;
|
||||
|
||||
assert(parser->flags & SGML_PARSER_COUNT_LINES);
|
||||
|
||||
if (dom_stack_is_empty(&parser->parsing))
|
||||
return 0;
|
||||
|
||||
state = get_dom_stack_top(&parser->parsing);
|
||||
pstate = get_dom_stack_state_data(parser->parsing.contexts[0], state);
|
||||
|
||||
assert(pstate->scanner.count_lines && pstate->scanner.lineno);
|
||||
|
||||
if (pstate->scanner.current
|
||||
&& pstate->scanner.current < pstate->scanner.table + DOM_SCANNER_TOKENS
|
||||
&& pstate->scanner.current->type == SGML_TOKEN_ERROR)
|
||||
return pstate->scanner.current->lineno;
|
||||
|
||||
return pstate->scanner.lineno;
|
||||
}
|
||||
|
||||
|
||||
/* Parser creation and destruction: */
|
||||
|
||||
@ -486,10 +585,10 @@ static struct dom_stack_context_info sgml_parser_context_info = {
|
||||
|
||||
struct sgml_parser *
|
||||
init_sgml_parser(enum sgml_parser_type type, enum sgml_document_type doctype,
|
||||
struct dom_string *uri)
|
||||
struct dom_string *uri, enum sgml_parser_flag flags)
|
||||
{
|
||||
struct sgml_parser *parser;
|
||||
enum dom_stack_flag flags = 0;
|
||||
enum dom_stack_flag stack_flags = 0;
|
||||
|
||||
parser = mem_calloc(1, sizeof(*parser));
|
||||
if (!parser) return NULL;
|
||||
@ -499,19 +598,23 @@ init_sgml_parser(enum sgml_parser_type type, enum sgml_document_type doctype,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
parser->type = type;
|
||||
parser->info = get_sgml_info(doctype);
|
||||
if (flags & SGML_PARSER_DETECT_ERRORS)
|
||||
flags |= SGML_PARSER_COUNT_LINES;
|
||||
|
||||
if (type == SGML_PARSER_TREE)
|
||||
flags |= DOM_STACK_KEEP_NODES;
|
||||
parser->type = type;
|
||||
parser->flags = flags;
|
||||
parser->info = get_sgml_info(doctype);
|
||||
|
||||
init_dom_stack(&parser->stack, flags);
|
||||
if (type == SGML_PARSER_STREAM)
|
||||
stack_flags |= DOM_STACK_FLAG_FREE_NODES;
|
||||
|
||||
init_dom_stack(&parser->stack, stack_flags);
|
||||
/* FIXME: Some sgml backend specific callbacks? Handle HTML script tags,
|
||||
* and feed document.write() data back to the parser. */
|
||||
add_dom_stack_context(&parser->stack, parser, &sgml_parser_context_info);
|
||||
|
||||
/* Don't keep the 'fake' text nodes that holds the parsing data. */
|
||||
init_dom_stack(&parser->parsing, 0);
|
||||
init_dom_stack(&parser->parsing, DOM_STACK_FLAG_FREE_NODES);
|
||||
add_dom_stack_context(&parser->parsing, parser, &sgml_parsing_context_info);
|
||||
|
||||
return parser;
|
||||
|
@ -7,49 +7,150 @@
|
||||
#include "dom/sgml/sgml.h"
|
||||
#include "dom/scanner.h"
|
||||
|
||||
struct sgml_parser;
|
||||
struct string;
|
||||
struct uri;
|
||||
|
||||
/** 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 {
|
||||
/* The first one is a DOM tree builder. */
|
||||
SGML_PARSER_TREE,
|
||||
/* The second one will simply push nodes on the stack, not building a
|
||||
/**
|
||||
* 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
|
||||
* useful when you are not actually interested in the DOM tree, but can
|
||||
* do all processing in a stream-like manner, such as when highlighting
|
||||
* HTML code. */
|
||||
SGML_PARSER_STREAM,
|
||||
/**
|
||||
* 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
|
||||
* element child nodes, or purge various node such as text nodes that
|
||||
* only contain space characters. */
|
||||
SGML_PARSER_TREE,
|
||||
};
|
||||
|
||||
/** 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 state
|
||||
*
|
||||
* The SGML parser has only little state.
|
||||
*/
|
||||
struct sgml_parser_state {
|
||||
/* Info about the properties of the node contained by state.
|
||||
/**
|
||||
* 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;
|
||||
/* This is used by the DOM source renderer for highlighting the
|
||||
/**
|
||||
* This is used by the DOM source renderer for highlighting the
|
||||
* end-tag of an element. */
|
||||
struct dom_scanner_token end_token;
|
||||
};
|
||||
|
||||
struct sgml_parser {
|
||||
enum sgml_parser_type type; /* Stream or tree */
|
||||
|
||||
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_stack stack; /* A stack for tracking parsed nodes */
|
||||
struct dom_stack parsing; /* Used for tracking parsing states */
|
||||
/** (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 */
|
||||
/**
|
||||
* FIXME: For when we will add support for requiring stricter parsing
|
||||
* or even a validator. */
|
||||
SGML_PARSER_CODE_ERROR,
|
||||
};
|
||||
|
||||
/** SGML error callback
|
||||
*
|
||||
* Called by the SGML parser when a parsing error has occurred.
|
||||
*
|
||||
* If the return code is not ref:[SGML_PARSER_CODE_OK] the parsing will be
|
||||
* ended and that code will be returned. */
|
||||
typedef enum sgml_parser_code
|
||||
(*sgml_error_T)(struct sgml_parser *, struct dom_string *, unsigned int);
|
||||
|
||||
|
||||
/** The SGML parser
|
||||
*
|
||||
* This struct hold info used while parsing SGML data.
|
||||
*
|
||||
* 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 */
|
||||
|
||||
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 */
|
||||
|
||||
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 */
|
||||
};
|
||||
|
||||
|
||||
/** Initialise an SGML parser
|
||||
*
|
||||
* Initialise an SGML parser with the given properties.
|
||||
*
|
||||
* type:: Stream or tree; one-time or persistant.
|
||||
* doctype:: The document type, this affects what sub type nodes are given.
|
||||
* uri:: The URI of the document root.
|
||||
* flags:: Flags controlling the behaviour of the parser.
|
||||
*
|
||||
* Returns the created parser or NULL.
|
||||
*/
|
||||
struct sgml_parser *
|
||||
init_sgml_parser(enum sgml_parser_type type, enum sgml_document_type doctype,
|
||||
struct dom_string *uri);
|
||||
struct dom_string *uri, enum sgml_parser_flag flags);
|
||||
|
||||
/** Release an SGML parser
|
||||
*
|
||||
* Deallocates all resources, _expect_ the root node.
|
||||
*
|
||||
* parser:: The parser being released.
|
||||
*/
|
||||
void done_sgml_parser(struct sgml_parser *parser);
|
||||
|
||||
struct dom_node *parse_sgml(struct sgml_parser *parser, struct dom_string *buffer);
|
||||
/** Parse a chunk of SGML source
|
||||
*
|
||||
* Parses the given `buffer`. For incremental rendering the last buffer can be
|
||||
* signals through the `complete` parameter.
|
||||
*
|
||||
* parser:: A parser created with ref:[init_sgml_parser].
|
||||
* buffer:: A string containing the chunk to parse.
|
||||
* complete:: Whether this is the last chunk to parse.
|
||||
*
|
||||
* The returned code is ref:[SGML_PARSER_CODE_OK] if the buffer was
|
||||
* successfully parserd, else a code hinting at the error.
|
||||
*/
|
||||
enum sgml_parser_code
|
||||
parse_sgml(struct sgml_parser *parser, struct dom_string *buffer, int complete);
|
||||
|
||||
/** 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 recorded in the scanner tokens.
|
||||
*/
|
||||
unsigned int get_sgml_parser_line_number(struct sgml_parser *parser);
|
||||
|
||||
#endif
|
||||
|
@ -98,6 +98,104 @@ skip_sgml_space(struct dom_scanner *scanner, unsigned char **string)
|
||||
*string = pos;
|
||||
}
|
||||
|
||||
#define check_sgml_incomplete(scanner, string) \
|
||||
((scanner)->check_complete \
|
||||
&& (scanner)->incomplete \
|
||||
&& (string) == (scanner)->end)
|
||||
|
||||
static void
|
||||
set_sgml_incomplete(struct dom_scanner *scanner, struct dom_scanner_token *token)
|
||||
{
|
||||
size_t left = scanner->end - scanner->position;
|
||||
|
||||
assert(left > 0);
|
||||
|
||||
token->type = SGML_TOKEN_INCOMPLETE;
|
||||
set_dom_string(&token->string, scanner->position, left);
|
||||
|
||||
/* Stop the scanning. */
|
||||
scanner->position = scanner->end;
|
||||
}
|
||||
|
||||
|
||||
static inline int
|
||||
check_sgml_error(struct dom_scanner *scanner)
|
||||
{
|
||||
unsigned int found_error = scanner->found_error;
|
||||
|
||||
/* Toggle if we found an error previously. */
|
||||
scanner->found_error = 0;
|
||||
|
||||
return scanner->detect_errors && !found_error;
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
get_sgml_error_end(struct dom_scanner *scanner, enum sgml_token_type type,
|
||||
unsigned char *end)
|
||||
{
|
||||
switch (type) {
|
||||
case SGML_TOKEN_CDATA_SECTION:
|
||||
case SGML_TOKEN_NOTATION_ATTLIST:
|
||||
case SGML_TOKEN_NOTATION_DOCTYPE:
|
||||
case SGML_TOKEN_NOTATION_ELEMENT:
|
||||
if (scanner->position + 9 < end)
|
||||
end = scanner->position + 9;
|
||||
break;
|
||||
|
||||
case SGML_TOKEN_NOTATION_COMMENT:
|
||||
/* Just include the '<!--' part. */
|
||||
if (scanner->position + 4 < end)
|
||||
end = scanner->position + 4;
|
||||
break;
|
||||
|
||||
case SGML_TOKEN_NOTATION_ENTITY:
|
||||
if (scanner->position + 6 < end)
|
||||
end = scanner->position + 6;
|
||||
break;
|
||||
|
||||
case SGML_TOKEN_PROCESS_XML:
|
||||
if (scanner->position + 5 < end)
|
||||
end = scanner->position + 5;
|
||||
break;
|
||||
|
||||
case SGML_TOKEN_PROCESS_XML_STYLESHEET:
|
||||
if (scanner->position + 16 < end)
|
||||
end = scanner->position + 16;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
|
||||
static struct dom_scanner_token *
|
||||
set_sgml_error(struct dom_scanner *scanner, unsigned char *end)
|
||||
{
|
||||
struct dom_scanner_token *token = scanner->current;
|
||||
struct dom_scanner_token *next;
|
||||
|
||||
assert(!scanner->found_error);
|
||||
|
||||
if (scanner->current >= scanner->table + DOM_SCANNER_TOKENS) {
|
||||
scanner->found_error = 1;
|
||||
next = NULL;
|
||||
|
||||
} else {
|
||||
scanner->current++;
|
||||
next = scanner->current;
|
||||
copy_struct(next, token);
|
||||
}
|
||||
|
||||
token->type = SGML_TOKEN_ERROR;
|
||||
token->lineno = scanner->lineno;
|
||||
set_dom_string(&token->string, scanner->position, end - scanner->position);
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
|
||||
/* Text token scanning */
|
||||
|
||||
@ -119,6 +217,8 @@ scan_sgml_text_token(struct dom_scanner *scanner, struct dom_scanner_token *toke
|
||||
token->string.string = string++;
|
||||
|
||||
if (first_char == '&') {
|
||||
int complete = 0;
|
||||
|
||||
if (is_sgml_entity(*string)) {
|
||||
scan_sgml(scanner, string, SGML_CHAR_ENTITY);
|
||||
type = SGML_TOKEN_ENTITY;
|
||||
@ -128,13 +228,32 @@ scan_sgml_text_token(struct dom_scanner *scanner, struct dom_scanner_token *toke
|
||||
|
||||
foreach_sgml_cdata (scanner, string) {
|
||||
if (*string == ';') {
|
||||
complete = 1;
|
||||
string++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* We want the biggest possible text token. */
|
||||
if (!complete) {
|
||||
if (check_sgml_incomplete(scanner, string)) {
|
||||
set_sgml_incomplete(scanner, token);
|
||||
return;
|
||||
}
|
||||
|
||||
if (check_sgml_error(scanner)) {
|
||||
token = set_sgml_error(scanner, string);
|
||||
if (!token)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if (is_sgml_space(first_char)) {
|
||||
if (scanner->count_lines
|
||||
&& is_sgml_newline(first_char))
|
||||
scanner->lineno++;
|
||||
|
||||
skip_sgml_space(scanner, &string);
|
||||
type = string < scanner->end && is_sgml_text(*string)
|
||||
? SGML_TOKEN_TEXT : SGML_TOKEN_SPACE;
|
||||
@ -142,8 +261,21 @@ scan_sgml_text_token(struct dom_scanner *scanner, struct dom_scanner_token *toke
|
||||
type = SGML_TOKEN_TEXT;
|
||||
}
|
||||
|
||||
foreach_sgml_cdata (scanner, string) {
|
||||
/* m33p */;
|
||||
if (scanner->count_lines) {
|
||||
foreach_sgml_cdata (scanner, string) {
|
||||
if (is_sgml_newline(*string))
|
||||
scanner->lineno++;
|
||||
}
|
||||
} else {
|
||||
foreach_sgml_cdata (scanner, string) {
|
||||
/* m33p */;
|
||||
}
|
||||
}
|
||||
|
||||
/* We want the biggest possible text token. */
|
||||
if (check_sgml_incomplete(scanner, string)) {
|
||||
set_sgml_incomplete(scanner, token);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -226,7 +358,8 @@ skip_sgml(struct dom_scanner *scanner, unsigned char **string, unsigned char ski
|
||||
}
|
||||
|
||||
static inline int
|
||||
skip_sgml_comment(struct dom_scanner *scanner, unsigned char **string)
|
||||
skip_sgml_comment(struct dom_scanner *scanner, unsigned char **string,
|
||||
int *possibly_incomplete)
|
||||
{
|
||||
unsigned char *pos = *string;
|
||||
int length = 0;
|
||||
@ -238,6 +371,7 @@ skip_sgml_comment(struct dom_scanner *scanner, unsigned char **string)
|
||||
* preceeding '-'. */
|
||||
if (pos[-2] == '-' && pos[-1] == '-' && &pos[-2] >= *string) {
|
||||
length = pos - *string - 2;
|
||||
*possibly_incomplete = 0;
|
||||
pos++;
|
||||
break;
|
||||
}
|
||||
@ -245,6 +379,9 @@ skip_sgml_comment(struct dom_scanner *scanner, unsigned char **string)
|
||||
|
||||
if (!pos) {
|
||||
pos = scanner->end;
|
||||
/* The token is incomplete but set the length to handle tag
|
||||
* tag soup graciously. */
|
||||
*possibly_incomplete = 1;
|
||||
length = pos - *string;
|
||||
}
|
||||
|
||||
@ -253,7 +390,8 @@ skip_sgml_comment(struct dom_scanner *scanner, unsigned char **string)
|
||||
}
|
||||
|
||||
static inline int
|
||||
skip_sgml_cdata_section(struct dom_scanner *scanner, unsigned char **string)
|
||||
skip_sgml_cdata_section(struct dom_scanner *scanner, unsigned char **string,
|
||||
int *possibly_incomplete)
|
||||
{
|
||||
unsigned char *pos = *string;
|
||||
int length = 0;
|
||||
@ -263,6 +401,7 @@ skip_sgml_cdata_section(struct dom_scanner *scanner, unsigned char **string)
|
||||
* are supposed to have '<![CDATA[' before this is called. */
|
||||
if (pos[-2] == ']' && pos[-1] == ']') {
|
||||
length = pos - *string - 2;
|
||||
*possibly_incomplete = 0;
|
||||
pos++;
|
||||
break;
|
||||
}
|
||||
@ -270,6 +409,9 @@ skip_sgml_cdata_section(struct dom_scanner *scanner, unsigned char **string)
|
||||
|
||||
if (!pos) {
|
||||
pos = scanner->end;
|
||||
/* The token is incomplete but set the length to handle tag
|
||||
* soup graciously. */
|
||||
*possibly_incomplete = 1;
|
||||
length = pos - *string;
|
||||
}
|
||||
|
||||
@ -288,6 +430,7 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
||||
unsigned char first_char = *string;
|
||||
enum sgml_token_type type = SGML_TOKEN_GARBAGE;
|
||||
int real_length = -1;
|
||||
int possibly_incomplete = 1;
|
||||
|
||||
token->string.string = string++;
|
||||
|
||||
@ -302,6 +445,9 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
||||
type = SGML_TOKEN_TAG_END;
|
||||
scanner->state = SGML_STATE_TEXT;
|
||||
|
||||
/* We are creating a 'virtual' that has no source. */
|
||||
possibly_incomplete = 0;
|
||||
|
||||
} else if (is_sgml_ident(*string)) {
|
||||
token->string.string = string;
|
||||
scan_sgml(scanner, string, SGML_CHAR_IDENT);
|
||||
@ -312,7 +458,16 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
||||
if (*string == '>') {
|
||||
type = SGML_TOKEN_ELEMENT;
|
||||
string++;
|
||||
|
||||
/* We found the end. */
|
||||
possibly_incomplete = 0;
|
||||
|
||||
} else {
|
||||
/* Was any space skipped? */
|
||||
if (is_sgml_space(string[-1])) {
|
||||
/* We found the end. */
|
||||
possibly_incomplete = 0;
|
||||
}
|
||||
scanner->state = SGML_STATE_ELEMENT;
|
||||
type = SGML_TOKEN_ELEMENT_BEGIN;
|
||||
}
|
||||
@ -330,7 +485,8 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
||||
string += 2;
|
||||
type = SGML_TOKEN_NOTATION_COMMENT;
|
||||
token->string.string = string;
|
||||
real_length = skip_sgml_comment(scanner, &string);
|
||||
real_length = skip_sgml_comment(scanner, &string,
|
||||
&possibly_incomplete);
|
||||
assert(real_length >= 0);
|
||||
|
||||
} else if (string + 6 < scanner->end
|
||||
@ -339,13 +495,17 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
||||
string += 7;
|
||||
type = SGML_TOKEN_CDATA_SECTION;
|
||||
token->string.string = string;
|
||||
real_length = skip_sgml_cdata_section(scanner, &string);
|
||||
real_length = skip_sgml_cdata_section(scanner, &string,
|
||||
&possibly_incomplete);
|
||||
assert(real_length >= 0);
|
||||
|
||||
} else {
|
||||
skip_sgml_space(scanner, &string);
|
||||
scan_sgml(scanner, string, SGML_CHAR_IDENT);
|
||||
type = map_dom_scanner_string(scanner, ident, string, base);
|
||||
skip_sgml(scanner, &string, '>', 0);
|
||||
if (skip_sgml(scanner, &string, '>', 0)) {
|
||||
/* We found the end. */
|
||||
possibly_incomplete = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (*string == '?') {
|
||||
@ -361,6 +521,16 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
||||
|
||||
scanner->state = SGML_STATE_PROC_INST;
|
||||
|
||||
real_length = string - token->string.string;
|
||||
skip_sgml_space(scanner, &string);
|
||||
|
||||
/* Make '<?xml ' cause the right kind of error. */
|
||||
if (is_sgml_space(string[-1])
|
||||
&& string < scanner->end) {
|
||||
/* We found the end. */
|
||||
possibly_incomplete = 0;
|
||||
}
|
||||
|
||||
} else if (*string == '/') {
|
||||
string++;
|
||||
skip_sgml_space(scanner, &string);
|
||||
@ -371,12 +541,18 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
||||
real_length = string - token->string.string;
|
||||
|
||||
type = SGML_TOKEN_ELEMENT_END;
|
||||
skip_sgml(scanner, &string, '>', 1);
|
||||
if (skip_sgml(scanner, &string, '>', 1)) {
|
||||
/* We found the end. */
|
||||
possibly_incomplete = 0;
|
||||
}
|
||||
|
||||
} else if (*string == '>') {
|
||||
string++;
|
||||
real_length = 0;
|
||||
type = SGML_TOKEN_ELEMENT_END;
|
||||
|
||||
/* We found the end. */
|
||||
possibly_incomplete = 0;
|
||||
}
|
||||
|
||||
if (type != SGML_TOKEN_GARBAGE)
|
||||
@ -384,15 +560,28 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
||||
|
||||
} else {
|
||||
/* Alien < > stuff so ignore it */
|
||||
skip_sgml(scanner, &string, '>', 0);
|
||||
if (skip_sgml(scanner, &string, '>', 0)) {
|
||||
/* We found the end. */
|
||||
possibly_incomplete = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (first_char == '=') {
|
||||
type = '=';
|
||||
/* We found the end. */
|
||||
possibly_incomplete = 0;
|
||||
|
||||
} else if (first_char == '?' || first_char == '>') {
|
||||
if (first_char == '?') {
|
||||
skip_sgml(scanner, &string, '>', 0);
|
||||
if (skip_sgml(scanner, &string, '>', 0)) {
|
||||
/* We found the end. */
|
||||
possibly_incomplete = 0;
|
||||
}
|
||||
} else {
|
||||
assert(first_char == '>');
|
||||
|
||||
/* We found the end. */
|
||||
possibly_incomplete = 0;
|
||||
}
|
||||
|
||||
type = SGML_TOKEN_TAG_END;
|
||||
@ -400,17 +589,33 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
||||
scanner->state = SGML_STATE_TEXT;
|
||||
|
||||
} else if (first_char == '/') {
|
||||
/* We allow '/' inside elements and only consider it as an end
|
||||
* tag if immediately preceeds the '>' char. This is to allow
|
||||
*
|
||||
* '<form action=/ >' where '/' is part of a path and
|
||||
* '<form action=a />' where '/>' is truely a tag end
|
||||
*
|
||||
* For stricter parsing we should always require attribute
|
||||
* values to be quoted.
|
||||
*/
|
||||
if (*string == '>') {
|
||||
string++;
|
||||
real_length = 0;
|
||||
type = SGML_TOKEN_ELEMENT_EMPTY_END;
|
||||
assert(scanner->state == SGML_STATE_ELEMENT);
|
||||
scanner->state = SGML_STATE_TEXT;
|
||||
|
||||
/* We found the end. */
|
||||
possibly_incomplete = 0;
|
||||
|
||||
} else if (is_sgml_attribute(*string)) {
|
||||
scan_sgml_attribute(scanner, string);
|
||||
type = SGML_TOKEN_ATTRIBUTE;
|
||||
if (string[-1] == '/' && string[0] == '>')
|
||||
if (string[-1] == '/' && string[0] == '>') {
|
||||
string--;
|
||||
/* We found the end. */
|
||||
possibly_incomplete = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (isquote(first_char)) {
|
||||
@ -422,6 +627,10 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
||||
real_length = string_end - token->string.string;
|
||||
string = string_end + 1;
|
||||
type = SGML_TOKEN_STRING;
|
||||
|
||||
/* We found the end. */
|
||||
possibly_incomplete = 0;
|
||||
|
||||
} else if (is_sgml_attribute(*string)) {
|
||||
token->string.string++;
|
||||
scan_sgml_attribute(scanner, string);
|
||||
@ -437,8 +646,27 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
||||
if (is_sgml_attribute(*string)) {
|
||||
scan_sgml_attribute(scanner, string);
|
||||
type = SGML_TOKEN_ATTRIBUTE;
|
||||
if (string[-1] == '/' && string[0] == '>')
|
||||
if (string[-1] == '/' && string[0] == '>') {
|
||||
/* We found the end. */
|
||||
possibly_incomplete = 0;
|
||||
string--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (possibly_incomplete) {
|
||||
if (check_sgml_incomplete(scanner, string)) {
|
||||
set_sgml_incomplete(scanner, token);
|
||||
return;
|
||||
}
|
||||
|
||||
if (check_sgml_error(scanner) && string == scanner->end) {
|
||||
unsigned char *end;
|
||||
|
||||
end = get_sgml_error_end(scanner, type, string);
|
||||
token = set_sgml_error(scanner, end);
|
||||
if (!token)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -455,6 +683,8 @@ static inline void
|
||||
scan_sgml_proc_inst_token(struct dom_scanner *scanner, struct dom_scanner_token *token)
|
||||
{
|
||||
unsigned char *string = scanner->position;
|
||||
/* The length can be empty for '<??>'. */
|
||||
size_t length = -1;
|
||||
|
||||
token->string.string = string;
|
||||
|
||||
@ -464,14 +694,30 @@ scan_sgml_proc_inst_token(struct dom_scanner *scanner, struct dom_scanner_token
|
||||
for ( ; (string = skip_sgml_chars(scanner, string, '>')); string++) {
|
||||
if (string[-1] == '?') {
|
||||
string++;
|
||||
length = string - token->string.string - 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!string) string = scanner->end;
|
||||
if (!string) {
|
||||
/* Makes the next succeed when checking for incompletion, and
|
||||
* puts the rest of the text within the token. */
|
||||
string = scanner->end;
|
||||
|
||||
if (check_sgml_incomplete(scanner, string)) {
|
||||
set_sgml_incomplete(scanner, token);
|
||||
return;
|
||||
}
|
||||
|
||||
if (check_sgml_error(scanner)) {
|
||||
token = set_sgml_error(scanner, string);
|
||||
if (!token)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
token->type = SGML_TOKEN_PROCESS_DATA;
|
||||
token->string.length = string - token->string.string - 2;
|
||||
token->string.length = length >= 0 ? length : string - token->string.string;
|
||||
token->precedence = get_sgml_precedence(token->type);
|
||||
scanner->position = string;
|
||||
scanner->state = SGML_STATE_TEXT;
|
||||
@ -484,36 +730,34 @@ static struct dom_scanner_token *
|
||||
scan_sgml_tokens(struct dom_scanner *scanner)
|
||||
{
|
||||
struct dom_scanner_token *table_end = scanner->table + DOM_SCANNER_TOKENS;
|
||||
struct dom_scanner_token *current;
|
||||
|
||||
if (!begin_dom_token_scanning(scanner))
|
||||
return get_dom_scanner_token(scanner);
|
||||
|
||||
/* Scan tokens until we fill the table */
|
||||
for (current = scanner->table + scanner->tokens;
|
||||
current < table_end && scanner->position < scanner->end;
|
||||
current++) {
|
||||
for (scanner->current = scanner->table + scanner->tokens;
|
||||
scanner->current < table_end && scanner->position < scanner->end;
|
||||
scanner->current++) {
|
||||
if (scanner->state == SGML_STATE_ELEMENT
|
||||
|| (*scanner->position == '<'
|
||||
&& scanner->state != SGML_STATE_PROC_INST)) {
|
||||
skip_sgml_space(scanner, &scanner->position);
|
||||
if (scanner->position >= scanner->end) break;
|
||||
|
||||
scan_sgml_element_token(scanner, current);
|
||||
scan_sgml_element_token(scanner, scanner->current);
|
||||
|
||||
/* Shall we scratch this token? */
|
||||
if (current->type == SGML_TOKEN_SKIP) {
|
||||
current--;
|
||||
if (scanner->current->type == SGML_TOKEN_SKIP) {
|
||||
scanner->current--;
|
||||
}
|
||||
|
||||
} else if (scanner->state == SGML_STATE_TEXT) {
|
||||
scan_sgml_text_token(scanner, current);
|
||||
scan_sgml_text_token(scanner, scanner->current);
|
||||
|
||||
} else {
|
||||
skip_sgml_space(scanner, &scanner->position);
|
||||
scan_sgml_proc_inst_token(scanner, current);
|
||||
scan_sgml_proc_inst_token(scanner, scanner->current);
|
||||
}
|
||||
}
|
||||
|
||||
return end_dom_token_scanning(scanner, current);
|
||||
return end_dom_token_scanning(scanner, scanner->current);
|
||||
}
|
||||
|
@ -48,6 +48,14 @@ enum sgml_token_type {
|
||||
/* A special token for unrecognized strings */
|
||||
SGML_TOKEN_GARBAGE,
|
||||
|
||||
/* A special token for marking that it is assummed that the token is
|
||||
* not complete. Only meaningful if scanner->complete is incomplete. */
|
||||
SGML_TOKEN_INCOMPLETE,
|
||||
|
||||
/* A special token for reporting that an error in the markup was found.
|
||||
* Only in effect when error checking has been requested. */
|
||||
SGML_TOKEN_ERROR,
|
||||
|
||||
/* Token type used internally when scanning to signal that the token
|
||||
* should not be recorded in the scanners token table. */
|
||||
SGML_TOKEN_SKIP,
|
||||
|
@ -213,7 +213,7 @@ pop_dom_node(struct dom_stack *stack)
|
||||
|
||||
call_dom_stack_callbacks(stack, state, DOM_STACK_POP);
|
||||
|
||||
if (!(stack->flags & DOM_STACK_KEEP_NODES))
|
||||
if (stack->flags & DOM_STACK_FLAG_FREE_NODES)
|
||||
done_dom_node(state->node);
|
||||
|
||||
stack->depth--;
|
||||
|
197
src/dom/stack.h
197
src/dom/stack.h
@ -7,73 +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 {
|
||||
/* Keep nodes when popping them or call done_dom_node() on them. */
|
||||
DOM_STACK_KEEP_NODES = 1,
|
||||
/** No flag needed. */
|
||||
DOM_STACK_FLAG_NONE = 0,
|
||||
|
||||
/** 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)
|
||||
{
|
||||
@ -82,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)
|
||||
@ -97,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)]))
|
||||
@ -123,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
|
||||
|
@ -39,21 +39,28 @@ dom_string_ncasecmp(struct dom_string *string1, struct dom_string *string2, size
|
||||
set_dom_string(string1, (string2)->string, (string2)->length)
|
||||
|
||||
static inline struct dom_string *
|
||||
init_dom_string(struct dom_string *string, unsigned char *str, size_t len)
|
||||
add_to_dom_string(struct dom_string *string, unsigned char *str, size_t len)
|
||||
{
|
||||
string->string = mem_alloc(len + 1);
|
||||
if (!string->string)
|
||||
unsigned char *newstring;
|
||||
|
||||
newstring = mem_realloc(string->string, string->length + len + 1);
|
||||
if (!newstring)
|
||||
return NULL;
|
||||
|
||||
memcpy(string->string, str, len);
|
||||
string->string[len] = 0;
|
||||
string->length = len;
|
||||
string->string = newstring;
|
||||
memcpy(string->string + string->length, str, len);
|
||||
string->length += len;
|
||||
string->string[string->length] = 0;
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
#define init_dom_string(string, str, len) add_to_dom_string(string, str, len)
|
||||
|
||||
#define is_dom_string_set(str) ((str)->string && (str)->length)
|
||||
|
||||
#define done_dom_string(str) mem_free((str)->string);
|
||||
#define done_dom_string(str) \
|
||||
do { mem_free_set(&(str)->string, NULL); (str)->length = 0; } while (0)
|
||||
|
||||
#define isquote(c) ((c) == '"' || (c) == '\'')
|
||||
|
||||
|
@ -11,33 +11,7 @@ TESTDEPS = \
|
||||
$(top_builddir)/src/util/error.o \
|
||||
$(top_builddir)/src/osdep/stub.o \
|
||||
$(top_builddir)/src/util/hash.o \
|
||||
$(top_builddir)/src/util/memdebug.o \
|
||||
$(top_builddir)/src/util/string.o \
|
||||
$(top_builddir)/src/util/memory.o
|
||||
|
||||
$(TEST_PROGS): $(TESTDEPS) $$@.o
|
||||
$(call cmd,link)
|
||||
|
||||
TESTS = $(wildcard test-*)
|
||||
|
||||
$(TESTS): $(TEST_PROGS)
|
||||
@echo "*** $@ ***"; $(call shellquote,$(SHELL)) $@ $(TEST_OPTS)
|
||||
|
||||
test: $(TESTS)
|
||||
|
||||
clean-local:
|
||||
@rm -fr trash
|
||||
|
||||
CLEAN += $(TEST_PROGS) $(patsubst %,%.o,$(TEST_PROGS))
|
||||
|
||||
.PHONY: $(TESTS)
|
||||
.NOPARALLEL:
|
||||
|
||||
include $(top_srcdir)/Makefile.lib
|
||||
|
||||
# Shell quote;
|
||||
# Result of this needs to be placed inside ''
|
||||
# XXX: Placed here because Vim cannot highlight things right afterwards
|
||||
shq = $(subst ','\'',$(1))
|
||||
# This has surrounding ''
|
||||
shellquote = '$(call shq,$(1))'
|
||||
|
@ -1,7 +1,7 @@
|
||||
Core GIT Tests
|
||||
==============
|
||||
ELinks testing infrastructure
|
||||
=============================
|
||||
|
||||
This directory holdstest scripts for the DOM implementation. The first part of
|
||||
This directory holds test scripts for the DOM implementation. The first part of
|
||||
this short document describes how to run the tests and read their output.
|
||||
|
||||
When fixing the tools or adding enhancements, you are strongly encouraged to
|
||||
@ -27,7 +27,7 @@ The easiest way to run tests is to say "make test". This runs all the tests.
|
||||
|
||||
Or you can run each test individually from command line, like this:
|
||||
|
||||
$ sh ./test-sgml-parser-basic
|
||||
$ TEST_LIB=${path_to_top_srcdir}/test/libtest.sh sh ./test-sgml-parser-basic
|
||||
* ok 1: parse a small document.
|
||||
...
|
||||
* ok 23: parse a CDATA section.
|
||||
@ -49,6 +49,10 @@ command line argument to the test.
|
||||
This causes the test to immediately exit upon the first
|
||||
failed test.
|
||||
|
||||
Note, these options can be passed indirectly to all tests when running test using
|
||||
make by setting TEST_OPTS, like this:
|
||||
|
||||
make test TEST_OPTS=--immediate
|
||||
|
||||
Naming Tests
|
||||
------------
|
||||
@ -91,20 +95,23 @@ The test script is written as a shell script. It should start with the standard
|
||||
|
||||
|
||||
Source 'libtest'
|
||||
--------------------
|
||||
----------------
|
||||
|
||||
After assigning test_description, the test script should source test-lib.sh
|
||||
like this:
|
||||
After assigning test_description, the test script should source the shell test
|
||||
library like this:
|
||||
|
||||
. ./libtest
|
||||
. "$TEST_LIB"
|
||||
|
||||
This assumes that the TEST_LIB environment variable has been set and is needed
|
||||
for test to run from out of tree builds.
|
||||
|
||||
This test harness library does the following things:
|
||||
|
||||
- If the script is invoked with command line argument --help (or -h), it shows
|
||||
the test_description and exits.
|
||||
|
||||
- Creates an empty test directory. This directory is 'test/trash' if you must
|
||||
know, but I do not think you care.
|
||||
- Creates an empty test directory. This directory is 'trash' if you must know,
|
||||
but I do not think you care.
|
||||
|
||||
- Defines standard test helper functions for your scripts to use. These
|
||||
functions are designed to make all scripts behave consistently when command
|
||||
|
@ -16,6 +16,24 @@
|
||||
#include "dom/stack.h"
|
||||
|
||||
|
||||
unsigned int number_of_lines = 0;
|
||||
|
||||
static int
|
||||
update_number_of_lines(struct dom_stack *stack)
|
||||
{
|
||||
struct sgml_parser *parser = stack->contexts[0]->data;
|
||||
int lines;
|
||||
|
||||
if (!(parser->flags & SGML_PARSER_COUNT_LINES))
|
||||
return 0;
|
||||
|
||||
lines = get_sgml_parser_line_number(parser);
|
||||
if (number_of_lines < lines)
|
||||
number_of_lines = lines;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Print the string in a compressed form: a single line with newlines etc.
|
||||
* replaced with "\\n" sequence. */
|
||||
static void
|
||||
@ -72,14 +90,25 @@ static unsigned char indent_string[] =
|
||||
#define get_indent_offset(stack) \
|
||||
(((stack)->depth < sizeof(indent_string)/2 ? (stack)->depth * 2 : sizeof(indent_string)) - 2)
|
||||
|
||||
|
||||
static void
|
||||
print_indent(struct dom_stack *stack)
|
||||
{
|
||||
printf("%.*s", get_indent_offset(stack), indent_string);
|
||||
}
|
||||
|
||||
static void
|
||||
sgml_parser_test_tree(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct dom_string *value = &node->string;
|
||||
struct dom_string *name = get_dom_node_name(node);
|
||||
|
||||
printf("%.*s%.*s: %.*s\n",
|
||||
get_indent_offset(stack), indent_string,
|
||||
/* Always print the URI for identification. */
|
||||
if (update_number_of_lines(stack))
|
||||
return;
|
||||
|
||||
print_indent(stack);
|
||||
printf("%.*s: %.*s\n",
|
||||
name->length, name->string,
|
||||
value->length, value->string);
|
||||
}
|
||||
@ -92,12 +121,16 @@ sgml_parser_test_id_leaf(struct dom_stack *stack, struct dom_node *node, void *d
|
||||
|
||||
assert(node);
|
||||
|
||||
if (update_number_of_lines(stack))
|
||||
return;
|
||||
|
||||
name = get_dom_node_name(node);
|
||||
id = get_dom_node_type_name(node->type);
|
||||
|
||||
printf("%.*s%.*s: %.*s -> ",
|
||||
get_indent_offset(stack), indent_string,
|
||||
id->length, id->string, name->length, name->string);
|
||||
print_indent(stack);
|
||||
printf("%.*s: %.*s -> ",
|
||||
id->length, id->string,
|
||||
name->length, name->string);
|
||||
print_dom_node_value(node);
|
||||
printf("\n");
|
||||
}
|
||||
@ -109,10 +142,13 @@ sgml_parser_test_leaf(struct dom_stack *stack, struct dom_node *node, void *data
|
||||
|
||||
assert(node);
|
||||
|
||||
if (update_number_of_lines(stack))
|
||||
return;
|
||||
|
||||
name = get_dom_node_name(node);
|
||||
|
||||
printf("%.*s%.*s: ",
|
||||
get_indent_offset(stack), indent_string,
|
||||
print_indent(stack);
|
||||
printf("%.*s: ",
|
||||
name->length, name->string);
|
||||
print_dom_node_value(node);
|
||||
printf("\n");
|
||||
@ -126,14 +162,28 @@ sgml_parser_test_branch(struct dom_stack *stack, struct dom_node *node, void *da
|
||||
|
||||
assert(node);
|
||||
|
||||
if (update_number_of_lines(stack))
|
||||
return;
|
||||
|
||||
name = get_dom_node_name(node);
|
||||
id = get_dom_node_type_name(node->type);
|
||||
|
||||
printf("%.*s%.*s: %.*s\n",
|
||||
get_indent_offset(stack), indent_string,
|
||||
print_indent(stack);
|
||||
printf("%.*s: %.*s\n",
|
||||
id->length, id->string, name->length, name->string);
|
||||
}
|
||||
|
||||
static void
|
||||
sgml_parser_test_end(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct sgml_parser *parser = stack->contexts[0]->data;
|
||||
|
||||
if ((parser->flags & SGML_PARSER_COUNT_LINES)
|
||||
&& !(parser->flags & SGML_PARSER_DETECT_ERRORS)) {
|
||||
printf("%d\n", number_of_lines);
|
||||
}
|
||||
}
|
||||
|
||||
struct dom_stack_context_info sgml_parser_test_context_info = {
|
||||
/* Object size: */ 0,
|
||||
/* Push: */
|
||||
@ -163,13 +213,22 @@ struct dom_stack_context_info sgml_parser_test_context_info = {
|
||||
/* DOM_NODE_ENTITY */ NULL,
|
||||
/* DOM_NODE_PROC_INSTRUCTION */ NULL,
|
||||
/* DOM_NODE_COMMENT */ NULL,
|
||||
/* DOM_NODE_DOCUMENT */ NULL,
|
||||
/* DOM_NODE_DOCUMENT */ sgml_parser_test_end,
|
||||
/* DOM_NODE_DOCUMENT_TYPE */ NULL,
|
||||
/* DOM_NODE_DOCUMENT_FRAGMENT */ NULL,
|
||||
/* DOM_NODE_NOTATION */ NULL,
|
||||
}
|
||||
};
|
||||
|
||||
static enum sgml_parser_code
|
||||
sgml_error_function(struct sgml_parser *parser, struct dom_string *string,
|
||||
unsigned int line_number)
|
||||
{
|
||||
printf("error on line %d: %.*s\n",
|
||||
line_number, string->length, string->string);
|
||||
|
||||
return SGML_PARSER_CODE_OK;
|
||||
}
|
||||
|
||||
void die(const char *msg, ...)
|
||||
{
|
||||
@ -188,9 +247,11 @@ void die(const char *msg, ...)
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct dom_node *root;
|
||||
struct sgml_parser *parser;
|
||||
enum sgml_document_type doctype = SGML_DOCTYPE_HTML;
|
||||
enum sgml_parser_flag flags = 0;
|
||||
enum sgml_parser_code code = 0;
|
||||
int complete = 1;
|
||||
struct dom_string uri = INIT_DOM_STRING("dom://test", -1);
|
||||
struct dom_string source = INIT_DOM_STRING("(no source)", -1);
|
||||
int i;
|
||||
@ -227,6 +288,16 @@ main(int argc, char *argv[])
|
||||
set_dom_string(&source, argv[i], strlen(argv[i]));
|
||||
}
|
||||
|
||||
} else if (!strcmp(arg, "print-lines")) {
|
||||
flags |= SGML_PARSER_COUNT_LINES;
|
||||
|
||||
} else if (!strcmp(arg, "incomplete")) {
|
||||
flags |= SGML_PARSER_INCREMENTAL;
|
||||
complete = 0;
|
||||
|
||||
} else if (!strcmp(arg, "error")) {
|
||||
flags |= SGML_PARSER_DETECT_ERRORS;
|
||||
|
||||
} else if (!strcmp(arg, "help")) {
|
||||
die(NULL);
|
||||
|
||||
@ -235,22 +306,27 @@ main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
parser = init_sgml_parser(SGML_PARSER_STREAM, doctype, &uri);
|
||||
parser = init_sgml_parser(SGML_PARSER_STREAM, doctype, &uri, flags);
|
||||
if (!parser) return 1;
|
||||
|
||||
parser->error_func = sgml_error_function;
|
||||
add_dom_stack_context(&parser->stack, NULL, &sgml_parser_test_context_info);
|
||||
|
||||
root = parse_sgml(parser, &source);
|
||||
if (root) {
|
||||
assert(parser->stack.depth == 1);
|
||||
code = parse_sgml(parser, &source, complete);
|
||||
if (parser->root) {
|
||||
size_t root_offset = parser->stack.depth - 1;
|
||||
|
||||
assert(!complete || root_offset == 0);
|
||||
|
||||
get_dom_stack_state(&parser->stack, root_offset)->immutable = 0;
|
||||
|
||||
get_dom_stack_top(&parser->stack)->immutable = 0;
|
||||
/* For SGML_PARSER_STREAM this will free the DOM
|
||||
* root node. */
|
||||
pop_dom_node(&parser->stack);
|
||||
while (!dom_stack_is_empty(&parser->stack))
|
||||
pop_dom_node(&parser->stack);
|
||||
}
|
||||
|
||||
done_sgml_parser(parser);
|
||||
|
||||
return 0;
|
||||
return code;
|
||||
}
|
||||
|
@ -9,12 +9,12 @@ This test runs very basic features, like checking that nodes are placed
|
||||
correctly in the DOM tree.
|
||||
'
|
||||
|
||||
. ./libtest
|
||||
. "$TEST_LIB"
|
||||
|
||||
test_output_equals () {
|
||||
desc="$1"
|
||||
src="$2"
|
||||
out="$3"
|
||||
desc="$1"; shift
|
||||
src="$1"; shift
|
||||
out="$1"; shift
|
||||
|
||||
URI="test:$(echo "$desc" | sed '
|
||||
s/^[ \t]*\[[^]]*\][ \t]*//;
|
||||
@ -28,7 +28,7 @@ test_output_equals () {
|
||||
echo "#document: $URI" > expected
|
||||
echo "$out" | sed -n '2,$p' >> expected
|
||||
|
||||
test_expect_success "$desc" 'cmp -b output expected'
|
||||
test_expect_success "$desc" 'cmp output expected'
|
||||
}
|
||||
|
||||
|
||||
@ -55,6 +55,16 @@ element: root
|
||||
element: child3
|
||||
#text: a'
|
||||
|
||||
test_output_equals \
|
||||
'Parse tag soup elements.' \
|
||||
'<parent attr="value" <child:1></><child:2</>a</parent>' \
|
||||
'
|
||||
element: parent
|
||||
attribute: attr -> value
|
||||
element: child:1
|
||||
element: child:2
|
||||
#text: a'
|
||||
|
||||
test_output_equals \
|
||||
'Parse an enclosed comment.' \
|
||||
'<root><!-- Hello World! --></root>' \
|
||||
@ -63,7 +73,7 @@ element: root
|
||||
#comment: Hello World! '
|
||||
|
||||
test_output_equals \
|
||||
'Parse comment combinations.' \
|
||||
'Parse comment combinations. (I)' \
|
||||
'<root><!-- <!-- -- > --><!--foo--><!----></root>' \
|
||||
'
|
||||
element: root
|
||||
@ -71,12 +81,29 @@ element: root
|
||||
#comment: foo
|
||||
#comment: '
|
||||
|
||||
test_output_equals \
|
||||
'Parse comment combinations. (II).' \
|
||||
'<! -- comment -->s<!-->-->t<!----->u' \
|
||||
'
|
||||
#comment: comment
|
||||
#text: s
|
||||
#comment: >
|
||||
#text: t
|
||||
#comment: -
|
||||
#text: u'
|
||||
|
||||
test_output_equals \
|
||||
'Parse bad comment.' \
|
||||
'<!--->s' \
|
||||
'
|
||||
#comment: ->s'
|
||||
|
||||
test_output_equals \
|
||||
'Parse empty notation.' \
|
||||
'<!>s' \
|
||||
'
|
||||
#text: s'
|
||||
|
||||
test_output_equals \
|
||||
'Parse an enclosed CDATA section.' \
|
||||
'<root><![CDATA[...] ]>...]]></root>' \
|
||||
@ -167,7 +194,7 @@ test_output_equals \
|
||||
'
|
||||
proc-instruction: xml -> version="1.0" />
|
||||
attribute: version -> 1.0
|
||||
proc-instruction: xml -> /'
|
||||
proc-instruction: xml -> />-'
|
||||
|
||||
test_output_equals \
|
||||
'Parse XML stylesheet processing instructions.' \
|
||||
|
164
src/dom/test/test-sgml-parser-error
Executable file
164
src/dom/test/test-sgml-parser-error
Executable file
@ -0,0 +1,164 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2005 Jonas Fonseca
|
||||
#
|
||||
|
||||
test_description='Test SGML parser error reporting
|
||||
|
||||
This test checks that the SGML parser will report errors in the source
|
||||
given to it.
|
||||
'
|
||||
|
||||
. "$TEST_LIB"
|
||||
|
||||
test_output_error () {
|
||||
desc="$1"; shift
|
||||
src="$1"; shift
|
||||
out="$1"; shift
|
||||
|
||||
sgml-parser --src "$src" --error > output
|
||||
echo "$out" | sed -n '2,$p' > expected
|
||||
|
||||
test_expect_success "$desc" 'cmp output expected'
|
||||
}
|
||||
|
||||
|
||||
################################################################
|
||||
# Check parsing errors
|
||||
|
||||
test_output_error \
|
||||
'Check an element error.' \
|
||||
'<html' \
|
||||
'
|
||||
error on line 1: <html'
|
||||
|
||||
test_output_error \
|
||||
'Check an entity reference error.' \
|
||||
'a
|
||||
b
|
||||
&c' \
|
||||
'
|
||||
error on line 3: &c'
|
||||
|
||||
test_output_error \
|
||||
'Check multiple entity reference errors.' \
|
||||
'a
|
||||
&b&
|
||||
c
|
||||
&d' \
|
||||
'
|
||||
error on line 2: &b
|
||||
error on line 4: &d'
|
||||
|
||||
test_output_error \
|
||||
'Check incomplete comment. (I)' \
|
||||
'<!-' \
|
||||
'
|
||||
error on line 1: <!-'
|
||||
|
||||
test_output_error \
|
||||
'Check incomplete comment. (II)' \
|
||||
'<!-- ... ' \
|
||||
"
|
||||
error on line 1: <!--"
|
||||
|
||||
test_output_error \
|
||||
'Check incomplete notation. (I)' \
|
||||
'<!' \
|
||||
'
|
||||
error on line 1: <!'
|
||||
|
||||
test_output_error \
|
||||
'Check incomplete notation. (II)' \
|
||||
'<!DOCTYPE ...' \
|
||||
'
|
||||
error on line 1: <!DOCTYPE'
|
||||
|
||||
|
||||
test_output_error \
|
||||
'Check incomplete cdata section. (I)' \
|
||||
'<![CDATA[ ... ' \
|
||||
'
|
||||
error on line 1: <![CDATA['
|
||||
|
||||
|
||||
test_output_error \
|
||||
'Check incomplete cdata section. (II)' \
|
||||
'<![CDAT' \
|
||||
'
|
||||
error on line 1: <![CDAT'
|
||||
|
||||
test_output_error \
|
||||
'Check incomplete processing instruction. (I)' \
|
||||
'<?xml ' \
|
||||
'
|
||||
error on line 1: <?xml'
|
||||
|
||||
test_output_error \
|
||||
'Check incomplete processing instruction. (II)' \
|
||||
'<?xml-stylesheet attr...' \
|
||||
'
|
||||
error on line 1: attr...'
|
||||
|
||||
test_output_error \
|
||||
'Check incomplete reference. (I)' \
|
||||
'�' \
|
||||
'
|
||||
error on line 1: �'
|
||||
|
||||
test_output_error \
|
||||
'Check incomplete reference. (II)' \
|
||||
'&' \
|
||||
'
|
||||
error on line 1: &'
|
||||
|
||||
test_output_error \
|
||||
'Check incomplete element. (I)' \
|
||||
'<elem...' \
|
||||
'
|
||||
error on line 1: <elem...'
|
||||
|
||||
|
||||
test_output_error \
|
||||
'Check incomplete element. (II)' \
|
||||
'<' \
|
||||
'
|
||||
error on line 1: <'
|
||||
|
||||
test_output_error \
|
||||
'Check incomplete element end. (I)' \
|
||||
'<a></a' \
|
||||
'
|
||||
error on line 1: </a'
|
||||
|
||||
test_output_error \
|
||||
'Check incomplete element end. (II)' \
|
||||
'<a></' \
|
||||
'
|
||||
error on line 1: </'
|
||||
|
||||
test_output_error \
|
||||
'Check incomplete attribute.' \
|
||||
'<element attr...' \
|
||||
'
|
||||
error on line 1: attr...'
|
||||
|
||||
test_output_error \
|
||||
'Check incomplete attribute value.' \
|
||||
'<element attr=...' \
|
||||
'
|
||||
error on line 1: ...'
|
||||
|
||||
test_output_error \
|
||||
'Check incomplete attribute quoted value. (I)' \
|
||||
'<element attr="...' \
|
||||
'
|
||||
error on line 1: "...'
|
||||
|
||||
test_output_error \
|
||||
'Check incomplete attribute quoted value. (II)' \
|
||||
"<element attr='..." \
|
||||
"
|
||||
error on line 1: '..."
|
||||
|
||||
test_done
|
107
src/dom/test/test-sgml-parser-incomplete
Executable file
107
src/dom/test/test-sgml-parser-incomplete
Executable file
@ -0,0 +1,107 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2005 Jonas Fonseca
|
||||
#
|
||||
|
||||
test_description='Test that incompleteness is correctly detected
|
||||
|
||||
This test checks that the SGML parser correctly finds and reports
|
||||
when a part of the source is incomplete.
|
||||
'
|
||||
|
||||
. "$TEST_LIB"
|
||||
|
||||
test_expect_incomplete () {
|
||||
desc="$1"; shift
|
||||
src="$1"; shift
|
||||
|
||||
sgml-parser --src "$src" --incomplete >/dev/null
|
||||
test_expect_success "$desc" \
|
||||
"test $? = 1"
|
||||
}
|
||||
|
||||
|
||||
################################################################
|
||||
# Check for incompleteness
|
||||
|
||||
test_expect_incomplete \
|
||||
'Check incomplete comment. (I)' \
|
||||
'<!-'
|
||||
|
||||
test_expect_incomplete \
|
||||
'Check incomplete comment. (II)' \
|
||||
'<!-- ... '
|
||||
|
||||
test_expect_incomplete \
|
||||
'Check incomplete notation. (I)' \
|
||||
'<!'
|
||||
|
||||
test_expect_incomplete \
|
||||
'Check incomplete notation. (II)' \
|
||||
'<!D'
|
||||
|
||||
test_expect_incomplete \
|
||||
'Check incomplete cdata section. (I)' \
|
||||
'<![CDATA[ ... '
|
||||
|
||||
test_expect_incomplete \
|
||||
'Check incomplete cdata section. (II)' \
|
||||
'<![CDAT'
|
||||
|
||||
test_expect_incomplete \
|
||||
'Check incomplete element. (I)' \
|
||||
'<elem...'
|
||||
|
||||
test_expect_incomplete \
|
||||
'Check incomplete element. (II)' \
|
||||
'<'
|
||||
|
||||
test_expect_incomplete \
|
||||
'Check incomplete element end. (I)' \
|
||||
'<a></a'
|
||||
|
||||
test_expect_incomplete \
|
||||
'Check incomplete element end. (II)' \
|
||||
'<a></'
|
||||
|
||||
test_expect_incomplete \
|
||||
'Check incomplete attribute.' \
|
||||
'<element attr...'
|
||||
|
||||
test_expect_incomplete \
|
||||
'Check incomplete attribute value.' \
|
||||
'<element attr=...'
|
||||
|
||||
test_expect_incomplete \
|
||||
'Check incomplete attribute quoted value. (I)' \
|
||||
'<element attr="...'
|
||||
|
||||
test_expect_incomplete \
|
||||
'Check incomplete attribute quoted value. (II)' \
|
||||
"<element attr='..."
|
||||
|
||||
test_expect_incomplete \
|
||||
'Check incomplete processing instruction. (I)' \
|
||||
'<?xml'
|
||||
|
||||
test_expect_incomplete \
|
||||
'Check incomplete processing instruction. (II)' \
|
||||
'<?xml attr...'
|
||||
|
||||
test_expect_incomplete \
|
||||
'Check incomplete notation.' \
|
||||
'<!DOCTYPE html PUBLIC ...'
|
||||
|
||||
test_expect_incomplete \
|
||||
'Check incomplete reference. (I)' \
|
||||
'�'
|
||||
|
||||
test_expect_incomplete \
|
||||
'Check incomplete reference. (II)' \
|
||||
'&'
|
||||
|
||||
test_expect_incomplete \
|
||||
'Check incomplete text.' \
|
||||
'plain text is always incomplete (if incomplete)'
|
||||
|
||||
test_done
|
59
src/dom/test/test-sgml-parser-lines
Executable file
59
src/dom/test/test-sgml-parser-lines
Executable file
@ -0,0 +1,59 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2005 Jonas Fonseca
|
||||
#
|
||||
|
||||
test_description='Test the SGML parsers counting of lines
|
||||
|
||||
Checks that the SGML parser correctly reports how many lines the
|
||||
source has.
|
||||
'
|
||||
|
||||
. "$TEST_LIB"
|
||||
|
||||
test_output_line_numbers () {
|
||||
desc="$1"; shift
|
||||
src="$1"; shift
|
||||
expected_lines="$1"; shift
|
||||
|
||||
lines=$(sgml-parser --src "$src" --print-lines)
|
||||
|
||||
test_expect_success "$desc" "test $lines = $expected_lines"
|
||||
}
|
||||
|
||||
|
||||
################################################################
|
||||
# Check line numbers
|
||||
|
||||
test_output_line_numbers \
|
||||
'Check line numbers. (I)' \
|
||||
'<!-- line --> number <one />' \
|
||||
1
|
||||
|
||||
test_output_line_numbers \
|
||||
'Check line numbers. (II)' \
|
||||
'<
|
||||
line:2
|
||||
line:3
|
||||
=
|
||||
"line:5"
|
||||
><?xml
|
||||
line:7="..."
|
||||
line:8
|
||||
=
|
||||
'\''...'\''></line:10>' \
|
||||
10
|
||||
|
||||
test_output_line_numbers \
|
||||
'Check line numbers. (III)' \
|
||||
'1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8' \
|
||||
8
|
||||
|
||||
test_done
|
@ -2,7 +2,10 @@ top_builddir=../..
|
||||
include $(top_builddir)/Makefile.config
|
||||
INCLUDES += $(SPIDERMONKEY_CFLAGS)
|
||||
|
||||
SUBDIRS = spidermonkey
|
||||
OBJS = ecmascript.o spidermonkey.o
|
||||
SUBDIRS-$(CONFIG_SPIDERMONKEY) += spidermonkey
|
||||
SUBDIRS-$(CONFIG_SEE) += see
|
||||
OBJS-$(CONFIG_SPIDERMONKEY) += spidermonkey.o
|
||||
OBJS-$(CONFIG_SEE) += see.o
|
||||
OBJS = ecmascript.o
|
||||
|
||||
include $(top_srcdir)/Makefile.lib
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include "document/document.h"
|
||||
#include "document/view.h"
|
||||
#include "ecmascript/ecmascript.h"
|
||||
#include "ecmascript/spidermonkey.h"
|
||||
#include "intl/gettext/libintl.h"
|
||||
#include "main/module.h"
|
||||
#include "protocol/uri.h"
|
||||
@ -61,49 +60,6 @@ static struct option_info ecmascript_options[] = {
|
||||
NULL_OPTION_INFO,
|
||||
};
|
||||
|
||||
#define get_ecmascript_enable() get_opt_bool("ecmascript.enable")
|
||||
|
||||
|
||||
static void
|
||||
ecmascript_init(struct module *module)
|
||||
{
|
||||
spidermonkey_init();
|
||||
}
|
||||
|
||||
static void
|
||||
ecmascript_done(struct module *module)
|
||||
{
|
||||
spidermonkey_done();
|
||||
}
|
||||
|
||||
|
||||
struct ecmascript_interpreter *
|
||||
ecmascript_get_interpreter(struct view_state *vs)
|
||||
{
|
||||
struct ecmascript_interpreter *interpreter;
|
||||
|
||||
assert(vs);
|
||||
|
||||
interpreter = mem_calloc(1, sizeof(*interpreter));
|
||||
if (!interpreter)
|
||||
return NULL;
|
||||
|
||||
interpreter->vs = vs;
|
||||
init_list(interpreter->onload_snippets);
|
||||
spidermonkey_get_interpreter(interpreter);
|
||||
|
||||
return interpreter;
|
||||
}
|
||||
|
||||
void
|
||||
ecmascript_put_interpreter(struct ecmascript_interpreter *interpreter)
|
||||
{
|
||||
assert(interpreter);
|
||||
spidermonkey_put_interpreter(interpreter);
|
||||
free_string_list(&interpreter->onload_snippets);
|
||||
mem_free(interpreter);
|
||||
}
|
||||
|
||||
void
|
||||
ecmascript_reset_state(struct view_state *vs)
|
||||
{
|
||||
@ -124,40 +80,6 @@ ecmascript_reset_state(struct view_state *vs)
|
||||
vs->ecmascript_fragile = 1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ecmascript_eval(struct ecmascript_interpreter *interpreter,
|
||||
struct string *code)
|
||||
{
|
||||
if (!get_ecmascript_enable())
|
||||
return;
|
||||
assert(interpreter);
|
||||
spidermonkey_eval(interpreter, code);
|
||||
}
|
||||
|
||||
|
||||
unsigned char *
|
||||
ecmascript_eval_stringback(struct ecmascript_interpreter *interpreter,
|
||||
struct string *code)
|
||||
{
|
||||
if (!get_ecmascript_enable())
|
||||
return NULL;
|
||||
assert(interpreter);
|
||||
return spidermonkey_eval_stringback(interpreter, code);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ecmascript_eval_boolback(struct ecmascript_interpreter *interpreter,
|
||||
struct string *code)
|
||||
{
|
||||
if (!get_ecmascript_enable())
|
||||
return -1;
|
||||
assert(interpreter);
|
||||
return spidermonkey_eval_boolback(interpreter, code);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ecmascript_protocol_handler(struct session *ses, struct uri *uri)
|
||||
{
|
||||
@ -197,6 +119,20 @@ ecmascript_protocol_handler(struct session *ses, struct uri *uri)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ecmascript_timeout_dialog(struct terminal *term, int max_exec_time)
|
||||
{
|
||||
info_box(term, MSGBOX_FREE_TEXT,
|
||||
N_("JavaScript Emergency"), ALIGN_LEFT,
|
||||
msg_text(term,
|
||||
N_("A script embedded in the current document was running\n"
|
||||
"for more than %d seconds. This probably means there is\n"
|
||||
"a bug in the script and it could have halted the whole\n"
|
||||
"ELinks, so the script execution was interrupted."),
|
||||
max_exec_time));
|
||||
|
||||
}
|
||||
|
||||
struct module ecmascript_module = struct_module(
|
||||
/* name: */ N_("ECMAScript"),
|
||||
/* options: */ ecmascript_options,
|
||||
|
@ -9,9 +9,12 @@
|
||||
#include "util/time.h"
|
||||
|
||||
struct string;
|
||||
struct terminal;
|
||||
struct uri;
|
||||
struct view_state;
|
||||
|
||||
#define get_ecmascript_enable() get_opt_bool("ecmascript.enable")
|
||||
|
||||
struct ecmascript_interpreter {
|
||||
struct view_state *vs;
|
||||
void *backend_data;
|
||||
@ -63,6 +66,11 @@ int ecmascript_eval_boolback(struct ecmascript_interpreter *interpreter, struct
|
||||
* follows a link with this synstax. */
|
||||
void ecmascript_protocol_handler(struct session *ses, struct uri *uri);
|
||||
|
||||
void ecmascript_init(struct module *);
|
||||
void ecmascript_done(struct module *);
|
||||
void ecmascript_timeout_dialog(struct terminal *term, int max_exec_time);
|
||||
|
||||
|
||||
extern struct module ecmascript_module;
|
||||
|
||||
#endif
|
||||
|
243
src/ecmascript/see.c
Normal file
243
src/ecmascript/see.c
Normal file
@ -0,0 +1,243 @@
|
||||
/* The SEE ECMAScript backend. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "elinks.h"
|
||||
|
||||
#include <see/see.h>
|
||||
|
||||
#include "bfu/dialog.h"
|
||||
#include "cache/cache.h"
|
||||
#include "cookies/cookies.h"
|
||||
#include "dialogs/menu.h"
|
||||
#include "dialogs/status.h"
|
||||
#include "document/html/frames.h"
|
||||
#include "document/document.h"
|
||||
#include "document/forms.h"
|
||||
#include "document/view.h"
|
||||
#include "ecmascript/ecmascript.h"
|
||||
#include "ecmascript/see.h"
|
||||
#include "ecmascript/see/document.h"
|
||||
#include "ecmascript/see/form.h"
|
||||
#include "ecmascript/see/input.h"
|
||||
#include "ecmascript/see/location.h"
|
||||
#include "ecmascript/see/navigator.h"
|
||||
#include "ecmascript/see/strings.h"
|
||||
#include "ecmascript/see/unibar.h"
|
||||
#include "ecmascript/see/window.h"
|
||||
#include "intl/gettext/libintl.h"
|
||||
#include "main/select.h"
|
||||
#include "osdep/newwin.h"
|
||||
#include "osdep/sysname.h"
|
||||
#include "protocol/http/http.h"
|
||||
#include "protocol/uri.h"
|
||||
#include "session/history.h"
|
||||
#include "session/location.h"
|
||||
#include "session/session.h"
|
||||
#include "session/task.h"
|
||||
#include "terminal/tab.h"
|
||||
#include "terminal/terminal.h"
|
||||
#include "util/conv.h"
|
||||
#include "util/string.h"
|
||||
#include "viewer/text/draw.h"
|
||||
#include "viewer/text/form.h"
|
||||
#include "viewer/text/link.h"
|
||||
#include "viewer/text/vs.h"
|
||||
|
||||
|
||||
/*** Global methods */
|
||||
|
||||
|
||||
/* TODO? Are there any which need to be implemented? */
|
||||
|
||||
|
||||
|
||||
/*** The ELinks interface */
|
||||
|
||||
void
|
||||
ecmascript_init(struct module *module)
|
||||
{
|
||||
see_init();
|
||||
}
|
||||
|
||||
void
|
||||
ecmascript_done(struct module *module)
|
||||
{
|
||||
see_done();
|
||||
}
|
||||
|
||||
struct ecmascript_interpreter *
|
||||
ecmascript_get_interpreter(struct view_state *vs)
|
||||
{
|
||||
struct ecmascript_interpreter *interpreter;
|
||||
|
||||
assert(vs);
|
||||
|
||||
interpreter = mem_calloc(1, sizeof(*interpreter));
|
||||
if (!interpreter)
|
||||
return NULL;
|
||||
|
||||
interpreter->vs = vs;
|
||||
init_list(interpreter->onload_snippets);
|
||||
see_get_interpreter(interpreter);
|
||||
|
||||
return interpreter;
|
||||
}
|
||||
|
||||
void
|
||||
ecmascript_put_interpreter(struct ecmascript_interpreter *interpreter)
|
||||
{
|
||||
assert(interpreter);
|
||||
see_put_interpreter(interpreter);
|
||||
free_string_list(&interpreter->onload_snippets);
|
||||
mem_free(interpreter);
|
||||
}
|
||||
|
||||
void
|
||||
ecmascript_eval(struct ecmascript_interpreter *interpreter,
|
||||
struct string *code)
|
||||
{
|
||||
if (!get_ecmascript_enable())
|
||||
return;
|
||||
assert(interpreter);
|
||||
see_eval(interpreter, code);
|
||||
}
|
||||
|
||||
unsigned char *
|
||||
ecmascript_eval_stringback(struct ecmascript_interpreter *interpreter,
|
||||
struct string *code)
|
||||
{
|
||||
if (!get_ecmascript_enable())
|
||||
return NULL;
|
||||
assert(interpreter);
|
||||
return see_eval_stringback(interpreter, code);
|
||||
}
|
||||
|
||||
int
|
||||
ecmascript_eval_boolback(struct ecmascript_interpreter *interpreter,
|
||||
struct string *code)
|
||||
{
|
||||
if (!get_ecmascript_enable())
|
||||
return -1;
|
||||
assert(interpreter);
|
||||
return see_eval_boolback(interpreter, code);
|
||||
}
|
||||
|
||||
void
|
||||
see_init(void)
|
||||
{
|
||||
init_intern_strings();
|
||||
}
|
||||
|
||||
void
|
||||
see_done(void)
|
||||
{
|
||||
}
|
||||
|
||||
void *
|
||||
see_get_interpreter(struct ecmascript_interpreter *interpreter)
|
||||
{
|
||||
struct global_object *g = SEE_NEW(NULL, struct global_object);
|
||||
struct SEE_interpreter *interp = &g->interp;
|
||||
|
||||
interpreter->backend_data = g;
|
||||
g->max_exec_time = get_opt_int("ecmascript.max_exec_time");
|
||||
g->exec_start = time(NULL);
|
||||
SEE_interpreter_init(interp);
|
||||
init_js_window_object(interpreter);
|
||||
init_js_menubar_object(interpreter);
|
||||
init_js_statusbar_object(interpreter);
|
||||
init_js_navigator_object(interpreter);
|
||||
init_js_history_object(interpreter);
|
||||
init_js_location_object(interpreter);
|
||||
init_js_document_object(interpreter);
|
||||
init_js_forms_object(interpreter);
|
||||
return interp;
|
||||
}
|
||||
|
||||
void
|
||||
see_put_interpreter(struct ecmascript_interpreter *interpreter)
|
||||
{
|
||||
interpreter->backend_data = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
see_eval(struct ecmascript_interpreter *interpreter,
|
||||
struct string *code)
|
||||
{
|
||||
|
||||
struct SEE_interpreter *interp = interpreter->backend_data;
|
||||
struct global_object *g = (struct global_object *)interp;
|
||||
struct SEE_input *input = SEE_input_elinks(interp, code->source);
|
||||
SEE_try_context_t try_ctxt;
|
||||
struct SEE_value result;
|
||||
struct SEE_value v;
|
||||
|
||||
g->exec_start = time(NULL);
|
||||
SEE_TRY(interp, try_ctxt) {
|
||||
SEE_Global_eval(interp, input, &result);
|
||||
}
|
||||
|
||||
SEE_INPUT_CLOSE(input);
|
||||
SEE_CAUGHT(try_ctxt);
|
||||
}
|
||||
|
||||
|
||||
unsigned char *
|
||||
see_eval_stringback(struct ecmascript_interpreter *interpreter,
|
||||
struct string *code)
|
||||
{
|
||||
struct SEE_interpreter *interp = interpreter->backend_data;
|
||||
struct global_object *g = (struct global_object *)interp;
|
||||
struct SEE_input *input = SEE_input_elinks(interp, code->source);
|
||||
SEE_try_context_t try_ctxt;
|
||||
struct SEE_value result;
|
||||
unsigned char *string = NULL;
|
||||
|
||||
g->exec_start = time(NULL);
|
||||
SEE_TRY(interp, try_ctxt) {
|
||||
SEE_Global_eval(interp, input, &result);
|
||||
if (SEE_VALUE_GET_TYPE(&result) != SEE_NULL)
|
||||
string = SEE_value_to_unsigned_char(interp, &result);
|
||||
|
||||
}
|
||||
SEE_INPUT_CLOSE(input);
|
||||
if (SEE_CAUGHT(try_ctxt)) {
|
||||
return NULL;
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
int
|
||||
see_eval_boolback(struct ecmascript_interpreter *interpreter,
|
||||
struct string *code)
|
||||
{
|
||||
struct SEE_interpreter *interp = interpreter->backend_data;
|
||||
struct global_object *g = (struct global_object *)interp;
|
||||
struct SEE_input *input = SEE_input_elinks(interp, code->source);
|
||||
SEE_try_context_t try_ctxt;
|
||||
struct SEE_value result;
|
||||
SEE_int32_t res = 0;
|
||||
|
||||
g->exec_start = time(NULL);
|
||||
SEE_TRY(interp, try_ctxt) {
|
||||
SEE_Global_eval(interp, input, &result);
|
||||
/* history.back() returns SEE_NULL */
|
||||
if (SEE_VALUE_GET_TYPE(&result) == SEE_NULL)
|
||||
res = 0;
|
||||
else
|
||||
res = SEE_ToInt32(interp, &result);
|
||||
}
|
||||
|
||||
SEE_INPUT_CLOSE(input);
|
||||
if (SEE_CAUGHT(try_ctxt)) {
|
||||
return -1;
|
||||
}
|
||||
return res;
|
||||
}
|
17
src/ecmascript/see.h
Normal file
17
src/ecmascript/see.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef EL__ECMASCRIPT_SEE_H
|
||||
#define EL__ECMASCRIPT_SEE_H
|
||||
|
||||
struct ecmascript_interpreter;
|
||||
struct string;
|
||||
|
||||
void see_init();
|
||||
void see_done();
|
||||
|
||||
void *see_get_interpreter(struct ecmascript_interpreter *interpreter);
|
||||
void see_put_interpreter(struct ecmascript_interpreter *interpreter);
|
||||
|
||||
void see_eval(struct ecmascript_interpreter *interpreter, struct string *code);
|
||||
unsigned char *see_eval_stringback(struct ecmascript_interpreter *interpreter, struct string *code);
|
||||
int see_eval_boolback(struct ecmascript_interpreter *interpreter, struct string *code);
|
||||
|
||||
#endif
|
6
src/ecmascript/see/Makefile
Normal file
6
src/ecmascript/see/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
top_builddir=../../..
|
||||
include $(top_builddir)/Makefile.config
|
||||
|
||||
OBJS = document.o form.o input.o location.o navigator.o strings.o unibar.o window.o
|
||||
|
||||
include $(top_srcdir)/Makefile.lib
|
257
src/ecmascript/see/document.c
Normal file
257
src/ecmascript/see/document.c
Normal file
@ -0,0 +1,257 @@
|
||||
/* The SEE document object implementation. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "elinks.h"
|
||||
|
||||
#include <see/see.h>
|
||||
|
||||
#include "bfu/dialog.h"
|
||||
#include "cache/cache.h"
|
||||
#include "cookies/cookies.h"
|
||||
#include "dialogs/menu.h"
|
||||
#include "dialogs/status.h"
|
||||
#include "document/html/frames.h"
|
||||
#include "document/document.h"
|
||||
#include "document/forms.h"
|
||||
#include "document/view.h"
|
||||
#include "ecmascript/ecmascript.h"
|
||||
#include "ecmascript/see/document.h"
|
||||
#include "ecmascript/see/form.h"
|
||||
#include "ecmascript/see/input.h"
|
||||
#include "ecmascript/see/strings.h"
|
||||
#include "ecmascript/see/window.h"
|
||||
#include "intl/gettext/libintl.h"
|
||||
#include "main/select.h"
|
||||
#include "osdep/newwin.h"
|
||||
#include "osdep/sysname.h"
|
||||
#include "protocol/http/http.h"
|
||||
#include "protocol/uri.h"
|
||||
#include "session/history.h"
|
||||
#include "session/location.h"
|
||||
#include "session/session.h"
|
||||
#include "session/task.h"
|
||||
#include "terminal/tab.h"
|
||||
#include "terminal/terminal.h"
|
||||
#include "util/conv.h"
|
||||
#include "util/memory.h"
|
||||
#include "util/string.h"
|
||||
#include "viewer/text/draw.h"
|
||||
#include "viewer/text/form.h"
|
||||
#include "viewer/text/link.h"
|
||||
#include "viewer/text/vs.h"
|
||||
|
||||
static void document_get(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *);
|
||||
static void document_put(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *, int);
|
||||
static int document_canput(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
|
||||
static int document_hasproperty(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
|
||||
static void js_document_write(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
|
||||
|
||||
void location_goto(struct document_view *, unsigned char *);
|
||||
|
||||
struct SEE_objectclass js_document_object_class = {
|
||||
NULL,
|
||||
document_get,
|
||||
document_put,
|
||||
document_canput,
|
||||
document_hasproperty,
|
||||
SEE_no_delete,
|
||||
SEE_no_defaultvalue,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
static void
|
||||
document_get(struct SEE_interpreter *interp, struct SEE_object *o,
|
||||
struct SEE_string *p, struct SEE_value *res)
|
||||
{
|
||||
struct global_object *g = (struct global_object *)interp;
|
||||
struct js_window_object *win = g->win;
|
||||
struct view_state *vs = win->vs;
|
||||
struct document_view *doc_view = vs->doc_view;
|
||||
struct document *document = doc_view->document;
|
||||
struct js_document_object *doc = (struct js_document_object *)o;
|
||||
struct session *ses = doc_view->session;
|
||||
struct SEE_string *str;
|
||||
unsigned char *string;
|
||||
|
||||
checktime(interp);
|
||||
SEE_SET_UNDEFINED(res);
|
||||
|
||||
if (p == s_cookie) {
|
||||
#ifdef CONFIG_COOKIES
|
||||
struct string *cookies = send_cookies(vs->uri);
|
||||
|
||||
if (cookies) {
|
||||
static unsigned char cookiestr[1024];
|
||||
strncpy(cookiestr, cookies->source, 1024);
|
||||
done_string(cookies);
|
||||
|
||||
str = string_to_SEE_string(interp, cookiestr);
|
||||
} else {
|
||||
str = string_to_SEE_string(interp, "");
|
||||
}
|
||||
SEE_SET_STRING(res, str);
|
||||
#endif
|
||||
} else if (p == s_title) {
|
||||
str = string_to_SEE_string(interp, document->title);
|
||||
SEE_SET_STRING(res, str);
|
||||
} else if (p == s_url) {
|
||||
string = get_uri_string(document->uri, URI_ORIGINAL);
|
||||
str = string_to_SEE_string(interp, string);
|
||||
mem_free_if(string);
|
||||
SEE_SET_STRING(res, str);
|
||||
} else if (p == s_location) {
|
||||
SEE_OBJECT_GET(interp, interp->Global, s_location, res);
|
||||
} else if (p == s_referrer) {
|
||||
switch (get_opt_int("protocol.http.referer.policy")) {
|
||||
case REFERER_NONE:
|
||||
SEE_SET_UNDEFINED(res);
|
||||
break;
|
||||
case REFERER_FAKE:
|
||||
str = string_to_SEE_string(interp,
|
||||
get_opt_str("protocol.http.referer.fake"));
|
||||
SEE_SET_STRING(res, str);
|
||||
break;
|
||||
case REFERER_TRUE:
|
||||
if (ses->referrer) {
|
||||
string = get_uri_string(ses->referrer, URI_HTTP_REFERRER);
|
||||
str = string_to_SEE_string(interp, string);
|
||||
mem_free_if(string);
|
||||
SEE_SET_STRING(res, str);
|
||||
}
|
||||
break;
|
||||
case REFERER_SAME_URL:
|
||||
string = get_uri_string(document->uri, URI_HTTP_REFERRER);
|
||||
str = string_to_SEE_string(interp, string);
|
||||
mem_free_if(string);
|
||||
SEE_SET_STRING(res, str);
|
||||
break;
|
||||
|
||||
}
|
||||
} else if (p == s_forms) {
|
||||
SEE_SET_OBJECT(res, doc->forms);
|
||||
} else {
|
||||
struct form *form;
|
||||
unsigned char *string = SEE_string_to_unsigned_char(p);
|
||||
struct form_view *form_view;
|
||||
struct js_form *form_object;
|
||||
|
||||
foreach (form, document->forms) {
|
||||
if (!form->name || strcasecmp(string, form->name))
|
||||
continue;
|
||||
mem_free_if(string);
|
||||
form_view = find_form_view(doc_view, form);
|
||||
form_object = js_get_form_object(interp, doc, form_view);
|
||||
SEE_SET_OBJECT(res, (struct SEE_object *)form_object);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
document_put(struct SEE_interpreter *interp, struct SEE_object *o,
|
||||
struct SEE_string *p, struct SEE_value *val, int attr)
|
||||
{
|
||||
struct global_object *g = (struct global_object *)interp;
|
||||
struct view_state *vs = g->win->vs;
|
||||
struct document_view *doc_view = vs->doc_view;
|
||||
struct document *document = doc_view->document;
|
||||
struct js_document_object *doc = (struct js_document_object *)o;
|
||||
struct SEE_value res;
|
||||
unsigned char *string;
|
||||
|
||||
checktime(interp);
|
||||
if (p == s_forms) {
|
||||
SEE_ToObject(interp, val, &res);
|
||||
doc->forms = res.u.object;
|
||||
} else if (p == s_title) {
|
||||
string = SEE_value_to_unsigned_char(interp, val);
|
||||
mem_free_set(&document->title, string);
|
||||
print_screen_status(doc_view->session);
|
||||
} else if (p == s_location || p == s_url) {
|
||||
/* According to the specs this should be readonly but some
|
||||
* broken sites still assign to it (i.e.
|
||||
* http://www.e-handelsfonden.dk/validering.asp?URL=www.polyteknisk.dk).
|
||||
* So emulate window.location. */
|
||||
string = SEE_value_to_unsigned_char(interp, val);
|
||||
location_goto(doc_view, string);
|
||||
mem_free_if(string);
|
||||
} else if (p == s_cookie) {
|
||||
#ifdef CONFIG_COOKIES
|
||||
string = SEE_value_to_unsigned_char(interp, val);
|
||||
set_cookie(vs->uri, string);
|
||||
mem_free_if(string);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
js_document_write(struct SEE_interpreter *interp, struct SEE_object *self,
|
||||
struct SEE_object *thisobj, int argc, struct SEE_value **argv,
|
||||
struct SEE_value *res)
|
||||
{
|
||||
#ifdef CONFIG_LEDS
|
||||
struct global_object *g = (struct global_object *)interp;
|
||||
struct view_state *vs = g->win->vs;
|
||||
|
||||
/* XXX: I don't know about you, but I have *ENOUGH* of those 'Undefined
|
||||
* function' errors, I want to see just the useful ones. So just
|
||||
* lighting a led and going away, no muss, no fuss. --pasky */
|
||||
/* TODO: Perhaps we can introduce ecmascript.error_report_unsupported
|
||||
* -> "Show information about the document using some valid,
|
||||
* nevertheless unsupported methods/properties." --pasky too */
|
||||
|
||||
set_led_value(vs->doc_view->session->status.ecmascript_led, 'J');
|
||||
#endif
|
||||
checktime(interp);
|
||||
SEE_SET_BOOLEAN(res, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
document_canput(struct SEE_interpreter *interp, struct SEE_object *o,
|
||||
struct SEE_string *p)
|
||||
{
|
||||
checktime(interp);
|
||||
if (p == s_location || p == s_url || p == s_cookie)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
document_hasproperty(struct SEE_interpreter *interp, struct SEE_object *o,
|
||||
struct SEE_string *p)
|
||||
{
|
||||
checktime(interp);
|
||||
/* all unknown properties return UNDEFINED value */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
init_js_document_object(struct ecmascript_interpreter *interpreter)
|
||||
{
|
||||
struct global_object *g = interpreter->backend_data;
|
||||
struct SEE_interpreter *interp = &g->interp;
|
||||
struct SEE_value v;
|
||||
struct js_document_object *doc = SEE_NEW(interp,
|
||||
struct js_document_object);
|
||||
|
||||
doc->object.objectclass = &js_document_object_class;
|
||||
doc->object.objectclass->Class = s_document;
|
||||
doc->object.Prototype = NULL;
|
||||
|
||||
SEE_SET_OBJECT(&v, (struct SEE_object *)doc);
|
||||
SEE_OBJECT_PUT(interp, interp->Global, s_document, &v, 0);
|
||||
|
||||
doc->write = SEE_cfunction_make(interp, js_document_write, s_write, 1);
|
||||
}
|
14
src/ecmascript/see/document.h
Normal file
14
src/ecmascript/see/document.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef EL__ECMASCRIPT_SEE_DOCUMENT_H
|
||||
#define EL__ECMASCRIPT_SEE_DOCUMENT_H
|
||||
|
||||
struct ecmascript_interpreter;
|
||||
|
||||
struct js_document_object {
|
||||
struct SEE_object object;
|
||||
struct SEE_object *write;
|
||||
struct SEE_object *forms;
|
||||
};
|
||||
|
||||
void init_js_document_object(struct ecmascript_interpreter *);
|
||||
|
||||
#endif
|
964
src/ecmascript/see/form.c
Normal file
964
src/ecmascript/see/form.c
Normal file
@ -0,0 +1,964 @@
|
||||
/* The SEE form object implementation. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "elinks.h"
|
||||
|
||||
#include <see/see.h>
|
||||
|
||||
#include "bfu/dialog.h"
|
||||
#include "cache/cache.h"
|
||||
#include "cookies/cookies.h"
|
||||
#include "dialogs/menu.h"
|
||||
#include "dialogs/status.h"
|
||||
#include "document/html/frames.h"
|
||||
#include "document/document.h"
|
||||
#include "document/forms.h"
|
||||
#include "document/view.h"
|
||||
#include "ecmascript/ecmascript.h"
|
||||
#include "ecmascript/see/document.h"
|
||||
#include "ecmascript/see/form.h"
|
||||
#include "ecmascript/see/input.h"
|
||||
#include "ecmascript/see/strings.h"
|
||||
#include "ecmascript/see/window.h"
|
||||
#include "intl/gettext/libintl.h"
|
||||
#include "main/select.h"
|
||||
#include "osdep/newwin.h"
|
||||
#include "osdep/sysname.h"
|
||||
#include "protocol/http/http.h"
|
||||
#include "protocol/uri.h"
|
||||
#include "session/history.h"
|
||||
#include "session/location.h"
|
||||
#include "session/session.h"
|
||||
#include "session/task.h"
|
||||
#include "terminal/tab.h"
|
||||
#include "terminal/terminal.h"
|
||||
#include "util/conv.h"
|
||||
#include "util/memory.h"
|
||||
#include "util/string.h"
|
||||
#include "viewer/text/draw.h"
|
||||
#include "viewer/text/form.h"
|
||||
#include "viewer/text/link.h"
|
||||
#include "viewer/text/vs.h"
|
||||
|
||||
static void input_get(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *);
|
||||
static void input_put(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *, int);
|
||||
static void js_input_blur(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
|
||||
static void js_input_click(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
|
||||
static void js_input_focus(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
|
||||
static void js_input_select(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
|
||||
static int input_canput(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
|
||||
static int input_hasproperty(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
|
||||
static struct js_input *js_get_input_object(struct SEE_interpreter *, struct js_form *, struct form_state *);
|
||||
static struct js_input *js_get_form_control_object(struct SEE_interpreter *, struct js_form *, enum form_type, struct form_state *);
|
||||
|
||||
static void js_form_elems_item(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
|
||||
static void js_form_elems_namedItem(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
|
||||
static void form_elems_get(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *);
|
||||
static int form_elems_hasproperty(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
|
||||
|
||||
static void js_forms_item(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
|
||||
static void js_forms_namedItem(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
|
||||
static void forms_get(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *);
|
||||
static int forms_hasproperty(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
|
||||
|
||||
static void form_get(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *);
|
||||
static void form_put(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *, int);
|
||||
static int form_canput(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
|
||||
static int form_hasproperty(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
|
||||
static void js_form_reset(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
|
||||
static void js_form_submit(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
|
||||
|
||||
|
||||
struct SEE_objectclass js_input_object_class = {
|
||||
NULL,
|
||||
input_get,
|
||||
input_put,
|
||||
input_canput,
|
||||
input_hasproperty,
|
||||
SEE_no_delete,
|
||||
SEE_no_defaultvalue,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
struct SEE_objectclass js_form_elems_class = {
|
||||
NULL,
|
||||
form_elems_get,
|
||||
SEE_no_put,
|
||||
SEE_no_canput,
|
||||
form_elems_hasproperty,
|
||||
SEE_no_delete,
|
||||
SEE_no_defaultvalue,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
struct SEE_objectclass js_forms_object_class = {
|
||||
NULL,
|
||||
forms_get,
|
||||
SEE_no_put,
|
||||
SEE_no_canput,
|
||||
forms_hasproperty,
|
||||
SEE_no_delete,
|
||||
SEE_no_defaultvalue,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
struct SEE_objectclass js_form_class = {
|
||||
NULL,
|
||||
form_get,
|
||||
form_put,
|
||||
form_canput,
|
||||
form_hasproperty,
|
||||
SEE_no_delete,
|
||||
SEE_no_defaultvalue,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
struct js_input {
|
||||
struct SEE_object object;
|
||||
struct js_form *parent;
|
||||
struct form_state *fs;
|
||||
struct SEE_object *blur;
|
||||
struct SEE_object *click;
|
||||
struct SEE_object *focus;
|
||||
struct SEE_object *select;
|
||||
};
|
||||
|
||||
struct js_forms_object {
|
||||
struct SEE_object object;
|
||||
struct js_document_object *parent;
|
||||
struct SEE_object *item;
|
||||
struct SEE_object *namedItem;
|
||||
};
|
||||
|
||||
struct js_form_elems {
|
||||
struct SEE_object object;
|
||||
struct js_form *parent;
|
||||
struct SEE_object *item;
|
||||
struct SEE_object *namedItem;
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
input_get(struct SEE_interpreter *interp, struct SEE_object *o,
|
||||
struct SEE_string *p, struct SEE_value *res)
|
||||
{
|
||||
struct global_object *g = (struct global_object *)interp;
|
||||
struct view_state *vs = g->win->vs;
|
||||
struct document_view *doc_view = vs->doc_view;
|
||||
struct document *document = doc_view->document;
|
||||
struct js_input *input = (struct js_input *)o;
|
||||
struct js_form *parent = input->parent;
|
||||
struct form_state *fs = input->fs;
|
||||
struct form_control *fc = find_form_control(document, fs);
|
||||
int linknum;
|
||||
struct link *link = NULL;
|
||||
struct SEE_string *str;
|
||||
|
||||
assert(fc);
|
||||
assert(fc->form && fs);
|
||||
|
||||
checktime(interp);
|
||||
linknum = get_form_control_link(document, fc);
|
||||
/* Hiddens have no link. */
|
||||
if (linknum >= 0) link = &document->links[linknum];
|
||||
SEE_SET_UNDEFINED(res);
|
||||
|
||||
if (p == s_accessKey) {
|
||||
struct string keystr;
|
||||
if (!link)
|
||||
return;
|
||||
|
||||
init_string(&keystr);
|
||||
add_accesskey_to_string(&keystr, link->accesskey);
|
||||
str = string_to_SEE_string(interp, keystr.source);
|
||||
SEE_SET_STRING(res, str);
|
||||
done_string(&keystr);
|
||||
} else if (p == s_alt) {
|
||||
str = string_to_SEE_string(interp, fc->alt);
|
||||
SEE_SET_STRING(res, str);
|
||||
} else if (p == s_checked) {
|
||||
SEE_SET_BOOLEAN(res, fs->state);
|
||||
} else if (p == s_defaultChecked) {
|
||||
SEE_SET_BOOLEAN(res, fc->default_state);
|
||||
} else if (p == s_defaultValue) {
|
||||
str = string_to_SEE_string(interp, fc->default_value);
|
||||
SEE_SET_STRING(res, str);
|
||||
} else if (p == s_disabled) {
|
||||
/* FIXME: <input readonly disabled> --pasky */
|
||||
SEE_SET_BOOLEAN(res, fc->mode == FORM_MODE_DISABLED);
|
||||
} else if (p == s_form) {
|
||||
SEE_SET_OBJECT(res, (struct SEE_object *)parent);
|
||||
} else if (p == s_maxLength) {
|
||||
SEE_SET_NUMBER(res, fc->maxlength);
|
||||
} else if (p == s_name) {
|
||||
str = string_to_SEE_string(interp, fc->name);
|
||||
SEE_SET_STRING(res, str);
|
||||
} else if (p == s_readonly) {
|
||||
/* FIXME: <input readonly disabled> --pasky */
|
||||
SEE_SET_BOOLEAN(res, fc->mode == FORM_MODE_READONLY);
|
||||
} else if (p == s_size) {
|
||||
SEE_SET_NUMBER(res, fc->size);
|
||||
} else if (p == s_src) {
|
||||
if (link && link->where_img) {
|
||||
str = string_to_SEE_string(interp, link->where_img);
|
||||
SEE_SET_STRING(res, str);
|
||||
}
|
||||
} else if (p == s_tabindex) {
|
||||
if (link) {
|
||||
/* FIXME: This is WRONG. --pasky */
|
||||
SEE_SET_NUMBER(res, link->number);
|
||||
}
|
||||
} else if (p == s_type) {
|
||||
switch (fc->type) {
|
||||
case FC_TEXT: str = s_text; break;
|
||||
case FC_PASSWORD: str = s_password; break;
|
||||
case FC_FILE: str = s_file; break;
|
||||
case FC_CHECKBOX: str = s_checkbox; break;
|
||||
case FC_RADIO: str = s_radio; break;
|
||||
case FC_SUBMIT: str = s_submit; break;
|
||||
case FC_IMAGE: str = s_image; break;
|
||||
case FC_RESET: str = s_reset; break;
|
||||
case FC_BUTTON: str = s_button; break;
|
||||
case FC_HIDDEN: str = s_hidden; break;
|
||||
default: str = NULL;
|
||||
}
|
||||
if (str) {
|
||||
SEE_SET_STRING(res, str);
|
||||
}
|
||||
} else if (p == s_value) {
|
||||
str = string_to_SEE_string(interp, fs->value);
|
||||
SEE_SET_STRING(res, str);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
input_put(struct SEE_interpreter *interp, struct SEE_object *o,
|
||||
struct SEE_string *p, struct SEE_value *val, int attr)
|
||||
{
|
||||
struct global_object *g = (struct global_object *)interp;
|
||||
struct view_state *vs = g->win->vs;
|
||||
struct document_view *doc_view = vs->doc_view;
|
||||
struct document *document = doc_view->document;
|
||||
struct js_input *input = (struct js_input *)o;
|
||||
struct form_state *fs = input->fs;
|
||||
struct form_control *fc = find_form_control(document, fs);
|
||||
int linknum;
|
||||
struct link *link = NULL;
|
||||
unsigned char *string = NULL;
|
||||
|
||||
assert(fc);
|
||||
assert(fc->form && fs);
|
||||
|
||||
checktime(interp);
|
||||
linknum = get_form_control_link(document, fc);
|
||||
/* Hiddens have no link. */
|
||||
if (linknum >= 0) link = &document->links[linknum];
|
||||
|
||||
if (p == s_accessKey) {
|
||||
if (link) {
|
||||
string = SEE_value_to_unsigned_char(interp, val);
|
||||
if (!string)
|
||||
return;
|
||||
link->accesskey = accesskey_string_to_unicode(string);
|
||||
mem_free(string);
|
||||
}
|
||||
} else if (p == s_alt) {
|
||||
string = SEE_value_to_unsigned_char(interp, val);
|
||||
mem_free_set(&fc->alt, string);
|
||||
} else if (p == s_checked) {
|
||||
if (fc->type != FC_CHECKBOX && fc->type != FC_RADIO)
|
||||
return;
|
||||
fs->state = SEE_ToUint32(interp, val);
|
||||
} else if (p == s_disabled) {
|
||||
/* FIXME: <input readonly disabled> --pasky */
|
||||
SEE_uint32_t boo = SEE_ToUint32(interp, val);
|
||||
fc->mode = (boo ? FORM_MODE_DISABLED
|
||||
: (fc->mode == FORM_MODE_READONLY ? FORM_MODE_READONLY
|
||||
: FORM_MODE_NORMAL));
|
||||
} else if (p == s_maxLength) {
|
||||
string = SEE_value_to_unsigned_char(interp, val);
|
||||
if (!string)
|
||||
return;
|
||||
fc->maxlength = atol(string);
|
||||
mem_free(string);
|
||||
} else if (p == s_name) {
|
||||
string = SEE_value_to_unsigned_char(interp, val);
|
||||
mem_free_set(&fc->name, string);
|
||||
} else if (p == s_readonly) {
|
||||
SEE_uint32_t boo = SEE_ToUint32(interp, val);
|
||||
fc->mode = (boo ? FORM_MODE_READONLY
|
||||
: fc->mode == FORM_MODE_DISABLED ? FORM_MODE_DISABLED
|
||||
: FORM_MODE_NORMAL);
|
||||
} else if (p == s_src) {
|
||||
if (link) {
|
||||
string = SEE_value_to_unsigned_char(interp, val);
|
||||
mem_free_set(&link->where_img, string);
|
||||
}
|
||||
} else if (p == s_value) {
|
||||
if (fc->type == FC_FILE)
|
||||
return;
|
||||
string = SEE_value_to_unsigned_char(interp, val);
|
||||
mem_free_set(&fs->value, string);
|
||||
if (fc->type == FC_TEXT || fc->type == FC_PASSWORD)
|
||||
fs->state = strlen(fs->value);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
js_input_blur(struct SEE_interpreter *interp, struct SEE_object *self,
|
||||
struct SEE_object *thisobj, int argc, struct SEE_value **argv,
|
||||
struct SEE_value *res)
|
||||
{
|
||||
/* We are a text-mode browser and there *always* has to be something
|
||||
* selected. So we do nothing for now. (That was easy.) */
|
||||
}
|
||||
|
||||
static void
|
||||
js_input_click(struct SEE_interpreter *interp, struct SEE_object *self,
|
||||
struct SEE_object *thisobj, int argc, struct SEE_value **argv,
|
||||
struct SEE_value *res)
|
||||
{
|
||||
struct global_object *g = (struct global_object *)interp;
|
||||
struct view_state *vs = g->win->vs;
|
||||
struct document_view *doc_view = vs->doc_view;
|
||||
struct document *document = doc_view->document;
|
||||
struct session *ses = doc_view->session;
|
||||
struct js_input *input = (struct js_input *)thisobj;
|
||||
struct form_state *fs = input->fs;
|
||||
struct form_control *fc;
|
||||
int linknum;
|
||||
|
||||
checktime(interp);
|
||||
SEE_SET_BOOLEAN(res, 0);
|
||||
assert(fs);
|
||||
fc = find_form_control(document, fs);
|
||||
assert(fc);
|
||||
|
||||
linknum = get_form_control_link(document, fc);
|
||||
/* Hiddens have no link. */
|
||||
if (linknum < 0)
|
||||
return;
|
||||
|
||||
/* Restore old current_link afterwards? */
|
||||
jump_to_link_number(ses, doc_view, linknum);
|
||||
if (enter(ses, doc_view, 0) == FRAME_EVENT_REFRESH)
|
||||
refresh_view(ses, doc_view, 0);
|
||||
else
|
||||
print_screen_status(ses);
|
||||
}
|
||||
|
||||
static void
|
||||
js_input_focus(struct SEE_interpreter *interp, struct SEE_object *self,
|
||||
struct SEE_object *thisobj, int argc, struct SEE_value **argv,
|
||||
struct SEE_value *res)
|
||||
{
|
||||
struct global_object *g = (struct global_object *)interp;
|
||||
struct view_state *vs = g->win->vs;
|
||||
struct document_view *doc_view = vs->doc_view;
|
||||
struct document *document = doc_view->document;
|
||||
struct session *ses = doc_view->session;
|
||||
struct js_input *input = (struct js_input *)thisobj;
|
||||
struct form_state *fs = input->fs;
|
||||
struct form_control *fc;
|
||||
int linknum;
|
||||
|
||||
checktime(interp);
|
||||
assert(fs);
|
||||
fc = find_form_control(document, fs);
|
||||
assert(fc);
|
||||
|
||||
linknum = get_form_control_link(document, fc);
|
||||
/* Hiddens have no link. */
|
||||
if (linknum < 0)
|
||||
return;
|
||||
|
||||
jump_to_link_number(ses, doc_view, linknum);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
js_input_select(struct SEE_interpreter *interp, struct SEE_object *self,
|
||||
struct SEE_object *thisobj, int argc, struct SEE_value **argv,
|
||||
struct SEE_value *res)
|
||||
{
|
||||
checktime(interp);
|
||||
/* We support no text selecting yet. So we do nothing for now.
|
||||
* (That was easy, too.) */
|
||||
}
|
||||
|
||||
static int
|
||||
input_canput(struct SEE_interpreter *interp, struct SEE_object *o,
|
||||
struct SEE_string *p)
|
||||
{
|
||||
checktime(interp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
input_hasproperty(struct SEE_interpreter *interp, struct SEE_object *o,
|
||||
struct SEE_string *p)
|
||||
{
|
||||
/* all unknown properties return UNDEFINED value */
|
||||
checktime(interp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct js_input *
|
||||
js_get_input_object(struct SEE_interpreter *interp, struct js_form *jsform,
|
||||
struct form_state *fs)
|
||||
{
|
||||
struct js_input *jsinput;
|
||||
|
||||
checktime(interp);
|
||||
if (fs->ecmascript_obj)
|
||||
return fs->ecmascript_obj;
|
||||
|
||||
/* jsform ('form') is input's parent */
|
||||
/* FIXME: That is NOT correct since the real containing element
|
||||
* should be its parent, but gimme DOM first. --pasky */
|
||||
jsinput = SEE_NEW(interp, struct js_input);
|
||||
|
||||
jsinput->object.objectclass = &js_input_object_class;
|
||||
jsinput->object.objectclass->Class = s_input;
|
||||
jsinput->object.Prototype = NULL;
|
||||
|
||||
jsinput->blur = SEE_cfunction_make(interp, js_input_blur, s_blur, 0);
|
||||
jsinput->click = SEE_cfunction_make(interp, js_input_click, s_click, 0);
|
||||
jsinput->focus = SEE_cfunction_make(interp, js_input_focus, s_focus, 0);
|
||||
jsinput->select = SEE_cfunction_make(interp, js_input_select, s_select, 0);
|
||||
|
||||
jsinput->fs = fs;
|
||||
jsinput->parent = jsform;
|
||||
|
||||
fs->ecmascript_obj = jsinput;
|
||||
return jsinput;
|
||||
}
|
||||
|
||||
static struct js_input *
|
||||
js_get_form_control_object(struct SEE_interpreter *interp, struct js_form *jsform,
|
||||
enum form_type type, struct form_state *fs)
|
||||
{
|
||||
checktime(interp);
|
||||
switch (type) {
|
||||
case FC_TEXT:
|
||||
case FC_PASSWORD:
|
||||
case FC_FILE:
|
||||
case FC_CHECKBOX:
|
||||
case FC_RADIO:
|
||||
case FC_SUBMIT:
|
||||
case FC_IMAGE:
|
||||
case FC_RESET:
|
||||
case FC_BUTTON:
|
||||
case FC_HIDDEN:
|
||||
return js_get_input_object(interp, jsform, fs);
|
||||
|
||||
case FC_TEXTAREA:
|
||||
case FC_SELECT:
|
||||
/* TODO */
|
||||
return NULL;
|
||||
|
||||
default:
|
||||
INTERNAL("Weird fc->type %d", type);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
js_form_elems_item(struct SEE_interpreter *interp, struct SEE_object *self,
|
||||
struct SEE_object *thisobj, int argc, struct SEE_value **argv,
|
||||
struct SEE_value *res)
|
||||
{
|
||||
struct global_object *g = (struct global_object *)interp;
|
||||
struct view_state *vs = g->win->vs;
|
||||
struct document_view *doc_view = vs->doc_view;
|
||||
struct document *document = doc_view->document;
|
||||
struct js_form_elems *jsfe = (struct js_form_elems *)thisobj;
|
||||
struct js_form *parent_form = jsfe->parent;
|
||||
struct form_view *fv = parent_form->fv;
|
||||
struct form *form = find_form_by_form_view(document, fv);
|
||||
struct form_control *fc;
|
||||
unsigned char *string;
|
||||
int counter = -1;
|
||||
int index;
|
||||
|
||||
checktime(interp);
|
||||
SEE_SET_UNDEFINED(res);
|
||||
if (argc < 1)
|
||||
return;
|
||||
string = SEE_value_to_unsigned_char(interp, argv[0]);
|
||||
if (!string)
|
||||
return;
|
||||
index = atol(string);
|
||||
mem_free(string);
|
||||
|
||||
foreach (fc, form->items) {
|
||||
counter++;
|
||||
if (counter == index) {
|
||||
struct js_input *fcobj = js_get_form_control_object(interp, parent_form, fc->type, find_form_state(doc_view, fc));
|
||||
|
||||
if (fcobj) {
|
||||
SEE_SET_OBJECT(res, (struct SEE_object *)fcobj);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
js_form_elems_namedItem(struct SEE_interpreter *interp, struct SEE_object *self,
|
||||
struct SEE_object *thisobj, int argc, struct SEE_value **argv,
|
||||
struct SEE_value *res)
|
||||
{
|
||||
struct global_object *g = (struct global_object *)interp;
|
||||
struct view_state *vs = g->win->vs;
|
||||
struct document_view *doc_view = vs->doc_view;
|
||||
struct document *document = doc_view->document;
|
||||
struct js_form_elems *jsfe = (struct js_form_elems *)thisobj;
|
||||
struct js_form *parent_form = jsfe->parent;
|
||||
struct form_view *fv = parent_form->fv;
|
||||
struct form *form = find_form_by_form_view(document, fv);
|
||||
struct form_control *fc;
|
||||
unsigned char *string;
|
||||
|
||||
checktime(interp);
|
||||
SEE_SET_UNDEFINED(res);
|
||||
if (argc < 1)
|
||||
return;
|
||||
string = SEE_value_to_unsigned_char(interp, argv[0]);
|
||||
if (!string)
|
||||
return;
|
||||
|
||||
foreach (fc, form->items) {
|
||||
if (fc->name && !strcasecmp(string, fc->name)) {
|
||||
struct js_input *fcobj = js_get_form_control_object(interp, parent_form, fc->type, find_form_state(doc_view, fc));
|
||||
|
||||
if (fcobj) {
|
||||
SEE_SET_OBJECT(res, (struct SEE_object *)fcobj);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
mem_free(string);
|
||||
}
|
||||
|
||||
static void
|
||||
form_elems_get(struct SEE_interpreter *interp, struct SEE_object *o,
|
||||
struct SEE_string *p, struct SEE_value *res)
|
||||
{
|
||||
struct global_object *g = (struct global_object *)interp;
|
||||
struct view_state *vs = g->win->vs;
|
||||
struct document_view *doc_view = vs->doc_view;
|
||||
struct document *document = doc_view->document;
|
||||
struct js_form_elems *jsfe = (struct js_form_elems *)o;
|
||||
struct js_form *parent_form = jsfe->parent;
|
||||
struct form_view *fv = parent_form->fv;
|
||||
struct form *form = find_form_by_form_view(document, fv);
|
||||
|
||||
checktime(interp);
|
||||
if (p == s_length) {
|
||||
SEE_number_t length = list_size(&form->items);
|
||||
SEE_SET_NUMBER(res, length);
|
||||
} else {
|
||||
unsigned char *string = SEE_string_to_unsigned_char(p);
|
||||
struct SEE_value argv;
|
||||
|
||||
if (!string) {
|
||||
SEE_SET_UNDEFINED(res);
|
||||
return;
|
||||
}
|
||||
SEE_SET_STRING(&argv, p);
|
||||
if (string[0] >= '0' && string[1] <= '9') {
|
||||
js_form_elems_item(interp, o, NULL, 1,
|
||||
(struct SEE_value **)&argv, res);
|
||||
} else {
|
||||
js_form_elems_namedItem(interp, o, NULL, 1,
|
||||
(struct SEE_value **)&argv, res);
|
||||
}
|
||||
mem_free(string);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
form_elems_hasproperty(struct SEE_interpreter *interp, struct SEE_object *o,
|
||||
struct SEE_string *p)
|
||||
{
|
||||
checktime(interp);
|
||||
/* all unknown properties return UNDEFINED value */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
js_forms_item(struct SEE_interpreter *interp, struct SEE_object *self,
|
||||
struct SEE_object *thisobj, int argc, struct SEE_value **argv,
|
||||
struct SEE_value *res)
|
||||
{
|
||||
struct global_object *g = (struct global_object *)interp;
|
||||
struct view_state *vs = g->win->vs;
|
||||
struct js_forms_object *fo = (struct js_forms_object *)thisobj;
|
||||
struct js_document_object *doc = fo->parent;
|
||||
struct form_view *fv;
|
||||
unsigned char *string;
|
||||
int counter = -1;
|
||||
int index;
|
||||
|
||||
checktime(interp);
|
||||
SEE_SET_UNDEFINED(res);
|
||||
if (argc < 1)
|
||||
return;
|
||||
|
||||
string = SEE_value_to_unsigned_char(interp, argv[0]);
|
||||
if (!string)
|
||||
return;
|
||||
index = atol(string);
|
||||
mem_free(string);
|
||||
|
||||
foreach (fv, vs->forms) {
|
||||
counter++;
|
||||
if (counter == index) {
|
||||
struct js_form *obj = js_get_form_object(interp, doc, fv);
|
||||
|
||||
SEE_SET_OBJECT(res, (struct SEE_object *)obj);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
js_forms_namedItem(struct SEE_interpreter *interp, struct SEE_object *self,
|
||||
struct SEE_object *thisobj, int argc, struct SEE_value **argv,
|
||||
struct SEE_value *res)
|
||||
{
|
||||
struct global_object *g = (struct global_object *)interp;
|
||||
struct view_state *vs = g->win->vs;
|
||||
struct document_view *doc_view = vs->doc_view;
|
||||
struct document *document = doc_view->document;
|
||||
struct js_forms_object *fo = (struct js_forms_object *)thisobj;
|
||||
struct js_document_object *doc = fo->parent;
|
||||
struct form *form;
|
||||
unsigned char *string;
|
||||
|
||||
checktime(interp);
|
||||
SEE_SET_UNDEFINED(res);
|
||||
if (argc < 1)
|
||||
return;
|
||||
|
||||
string = SEE_value_to_unsigned_char(interp, argv[0]);
|
||||
if (!string)
|
||||
return;
|
||||
foreach (form, document->forms) {
|
||||
if (form->name && !strcasecmp(string, form->name)) {
|
||||
struct form_view *fv = find_form_view(doc_view, form);
|
||||
struct js_form *obj = js_get_form_object(interp,
|
||||
doc, fv);
|
||||
|
||||
SEE_SET_OBJECT(res, (struct SEE_object *)obj);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
mem_free(string);
|
||||
}
|
||||
|
||||
static void
|
||||
forms_get(struct SEE_interpreter *interp, struct SEE_object *o,
|
||||
struct SEE_string *p, struct SEE_value *res)
|
||||
{
|
||||
struct global_object *g = (struct global_object *)interp;
|
||||
struct view_state *vs = g->win->vs;
|
||||
struct document_view *doc_view = vs->doc_view;
|
||||
struct document *document = doc_view->document;
|
||||
|
||||
checktime(interp);
|
||||
if (p == s_length) {
|
||||
SEE_number_t length = list_size(&document->forms);
|
||||
SEE_SET_NUMBER(res, length);
|
||||
} else {
|
||||
unsigned char *string = SEE_string_to_unsigned_char(p);
|
||||
struct SEE_value argv;
|
||||
|
||||
if (!string) {
|
||||
SEE_SET_UNDEFINED(res);
|
||||
return;
|
||||
}
|
||||
SEE_SET_STRING(&argv, p);
|
||||
if (string[0] >= '0' && string[1] <= '9') {
|
||||
js_forms_item(interp, o, NULL, 1,
|
||||
(struct SEE_value **)&argv, res);
|
||||
} else {
|
||||
js_forms_namedItem(interp, o, NULL, 1,
|
||||
(struct SEE_value **)&argv, res);
|
||||
}
|
||||
mem_free(string);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
forms_hasproperty(struct SEE_interpreter *interp, struct SEE_object *o,
|
||||
struct SEE_string *p)
|
||||
{
|
||||
checktime(interp);
|
||||
/* all unknown properties return UNDEFINED value */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
form_get(struct SEE_interpreter *interp, struct SEE_object *o,
|
||||
struct SEE_string *p, struct SEE_value *res)
|
||||
{
|
||||
struct global_object *g = (struct global_object *)interp;
|
||||
struct view_state *vs = g->win->vs;
|
||||
struct document_view *doc_view = vs->doc_view;
|
||||
struct js_form *js_form = (struct js_form *)o;
|
||||
struct form_view *fv = js_form->fv;
|
||||
struct form *form = find_form_by_form_view(doc_view->document, fv);
|
||||
struct SEE_string *str;
|
||||
|
||||
checktime(interp);
|
||||
SEE_SET_UNDEFINED(res);
|
||||
|
||||
if (p == s_action) {
|
||||
str = string_to_SEE_string(interp, form->action);
|
||||
SEE_SET_STRING(res, str);
|
||||
} else if (p == s_encoding) {
|
||||
switch (form->method) {
|
||||
case FORM_METHOD_GET:
|
||||
case FORM_METHOD_POST:
|
||||
/* "application/x-www-form-urlencoded" */
|
||||
SEE_SET_STRING(res, s_application_);
|
||||
break;
|
||||
case FORM_METHOD_POST_MP:
|
||||
/* "multipart/form-data" */
|
||||
SEE_SET_STRING(res, s_multipart_);
|
||||
break;
|
||||
case FORM_METHOD_POST_TEXT_PLAIN:
|
||||
/* "text/plain") */
|
||||
SEE_SET_STRING(res, s_textplain);
|
||||
break;
|
||||
}
|
||||
} else if (p == s_length) {
|
||||
SEE_number_t num = list_size(&form->items);
|
||||
SEE_SET_NUMBER(res, num);
|
||||
} else if (p == s_method) {
|
||||
switch (form->method) {
|
||||
case FORM_METHOD_GET:
|
||||
SEE_SET_STRING(res, s_GET);
|
||||
break;
|
||||
|
||||
case FORM_METHOD_POST:
|
||||
case FORM_METHOD_POST_MP:
|
||||
case FORM_METHOD_POST_TEXT_PLAIN:
|
||||
SEE_SET_STRING(res, s_POST);
|
||||
break;
|
||||
}
|
||||
} else if (p == s_name) {
|
||||
str = string_to_SEE_string(interp, form->name);
|
||||
SEE_SET_STRING(res, str);
|
||||
} else if (p == s_target) {
|
||||
str = string_to_SEE_string(interp, form->target);
|
||||
SEE_SET_STRING(res, str);
|
||||
} else if (p == s_elements) {
|
||||
struct js_form_elems *jsfe = SEE_NEW(interp, struct js_form_elems);
|
||||
|
||||
jsfe->object.objectclass = &js_form_elems_class;
|
||||
jsfe->object.objectclass->Class = s_elements;
|
||||
jsfe->object.Prototype = NULL;
|
||||
jsfe->parent = js_form;
|
||||
jsfe->item = SEE_cfunction_make(interp, js_form_elems_item, s_item, 1);
|
||||
jsfe->namedItem = SEE_cfunction_make(interp, js_form_elems_namedItem, s_namedItem, 1);
|
||||
SEE_SET_OBJECT(res, (struct SEE_object *)jsfe);
|
||||
} else if (p == s_submit) {
|
||||
SEE_SET_OBJECT(res, js_form->submit);
|
||||
} else if (p == s_reset) {
|
||||
SEE_SET_OBJECT(res, js_form->reset);
|
||||
} else {
|
||||
unsigned char *string = SEE_string_to_unsigned_char(p);
|
||||
struct form_control *fc;
|
||||
|
||||
if (!string)
|
||||
return;
|
||||
foreach(fc, form->items) {
|
||||
struct js_input *fcobj = NULL;
|
||||
|
||||
if (!fc->name || strcasecmp(string, fc->name))
|
||||
continue;
|
||||
fcobj = js_get_form_control_object(interp, js_form, fc->type, find_form_state(doc_view, fc));
|
||||
|
||||
if (fcobj) {
|
||||
SEE_SET_OBJECT(res, (struct SEE_object *)fcobj);
|
||||
}
|
||||
break;
|
||||
}
|
||||
mem_free(string);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
form_put(struct SEE_interpreter *interp, struct SEE_object *o,
|
||||
struct SEE_string *p, struct SEE_value *val, int attr)
|
||||
{
|
||||
struct global_object *g = (struct global_object *)interp;
|
||||
struct view_state *vs = g->win->vs;
|
||||
struct document_view *doc_view = vs->doc_view;
|
||||
struct js_form *js_form = (struct js_form *)o;
|
||||
struct form_view *fv = js_form->fv;
|
||||
struct form *form = find_form_by_form_view(doc_view->document, fv);
|
||||
unsigned char *string = SEE_value_to_unsigned_char(interp, val);
|
||||
|
||||
checktime(interp);
|
||||
if (!string)
|
||||
return;
|
||||
|
||||
if (p == s_action) {
|
||||
mem_free_set(&form->action, string);
|
||||
} else if (p == s_encoding) {
|
||||
if (!strcasecmp(string, "application/x-www-form-urlencoded")) {
|
||||
form->method = form->method == FORM_METHOD_GET ? FORM_METHOD_GET
|
||||
: FORM_METHOD_POST;
|
||||
} else if (!strcasecmp(string, "multipart/form-data")) {
|
||||
form->method = FORM_METHOD_POST_MP;
|
||||
} else if (!strcasecmp(string, "text/plain")) {
|
||||
form->method = FORM_METHOD_POST_TEXT_PLAIN;
|
||||
}
|
||||
mem_free(string);
|
||||
} else if (p == s_method) {
|
||||
if (!strcasecmp(string, "GET")) {
|
||||
form->method = FORM_METHOD_GET;
|
||||
} else if (!strcasecmp(string, "POST")) {
|
||||
form->method = FORM_METHOD_POST;
|
||||
}
|
||||
mem_free(string);
|
||||
} else if (p == s_name) {
|
||||
mem_free_set(&form->name, string);
|
||||
} else if (p == s_target) {
|
||||
mem_free_set(&form->target, string);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
form_canput(struct SEE_interpreter *interp, struct SEE_object *o,
|
||||
struct SEE_string *p)
|
||||
{
|
||||
checktime(interp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
form_hasproperty(struct SEE_interpreter *interp, struct SEE_object *o,
|
||||
struct SEE_string *p)
|
||||
{
|
||||
checktime(interp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
js_form_reset(struct SEE_interpreter *interp, struct SEE_object *self,
|
||||
struct SEE_object *thisobj, int argc, struct SEE_value **argv,
|
||||
struct SEE_value *res)
|
||||
{
|
||||
struct global_object *g = (struct global_object *)interp;
|
||||
struct view_state *vs = g->win->vs;
|
||||
struct document_view *doc_view = vs->doc_view;
|
||||
struct js_form *js_form = (struct js_form *)thisobj;
|
||||
struct form_view *fv = js_form->fv;
|
||||
struct form *form = find_form_by_form_view(doc_view->document, fv);
|
||||
|
||||
assert(form);
|
||||
|
||||
checktime(interp);
|
||||
do_reset_form(doc_view, form);
|
||||
draw_forms(doc_view->session->tab->term, doc_view);
|
||||
SEE_SET_BOOLEAN(res, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
js_form_submit(struct SEE_interpreter *interp, struct SEE_object *self,
|
||||
struct SEE_object *thisobj, int argc, struct SEE_value **argv,
|
||||
struct SEE_value *res)
|
||||
{
|
||||
struct global_object *g = (struct global_object *)interp;
|
||||
struct view_state *vs = g->win->vs;
|
||||
struct document_view *doc_view = vs->doc_view;
|
||||
struct session *ses = doc_view->session;
|
||||
struct js_form *js_form = (struct js_form *)thisobj;
|
||||
struct form_view *fv = js_form->fv;
|
||||
struct form *form = find_form_by_form_view(doc_view->document, fv);
|
||||
|
||||
assert(form);
|
||||
checktime(interp);
|
||||
submit_given_form(ses, doc_view, form);
|
||||
SEE_SET_BOOLEAN(res, 0);
|
||||
}
|
||||
|
||||
struct js_form *js_get_form_object(struct SEE_interpreter *interp,
|
||||
struct js_document_object *doc, struct form_view *fv)
|
||||
{
|
||||
struct js_form *js_form;
|
||||
|
||||
checktime(interp);
|
||||
if (fv->ecmascript_obj)
|
||||
return fv->ecmascript_obj;
|
||||
|
||||
/* jsdoc ('document') is fv's parent */
|
||||
/* FIXME: That is NOT correct since the real containing element
|
||||
* should be its parent, but gimme DOM first. --pasky */
|
||||
js_form = SEE_NEW(interp, struct js_form);
|
||||
js_form->object.objectclass = &js_form_class;
|
||||
js_form->object.objectclass->Class = s_form;
|
||||
js_form->object.Prototype = NULL; /* TODO: use prototype for form */
|
||||
js_form->parent = doc;
|
||||
js_form->reset = SEE_cfunction_make(interp, js_form_reset, s_reset, 0);
|
||||
js_form->submit = SEE_cfunction_make(interp, js_form_submit, s_submit, 0);
|
||||
js_form->fv = fv;
|
||||
|
||||
fv->ecmascript_obj = js_form;
|
||||
return js_form;
|
||||
}
|
||||
|
||||
void
|
||||
init_js_forms_object(struct ecmascript_interpreter *interpreter)
|
||||
{
|
||||
struct global_object *g = interpreter->backend_data;
|
||||
struct SEE_interpreter *interp = &g->interp;
|
||||
struct SEE_value v, document;
|
||||
struct js_forms_object *forms = SEE_NEW(interp,
|
||||
struct js_forms_object);
|
||||
|
||||
forms->object.objectclass = &js_forms_object_class;
|
||||
forms->object.objectclass->Class = s_forms;
|
||||
forms->object.Prototype = NULL;
|
||||
|
||||
SEE_OBJECT_GET(interp, interp->Global, s_document, &document);
|
||||
SEE_SET_OBJECT(&v, (struct SEE_object *)forms);
|
||||
SEE_OBJECT_PUT(interp, document.u.object, s_forms, &v, 0);
|
||||
|
||||
forms->item = SEE_cfunction_make(interp, js_forms_item, s_item, 1);
|
||||
forms->namedItem = SEE_cfunction_make(interp, js_forms_namedItem,
|
||||
s_namedItem, 1);
|
||||
forms->parent = (struct js_document_object *)document.u.object;
|
||||
}
|
19
src/ecmascript/see/form.h
Normal file
19
src/ecmascript/see/form.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef EL__ECMASCRIPT_SEE_FORM_H
|
||||
#define EL__ECMASCRIPT_SEE_FORM_H
|
||||
|
||||
struct js_document_object;
|
||||
struct ecmascript_interpreter;
|
||||
struct form_view;
|
||||
|
||||
struct js_form {
|
||||
struct SEE_object object;
|
||||
struct js_document_object *parent;
|
||||
struct form_view *fv;
|
||||
struct SEE_object *reset;
|
||||
struct SEE_object *submit;
|
||||
};
|
||||
|
||||
struct js_form *js_get_form_object(struct SEE_interpreter *, struct js_document_object*, struct form_view *);
|
||||
void init_js_forms_object(struct ecmascript_interpreter *);
|
||||
|
||||
#endif
|
100
src/ecmascript/see/input.c
Normal file
100
src/ecmascript/see/input.c
Normal file
@ -0,0 +1,100 @@
|
||||
/* Input for SEE */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <see/see.h>
|
||||
#include <string.h>
|
||||
#include "ecmascript/see/input.h"
|
||||
#include "util/memory.h"
|
||||
|
||||
static SEE_unicode_t input_elinks_next(struct SEE_input *);
|
||||
static void input_elinks_close(struct SEE_input *);
|
||||
|
||||
static struct SEE_inputclass input_elinks_class = {
|
||||
input_elinks_next,
|
||||
input_elinks_close
|
||||
};
|
||||
|
||||
struct input_elinks {
|
||||
struct SEE_input inp;
|
||||
unsigned char *s;
|
||||
};
|
||||
|
||||
static SEE_unicode_t
|
||||
input_elinks_next(struct SEE_input *inp)
|
||||
{
|
||||
struct input_elinks *input = (struct input_elinks*)inp;
|
||||
SEE_unicode_t next;
|
||||
|
||||
next = input->inp.lookahead;
|
||||
|
||||
if (*input->s == '\0') {
|
||||
input->inp.eof = 1;
|
||||
} else {
|
||||
input->inp.lookahead = *input->s++;
|
||||
input->inp.eof = 0;
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
static void
|
||||
input_elinks_close(struct SEE_input *inp)
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
struct SEE_input *
|
||||
SEE_input_elinks(struct SEE_interpreter *interp, unsigned char *s)
|
||||
{
|
||||
struct input_elinks *input;
|
||||
|
||||
input = SEE_NEW(interp, struct input_elinks);
|
||||
input->inp.interpreter = interp;
|
||||
input->inp.inputclass = &input_elinks_class;
|
||||
input->inp.filename = NULL;
|
||||
input->inp.first_lineno = 1;
|
||||
input->s = s;
|
||||
SEE_INPUT_NEXT((struct SEE_input *)input); /* prime */
|
||||
return (struct SEE_input *)input;
|
||||
}
|
||||
|
||||
unsigned char *
|
||||
SEE_string_to_unsigned_char(struct SEE_string *S)
|
||||
{
|
||||
int i;
|
||||
unsigned char *str = mem_alloc(S->length + 1);
|
||||
|
||||
if (!str)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < S->length; i++)
|
||||
str[i] = (unsigned char)S->data[i];
|
||||
str[S->length] = '\0';
|
||||
return str;
|
||||
}
|
||||
|
||||
unsigned char *
|
||||
SEE_value_to_unsigned_char(struct SEE_interpreter *interp, struct SEE_value *val)
|
||||
{
|
||||
struct SEE_value result;
|
||||
|
||||
SEE_ToString(interp, val, &result);
|
||||
return SEE_string_to_unsigned_char(result.u.string);
|
||||
}
|
||||
|
||||
struct SEE_string *
|
||||
string_to_SEE_string(struct SEE_interpreter *interp, unsigned char *s)
|
||||
{
|
||||
unsigned int len;
|
||||
unsigned int i;
|
||||
struct SEE_string *str;
|
||||
|
||||
len = s ? strlen(s) : 0;
|
||||
str = SEE_string_new(interp, len);
|
||||
str->length = len;
|
||||
for (i = 0; i < len; i++)
|
||||
str->data[i] = s[i];
|
||||
return str;
|
||||
}
|
11
src/ecmascript/see/input.h
Normal file
11
src/ecmascript/see/input.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef EL__ECMASCRIPT_SEE_INPUT_H
|
||||
#define EL__ECMASCRIPT_SEE_INPUT_H
|
||||
|
||||
#include <see/see.h>
|
||||
|
||||
struct SEE_input *SEE_input_elinks(struct SEE_interpreter *, unsigned char *);
|
||||
unsigned char *SEE_string_to_unsigned_char(struct SEE_string *);
|
||||
unsigned char *SEE_value_to_unsigned_char(struct SEE_interpreter *, struct SEE_value *);
|
||||
struct SEE_string *string_to_SEE_string(struct SEE_interpreter *, unsigned char *);
|
||||
|
||||
#endif
|
363
src/ecmascript/see/location.c
Normal file
363
src/ecmascript/see/location.c
Normal file
@ -0,0 +1,363 @@
|
||||
/* The SEE location and history objects implementation. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "elinks.h"
|
||||
|
||||
#include <see/see.h>
|
||||
|
||||
#include "bfu/dialog.h"
|
||||
#include "cache/cache.h"
|
||||
#include "cookies/cookies.h"
|
||||
#include "dialogs/menu.h"
|
||||
#include "dialogs/status.h"
|
||||
#include "document/html/frames.h"
|
||||
#include "document/document.h"
|
||||
#include "document/forms.h"
|
||||
#include "document/view.h"
|
||||
#include "ecmascript/ecmascript.h"
|
||||
#include "ecmascript/see/input.h"
|
||||
#include "ecmascript/see/location.h"
|
||||
#include "ecmascript/see/strings.h"
|
||||
#include "ecmascript/see/window.h"
|
||||
#include "intl/gettext/libintl.h"
|
||||
#include "main/select.h"
|
||||
#include "osdep/newwin.h"
|
||||
#include "osdep/sysname.h"
|
||||
#include "protocol/http/http.h"
|
||||
#include "protocol/uri.h"
|
||||
#include "session/history.h"
|
||||
#include "session/location.h"
|
||||
#include "session/session.h"
|
||||
#include "session/task.h"
|
||||
#include "terminal/tab.h"
|
||||
#include "terminal/terminal.h"
|
||||
#include "util/conv.h"
|
||||
#include "util/memory.h"
|
||||
#include "util/string.h"
|
||||
#include "viewer/text/draw.h"
|
||||
#include "viewer/text/form.h"
|
||||
#include "viewer/text/link.h"
|
||||
#include "viewer/text/vs.h"
|
||||
|
||||
static void delayed_goto(void *);
|
||||
static void history_get(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *);
|
||||
static int history_hasproperty(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
|
||||
static void js_history_back(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
|
||||
static void js_history_forward(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
|
||||
static void js_history_go(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
|
||||
static void js_location_toString(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
|
||||
static void location_get(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *);
|
||||
static void location_put(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *, int);
|
||||
static int location_hasproperty(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
|
||||
static int location_canput(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
|
||||
|
||||
void location_goto(struct document_view *, unsigned char *);
|
||||
|
||||
struct js_history_object {
|
||||
struct SEE_object object;
|
||||
struct SEE_object *back;
|
||||
struct SEE_object *forward;
|
||||
struct SEE_object *go;
|
||||
};
|
||||
|
||||
struct js_location_object {
|
||||
struct SEE_object object;
|
||||
struct SEE_object *toString;
|
||||
};
|
||||
|
||||
struct delayed_goto {
|
||||
/* It might look more convenient to pass doc_view around but it could
|
||||
* disappear during wild dances inside of frames or so. */
|
||||
struct view_state *vs;
|
||||
struct uri *uri;
|
||||
};
|
||||
|
||||
struct SEE_objectclass js_history_object_class = {
|
||||
NULL,
|
||||
history_get,
|
||||
SEE_no_put,
|
||||
SEE_no_canput,
|
||||
history_hasproperty,
|
||||
SEE_no_delete,
|
||||
SEE_no_defaultvalue,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
struct SEE_objectclass js_location_object_class = {
|
||||
NULL,
|
||||
location_get,
|
||||
location_put,
|
||||
location_canput,
|
||||
location_hasproperty,
|
||||
SEE_no_delete,
|
||||
SEE_no_defaultvalue,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
static void
|
||||
delayed_goto(void *data)
|
||||
{
|
||||
struct delayed_goto *deg = data;
|
||||
|
||||
assert(deg);
|
||||
if (deg->vs->doc_view
|
||||
&& deg->vs->doc_view == deg->vs->doc_view->session->doc_view) {
|
||||
goto_uri_frame(deg->vs->doc_view->session, deg->uri,
|
||||
deg->vs->doc_view->name,
|
||||
CACHE_MODE_NORMAL);
|
||||
}
|
||||
done_uri(deg->uri);
|
||||
mem_free(deg);
|
||||
}
|
||||
|
||||
void
|
||||
location_goto(struct document_view *doc_view, unsigned char *url)
|
||||
{
|
||||
unsigned char *new_abs_url;
|
||||
struct uri *new_uri;
|
||||
struct delayed_goto *deg;
|
||||
|
||||
/* Workaround for bug 611. Does not crash, but may lead to infinite loop.*/
|
||||
if (!doc_view) return;
|
||||
new_abs_url = join_urls(doc_view->document->uri,
|
||||
trim_chars(url, ' ', 0));
|
||||
if (!new_abs_url)
|
||||
return;
|
||||
new_uri = get_uri(new_abs_url, 0);
|
||||
mem_free(new_abs_url);
|
||||
if (!new_uri)
|
||||
return;
|
||||
deg = mem_calloc(1, sizeof(*deg));
|
||||
if (!deg) {
|
||||
done_uri(new_uri);
|
||||
return;
|
||||
}
|
||||
assert(doc_view->vs);
|
||||
deg->vs = doc_view->vs;
|
||||
deg->uri = new_uri;
|
||||
/* It does not seem to be very safe inside of frames to
|
||||
* call goto_uri() right away. */
|
||||
register_bottom_half(delayed_goto, deg);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
history_get(struct SEE_interpreter *interp, struct SEE_object *o,
|
||||
struct SEE_string *p, struct SEE_value *res)
|
||||
{
|
||||
struct js_history_object *history = (struct js_history_object *)o;
|
||||
|
||||
checktime(interp);
|
||||
if (p == s_back) {
|
||||
SEE_SET_OBJECT(res, history->back);
|
||||
} else if (p == s_forward) {
|
||||
SEE_SET_OBJECT(res, history->forward);
|
||||
} else if (p == s_go) {
|
||||
SEE_SET_OBJECT(res, history->go);
|
||||
} else {
|
||||
SEE_SET_UNDEFINED(res);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
history_hasproperty(struct SEE_interpreter *interp, struct SEE_object *o,
|
||||
struct SEE_string *p)
|
||||
{
|
||||
checktime(interp);
|
||||
if (p == s_back || p == s_forward || p == s_go)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
js_history_back(struct SEE_interpreter *interp, struct SEE_object *self,
|
||||
struct SEE_object *thisobj, int argc, struct SEE_value **argv,
|
||||
struct SEE_value *res)
|
||||
{
|
||||
struct global_object *g = (struct global_object *)interp;
|
||||
struct view_state *vs = g->win->vs;
|
||||
struct document_view *doc_view = vs->doc_view;
|
||||
struct session *ses = doc_view->session;
|
||||
|
||||
SEE_SET_NULL(res);
|
||||
go_back(ses);
|
||||
}
|
||||
|
||||
static void
|
||||
js_history_forward(struct SEE_interpreter *interp, struct SEE_object *self,
|
||||
struct SEE_object *thisobj, int argc, struct SEE_value **argv,
|
||||
struct SEE_value *res)
|
||||
{
|
||||
struct global_object *g = (struct global_object *)interp;
|
||||
struct view_state *vs = g->win->vs;
|
||||
struct document_view *doc_view = vs->doc_view;
|
||||
struct session *ses = doc_view->session;
|
||||
|
||||
checktime(interp);
|
||||
SEE_SET_NULL(res);
|
||||
go_unback(ses);
|
||||
}
|
||||
|
||||
static void
|
||||
js_history_go(struct SEE_interpreter *interp, struct SEE_object *self,
|
||||
struct SEE_object *thisobj, int argc, struct SEE_value **argv,
|
||||
struct SEE_value *res)
|
||||
{
|
||||
struct global_object *g = (struct global_object *)interp;
|
||||
struct view_state *vs = g->win->vs;
|
||||
struct document_view *doc_view = vs->doc_view;
|
||||
struct session *ses = doc_view->session;
|
||||
unsigned char *str;
|
||||
int index;
|
||||
struct location *loc;
|
||||
|
||||
checktime(interp);
|
||||
SEE_SET_NULL(res);
|
||||
if (argc < 1)
|
||||
return;
|
||||
|
||||
str = SEE_value_to_unsigned_char(interp, argv[0]);
|
||||
if (!str)
|
||||
return;
|
||||
|
||||
index = atol(str);
|
||||
mem_free(str);
|
||||
|
||||
for (loc = cur_loc(ses);
|
||||
loc != (struct location *) &ses->history.history;
|
||||
loc = index > 0 ? loc->next : loc->prev) {
|
||||
if (!index) {
|
||||
go_history(ses, loc);
|
||||
break;
|
||||
}
|
||||
|
||||
index += index > 0 ? -1 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
js_location_toString(struct SEE_interpreter *interp, struct SEE_object *self,
|
||||
struct SEE_object *thisobj, int argc, struct SEE_value **argv,
|
||||
struct SEE_value *res)
|
||||
{
|
||||
struct global_object *g = (struct global_object *)interp;
|
||||
struct view_state *vs = g->win->vs;
|
||||
unsigned char *string = get_uri_string(vs->uri, URI_ORIGINAL);
|
||||
struct SEE_string *str = string_to_SEE_string(interp, string);
|
||||
|
||||
mem_free_if(string);
|
||||
checktime(interp);
|
||||
|
||||
SEE_SET_STRING(res, str);
|
||||
}
|
||||
|
||||
static void
|
||||
location_get(struct SEE_interpreter *interp, struct SEE_object *o,
|
||||
struct SEE_string *p, struct SEE_value *res)
|
||||
{
|
||||
struct js_location_object *loc = (struct js_location_object *)o;
|
||||
|
||||
checktime(interp);
|
||||
if (p == s_toString || p == s_toLocaleString) {
|
||||
SEE_SET_OBJECT(res, loc->toString);
|
||||
} else if (p == s_href) {
|
||||
struct global_object *g = (struct global_object *)interp;
|
||||
struct view_state *vs = g->win->vs;
|
||||
unsigned char *string = get_uri_string(vs->uri, URI_ORIGINAL);
|
||||
struct SEE_string *str = string_to_SEE_string(interp, string);
|
||||
|
||||
mem_free_if(string);
|
||||
SEE_SET_STRING(res, str);
|
||||
} else {
|
||||
SEE_SET_UNDEFINED(res);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
location_put(struct SEE_interpreter *interp, struct SEE_object *o,
|
||||
struct SEE_string *p, struct SEE_value *val, int attr)
|
||||
{
|
||||
checktime(interp);
|
||||
if (p == s_href) {
|
||||
struct global_object *g = (struct global_object *)interp;
|
||||
struct view_state *vs = g->win->vs;
|
||||
struct document_view *doc_view = vs->doc_view;
|
||||
unsigned char *url = SEE_value_to_unsigned_char(interp, val);
|
||||
|
||||
location_goto(doc_view, url);
|
||||
mem_free(url);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
location_hasproperty(struct SEE_interpreter *interp, struct SEE_object *o,
|
||||
struct SEE_string *p)
|
||||
{
|
||||
checktime(interp);
|
||||
if (p == s_toString || p == s_toLocaleString || p == s_href)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
location_canput(struct SEE_interpreter *interp, struct SEE_object *o,
|
||||
struct SEE_string *p)
|
||||
{
|
||||
checktime(interp);
|
||||
if (p == s_href)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
init_js_history_object(struct ecmascript_interpreter *interpreter)
|
||||
{
|
||||
struct global_object *g = interpreter->backend_data;
|
||||
struct SEE_interpreter *interp = &g->interp;
|
||||
struct SEE_value v;
|
||||
struct js_history_object *history = SEE_NEW(interp,
|
||||
struct js_history_object);
|
||||
|
||||
history->object.objectclass = &js_history_object_class;
|
||||
history->object.objectclass->Class = s_history;
|
||||
history->object.Prototype = NULL;
|
||||
|
||||
SEE_SET_OBJECT(&v, (struct SEE_object *)history);
|
||||
SEE_OBJECT_PUT(interp, interp->Global, s_history, &v, 0);
|
||||
|
||||
history->back = SEE_cfunction_make(interp, js_history_back, s_back, 0);
|
||||
history->forward = SEE_cfunction_make(interp, js_history_forward, s_forward, 0);
|
||||
history->go = SEE_cfunction_make(interp, js_history_go, s_go, 1);
|
||||
}
|
||||
|
||||
void
|
||||
init_js_location_object(struct ecmascript_interpreter *interpreter)
|
||||
{
|
||||
struct global_object *g = interpreter->backend_data;
|
||||
struct SEE_interpreter *interp = &g->interp;
|
||||
struct SEE_value v;
|
||||
struct js_location_object *loc = SEE_NEW(interp,
|
||||
struct js_location_object);
|
||||
|
||||
loc->object.objectclass = &js_location_object_class;
|
||||
loc->object.objectclass->Class = s_location;
|
||||
loc->object.Prototype = NULL;
|
||||
|
||||
SEE_SET_OBJECT(&v, (struct SEE_object *)loc);
|
||||
SEE_OBJECT_PUT(interp, interp->Global, s_location, &v, 0);
|
||||
|
||||
loc->toString = SEE_cfunction_make(interp, js_location_toString, s_toString, 0);
|
||||
}
|
9
src/ecmascript/see/location.h
Normal file
9
src/ecmascript/see/location.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef EL__ECMASCRIPT_SEE_LOCATION_H
|
||||
#define EL__ECMASCRIPT_SEE_LOCATION_H
|
||||
|
||||
struct ecmascript_interpreter;
|
||||
|
||||
void init_js_history_object(struct ecmascript_interpreter *);
|
||||
void init_js_location_object(struct ecmascript_interpreter *);
|
||||
|
||||
#endif
|
150
src/ecmascript/see/navigator.c
Normal file
150
src/ecmascript/see/navigator.c
Normal file
@ -0,0 +1,150 @@
|
||||
/* The SEE navigator objects implementation. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "elinks.h"
|
||||
|
||||
#include <see/see.h>
|
||||
|
||||
#include "bfu/dialog.h"
|
||||
#include "cache/cache.h"
|
||||
#include "cookies/cookies.h"
|
||||
#include "dialogs/menu.h"
|
||||
#include "dialogs/status.h"
|
||||
#include "document/html/frames.h"
|
||||
#include "document/document.h"
|
||||
#include "document/forms.h"
|
||||
#include "document/view.h"
|
||||
#include "ecmascript/ecmascript.h"
|
||||
#include "ecmascript/see/input.h"
|
||||
#include "ecmascript/see/navigator.h"
|
||||
#include "ecmascript/see/strings.h"
|
||||
#include "ecmascript/see/window.h"
|
||||
#include "intl/gettext/libintl.h"
|
||||
#include "main/select.h"
|
||||
#include "osdep/newwin.h"
|
||||
#include "osdep/sysname.h"
|
||||
#include "protocol/http/http.h"
|
||||
#include "protocol/uri.h"
|
||||
#include "session/history.h"
|
||||
#include "session/location.h"
|
||||
#include "session/session.h"
|
||||
#include "session/task.h"
|
||||
#include "terminal/tab.h"
|
||||
#include "terminal/terminal.h"
|
||||
#include "util/conv.h"
|
||||
#include "util/memory.h"
|
||||
#include "util/string.h"
|
||||
#include "viewer/text/draw.h"
|
||||
#include "viewer/text/form.h"
|
||||
#include "viewer/text/link.h"
|
||||
#include "viewer/text/vs.h"
|
||||
|
||||
static void navigator_get(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *);
|
||||
static int navigator_hasproperty(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
|
||||
|
||||
struct SEE_objectclass js_navigator_object_class = {
|
||||
NULL,
|
||||
navigator_get,
|
||||
SEE_no_put,
|
||||
SEE_no_canput,
|
||||
navigator_hasproperty,
|
||||
SEE_no_delete,
|
||||
SEE_no_defaultvalue,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
static void
|
||||
navigator_get(struct SEE_interpreter *interp, struct SEE_object *o,
|
||||
struct SEE_string *p, struct SEE_value *res)
|
||||
{
|
||||
struct SEE_string *str;
|
||||
|
||||
checktime(interp);
|
||||
SEE_SET_UNDEFINED(res);
|
||||
if (p == s_appCodeName) {
|
||||
SEE_SET_STRING(res, s_Mozilla);
|
||||
} else if (p == s_appName) {
|
||||
SEE_SET_STRING(res, s_ELinks_);
|
||||
} else if (p == s_appVersion) {
|
||||
str = string_to_SEE_string(interp, VERSION);
|
||||
SEE_SET_STRING(res, str);
|
||||
} else if (p == s_language) {
|
||||
#ifdef CONFIG_NLS
|
||||
if (get_opt_bool("protocol.http.accept_ui_language")) {
|
||||
str = string_to_SEE_string(interp,
|
||||
language_to_iso639(current_language));
|
||||
SEE_SET_STRING(res, str);
|
||||
}
|
||||
#endif
|
||||
} else if (p == s_platform) {
|
||||
str = string_to_SEE_string(interp, system_name);
|
||||
SEE_SET_STRING(res, str);
|
||||
} else if (p == s_userAgent) {
|
||||
/* FIXME: Code duplication. */
|
||||
unsigned char *optstr = get_opt_str("protocol.http.user_agent");
|
||||
|
||||
if (*optstr && strcmp(optstr, " ")) {
|
||||
unsigned char *ustr, ts[64] = "";
|
||||
static unsigned char custr[256];
|
||||
|
||||
if (!list_empty(terminals)) {
|
||||
unsigned int tslen = 0;
|
||||
struct terminal *term = terminals.prev;
|
||||
|
||||
ulongcat(ts, &tslen, term->width, 3, 0);
|
||||
ts[tslen++] = 'x';
|
||||
ulongcat(ts, &tslen, term->height, 3, 0);
|
||||
}
|
||||
ustr = subst_user_agent(optstr, VERSION_STRING, system_name, ts);
|
||||
|
||||
if (ustr) {
|
||||
safe_strncpy(custr, ustr, 256);
|
||||
mem_free(ustr);
|
||||
str = string_to_SEE_string(interp, custr);
|
||||
SEE_SET_STRING(res, str);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
navigator_hasproperty(struct SEE_interpreter *interp, struct SEE_object *o,
|
||||
struct SEE_string *p)
|
||||
{
|
||||
checktime(interp);
|
||||
if (p == s_appCodeName || p == s_appName || p == s_appVersion
|
||||
|| p == s_language || p == s_platform || p == s_userAgent)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
init_js_navigator_object(struct ecmascript_interpreter *interpreter)
|
||||
{
|
||||
struct global_object *g = interpreter->backend_data;
|
||||
struct SEE_interpreter *interp = &g->interp;
|
||||
struct SEE_value v;
|
||||
struct SEE_object *navigator;
|
||||
|
||||
navigator = SEE_NEW(interp, struct SEE_object);
|
||||
|
||||
navigator->objectclass = &js_navigator_object_class;
|
||||
navigator->objectclass->Class = s_navigator;
|
||||
navigator->Prototype = NULL;
|
||||
|
||||
SEE_SET_OBJECT(&v, navigator);
|
||||
SEE_OBJECT_PUT(interp, interp->Global, s_navigator, &v, 0);
|
||||
}
|
8
src/ecmascript/see/navigator.h
Normal file
8
src/ecmascript/see/navigator.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef EL__ECMASCRIPT_SEE_NAVIGATOR_H
|
||||
#define EL__ECMASCRIPT_SEE_NAVIGATOR_H
|
||||
|
||||
struct ecmascript_interpreter;
|
||||
|
||||
void init_js_navigator_object(struct ecmascript_interpreter *);
|
||||
|
||||
#endif
|
379
src/ecmascript/see/strings.c
Normal file
379
src/ecmascript/see/strings.c
Normal file
@ -0,0 +1,379 @@
|
||||
#include <see/see.h>
|
||||
|
||||
struct SEE_string *s_window;
|
||||
struct SEE_string *s_closed;
|
||||
struct SEE_string *s_parent;
|
||||
struct SEE_string *s_self;
|
||||
struct SEE_string *s_top;
|
||||
struct SEE_string *s_alert;
|
||||
struct SEE_string *s_open;
|
||||
|
||||
struct SEE_string *s_menubar;
|
||||
|
||||
struct SEE_string *s_statusbar;
|
||||
struct SEE_string *s_visible;
|
||||
|
||||
struct SEE_string *s_navigator;
|
||||
struct SEE_string *s_appCodeName;
|
||||
struct SEE_string *s_appName;
|
||||
struct SEE_string *s_appVersion;
|
||||
struct SEE_string *s_language;
|
||||
struct SEE_string *s_platform;
|
||||
struct SEE_string *s_userAgent;
|
||||
|
||||
struct SEE_string *s_history;
|
||||
struct SEE_string *s_back;
|
||||
struct SEE_string *s_forward;
|
||||
struct SEE_string *s_go;
|
||||
|
||||
struct SEE_string *s_location;
|
||||
struct SEE_string *s_href;
|
||||
struct SEE_string *s_toString;
|
||||
struct SEE_string *s_toLocaleString;
|
||||
|
||||
struct SEE_string *s_input;
|
||||
struct SEE_string *s_accessKey;
|
||||
struct SEE_string *s_alt;
|
||||
struct SEE_string *s_checked;
|
||||
struct SEE_string *s_defaultChecked;
|
||||
struct SEE_string *s_defaultValue;
|
||||
struct SEE_string *s_disabled;
|
||||
struct SEE_string *s_form;
|
||||
struct SEE_string *s_maxLength;
|
||||
struct SEE_string *s_name;
|
||||
struct SEE_string *s_readonly;
|
||||
struct SEE_string *s_size;
|
||||
struct SEE_string *s_src;
|
||||
struct SEE_string *s_tabindex;
|
||||
struct SEE_string *s_type;
|
||||
struct SEE_string *s_value;
|
||||
struct SEE_string *s_blur;
|
||||
struct SEE_string *s_click;
|
||||
struct SEE_string *s_focus;
|
||||
struct SEE_string *s_select;
|
||||
|
||||
struct SEE_string *s_elements;
|
||||
struct SEE_string *s_item;
|
||||
struct SEE_string *s_namedItem;
|
||||
struct SEE_string *s_length;
|
||||
|
||||
struct SEE_string *s_action;
|
||||
struct SEE_string *s_encoding;
|
||||
struct SEE_string *s_method;
|
||||
struct SEE_string *s_target;
|
||||
struct SEE_string *s_reset;
|
||||
struct SEE_string *s_submit;
|
||||
|
||||
struct SEE_string *s_forms;
|
||||
|
||||
struct SEE_string *s_document;
|
||||
struct SEE_string *s_referrer;
|
||||
struct SEE_string *s_title;
|
||||
struct SEE_string *s_url;
|
||||
struct SEE_string *s_write;
|
||||
|
||||
struct SEE_string *s_Mozilla;
|
||||
struct SEE_string *s_ELinks_;
|
||||
struct SEE_string *s_cookie;
|
||||
|
||||
struct SEE_string *s_GET;
|
||||
struct SEE_string *s_POST;
|
||||
struct SEE_string *s_application_;
|
||||
struct SEE_string *s_multipart_;
|
||||
struct SEE_string *s_textplain;
|
||||
|
||||
struct SEE_string *s_text;
|
||||
struct SEE_string *s_password;
|
||||
struct SEE_string *s_file;
|
||||
struct SEE_string *s_checkbox;
|
||||
struct SEE_string *s_radio;
|
||||
struct SEE_string *s_image;
|
||||
struct SEE_string *s_button;
|
||||
struct SEE_string *s_hidden;
|
||||
|
||||
struct SEE_string *s_timeout;
|
||||
|
||||
void
|
||||
init_intern_strings(void)
|
||||
{
|
||||
static SEE_char_t SA_window[] = {'w','i','n','d','o','w'};
|
||||
static struct SEE_string S_window = SEE_STRING_DECL(SA_window);
|
||||
static SEE_char_t SA_closed[] = {'c','l','o','s','e','d'};
|
||||
static struct SEE_string S_closed = SEE_STRING_DECL(SA_closed);
|
||||
static SEE_char_t SA_parent[] = {'p','a','r','e','n','t'};
|
||||
static struct SEE_string S_parent = SEE_STRING_DECL(SA_parent);
|
||||
static SEE_char_t SA_self[] = {'s','e','l','f'};
|
||||
static struct SEE_string S_self = SEE_STRING_DECL(SA_self);
|
||||
static SEE_char_t SA_top[] = {'t','o','p'};
|
||||
static struct SEE_string S_top = SEE_STRING_DECL(SA_top);
|
||||
static SEE_char_t SA_alert[] ={'a','l','e','r','t'};
|
||||
static struct SEE_string S_alert = SEE_STRING_DECL(SA_alert);
|
||||
static SEE_char_t SA_open[] ={'o','p','e','n'};
|
||||
static struct SEE_string S_open = SEE_STRING_DECL(SA_open);
|
||||
|
||||
static SEE_char_t SA_menubar[] = {'m','e','n','u','b','a','r'};
|
||||
static struct SEE_string S_menubar = SEE_STRING_DECL(SA_menubar);
|
||||
|
||||
static SEE_char_t SA_statusbar[] = {'s','t','a','t','u','s','b','a','r'};
|
||||
static struct SEE_string S_statusbar = SEE_STRING_DECL(SA_statusbar);
|
||||
static SEE_char_t SA_visible[] = {'v','i','s','i','b','l','e'};
|
||||
static struct SEE_string S_visible = SEE_STRING_DECL(SA_visible);
|
||||
|
||||
static SEE_char_t SA_navigator[] ={'n','a','v','i','g','a','t','o','r'};
|
||||
static struct SEE_string S_navigator = SEE_STRING_DECL(SA_navigator);
|
||||
static SEE_char_t SA_appCodeName[] ={'a','p','p','C','o','d','e','N','a','m','e'};
|
||||
static struct SEE_string S_appCodeName = SEE_STRING_DECL(SA_appCodeName);
|
||||
static SEE_char_t SA_appName[] ={'a','p','p','N','a','m','e'};
|
||||
static struct SEE_string S_appName = SEE_STRING_DECL(SA_appName);
|
||||
static SEE_char_t SA_appVersion[] ={'a','p','p','V','e','r','s','i','o','n'};
|
||||
static struct SEE_string S_appVersion = SEE_STRING_DECL(SA_appVersion);
|
||||
static SEE_char_t SA_language[] ={'l','a','n','g','u','a','g','e'};
|
||||
static struct SEE_string S_language = SEE_STRING_DECL(SA_language);
|
||||
static SEE_char_t SA_platform[] ={'p','l','a','t','f','o','r','m'};
|
||||
static struct SEE_string S_platform = SEE_STRING_DECL(SA_platform);
|
||||
static SEE_char_t SA_userAgent[] ={'u','s','e','r','A','g','e','n','t'};
|
||||
static struct SEE_string S_userAgent = SEE_STRING_DECL(SA_userAgent);
|
||||
|
||||
static SEE_char_t SA_history[] ={'h','i','s','t','o','r','y'};
|
||||
static struct SEE_string S_history = SEE_STRING_DECL(SA_history);
|
||||
static SEE_char_t SA_back[] ={'b','a','c','k'};
|
||||
static struct SEE_string S_back = SEE_STRING_DECL(SA_back);
|
||||
static SEE_char_t SA_forward[] ={'f','o','r','w','a','r','d'};
|
||||
static struct SEE_string S_forward = SEE_STRING_DECL(SA_forward);
|
||||
static SEE_char_t SA_go[] ={'g','o'};
|
||||
static struct SEE_string S_go = SEE_STRING_DECL(SA_go);
|
||||
|
||||
static SEE_char_t SA_location[] ={'l','o','c','a','t','i','o','n'};
|
||||
static struct SEE_string S_location = SEE_STRING_DECL(SA_location);
|
||||
static SEE_char_t SA_href[] ={'h','r','e','f'};
|
||||
static struct SEE_string S_href = SEE_STRING_DECL(SA_href);
|
||||
static SEE_char_t SA_toString[] ={'t','o','S','t','r','i','n','g'};
|
||||
static struct SEE_string S_toString = SEE_STRING_DECL(SA_toString);
|
||||
static SEE_char_t SA_toLocaleString[] ={'t','o','L','o','c','a','l','e','S','t','r','i','n','g'};
|
||||
static struct SEE_string S_toLocaleString = SEE_STRING_DECL(SA_toLocaleString);
|
||||
|
||||
static SEE_char_t SA_input[] ={'i','n','p','u','t'};
|
||||
static struct SEE_string S_input = SEE_STRING_DECL(SA_input);
|
||||
static SEE_char_t SA_accessKey[] ={'a','c','c','e','s','s','K','e','y'};
|
||||
static struct SEE_string S_accessKey = SEE_STRING_DECL(SA_accessKey);
|
||||
static SEE_char_t SA_alt[] ={'a','l','t'};
|
||||
static struct SEE_string S_alt = SEE_STRING_DECL(SA_alt);
|
||||
static SEE_char_t SA_checked[] ={'c','h','e','c','k','e','d'};
|
||||
static struct SEE_string S_checked = SEE_STRING_DECL(SA_checked);
|
||||
static SEE_char_t SA_defaultChecked[] ={'d','e','f','a','u','l','t','C','h','e','c','k','e','d'};
|
||||
static struct SEE_string S_defaultChecked = SEE_STRING_DECL(SA_defaultChecked);
|
||||
static SEE_char_t SA_defaultValue[] ={'d','e','f','a','u','l','t','V','a','l','u','e'};
|
||||
static struct SEE_string S_defaultValue = SEE_STRING_DECL(SA_defaultValue);
|
||||
static SEE_char_t SA_disabled[] ={'d','i','s','a','b','l','e','d'};
|
||||
static struct SEE_string S_disabled = SEE_STRING_DECL(SA_disabled);
|
||||
static SEE_char_t SA_form[] ={'f','o','r','m'};
|
||||
static struct SEE_string S_form = SEE_STRING_DECL(SA_form);
|
||||
static SEE_char_t SA_maxLength[] ={'m','a','x','L','e','n','g','t','h'};
|
||||
static struct SEE_string S_maxLength = SEE_STRING_DECL(SA_maxLength);
|
||||
static SEE_char_t SA_name[] ={'n','a','m','e'};
|
||||
static struct SEE_string S_name = SEE_STRING_DECL(SA_name);
|
||||
static SEE_char_t SA_readonly[] ={'r','e','a','d','o','n','l','y'};
|
||||
static struct SEE_string S_readonly = SEE_STRING_DECL(SA_readonly);
|
||||
static SEE_char_t SA_size[] ={'s','i','z','e'};
|
||||
static struct SEE_string S_size = SEE_STRING_DECL(SA_size);
|
||||
static SEE_char_t SA_src[] ={'s','r','c'};
|
||||
static struct SEE_string S_src = SEE_STRING_DECL(SA_src);
|
||||
static SEE_char_t SA_tabindex[] ={'t','a','b','i','n','d','e','x'};
|
||||
static struct SEE_string S_tabindex = SEE_STRING_DECL(SA_tabindex);
|
||||
static SEE_char_t SA_type[] ={'t','y','p','e'};
|
||||
static struct SEE_string S_type = SEE_STRING_DECL(SA_type);
|
||||
static SEE_char_t SA_value[] ={'v','a','l','u','e'};
|
||||
static struct SEE_string S_value = SEE_STRING_DECL(SA_value);
|
||||
static SEE_char_t SA_blur[] ={'b','l','u','r'};
|
||||
static struct SEE_string S_blur = SEE_STRING_DECL(SA_blur);
|
||||
static SEE_char_t SA_click[] ={'c','l','i','c','k'};
|
||||
static struct SEE_string S_click = SEE_STRING_DECL(SA_click);
|
||||
static SEE_char_t SA_focus[] ={'f','o','c','u','s'};
|
||||
static struct SEE_string S_focus = SEE_STRING_DECL(SA_focus);
|
||||
static SEE_char_t SA_select[] ={'s','e','l','e','c','t'};
|
||||
static struct SEE_string S_select = SEE_STRING_DECL(SA_select);
|
||||
|
||||
static SEE_char_t SA_elements[] ={'e','l','e','m','e','n','t','s'};
|
||||
static struct SEE_string S_elements = SEE_STRING_DECL(SA_elements);
|
||||
static SEE_char_t SA_item[] ={'i','t','e','m'};
|
||||
static struct SEE_string S_item = SEE_STRING_DECL(SA_item);
|
||||
static SEE_char_t SA_namedItem[] ={'n','a','m','e','d','I','t','e','m'};
|
||||
static struct SEE_string S_namedItem = SEE_STRING_DECL(SA_namedItem);
|
||||
static SEE_char_t SA_length[] ={'l','e','n','g','t','h'};
|
||||
static struct SEE_string S_length = SEE_STRING_DECL(SA_length);
|
||||
|
||||
static SEE_char_t SA_action[] ={'a','c','t','i','o','n'};
|
||||
static struct SEE_string S_action = SEE_STRING_DECL(SA_action);
|
||||
static SEE_char_t SA_encoding[] ={'e','n','c','o','d','i','g'};
|
||||
static struct SEE_string S_encoding = SEE_STRING_DECL(SA_encoding);
|
||||
static SEE_char_t SA_method[] ={'m','e','t','h','o','d'};
|
||||
static struct SEE_string S_method = SEE_STRING_DECL(SA_method);
|
||||
static SEE_char_t SA_target[] ={'t','a','r','g','e','t'};
|
||||
static struct SEE_string S_target = SEE_STRING_DECL(SA_target);
|
||||
static SEE_char_t SA_reset[] ={'r','e','s','e','t'};
|
||||
static struct SEE_string S_reset = SEE_STRING_DECL(SA_reset);
|
||||
static SEE_char_t SA_submit[] ={'s','u','b','m','i','t'};
|
||||
static struct SEE_string S_submit = SEE_STRING_DECL(SA_submit);
|
||||
|
||||
static SEE_char_t SA_forms[] ={'f','o','r','m','s'};
|
||||
static struct SEE_string S_forms = SEE_STRING_DECL(SA_forms);
|
||||
|
||||
static SEE_char_t SA_document[] = {'d','o','c','u','m','e','n','t'};
|
||||
static struct SEE_string S_document = SEE_STRING_DECL(SA_document);
|
||||
static SEE_char_t SA_referrer[] ={'r','e','f','e','r','r','e','r'};
|
||||
static struct SEE_string S_referrer = SEE_STRING_DECL(SA_referrer);
|
||||
static SEE_char_t SA_title[] ={'t','i','t','l','e'};
|
||||
static struct SEE_string S_title = SEE_STRING_DECL(SA_title);
|
||||
static SEE_char_t SA_url[] ={'u','r','l'};
|
||||
static struct SEE_string S_url = SEE_STRING_DECL(SA_url);
|
||||
static SEE_char_t SA_write[] = {'w','r','i','t','e'};
|
||||
static struct SEE_string S_write = SEE_STRING_DECL(SA_write);
|
||||
|
||||
static SEE_char_t SA_Mozilla[] = {'M','o','z','i','l','l','a'};
|
||||
static struct SEE_string S_Mozilla = SEE_STRING_DECL(SA_Mozilla);
|
||||
static SEE_char_t SA_ELinks_[] = {'E','L','i','n','k','s',' ','(',
|
||||
'r','o','u','g','h','l','y',' ','c','o','m','p','a','t','i','b','l','e',
|
||||
' ','w','i','t','h',' ','N','e','t','s','c','a','p','e',' ',
|
||||
'N','a','v','i','g','a','t','o','r',',',' ','M','o','z','i','l','l','a',
|
||||
' ','a','n','d',' ','M','i','c','r','o','s','o','f','t',' ',
|
||||
'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r',')'};
|
||||
static struct SEE_string S_ELinks_ = SEE_STRING_DECL(SA_ELinks_);
|
||||
|
||||
static SEE_char_t SA_cookie[] = {'c','o','o','k','i','e'};
|
||||
static struct SEE_string S_cookie = SEE_STRING_DECL(SA_cookie);
|
||||
|
||||
static SEE_char_t SA_GET[] = {'G','E','T'};
|
||||
static struct SEE_string S_GET = SEE_STRING_DECL(SA_GET);
|
||||
static SEE_char_t SA_POST[] = {'P','O','S','T'};
|
||||
static struct SEE_string S_POST = SEE_STRING_DECL(SA_POST);
|
||||
|
||||
static SEE_char_t SA_application_[] = {'a','p','p','l','i','c','a','t',
|
||||
'i','o','n','/','x','-','w','w','w','-','f','o','r','m','-','u','r','l',
|
||||
'e','n','c','o','d','e','d'};
|
||||
static struct SEE_string S_application_ = SEE_STRING_DECL(SA_application_);
|
||||
static SEE_char_t SA_multipart_[] = {'m','u','l','t','i','p','a','r','t','/',
|
||||
'f','o','r','m','-','d','a','t','a'};
|
||||
static struct SEE_string S_multipart_ = SEE_STRING_DECL(SA_multipart_);
|
||||
static SEE_char_t SA_textplain[] = {'t','e','x','t','/','p','l','a','i','n'};
|
||||
static struct SEE_string S_textplain = SEE_STRING_DECL(SA_textplain);
|
||||
|
||||
static SEE_char_t SA_text[] = {'t','e','x','t'};
|
||||
static struct SEE_string S_text = SEE_STRING_DECL(SA_text);
|
||||
|
||||
static SEE_char_t SA_password[] = {'p','a','s','s','w','o','r','d'};
|
||||
static struct SEE_string S_password = SEE_STRING_DECL(SA_password);
|
||||
|
||||
static SEE_char_t SA_file[] = {'f','i','l','e'};
|
||||
static struct SEE_string S_file = SEE_STRING_DECL(SA_file);
|
||||
|
||||
static SEE_char_t SA_checkbox[] = {'c','h','e','c','k','b','o','x'};
|
||||
static struct SEE_string S_checkbox = SEE_STRING_DECL(SA_checkbox);
|
||||
|
||||
static SEE_char_t SA_radio[] = {'r','a','d','i','o'};
|
||||
static struct SEE_string S_radio = SEE_STRING_DECL(SA_radio);
|
||||
|
||||
static SEE_char_t SA_image[] = {'i','m','a','g','e'};
|
||||
static struct SEE_string S_image = SEE_STRING_DECL(SA_image);
|
||||
|
||||
static SEE_char_t SA_button[] = {'b','u','t','t','o','n'};
|
||||
static struct SEE_string S_button = SEE_STRING_DECL(SA_button);
|
||||
|
||||
static SEE_char_t SA_hidden[] = {'h','i','d','d','e','n'};
|
||||
static struct SEE_string S_hidden = SEE_STRING_DECL(SA_hidden);
|
||||
|
||||
static SEE_char_t SA_timeout[] = {'t','i','m','e','o','u','t'};
|
||||
static struct SEE_string S_timeout = SEE_STRING_DECL(SA_timeout);
|
||||
|
||||
SEE_intern_global(s_window = &S_window);
|
||||
SEE_intern_global(s_closed = &S_closed);
|
||||
SEE_intern_global(s_parent = &S_parent);
|
||||
SEE_intern_global(s_self = &S_self);
|
||||
SEE_intern_global(s_top = &S_top);
|
||||
SEE_intern_global(s_alert = &S_alert);
|
||||
SEE_intern_global(s_open = &S_open);
|
||||
|
||||
SEE_intern_global(s_menubar = &S_menubar);
|
||||
SEE_intern_global(s_statusbar = &S_statusbar);
|
||||
SEE_intern_global(s_visible = &S_visible);
|
||||
|
||||
SEE_intern_global(s_navigator = &S_navigator);
|
||||
SEE_intern_global(s_appCodeName = &S_appCodeName);
|
||||
SEE_intern_global(s_appName = &S_appName);
|
||||
SEE_intern_global(s_appVersion = &S_appVersion);
|
||||
SEE_intern_global(s_language = &S_language);
|
||||
SEE_intern_global(s_platform = &S_platform);
|
||||
SEE_intern_global(s_userAgent = &S_userAgent);
|
||||
|
||||
SEE_intern_global(s_history = &S_history);
|
||||
SEE_intern_global(s_back = &S_back);
|
||||
SEE_intern_global(s_forward = &S_forward);
|
||||
SEE_intern_global(s_go = &S_go);
|
||||
|
||||
SEE_intern_global(s_location = &S_location);
|
||||
SEE_intern_global(s_href = &S_href);
|
||||
SEE_intern_global(s_toString = &S_toString);
|
||||
SEE_intern_global(s_toLocaleString = &S_toLocaleString);
|
||||
|
||||
SEE_intern_global(s_input = &S_input);
|
||||
SEE_intern_global(s_accessKey = &S_accessKey);
|
||||
SEE_intern_global(s_alt = &S_alt);
|
||||
SEE_intern_global(s_checked = &S_checked);
|
||||
SEE_intern_global(s_defaultChecked = &S_defaultChecked);
|
||||
SEE_intern_global(s_defaultValue = &S_defaultValue);
|
||||
SEE_intern_global(s_disabled = &S_disabled);
|
||||
SEE_intern_global(s_form = &S_form);
|
||||
SEE_intern_global(s_maxLength = &S_maxLength);
|
||||
SEE_intern_global(s_name = &S_name);
|
||||
SEE_intern_global(s_readonly = &S_readonly);
|
||||
SEE_intern_global(s_size = &S_size);
|
||||
SEE_intern_global(s_src = &S_src);
|
||||
SEE_intern_global(s_tabindex = &S_tabindex);
|
||||
SEE_intern_global(s_type = &S_type);
|
||||
SEE_intern_global(s_value = &S_value);
|
||||
SEE_intern_global(s_blur = &S_blur);
|
||||
SEE_intern_global(s_click = &S_click);
|
||||
SEE_intern_global(s_focus = &S_focus);
|
||||
SEE_intern_global(s_select = &S_select);
|
||||
|
||||
SEE_intern_global(s_elements = &S_elements);
|
||||
SEE_intern_global(s_item = &S_item);
|
||||
SEE_intern_global(s_namedItem = &S_namedItem);
|
||||
SEE_intern_global(s_length = &S_length);
|
||||
|
||||
SEE_intern_global(s_action = &S_action);
|
||||
SEE_intern_global(s_encoding = &S_encoding);
|
||||
SEE_intern_global(s_method = &S_method);
|
||||
SEE_intern_global(s_target = &S_target);
|
||||
SEE_intern_global(s_reset = &S_reset);
|
||||
SEE_intern_global(s_submit = &S_submit);
|
||||
|
||||
SEE_intern_global(s_forms = &S_forms);
|
||||
|
||||
SEE_intern_global(s_document = &S_document);
|
||||
SEE_intern_global(s_referrer = &S_referrer);
|
||||
SEE_intern_global(s_title = &S_title);
|
||||
SEE_intern_global(s_url = &S_url);
|
||||
SEE_intern_global(s_write = &S_write);
|
||||
|
||||
SEE_intern_global(s_Mozilla = &S_Mozilla);
|
||||
SEE_intern_global(s_ELinks_ = &S_ELinks_);
|
||||
SEE_intern_global(s_cookie = &S_cookie);
|
||||
|
||||
SEE_intern_global(s_GET = &S_GET);
|
||||
SEE_intern_global(s_POST = &S_POST);
|
||||
|
||||
SEE_intern_global(s_application_ = &S_application_);
|
||||
SEE_intern_global(s_multipart_ = &S_multipart_);
|
||||
SEE_intern_global(s_textplain = &S_textplain);
|
||||
|
||||
SEE_intern_global(s_text = &S_text);
|
||||
SEE_intern_global(s_password = &S_password);
|
||||
SEE_intern_global(s_file = &S_file);
|
||||
SEE_intern_global(s_checkbox = &S_checkbox);
|
||||
SEE_intern_global(s_radio = &S_radio);
|
||||
SEE_intern_global(s_image = &S_image);
|
||||
SEE_intern_global(s_button = &S_button);
|
||||
SEE_intern_global(s_hidden = &S_hidden);
|
||||
|
||||
SEE_intern_global(s_timeout = &S_timeout);
|
||||
}
|
101
src/ecmascript/see/strings.h
Normal file
101
src/ecmascript/see/strings.h
Normal file
@ -0,0 +1,101 @@
|
||||
|
||||
#ifndef EL__ECMASCRIPT_SEE_STRINGS_H
|
||||
#define EL__ECMASCRIPT_SEE_STRINGS_H
|
||||
|
||||
#include <see/see.h>
|
||||
|
||||
void init_intern_strings(void);
|
||||
|
||||
extern struct SEE_string *s_window;
|
||||
extern struct SEE_string *s_closed;
|
||||
extern struct SEE_string *s_parent;
|
||||
extern struct SEE_string *s_self;
|
||||
extern struct SEE_string *s_top;
|
||||
extern struct SEE_string *s_alert;
|
||||
extern struct SEE_string *s_open;
|
||||
|
||||
extern struct SEE_string *s_menubar;
|
||||
|
||||
extern struct SEE_string *s_statusbar;
|
||||
extern struct SEE_string *s_visible;
|
||||
|
||||
extern struct SEE_string *s_navigator;
|
||||
extern struct SEE_string *s_appCodeName;
|
||||
extern struct SEE_string *s_appName;
|
||||
extern struct SEE_string *s_appVersion;
|
||||
extern struct SEE_string *s_language;
|
||||
extern struct SEE_string *s_platform;
|
||||
extern struct SEE_string *s_userAgent;
|
||||
|
||||
extern struct SEE_string *s_history;
|
||||
extern struct SEE_string *s_back;
|
||||
extern struct SEE_string *s_forward;
|
||||
extern struct SEE_string *s_go;
|
||||
|
||||
extern struct SEE_string *s_location;
|
||||
extern struct SEE_string *s_href;
|
||||
extern struct SEE_string *s_toString;
|
||||
extern struct SEE_string *s_toLocaleString;
|
||||
|
||||
extern struct SEE_string *s_input;
|
||||
extern struct SEE_string *s_accessKey;
|
||||
extern struct SEE_string *s_alt;
|
||||
extern struct SEE_string *s_checked;
|
||||
extern struct SEE_string *s_defaultChecked;
|
||||
extern struct SEE_string *s_defaultValue;
|
||||
extern struct SEE_string *s_disabled;
|
||||
extern struct SEE_string *s_form;
|
||||
extern struct SEE_string *s_maxLength;
|
||||
extern struct SEE_string *s_name;
|
||||
extern struct SEE_string *s_readonly;
|
||||
extern struct SEE_string *s_size;
|
||||
extern struct SEE_string *s_src;
|
||||
extern struct SEE_string *s_tabindex;
|
||||
extern struct SEE_string *s_type;
|
||||
extern struct SEE_string *s_value;
|
||||
extern struct SEE_string *s_blur;
|
||||
extern struct SEE_string *s_click;
|
||||
extern struct SEE_string *s_focus;
|
||||
extern struct SEE_string *s_select;
|
||||
|
||||
extern struct SEE_string *s_elements;
|
||||
extern struct SEE_string *s_item;
|
||||
extern struct SEE_string *s_namedItem;
|
||||
extern struct SEE_string *s_length;
|
||||
|
||||
extern struct SEE_string *s_action;
|
||||
extern struct SEE_string *s_encoding;
|
||||
extern struct SEE_string *s_method;
|
||||
extern struct SEE_string *s_target;
|
||||
extern struct SEE_string *s_reset;
|
||||
extern struct SEE_string *s_submit;
|
||||
|
||||
extern struct SEE_string *s_forms;
|
||||
|
||||
extern struct SEE_string *s_document;
|
||||
extern struct SEE_string *s_referrer;
|
||||
extern struct SEE_string *s_title;
|
||||
extern struct SEE_string *s_url;
|
||||
extern struct SEE_string *s_write;
|
||||
|
||||
extern struct SEE_string *s_Mozilla;
|
||||
extern struct SEE_string *s_ELinks_;
|
||||
extern struct SEE_string *s_cookie;
|
||||
|
||||
extern struct SEE_string *s_GET;
|
||||
extern struct SEE_string *s_POST;
|
||||
extern struct SEE_string *s_application_;
|
||||
extern struct SEE_string *s_multipart_;
|
||||
extern struct SEE_string *s_textplain;
|
||||
|
||||
extern struct SEE_string *s_text;
|
||||
extern struct SEE_string *s_password;
|
||||
extern struct SEE_string *s_file;
|
||||
extern struct SEE_string *s_checkbox;
|
||||
extern struct SEE_string *s_radio;
|
||||
extern struct SEE_string *s_image;
|
||||
extern struct SEE_string *s_button;
|
||||
extern struct SEE_string *s_hidden;
|
||||
|
||||
extern struct SEE_string *s_timeout;
|
||||
#endif
|
206
src/ecmascript/see/unibar.c
Normal file
206
src/ecmascript/see/unibar.c
Normal file
@ -0,0 +1,206 @@
|
||||
/* The SEE location and history objects implementation. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "elinks.h"
|
||||
|
||||
#include <see/see.h>
|
||||
|
||||
#include "bfu/dialog.h"
|
||||
#include "cache/cache.h"
|
||||
#include "cookies/cookies.h"
|
||||
#include "dialogs/menu.h"
|
||||
#include "dialogs/status.h"
|
||||
#include "document/html/frames.h"
|
||||
#include "document/document.h"
|
||||
#include "document/forms.h"
|
||||
#include "document/view.h"
|
||||
#include "ecmascript/ecmascript.h"
|
||||
#include "ecmascript/see/input.h"
|
||||
#include "ecmascript/see/strings.h"
|
||||
#include "ecmascript/see/unibar.h"
|
||||
#include "ecmascript/see/window.h"
|
||||
#include "intl/gettext/libintl.h"
|
||||
#include "main/select.h"
|
||||
#include "osdep/newwin.h"
|
||||
#include "osdep/sysname.h"
|
||||
#include "protocol/http/http.h"
|
||||
#include "protocol/uri.h"
|
||||
#include "session/history.h"
|
||||
#include "session/location.h"
|
||||
#include "session/session.h"
|
||||
#include "session/task.h"
|
||||
#include "terminal/tab.h"
|
||||
#include "terminal/terminal.h"
|
||||
#include "util/conv.h"
|
||||
#include "util/memory.h"
|
||||
#include "util/string.h"
|
||||
#include "viewer/text/draw.h"
|
||||
#include "viewer/text/form.h"
|
||||
#include "viewer/text/link.h"
|
||||
#include "viewer/text/vs.h"
|
||||
|
||||
static void unibar_get(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *);
|
||||
static void unibar_put(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *, int);
|
||||
static int unibar_canput(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
|
||||
static int unibar_hasproperty(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
|
||||
|
||||
struct js_unibar_object {
|
||||
struct SEE_object object;
|
||||
unsigned char bar;
|
||||
};
|
||||
|
||||
struct SEE_objectclass js_menubar_object_class = {
|
||||
NULL,
|
||||
unibar_get,
|
||||
unibar_put,
|
||||
unibar_canput,
|
||||
unibar_hasproperty,
|
||||
SEE_no_delete,
|
||||
SEE_no_defaultvalue,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
struct SEE_objectclass js_statusbar_object_class = {
|
||||
NULL,
|
||||
unibar_get,
|
||||
unibar_put,
|
||||
unibar_canput,
|
||||
unibar_hasproperty,
|
||||
SEE_no_delete,
|
||||
SEE_no_defaultvalue,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
static void
|
||||
unibar_get(struct SEE_interpreter *interp, struct SEE_object *o,
|
||||
struct SEE_string *p, struct SEE_value *res)
|
||||
{
|
||||
struct global_object *g = (struct global_object *)interp;
|
||||
struct view_state *vs = g->win->vs;
|
||||
struct document_view *doc_view = vs->doc_view;
|
||||
struct session_status *status = &doc_view->session->status;
|
||||
struct js_unibar_object *obj = (struct js_unibar_object *)o;
|
||||
unsigned char bar = obj->bar;
|
||||
|
||||
checktime(interp);
|
||||
if (p == s_visible) {
|
||||
#define unibar_fetch(bar) \
|
||||
SEE_SET_BOOLEAN(res, status->force_show_##bar##_bar >= 0 \
|
||||
? status->force_show_##bar##_bar \
|
||||
: status->show_##bar##_bar)
|
||||
switch (bar) {
|
||||
case 's':
|
||||
unibar_fetch(status);
|
||||
break;
|
||||
case 't':
|
||||
unibar_fetch(title);
|
||||
break;
|
||||
default:
|
||||
SEE_SET_BOOLEAN(res, 0);
|
||||
break;
|
||||
}
|
||||
#undef unibar_fetch
|
||||
return;
|
||||
}
|
||||
SEE_SET_UNDEFINED(res);
|
||||
}
|
||||
|
||||
static void
|
||||
unibar_put(struct SEE_interpreter *interp, struct SEE_object *o,
|
||||
struct SEE_string *p, struct SEE_value *val, int attr)
|
||||
{
|
||||
checktime(interp);
|
||||
if (p == s_location) {
|
||||
struct global_object *g = (struct global_object *)interp;
|
||||
struct view_state *vs = g->win->vs;
|
||||
struct document_view *doc_view = vs->doc_view;
|
||||
struct session_status *status = &doc_view->session->status;
|
||||
struct js_unibar_object *obj = (struct js_unibar_object *)o;
|
||||
unsigned char bar = obj->bar;
|
||||
|
||||
switch (bar) {
|
||||
case 's':
|
||||
status->force_show_status_bar =
|
||||
SEE_ToUint32(interp, val);
|
||||
break;
|
||||
case 't':
|
||||
status->force_show_title_bar =
|
||||
SEE_ToUint32(interp, val);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
unibar_canput(struct SEE_interpreter *interp, struct SEE_object *o,
|
||||
struct SEE_string *p)
|
||||
{
|
||||
checktime(interp);
|
||||
if (p == s_visible)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
unibar_hasproperty(struct SEE_interpreter *interp, struct SEE_object *o,
|
||||
struct SEE_string *p)
|
||||
{
|
||||
checktime(interp);
|
||||
if (p == s_visible)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
init_js_menubar_object(struct ecmascript_interpreter *interpreter)
|
||||
{
|
||||
struct global_object *g = interpreter->backend_data;
|
||||
struct SEE_interpreter *interp = &g->interp;
|
||||
struct SEE_value v;
|
||||
struct js_unibar_object *menu;
|
||||
|
||||
menu = SEE_NEW(interp, struct js_unibar_object);
|
||||
|
||||
menu->object.objectclass = &js_menubar_object_class;
|
||||
menu->object.objectclass->Class = s_menubar;
|
||||
menu->object.Prototype = NULL;
|
||||
menu->bar = 't';
|
||||
|
||||
SEE_SET_OBJECT(&v, (struct SEE_object *)menu);
|
||||
SEE_OBJECT_PUT(interp, interp->Global, s_menubar, &v, 0);
|
||||
}
|
||||
|
||||
void
|
||||
init_js_statusbar_object(struct ecmascript_interpreter *interpreter)
|
||||
{
|
||||
struct global_object *g = interpreter->backend_data;
|
||||
struct SEE_interpreter *interp = &g->interp;
|
||||
struct SEE_value v;
|
||||
struct js_unibar_object *status;
|
||||
|
||||
status = SEE_NEW(interp, struct js_unibar_object);
|
||||
|
||||
status->object.objectclass = &js_statusbar_object_class;
|
||||
status->object.objectclass->Class = s_statusbar;
|
||||
status->object.Prototype = NULL;
|
||||
status->bar = 's';
|
||||
|
||||
SEE_SET_OBJECT(&v, (struct SEE_object *)status);
|
||||
SEE_OBJECT_PUT(interp, interp->Global, s_statusbar, &v, 0);
|
||||
}
|
9
src/ecmascript/see/unibar.h
Normal file
9
src/ecmascript/see/unibar.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef EL__ECMASCRIPT_SEE_UNIBAR_H
|
||||
#define EL__ECMASCRIPT_SEE_UNIBAR_H
|
||||
|
||||
struct emascript_interpreter;
|
||||
|
||||
void init_js_menubar_object(struct ecmascript_interpreter *);
|
||||
void init_js_statusbar_object(struct ecmascript_interpreter *);
|
||||
|
||||
#endif
|
371
src/ecmascript/see/window.c
Normal file
371
src/ecmascript/see/window.c
Normal file
@ -0,0 +1,371 @@
|
||||
/* The SEE window object implementation. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "elinks.h"
|
||||
|
||||
#include <see/see.h>
|
||||
|
||||
#include "bfu/dialog.h"
|
||||
#include "cache/cache.h"
|
||||
#include "cookies/cookies.h"
|
||||
#include "dialogs/menu.h"
|
||||
#include "dialogs/status.h"
|
||||
#include "document/html/frames.h"
|
||||
#include "document/document.h"
|
||||
#include "document/forms.h"
|
||||
#include "document/view.h"
|
||||
#include "ecmascript/ecmascript.h"
|
||||
#include "ecmascript/see/input.h"
|
||||
#include "ecmascript/see/strings.h"
|
||||
#include "ecmascript/see/window.h"
|
||||
#include "intl/gettext/libintl.h"
|
||||
#include "main/select.h"
|
||||
#include "osdep/newwin.h"
|
||||
#include "osdep/sysname.h"
|
||||
#include "protocol/http/http.h"
|
||||
#include "protocol/uri.h"
|
||||
#include "session/history.h"
|
||||
#include "session/location.h"
|
||||
#include "session/session.h"
|
||||
#include "session/task.h"
|
||||
#include "terminal/tab.h"
|
||||
#include "terminal/terminal.h"
|
||||
#include "util/conv.h"
|
||||
#include "util/memory.h"
|
||||
#include "util/string.h"
|
||||
#include "viewer/text/draw.h"
|
||||
#include "viewer/text/form.h"
|
||||
#include "viewer/text/link.h"
|
||||
#include "viewer/text/vs.h"
|
||||
|
||||
static struct js_window_object *js_get_global_object(void *);
|
||||
static struct js_window_object *js_try_resolve_frame(struct document_view *, unsigned char *);
|
||||
static void delayed_open(void *);
|
||||
static void delayed_goto_uri_frame(void *);
|
||||
static void window_get(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *);
|
||||
static void window_put(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *, int);
|
||||
static int window_canput(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
|
||||
static int window_hasproperty(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
|
||||
static void js_window_alert(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
|
||||
static void js_window_open(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
|
||||
|
||||
void location_goto(struct document_view *, unsigned char *);
|
||||
|
||||
struct delayed_open {
|
||||
struct session *ses;
|
||||
struct uri *uri;
|
||||
unsigned char *target;
|
||||
};
|
||||
|
||||
struct SEE_objectclass js_window_object_class = {
|
||||
NULL,
|
||||
window_get,
|
||||
window_put,
|
||||
window_canput,
|
||||
window_hasproperty,
|
||||
SEE_no_delete,
|
||||
SEE_no_defaultvalue,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct js_window_object *
|
||||
js_get_global_object(void *data)
|
||||
{
|
||||
struct global_object *g = (struct global_object *)data;
|
||||
return g->win;
|
||||
}
|
||||
|
||||
static struct js_window_object *
|
||||
js_try_resolve_frame(struct document_view *doc_view, unsigned char *id)
|
||||
{
|
||||
struct session *ses = doc_view->session;
|
||||
struct frame *target;
|
||||
|
||||
assert(ses);
|
||||
target = ses_find_frame(ses, id);
|
||||
if (!target) return NULL;
|
||||
if (target->vs.ecmascript_fragile)
|
||||
ecmascript_reset_state(&target->vs);
|
||||
if (!target->vs.ecmascript) return NULL;
|
||||
return js_get_global_object(target->vs.ecmascript->backend_data);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
delayed_open(void *data)
|
||||
{
|
||||
struct delayed_open *deo = data;
|
||||
|
||||
assert(deo);
|
||||
open_uri_in_new_tab(deo->ses, deo->uri, 0, 0);
|
||||
done_uri(deo->uri);
|
||||
mem_free(deo);
|
||||
}
|
||||
|
||||
static void
|
||||
delayed_goto_uri_frame(void *data)
|
||||
{
|
||||
struct delayed_open *deo = data;
|
||||
|
||||
assert(deo);
|
||||
goto_uri_frame(deo->ses, deo->uri, deo->target, CACHE_MODE_NORMAL);
|
||||
done_uri(deo->uri);
|
||||
mem_free(deo);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
window_get(struct SEE_interpreter *interp, struct SEE_object *o,
|
||||
struct SEE_string *p, struct SEE_value *res)
|
||||
{
|
||||
struct js_window_object *win = (struct js_window_object *)o;
|
||||
struct view_state *vs = win->vs;
|
||||
|
||||
checktime(interp);
|
||||
if (p == s_closed) {
|
||||
SEE_SET_BOOLEAN(res, 0);
|
||||
} else if (p == s_self) {
|
||||
SEE_SET_OBJECT(res, o);
|
||||
} else if (p == s_top || p == s_parent) {
|
||||
struct document_view *doc_view = vs->doc_view;
|
||||
struct document_view *top_view = doc_view->session->doc_view;
|
||||
struct js_window_object *newjsframe;
|
||||
|
||||
assert(top_view && top_view->vs);
|
||||
if (top_view->vs->ecmascript_fragile)
|
||||
ecmascript_reset_state(top_view->vs);
|
||||
if (!top_view->vs->ecmascript) {
|
||||
SEE_SET_UNDEFINED(res);
|
||||
return;
|
||||
}
|
||||
newjsframe = js_get_global_object(
|
||||
top_view->vs->ecmascript->backend_data);
|
||||
|
||||
/* Keep this unrolled this way. Will have to check document.domain
|
||||
* JS property. */
|
||||
/* Note that this check is perhaps overparanoid. If top windows
|
||||
* is alien but some other child window is not, we should still
|
||||
* let the script walk thru. That'd mean moving the check to
|
||||
* other individual properties in this switch. */
|
||||
if (compare_uri(vs->uri, top_view->vs->uri, URI_HOST)) {
|
||||
SEE_SET_OBJECT(res, (struct SEE_object *)newjsframe);
|
||||
}
|
||||
|
||||
} else if (p == s_alert) {
|
||||
SEE_SET_OBJECT(res, win->alert);
|
||||
} else if (p == s_open) {
|
||||
SEE_SET_OBJECT(res, win->open);
|
||||
} else {
|
||||
unsigned char *frame = SEE_string_to_unsigned_char(p);
|
||||
struct document_view *doc_view = vs->doc_view;
|
||||
struct js_window_object *obj =
|
||||
js_try_resolve_frame(doc_view, frame);
|
||||
|
||||
mem_free_if(frame);
|
||||
if (obj) {
|
||||
SEE_SET_OBJECT(res, (struct SEE_object *)obj);
|
||||
} else {
|
||||
SEE_SET_UNDEFINED(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
window_put(struct SEE_interpreter *interp, struct SEE_object *o,
|
||||
struct SEE_string *p, struct SEE_value *val, int attr)
|
||||
{
|
||||
checktime(interp);
|
||||
if (p == s_location) {
|
||||
struct js_window_object *win = (struct js_window_object *)o;
|
||||
struct view_state *vs = win->vs;
|
||||
struct document_view *doc_view = vs->doc_view;
|
||||
unsigned char *str = SEE_value_to_unsigned_char(interp, val);
|
||||
|
||||
if (str) {
|
||||
location_goto(doc_view, str);
|
||||
mem_free(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
window_canput(struct SEE_interpreter *interp, struct SEE_object *o,
|
||||
struct SEE_string *p)
|
||||
{
|
||||
checktime(interp);
|
||||
if (p == s_location)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
window_hasproperty(struct SEE_interpreter *interp, struct SEE_object *o,
|
||||
struct SEE_string *p)
|
||||
{
|
||||
checktime(interp);
|
||||
/* all unknown properties return UNDEFINED value */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
js_window_alert(struct SEE_interpreter *interp, struct SEE_object *self,
|
||||
struct SEE_object *thisobj, int argc, struct SEE_value **argv,
|
||||
struct SEE_value *res)
|
||||
{
|
||||
struct js_window_object *win = (struct js_window_object *)thisobj;
|
||||
struct view_state *vs = win->vs;
|
||||
unsigned char *string;
|
||||
|
||||
checktime(interp);
|
||||
SEE_SET_BOOLEAN(res, 1);
|
||||
if (argc < 1)
|
||||
return;
|
||||
|
||||
string = SEE_value_to_unsigned_char(interp, argv[0]);
|
||||
if (!string || !*string)
|
||||
return;
|
||||
|
||||
info_box(vs->doc_view->session->tab->term, MSGBOX_FREE_TEXT,
|
||||
N_("JavaScript Alert"), ALIGN_CENTER, string);
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
js_window_open(struct SEE_interpreter *interp, struct SEE_object *self,
|
||||
struct SEE_object *thisobj, int argc, struct SEE_value **argv,
|
||||
struct SEE_value *res)
|
||||
{
|
||||
struct js_window_object *win = (struct js_window_object*)thisobj;
|
||||
struct view_state *vs = win->vs;
|
||||
struct document_view *doc_view = vs->doc_view;
|
||||
struct session *ses = doc_view->session;
|
||||
unsigned char *target = "";
|
||||
unsigned char *url, *url2;
|
||||
struct uri *uri;
|
||||
#if 0
|
||||
static time_t ratelimit_start;
|
||||
static int ratelimit_count;
|
||||
#endif
|
||||
checktime(interp);
|
||||
SEE_SET_UNDEFINED(res);
|
||||
if (get_opt_bool("ecmascript.block_window_opening")) {
|
||||
#ifdef CONFIG_LEDS
|
||||
set_led_value(ses->status.popup_led, 'P');
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (argc < 1) return;
|
||||
#if 0
|
||||
/* Ratelimit window opening. Recursive window.open() is very nice.
|
||||
* We permit at most 20 tabs in 2 seconds. The ratelimiter is very
|
||||
* rough but shall suffice against the usual cases. */
|
||||
|
||||
if (!ratelimit_start || time(NULL) - ratelimit_start > 2) {
|
||||
ratelimit_start = time(NULL);
|
||||
ratelimit_count = 0;
|
||||
} else {
|
||||
ratelimit_count++;
|
||||
if (ratelimit_count > 20)
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
url = SEE_value_to_unsigned_char(interp, argv[0]);
|
||||
if (!url) return;
|
||||
|
||||
/* TODO: Support for window naming and perhaps some window features? */
|
||||
|
||||
url2 = join_urls(doc_view->document->uri,
|
||||
trim_chars(url, ' ', 0));
|
||||
mem_free(url);
|
||||
if (!url2) return;
|
||||
uri = get_uri(url2, 0);
|
||||
mem_free(url2);
|
||||
if (!uri) return;
|
||||
|
||||
if (argc > 1)
|
||||
target = SEE_value_to_unsigned_char(interp, argv[1]);
|
||||
|
||||
if (target && *target && strcasecmp(target, "_blank")) {
|
||||
struct delayed_open *deo = mem_calloc(1, sizeof(*deo));
|
||||
|
||||
if (deo) {
|
||||
deo->ses = ses;
|
||||
deo->uri = get_uri_reference(uri);
|
||||
deo->target = target;
|
||||
register_bottom_half(delayed_goto_uri_frame, deo);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (!get_cmd_opt_bool("no-connect")
|
||||
&& !get_cmd_opt_bool("no-home")
|
||||
&& !get_cmd_opt_bool("anonymous")
|
||||
&& can_open_in_new(ses->tab->term)) {
|
||||
open_uri_in_new_window(ses, uri, NULL, ENV_ANY,
|
||||
CACHE_MODE_NORMAL, TASK_NONE);
|
||||
} else {
|
||||
/* When opening a new tab, we might get rerendered, losing our
|
||||
* context and triggerring a disaster, so postpone that. */
|
||||
struct delayed_open *deo = mem_calloc(1, sizeof(*deo));
|
||||
|
||||
if (deo) {
|
||||
deo->ses = ses;
|
||||
deo->uri = get_uri_reference(uri);
|
||||
register_bottom_half(delayed_open, deo);
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
done_uri(uri);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
init_js_window_object(struct ecmascript_interpreter *interpreter)
|
||||
{
|
||||
struct global_object *g = interpreter->backend_data;
|
||||
struct SEE_interpreter *interp = &g->interp;
|
||||
struct SEE_value v;
|
||||
|
||||
g->win = SEE_NEW(interp, struct js_window_object);
|
||||
|
||||
g->win->object.objectclass = &js_window_object_class;
|
||||
g->win->object.objectclass->Class = s_window;
|
||||
g->win->object.Prototype = NULL;
|
||||
g->win->vs = interpreter->vs;
|
||||
|
||||
SEE_SET_OBJECT(&v, (struct SEE_object *)g->win);
|
||||
SEE_OBJECT_PUT(interp, interp->Global, s_window, &v, 0);
|
||||
|
||||
g->win->alert = SEE_cfunction_make(interp, js_window_alert, s_alert, 1);
|
||||
g->win->open = SEE_cfunction_make(interp, js_window_open, s_open, 3);
|
||||
}
|
||||
|
||||
void
|
||||
checktime(struct SEE_interpreter *interp)
|
||||
{
|
||||
struct global_object *g = (struct global_object *)interp;
|
||||
|
||||
if (time(NULL) - g->exec_start > g->max_exec_time) {
|
||||
struct terminal *term = g->win->vs->doc_view->session->tab->term;
|
||||
/* A killer script! Alert! */
|
||||
ecmascript_timeout_dialog(term, g->max_exec_time);
|
||||
SEE_error_throw_string(interp, interp->Error, s_timeout);
|
||||
}
|
||||
}
|
27
src/ecmascript/see/window.h
Normal file
27
src/ecmascript/see/window.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef EL__ECMASCRIPT_SEE_WINDOW_H
|
||||
#define EL__ECMASCRIPT_SEE_WINDOW_H
|
||||
|
||||
struct SEE_object;
|
||||
struct SEE_interpreter;
|
||||
struct string;
|
||||
struct view_state;
|
||||
|
||||
|
||||
struct js_window_object {
|
||||
struct SEE_object object;
|
||||
struct view_state *vs;
|
||||
struct SEE_object *alert;
|
||||
struct SEE_object *open;
|
||||
};
|
||||
|
||||
struct global_object {
|
||||
struct SEE_interpreter interp;
|
||||
struct js_window_object *win;
|
||||
int exec_start;
|
||||
int max_exec_time;
|
||||
};
|
||||
|
||||
void init_js_window_object(struct ecmascript_interpreter *);
|
||||
void checktime(struct SEE_interpreter *interp);
|
||||
|
||||
#endif
|
@ -61,6 +61,76 @@
|
||||
|
||||
static JSRuntime *jsrt;
|
||||
|
||||
void
|
||||
ecmascript_init(struct module *module)
|
||||
{
|
||||
spidermonkey_init();
|
||||
}
|
||||
|
||||
void
|
||||
ecmascript_done(struct module *module)
|
||||
{
|
||||
spidermonkey_done();
|
||||
}
|
||||
|
||||
struct ecmascript_interpreter *
|
||||
ecmascript_get_interpreter(struct view_state *vs)
|
||||
{
|
||||
struct ecmascript_interpreter *interpreter;
|
||||
|
||||
assert(vs);
|
||||
|
||||
interpreter = mem_calloc(1, sizeof(*interpreter));
|
||||
if (!interpreter)
|
||||
return NULL;
|
||||
|
||||
interpreter->vs = vs;
|
||||
init_list(interpreter->onload_snippets);
|
||||
spidermonkey_get_interpreter(interpreter);
|
||||
|
||||
return interpreter;
|
||||
}
|
||||
|
||||
void
|
||||
ecmascript_put_interpreter(struct ecmascript_interpreter *interpreter)
|
||||
{
|
||||
assert(interpreter);
|
||||
spidermonkey_put_interpreter(interpreter);
|
||||
free_string_list(&interpreter->onload_snippets);
|
||||
mem_free(interpreter);
|
||||
}
|
||||
|
||||
void
|
||||
ecmascript_eval(struct ecmascript_interpreter *interpreter,
|
||||
struct string *code)
|
||||
{
|
||||
if (!get_ecmascript_enable())
|
||||
return;
|
||||
assert(interpreter);
|
||||
spidermonkey_eval(interpreter, code);
|
||||
}
|
||||
|
||||
unsigned char *
|
||||
ecmascript_eval_stringback(struct ecmascript_interpreter *interpreter,
|
||||
struct string *code)
|
||||
{
|
||||
if (!get_ecmascript_enable())
|
||||
return NULL;
|
||||
assert(interpreter);
|
||||
return spidermonkey_eval_stringback(interpreter, code);
|
||||
}
|
||||
|
||||
int
|
||||
ecmascript_eval_boolback(struct ecmascript_interpreter *interpreter,
|
||||
struct string *code)
|
||||
{
|
||||
if (!get_ecmascript_enable())
|
||||
return -1;
|
||||
assert(interpreter);
|
||||
return spidermonkey_eval_boolback(interpreter, code);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
error_reporter(JSContext *ctx, const char *message, JSErrorReport *report)
|
||||
{
|
||||
@ -123,14 +193,7 @@ safeguard(JSContext *ctx, JSScript *script)
|
||||
struct terminal *term = interpreter->vs->doc_view->session->tab->term;
|
||||
|
||||
/* A killer script! Alert! */
|
||||
info_box(term, MSGBOX_FREE_TEXT,
|
||||
N_("JavaScript Emergency"), ALIGN_LEFT,
|
||||
msg_text(term,
|
||||
N_("A script embedded in the current document was running\n"
|
||||
"for more than %d seconds. This probably means there is\n"
|
||||
"a bug in the script and it could have halted the whole\n"
|
||||
"ELinks, so the script execution was interrupted."),
|
||||
max_exec_time));
|
||||
ecmascript_timeout_dialog(term, max_exec_time);
|
||||
return JS_FALSE;
|
||||
}
|
||||
return JS_TRUE;
|
||||
|
@ -225,7 +225,7 @@ save_formhist_to_file(void)
|
||||
file = straconcat(elinks_home, FORMS_HISTORY_FILENAME, NULL);
|
||||
if (!file) return 0;
|
||||
|
||||
ssi = secure_open(file, 0177);
|
||||
ssi = secure_open(file);
|
||||
mem_free(file);
|
||||
if (!ssi) return 0;
|
||||
|
||||
|
@ -369,7 +369,7 @@ write_global_history(void)
|
||||
file_name = straconcat(elinks_home, GLOBAL_HISTORY_FILENAME, NULL);
|
||||
if (!file_name) return;
|
||||
|
||||
ssi = secure_open(file_name, 0177); /* rw for user only */
|
||||
ssi = secure_open(file_name);
|
||||
mem_free(file_name);
|
||||
if (!ssi) return;
|
||||
|
||||
|
2004
src/intl/entity.inc
2004
src/intl/entity.inc
File diff suppressed because it is too large
Load Diff
@ -267,7 +267,7 @@ get_address(struct socket_info *info, enum addr_type type)
|
||||
info->addr = (struct sockaddr *) sin;
|
||||
info->size = sizeof(*sin);
|
||||
|
||||
return AF_INET;
|
||||
return PF_INET;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -371,14 +371,14 @@ elinks_usleep(unsigned long useconds)
|
||||
static int
|
||||
bind_to_af_unix(void)
|
||||
{
|
||||
mode_t saved_mask = umask(0177);
|
||||
mode_t saved_mask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
|
||||
int attempts = 0;
|
||||
int af = get_address(&s_info_listen, ADDR_IP_SERVER);
|
||||
int pf = get_address(&s_info_listen, ADDR_IP_SERVER);
|
||||
|
||||
if (af == -1) goto free_and_error;
|
||||
if (pf == -1) goto free_and_error;
|
||||
|
||||
while (1) {
|
||||
s_info_listen.fd = socket(af, SOCK_STREAM, 0);
|
||||
s_info_listen.fd = socket(pf, SOCK_STREAM, 0);
|
||||
if (s_info_listen.fd == -1) {
|
||||
report_af_unix_error("socket()", errno);
|
||||
goto free_and_error;
|
||||
@ -435,12 +435,12 @@ static int
|
||||
connect_to_af_unix(void)
|
||||
{
|
||||
int attempts = 0;
|
||||
int af = get_address(&s_info_connect, ADDR_IP_CLIENT);
|
||||
int pf = get_address(&s_info_connect, ADDR_IP_CLIENT);
|
||||
|
||||
while (af != -1 && attempts++ < MAX_CONNECT_TRIES) {
|
||||
while (pf != -1 && attempts++ < MAX_CONNECT_TRIES) {
|
||||
int saved_errno;
|
||||
|
||||
s_info_connect.fd = socket(af, SOCK_STREAM, 0);
|
||||
s_info_connect.fd = socket(pf, SOCK_STREAM, 0);
|
||||
if (s_info_connect.fd == -1) {
|
||||
report_af_unix_error("socket()", errno);
|
||||
break;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user