1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-12-04 14:46:47 -05:00
This commit is contained in:
Kalle Olavi Niemitalo 2007-07-09 11:39:21 +03:00 committed by Kalle Olavi Niemitalo
commit eccc8c23f0
106 changed files with 2274 additions and 4704 deletions

View File

@ -3,9 +3,17 @@ by doing
$ cg log $ cg log
in a checked out GIT tree, or using the gitweb interface currently in a checked out GIT tree, or using the gitweb interface available at:
available at
http://pasky.or.cz/gitweb.cgi http://repo.or.cz/w/elinks.git
(to be moved to a nicer location later). The data in the main repository reaches back to 2005-09-16, when
ELinks switched from CVS to GIT. To see changes made in CVS before
that, download the history with the contrib/grafthistory.sh script.
Unfortunately, because files in the CVS repository have been moved or
copied around, checking out a historical version often places files in
the wrong directories. The history is usable for git-blame, however.
It is currently also viewable at these sites:
http://pasky.or.cz/gitweb.cgi?p=elinks-history.git
http://cvsweb.elinks.cz/cvsweb.cgi/elinks/

View File

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

View File

@ -191,6 +191,21 @@ test-default:
ifdef TEST_PROGS ifdef TEST_PROGS
TESTDEPS-$(CONFIG_DEBUG) += $(top_builddir)/src/util/memdebug.o TESTDEPS-$(CONFIG_DEBUG) += $(top_builddir)/src/util/memdebug.o
TESTDEPS-$(call not,$(CONFIG_SMALL)) += \
$(top_builddir)/src/util/fastfind.o \
# Add most of the basic utility library to the test dependencies.
TESTDEPS += \
$(top_builddir)/src/intl/charsets.o \
$(top_builddir)/src/osdep/stub.o \
$(top_builddir)/src/util/conv.o \
$(top_builddir)/src/util/error.o \
$(top_builddir)/src/util/file.o \
$(top_builddir)/src/util/hash.o \
$(top_builddir)/src/util/memory.o \
$(top_builddir)/src/util/string.o \
$(top_builddir)/src/util/time.o
TESTDEPS += $(TESTDEPS-yes) TESTDEPS += $(TESTDEPS-yes)
TEST_LIB=$(top_srcdir)/test/libtest.sh TEST_LIB=$(top_srcdir)/test/libtest.sh

403
NEWS
View File

@ -1,8 +1,8 @@
Release info Release info
============ ============
You can see the complete list of recent changes, bugfixes and new features in You can see the complete list of recent changes, bugfixes and new features
the link:http://pasky.or.cz/gitweb.cgi[gitweb interface]. See the ChangeLog in the http://repo.or.cz/w/elinks.git[gitweb interface]. See the ChangeLog
file for details. file for details.
ELinks 0.13.GIT now: ELinks 0.13.GIT now:
@ -17,192 +17,160 @@ To be released as ELinks 0.12.0.
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
This list now contains all the important changes from ELinks 0.11.0 to This list now contains all the important changes from ELinks 0.11.0 to
ELinks 0.12.GIT (049cc9c6b37951a739dfd6b20ca92c170188824c). The next ELinks 0.12.GIT (0cf15ca9d9dbc00c10f23440674fcdb832dffd75) and related
step will be to scan through Bugzilla and look for bug numbers that bug numbers. Each section is sorted by severity and grouped by topic.
were not mentioned in related commit messages.
The list no doubt includes several changes that are not really The list no doubt includes several changes that are not really
important enough. Please move them to the separate "should be removed important enough. Please move them to the separate "should be removed
from NEWS" list below, or coalesce several changes into one entry (but from NEWS" list below, or coalesce several changes into one entry (but
do list all bug numbers). It might be a good idea to sort the entries do list all bug numbers).
roughly in decreasing order of importance.
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
* Notable new features Notable new features:
- (unfinished enhancement 822) UTF-8 as terminal charset: not
merely UTF-8 I/O of a unibyte codepage as in previous versions. * enhancement 822: UTF-8 as terminal charset, not merely UTF-8 I/O
Double-cell (aka fullwidth) and non-BMP characters work too, but of a unibyte codepage as in previous versions. Double-cell (aka
combining characters and right-to-left text do not. The only fullwidth) and supplementary characters work too, but combining
multibyte charset ELinks can decode is still UTF-8, so if the characters and right-to-left text do not. The only multibyte
server outputs e.g. Shift-JIS, you'd better recode with a proxy. charset ELinks can decode is still UTF-8, so if the server outputs
- (enhancement 844) SMB protocol using libsmbclient. This replaces e.g. Shift-JIS, you'd better recode with a proxy. See more notes
the smbclient-based code that was disabled in ELinks 0.11.2. in features.conf.
* Incompatibilities * enhancement 844: SMB protocol using libsmbclient. This replaces
- ECMAScript support is now disabled by default. It has known the smbclient-based code that was disabled in ELinks 0.11.2.
bugs (548, 755, 771) with which malicious web pages can crash or
hang ELinks, and its security goals are undocumented. If you must Incompatibilities:
enable ECMAScript support, it would be prudent to restrict the
ELinks process with a sandbox of some kind. * ECMAScript support is now disabled by default. It has known
- (bug 871) The numbering of terminal.*.colors no longer depends on bugs 548 and 771 with which malicious web pages can hang ELinks,
config options. This change makes elinks.conf portable between and its security goals are undocumented. If you must enable
different configurations but unfortunately not between this and ECMAScript support, it would be prudent to restrict the ELinks
previous versions. process with a sandbox of some kind.
- Changed Python goto_url_hook(current) to goto_url_hook(new). The * ECMAScript support no longer works with SpiderMonkey versions
hook can call the new function elinks.current_url() if desired. earlier than JS1.5 RC3a.
The Python scripting back-end is much more featureful than in * Gzip decompression support now requires zlib 1.2.0.2 or later.
previous releases, but it is still considered experimental. * bugs 871, 752: The numbering of terminal.*.colors no longer depends
* Miscellaneous on config options. This change makes elinks.conf portable between
- (enhancement 752) Documentation updates different configurations but unfortunately not between this and
- (enhancement 381) Reduce memory consumption of codepages and some previous versions.
other arrays. * Changed Python goto_url_hook(current) to goto_url_hook(new). The
- (enhancement) Reject invalid UTF-8 input from documents and hook can call the new function elinks.current_url() if desired.
terminals. The Python scripting back-end is much more featureful than in
* Changes in terminal support previous releases, but it is still considered experimental.
- (enhancement) Mouse wheel support on BSD via moused -z 4 * Guile scripting reads hooks.scm rather than internal-hooks.scm.
- (enhancement) Support for mouse wheel over GPM (It still reads user-hooks.scm, too.)
- (bugfix 724) Better parsing of escape sequences and control
sequences from the terminal. Miscellaneous:
- (bugfix) Decode UTF-8 only from bytes, not from codes of special
keys. * critical bug 756: ``assertion (cached)->object.refcount >= 0 failed''
- (new feature) 24-bit truecolor mode after HTTP proxy was changed
- (enhancement) "Resize terminal" tries to use the window size * tabs opened by -remote now go behind existing dialogs
increment. * Debian bug 257762: turn terminal transparency off by default
- (new feature) Support Ctrl+Alt+letter key combinations. * bug 724: better parsing of escape sequences and control
- (bugfix) Subprocess forked for SIGTSTP calls _exit, not exit. sequences from the terminal
- (enhancement) Turn terminal transparency off by default. * bug 948: fix wrong UTF-8 output after the charset menu was used
* Changes in cookies and bookmarks * gzip_read: always call gzclearerr
- (new feature) "Add server" button in the cookie manager. * bug 816: convert entity references in input/@value only once
- (enhancement) Tell the user how to move bookmarks. * bug 916: if a mailcap entry has no %s, provide the file as stdin
- (enhancement 887) Save in cookie manager should save cookies even * bug 355: add documents displayed via ``What to do'' dialog to the
if unmodified. global history
* Changes in the user interface * encode and decode filenames in FSP URLs
- (new feature 145) Internal clipboard support * don't use a busy cache entry if it has expired or should be
- (enhancement) Localization updates reloaded. See elinks-users mail from 28 Oct 2005.
- (bugfix 355) Add documents displayed via "What to do" dialog to * several accesskey fixes
globhist * in Lua: don't write to the string returned by lua_tostring
- (new feature) Autocreate directories needed to download a file. * minor bug 284: render closing bracket for HTML element SUB in the
- (new feature) Option ui.show_menu_bar_always same line; don't let it fall to the next
- (new feature) Option ui.tabs moves the tab bar to the top. * minor: show quote characters for HTML element Q, rather than italics
- (new feature) New actions: kill-word-back, move-backward-word, * trivial bug 387: treat &#013; inside <pre>...</pre> as a newline
move-forward-word * trivial bug 930: refresh status bar when key prefix is eaten
- (enhancement) Ctrl+characters don't trigger hotkeys in menus and * trivial bug 776: ``elinks -remote http://elinks.cz/'' no longer clears
dialogs. the screen
- (bugfix 396) Never show empty filename in the what-to-do dialog * enhancement 121: if a mailcap entry indicates 'copiousoutput', ELinks
- (bugfix 930) Refresh status bar when key prefix is eaten. itself acts as a pager
* Changes in support for URI schemes, protocols, caching, and encodings * enhancement 790: If-Modified-Since and If-None-Match
- (bugfix) Fixes cache-control issue. See elinks-users mail from 28 Oct 2005 * enhancement: HTTP negotiate-auth using GSSAPI
- (new feature) LZMA decompression * enhancement 517: fixed and enabled HTTP bzip2 decompression
- (bugfix 517) Fixed and enabled HTTP bzip2 decompression * enhancement: LZMA decompression
- (new feature) HTTP negotiate-auth using GSSAPI * enhancement: FSP progress indicator and password prompt
- (bugfix 770) Download resuming simply restarts the download * enhancement: autocreate directories needed to download a file
- (bugfix 691) Fix IPv4 DNS lookup bug * enhancement: ``Add server'' button in the cookie manager
- (enhancement 790) If-Modified-Since and If-None-Match * enhancement 887: ``Save'' in the cookie manager now saves cookies
- (bugfix) gzip_read: always call gzclearerr even if unmodified
- (bugfix 107) Recognize "localhost" in file: URIs. * enhancement 145: internal clipboard support
- (bugfix 756) "assertion (cached)->object.refcount >= 0 failed" * enhancement: new actions kill-word-back, move-backward-word,
after HTTP proxy was changed move-forward-word
- (bugfix) Encode and decode filenames in FSP URLs. * enhancements 687, 688: options ui.tabs.top, ui.show_menu_bar_always
- (enhancement) FSP progress indicator and password prompt. * enhancement: highlight links as one enters link prefixes
- (bugfix) Support much longer locale-specific timestamps when * enhancement: backspace backs out the last digit of the prefix
formatting a directory listing. LC_TIME=fi_FI.UTF-8 now works. * enhancement: in text type-ahead searching, don't follow current link
- (bugfix 712) GnuTLS works on https://www-s.uiuc.edu on enter
* Changes in parsing and rendering of HTML (without DOM) * enhancement: add support for parsing space separated CSS class
- (bugfix) Use frame->name instead of target avoiding possible segfault. attribute values
- (bugfix 284) Render closing parentheses for HTML elements SUB, SUP * enhancement: mouse wheel support over GPM (contrib/gpm-wheel.patch),
in the same line; don't let them fall to the next. and on BSD via moused -z 4
- (enhancement) Show quote characters for HTML element Q, rather * enhancement: 24-bit truecolor mode
than italics. * enhancement 622: -dump-color-mode
- (enhancement) Add support for parsing space separated CSS class * enhancement: support Ctrl+Alt+letter key combinations
attribute values * enhancement 381: reduce memory consumption of codepages and some
- (bugfix 387) Treat &#013; inside <pre>...</pre> as a newline. other arrays
* Changes in parsing and rendering of non-HTML content-types * enhancement in user SMJS: new properties/functions elinks.action,
- (new feature 121) If a mailcap entry indicates copiousoutput, elinks.execute, elinks.globhist, elinks.load_uri, elinks.vs
ELinks itself acts as a pager.
- (new feature 916) If a mailcap entry has no %s, provide the file Build system and compile-time errors (ignore if you don't build ELinks):
as stdin.
* Changes in the document viewer and tabs * bug 725: fix version checking for Ruby in 'configure'
- (new feature) Highlight links as one enters link prefixes. * enhancement: if make -k was used and a sub-Make fails, build the
- (new feature) Backspace backs out the last digit of the prefix. rest before propagating
- (bugfix) Tabs opened by -remote now go behind existing dialogs. * enhancement: avoid compilation of vernum.c in 'make install'
- (new feature 622) -dump-color-mode * enhancement: make uninstall
- (bugfix) Fix accesskeys so that they work when priority is 0 * experimental enhancements: --with-python=DIRECTORY, --with-gc=DIRECTORY
- (enhancement) Text type-ahead searching: don't follow current link * experimental enhancement: native Win32 port
on enter
- (bugfix) Take the terminal charset in account when comparing Changes in the experimental ECMAScript support:
accesskeys.
- (enhancement) Display accesskeys as e.g. (Alt-f), not just (f). * disabled by default, as mentioned under ``Incompatibilities'' above
* Changes in user scripting * execute event-handler scripts as function bodies, so ``return''
- (enhancement) Guile: Read hooks.scm rather than internal-hooks.scm. statements work as intended
(Keep reading user-hooks.scm, too.) * fix error ``forms.namedItem is not a function''
- (bugfix) Lua: Don't write to the string returned by lua_tostring. * enhancement: SEE ECMAScript backend, an alternative to SpiderMonkey
- (bugfix 945) Lua: Don't crash if a script calls e.g. error(nil). * enhancement: handling onsubmit
- (enhancement) SMJS: elinks.alert no longer displays as an "error". * workaround: window.open remembers the last few URLs and doesn't
- (new feature) SMJS: New properties elinks.action, elinks.globhist, reopen them when incremental rendering reruns the onload script
elinks.vs. * enhancement: better handling of form.action assignments
- (new feature) SMJS: New function elinks.load_uri. * enhancement: form[x] looks up controls also by 'id', not only 'name'
- (new feature) SMJS: New method elinks.execute. * enhancement: added document.location.href, input.selectedIndex,
- (enhancement) SMJS: Garbage-collect SMJS objects before flushing window.setTimeout, window.status
caches.
- (bitrot) Perl: Don't assume POPpx stores the length to n_a. Changes in the experimental SGML/DOM implementation:
- (bugfix) Perl: Fix pre_format_html hook wrt. binary files.
* Build system and compile-time errors (ignore if you don't build ELinks) * enhancement: minimalistic RSS renderer
- (bugfix) Fixed some bugs about compiling outside the source * enhancement: source highlighting also recognizes
directory. application/xhtml+xml and application/docbook+xml. It doesn't yet
- (bugfix) Don't use cmp -b, which FreeBSD doesn't support. support arbitrary XML though.
- (bugfix) Don't include <sys/param.h> for MIN and MAX because it * enhancement: make it possible to use more CSS properties with the
may interfere with CONFIG_IPV6 on Linux. source highlighting
- (bugfix) When the configure script cleans old object files, this * enhancement: handle <base href=""> for HTML source rendering
no longer causes it to loop. * enhancement: add support for scanning comment endings such as
- (experimental, new feature) --with-python=DIRECTORY, --with-gc=DIRECTORY '--!>' correctly
- (bugfix) Include <sys/types.h> and fix compilation on an old * enhancement: incremental parsing
PPC/Debian system * and more.
- (bitrot) Fix compilation under gcc 4.x. Backported from gentoo portage.
Also, reduce warnings on gcc 4.2 snapshots.
- (bitrot) Update SpiderMonkey configure check Debian compatibility
- (new feature 779) make uninstall
- (experimental, new feature) Native Win32 port
- (enhancement) If make -k was used and a sub-Make fails, build the
rest before propagating.
- (enhancement) Avoid compilation of vernum.c in 'make install'
- (bugfix) Don't use $(AM_CFLAGS) anymore. Use $(CPPFLAGS) instead.
- (bitrot) Fix two warnings on Mac OS X.
* (experimental) Changes in ECMAScript support
- (new feature) SEE ECMAScript backend, an alternative to SpiderMonkey.
- (new feature) Handling onsubmit
- (workaround) window.open remembers the last few URLs and doesn't
reopen them when incremental rendering reruns the onload script.
- (enhancement) Recognize document.location.href for SMJS.
- (enhancement) Better handling of form.action assignments
- (enhancement) form[x] looks up controls also by id, not only name.
- (new feature) New property input.selectedIndex.
- (new feature) Activate link only when onClick returns true.
- (enhancement) input.accessKey can be any Unicode character except
U+0000.
- (new feature) window.setTimeout, window.status
* (experimental) Changes in SGML/DOM implementation
- (new feature) Minimalistic RSS renderer
- (enhancement) Source highlighting also recognizes
application/xhtml+xml and application/docbook+xml. It doesn't yet
support arbitrary XML though.
- (enhancement) Make it possible to use more CSS properties with the
source highlighting
- (enhancement) Handle <base href=""> for HTML source rendering
- (enhancement) Add support for scanning comment endings such as
'--!>' correctly
- (new feature) Incremental parsing
- And more.
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
The following changes should be removed from NEWS before ELinks 0.12.0 The following changes should be removed from NEWS before ELinks 0.12.0
is released. They are currently listed here just to show that they is released. They are currently listed here just to show that they
have already been considered. have already been considered.
* Not clear whether the bugs have been fixed:
- (bugfix 674) Reproduceable crashes while trying to unsubscribe
from a community on Orkut
- (bugfix 770) Download resuming simply restarts the download
* Only partially fixed bugs: * Only partially fixed bugs:
- (bugfix 764) int/long type punning in options - (bugfix 764) int/long type punning in options
- (bugfix 725) Fixes version checking for Ruby in 'configure'
- (bugfix 890) Change colors 0-15 to match xterm defaults. - (bugfix 890) Change colors 0-15 to match xterm defaults.
The bug report also requests asking xterm to report its palette, The bug report also requests asking xterm to report its palette,
but that part will be delayed to 0.13 or later. but that part will be delayed to 0.13 or later.
- (bugfix 784) attributes corrupt character entity references if
terminal charset != document charset
* Fixed bugs that were not in previous versions: * Fixed bugs that were not in previous versions:
- (bugfix) Fix a crash when adding a server in the cookie manager. - (bugfix) Fix a crash when adding a server in the cookie manager.
- (bugfix) cookies: "Add Server" ignores "cookies.accept_policy". - (bugfix) cookies: "Add Server" ignores "cookies.accept_policy".
@ -210,8 +178,6 @@ have already been considered.
- (bugfix 747) Properly deselect the main menu instead of crashing - (bugfix 747) Properly deselect the main menu instead of crashing
- (bugfix 778) ELinks crashes on binary files when - (bugfix 778) ELinks crashes on binary files when
document.plain.display_links is set document.plain.display_links is set
- (bugfix 784) UTF-8 mode misconverts non-ASCII entity in Latin-1
document
- (bugfix 782) UTF-8 buffer overwritten while in use - (bugfix 782) UTF-8 buffer overwritten while in use
- (bugfix) switch_to_tab: Prevent "tab number out of range" - (bugfix) switch_to_tab: Prevent "tab number out of range"
assertion failure. assertion failure.
@ -219,7 +185,6 @@ have already been considered.
- (bugfix 821) I cannot enter national characters in dialog boxes - (bugfix 821) I cannot enter national characters in dialog boxes
- (bugfix 834) Gzip decompression doesn't work - (bugfix 834) Gzip decompression doesn't work
- (bugfix) Fix out-of-bound access to the quote_char buffer - (bugfix) Fix out-of-bound access to the quote_char buffer
- (bugfix 788) compile error with --enable-perl
- (bugfix 827) Crash with term charset set to Unicode and UTF-8 I/O - (bugfix 827) Crash with term charset set to Unicode and UTF-8 I/O
disabled disabled
- (bugfix 826) too small table for double-cell characters - (bugfix 826) too small table for double-cell characters
@ -235,6 +200,28 @@ have already been considered.
as entity references as entity references
- (bugfix 935) Yes and No buttons override the bottom border of the - (bugfix 935) Yes and No buttons override the bottom border of the
dialog. dialog.
- (bugfix in SEE) Use frame->name instead of target avoiding
possible segfault.
- (bugfix 957) crash within js_Interpret: cx->fp points to freed
memory
- (bugfix 920) assertion priority >= prev_priority failed: queue is
not sorted
* Already backported to a previous release but not listed there:
- (enhancement) Activate link only when onClick returns true.
Fixed bug 786 in ELinks 0.11.2.
- when the configure script cleans old object files, this no longer
causes it to loop. Commit 564b67883b189a05839bcd2a30d8d4c6eb89c66d
in ELinks 0.11.1.
- don't include <sys/param.h> for MIN and MAX because it may interfere with
CONFIG_IPV6 on Linux. Commit 63797ae9b331efd91be27512bd9d5b2e2ff74741
in ELinks 0.11.1.
- Debian bug 400872: include <sys/types.h> for off_t.
(Related to bug 936 but not the same.)
Commit 135a79a3c309af36cf963f1d3c34b07f296fa2f7 in ELinks 0.11.3.
- bug 107: recognize "localhost" in file: URIs. Cannot reproduce in
earlier versions.
- fix compilation under gcc 4.x. Backported from gentoo portage.
Commit bcabd8b7951f3319199811088e607501296ee573 in ELinks 0.11.3.
* Reverted changes: * Reverted changes:
- (new feature) document.write, reverted in - (new feature) document.write, reverted in
2c087e52e74528a720621186b91880463e039d50 2c087e52e74528a720621186b91880463e039d50
@ -263,8 +250,67 @@ have already been considered.
(commit 539f756438fca4264ab937b2ccfba2351e916a16) (commit 539f756438fca4264ab937b2ccfba2351e916a16)
- (bugfix) Don't claim that the authentication is for HTTP. - (bugfix) Don't claim that the authentication is for HTTP.
(commit ef2f6383c6f0bed576e6f69030eacc4931b42a27) (commit ef2f6383c6f0bed576e6f69030eacc4931b42a27)
- (enhancement) Reject invalid UTF-8 input from documents and
terminals
- (bugfix) Decode UTF-8 only from bytes, not from codes of special
keys.
- (enhancement) "Resize terminal" tries to use the window size
increment.
- (bugfix) Subprocess forked for SIGTSTP calls _exit, not exit.
- (enhancement) Tell the user how to move bookmarks.
- (enhancement) Localization updates. For this to be important, we
should at least list the languages.
- (enhancement) Ctrl+characters don't trigger hotkeys in menus and
dialogs.
- (bitrot) Fix two warnings on Mac OS X.
- (enhancement) reduce warnings on gcc 4.2 snapshots
* don't use cmp -b, which FreeBSD doesn't support. This is commit
7a5f699a88c5fc89c510854b04702c16c30ece5a in src/dom/test/ which
is run only by "make test" rather than "make".
* support much longer locale-specific timestamps when formatting a
directory listing. LC_TIME=fi_FI.UTF-8 now works. Let's treat
this as part of the UTF-8 support.
* enhancement in user SMJS: elinks.alert no longer displays as an
"error"
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
ELinks 0.11.3.GIT now:
----------------------
To be released as 0.11.4.
* critical bug 755: fix crashes due to dangling pointers to struct
form_state
* critical bug 945: don't crash if a Lua script calls e.g. error(nil)
* major bug 956: don't reuse pointers to SpiderMonkey objects that may
have been collected as garbage. This fix causes bug 954.
* CVE-2007-2027: check if the program path contains "src/" before
using ../po files
* important Debian bug 380347: prevent a buffer overflow in entity_cache
and a possible subsequent crash
* major bug 788: don't read STRLEN n_a, which isn't initialized by
POPpx of Perl v5.8.8 and later
* fix query parsing in file: URIs for local CGI (was broken in 0.11.3)
* bug 691: don't look up bogus IPv4 addresses based on characters of a
hostname
* bug 712: GnuTLS works on https://www-s.uiuc.edu/[]
* fix passive FTP over IPv6 when connect() fails with EINPROGRESS
* minor bug 951 in user SMJS: garbage-collect SMJS objects on 'File ->
Flush all caches' to work around their holding cache entries busy
* minor bug 396: never show empty filename in the what-to-do dialog
* minor bug 461: ensure contrast in blank areas, to keep the cursor visible
* minor bug 928: properly display no-break spaces in a UTF-8 document
if the terminal uses some other charset
* trivial bug 947: document.html.wrap_nbsp also affects text in tables
* build bug 950: fix ``config/install-sh: No such file or directory''
on SunOS
* build bug 936: fix errors about undefined off_t (autoheader
incompatibility)
* build: update SpiderMonkey configure check Debian compatibility
* build: use $(CPPFLAGS) rather than $(AM_CFLAGS)
* minor build bug 960: fix errors in loadmsgcat.c if mmap() exists but
munmap() doesn't
ELinks 0.11.3: ELinks 0.11.3:
-------------- --------------
@ -305,7 +351,7 @@ Released on 2007-04-15.
* remove a garbage character from the end of the authentication prompt * remove a garbage character from the end of the authentication prompt
* bugs 872, 886: editing or deleting cookies in the cookie manager * bugs 872, 886: editing or deleting cookies in the cookie manager
should cause a save should cause a save
* secure file saving: restore umask after _all_ failure conditions * secure file saving: restore umask after *all* failure conditions
* decode the fragment identifier extracted from the URI when looking * decode the fragment identifier extracted from the URI when looking
it up it up
* bug 768 in experimental Python scripting: link with e.g. -lpython2.4 * bug 768 in experimental Python scripting: link with e.g. -lpython2.4
@ -402,6 +448,7 @@ ELinks 0.10.0 (Thelma):
Released on 2004-12-24. Released on 2004-12-24.
* licensed under GPLv2 only
* simple CSS * simple CSS
* simple JavaScript/ECMAScript support by the SpiderMonkey Mozilla JS engine * simple JavaScript/ECMAScript support by the SpiderMonkey Mozilla JS engine
* plain-text mark-up (_^Hx to underline, x^Hx to embolden) * plain-text mark-up (_^Hx to underline, x^Hx to embolden)
@ -416,12 +463,12 @@ Released on 2004-12-24.
* incremental searching (press '#/') * incremental searching (press '#/')
* Perl scripting back-end (experimental) * Perl scripting back-end (experimental)
* build-time configurability and feature documentation through features.conf * build-time configurability and feature documentation through features.conf
* Mozilla-compatible -remote option (http://www.mozilla.org/unix/remote.html) * Mozilla-compatible -remote option (http://www.mozilla.org/unix/remote.html[])
* support for specifying IP family as protocol postfix (i.e. http4 or ftp6) * support for specifying IP family as protocol postfix (e.g. http4 or ftp6)
* internationalized domain names via libidn (RFC 3490) * internationalized domain names via libidn (RFC 3490)
* data URI protocol (RFC 2397) * data URI protocol (RFC 2397)
* gopher protocol (RFC 1436) * gopher protocol (RFC 1436)
* NNTP protocol (RFC 977 and 2980) (experimental) * NNTP protocol (RFC 977 and RFC 2980) (experimental)
* build system fine-tuned to use automake conditionals * build system fine-tuned to use automake conditionals
* -localhost option to block connections to remote hosts * -localhost option to block connections to remote hosts
* -verbose option to control messages printed at startup * -verbose option to control messages printed at startup

26
TODO
View File

@ -1,20 +1,18 @@
The ELinks TODO items are kept in Bugzilla (http://bugzilla.elinks.cz/), TODO list
look for the bugs with 'enhancement' severity. Some generic goals are still =========
kept here, though, to be more on the developers' eyes ;-).
What yet needs to take its way to Bugzilla:
Rewrite HTML parser (see the SGML+DOM stuff: src/dom/ & src/document/dom)
Reorganization of user interface (nothing particular at all, just an
uncertain feel that it could be better and bear a look of some UI designer ;)
The ELinks TODO items are kept in Bugzilla <http://bugzilla.elinks.cz/>;
look for the bugs with 'enhancement' severity. More general goals are
still kept here, though, to be more visible to developers. ;-) Finally,
the code contains several (greppable) "FIXME" and "TODO" notes regarding
smaller fixes and enhancements.
General goals: General goals:
Write some more documentation.. docs, a lot of docs! - Rewrite HTML parser (see the SGML+DOM stuff: src/dom/ & src/document/dom)
General code cleanup - Write more documentation; docs, a lot of docs!
Speed/memory optimizations - General code cleanup
- Speed/memory optimizations

View File

@ -12,6 +12,11 @@ aclocal
echo autoheader... echo autoheader...
autoheader autoheader
# The timestamp of stamp-h.in indicates when config.h.in was last
# generated or found to be already correct. Create stamp-h.in so
# that it gets included in elinks-*.tar.gz and Makefile won't try
# to run a possibly incompatible version of autoheader (bug 936).
echo timestamp > stamp-h.in
echo autoconf... echo autoconf...
autoconf autoconf

View File

@ -1,6 +1,9 @@
dnl Process this file with autoconf to produce a configure script. dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.13) dnl Autoconf 2.13 generates an incomplete config.h.in; see ELinks bug 936.
dnl Autoconf 2.59 is installed in the computer that generates our daily
dnl snapshots, so we need to be compatible with that.
AC_PREREQ(2.59)
AC_INIT(src/main/main.c) AC_INIT(src/main/main.c)
AC_CONFIG_AUX_DIR(config) AC_CONFIG_AUX_DIR(config)
@ -465,7 +468,7 @@ AC_DEFUN([EL_CONFIG_OPTIONAL_LIBRARY],
EL_CONFIG_OPTIONAL_LIBRARY(CONFIG_GPM, gpm, gpm.h, gpm, Gpm_Open, EL_CONFIG_OPTIONAL_LIBRARY(CONFIG_GPM, gpm, gpm.h, gpm, Gpm_Open,
[ --without-gpm disable gpm (mouse) support]) [ --without-gpm disable gpm (mouse) support])
EL_CONFIG_OPTIONAL_LIBRARY(CONFIG_GZIP, zlib, zlib.h, z, gzdopen, EL_CONFIG_OPTIONAL_LIBRARY(CONFIG_GZIP, zlib, zlib.h, z, gzclearerr,
[ --without-zlib disable zlib support]) [ --without-zlib disable zlib support])
EL_CONFIG_OPTIONAL_LIBRARY(CONFIG_BZIP2, bzlib, bzlib.h, bz2, BZ2_bzReadOpen, EL_CONFIG_OPTIONAL_LIBRARY(CONFIG_BZIP2, bzlib, bzlib.h, bz2, BZ2_bzReadOpen,
@ -572,14 +575,9 @@ AC_ARG_WITH(see, [ --with-see enable Simple Ecmascript Engine (SEE
# to compile CVS. Also, the macro seems to be really stupid regarding searching # to compile CVS. Also, the macro seems to be really stupid regarding searching
# for Guile in $PATH etc. --pasky # for Guile in $PATH etc. --pasky
AC_MSG_CHECKING([for SEE])
CONFIG_ECMASCRIPT_SEE=no CONFIG_ECMASCRIPT_SEE=no
if test "$enable_see" = "yes"; then if test "$enable_see" = "yes"; then
AC_MSG_RESULT(yes);
## Based on the SEE_FLAGS macro.
if test -d "$withval"; then if test -d "$withval"; then
SEE_PATH="$withval:$PATH" SEE_PATH="$withval:$PATH"
else else
@ -587,16 +585,24 @@ if test "$enable_see" = "yes"; then
fi fi
AC_PATH_PROG(SEE_CONFIG, libsee-config, no, $SEE_PATH) AC_PATH_PROG(SEE_CONFIG, libsee-config, no, $SEE_PATH)
AC_MSG_CHECKING([for SEE (2.0.1131 or later)])
## First, let's just see if we can find Guile at all.
if test "$SEE_CONFIG" != no; then if test "$SEE_CONFIG" != no; then
cf_result="yes"; EL_SAVE_FLAGS
SEE_LIBS="`$SEE_CONFIG --libs`" SEE_LIBS="`$SEE_CONFIG --libs`"
SEE_CFLAGS="`$SEE_CONFIG --cppflags`" SEE_CFLAGS="`$SEE_CONFIG --cppflags`"
LIBS="$SEE_LIBS $LIBS" CPPFLAGS="$SEE_CFLAGS $CPPFLAGS"
EL_CONFIG(CONFIG_ECMASCRIPT_SEE, [SEE]) LIBS="$SEE_LIBS $LIBS_X"
AC_SUBST(SEE_CFLAGS) AC_TRY_LINK([#include <see/see.h>],[#if SEE_VERSION_API_MAJOR < 2
#error SEE too old
#endif
], cf_result=yes, cf_result=no)
EL_RESTORE_FLAGS
if test "$cf_result" = yes; then
LIBS="$SEE_LIBS $LIBS"
EL_CONFIG(CONFIG_ECMASCRIPT_SEE, [SEE])
AC_SUBST(SEE_CFLAGS)
fi
AC_MSG_RESULT($cf_result)
else else
if test -n "$withval" && test "x$withval" != xno; then if test -n "$withval" && test "x$withval" != xno; then
AC_MSG_ERROR([SEE not found]) AC_MSG_ERROR([SEE not found])
@ -604,18 +610,15 @@ if test "$enable_see" = "yes"; then
AC_MSG_WARN([SEE support disabled]) AC_MSG_WARN([SEE support disabled])
fi fi
fi fi
else
AC_MSG_RESULT(no);
fi fi
dnl =================================================================== dnl ===================================================================
dnl Check for SpiderMonkey, optional even if installed. dnl Check for SpiderMonkey, optional even if installed.
dnl =================================================================== dnl ===================================================================
AC_ARG_WITH(spidermonkey, [ --without-spidermonkey disable SpiderMonkey Mozilla JavaScript engine support], AC_ARG_WITH(spidermonkey, [ --without-spidermonkey disable SpiderMonkey Mozilla JavaScript engine support],
[if test "$withval" = no; then disable_spidermonkey=yes; fi]) [if test "$withval" = no; then disable_spidermonkey=yes; fi])
AC_MSG_CHECKING([for SpiderMonkey]) AC_MSG_CHECKING([for SpiderMonkey (1.5 RC3a or later)])
EL_SAVE_FLAGS EL_SAVE_FLAGS
cf_result=no cf_result=no
@ -641,7 +644,7 @@ if test -z "$disable_spidermonkey"; then
AC_TRY_LINK([#define XP_UNIX AC_TRY_LINK([#define XP_UNIX
#include <jsapi.h>], #include <jsapi.h>],
[JS_GetImplementationVersion()], [JS_GetReservedSlot(NULL, NULL, 0, NULL)],
cf_result=yes, cf_result=no) cf_result=yes, cf_result=no)
fi fi
done done

View File

@ -9,7 +9,6 @@ Copyright:
This program is free software. You may redistribute it and/or modify it This program is free software. You may redistribute it and/or modify it
under the terms of The GNU General Public License, as published by the Free under the terms of The GNU General Public License, as published by the Free
Software Foundation; either version 2, or (at your option) any later Software Foundation, specifically version 2 of the License. A copy of this
version. A copy of this license is in the file license is in the file /usr/share/common-licenses/GPL-2.
/usr/share/common-licenses/GPL.

File diff suppressed because it is too large Load Diff

5
contrib/proxy/Makefile Normal file
View File

@ -0,0 +1,5 @@
all: /tmp/log gen
./gen
gen: gen.c
$(CC) -g -o $@ $<

29
contrib/proxy/README Normal file
View File

@ -0,0 +1,29 @@
This program generate proxy.py - a tool for developers to find bugs offline.
How to use it:
1) make the change in src/network/socket.c and recompile the ELinks
/* To enable logging of tranfers, for debugging purposes. */
#if 0
^^^^^
set this to 1
2) set connection.max_connections = 1
set connection.max_connections_to_host = 1
3) run the ELinks and gather data.
4) revert "#if 1 change" and recompile ELinks.
5) run make in directory with this file. The proxy.py should be generated
and some files with .txt extension.
6) run proxy.py
7) run ELinks and set protocol.http.proxy = localhost:8000
8) repeat previous session, go to the same pages, etc.
If you want to use https use browser scripting to replace
'https' with 'http' in follow_url.
Enjoy,
Witek

177
contrib/proxy/gen.c Normal file
View File

@ -0,0 +1,177 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
struct stat st;
char *file = "/tmp/log";
unsigned char *data;
int counter = 0;
struct {
unsigned char *string;
unsigned char *host;
unsigned char *data;
int length;
} tab[100000]; /* should be enough */
unsigned char header[] =
"#!/usr/bin/env python\n"
"import BaseHTTPServer\n\n";
unsigned char footer[] =
"class Serwer(BaseHTTPServer.BaseHTTPRequestHandler):\n"
"\tdef do_GET(self):\n"
"\t\tglobal slownik\n"
"\t\tof = open(slownik[self.path])\n"
"\t\tprint (self.path)\n"
"\t\tself.wfile.write(of.read())\n"
"\t\tof.close()\n\n"
"\tdef do_POST(self):\n"
"\t\tself.do_GET()\n\n"
"def run(server_class = BaseHTTPServer.HTTPServer, handler_class = Serwer):\n"
"\tserver_address = ('', 8000)\n"
"\thttpd = server_class(server_address, handler_class)\n"
"\thttpd.serve_forever()\n\n"
"run()\n";
static unsigned char *
find(unsigned char *from, unsigned char *key)
{
unsigned char *end = data + st.st_size;
unsigned char *beg;
int l = strlen(key);
for (beg = from;; beg++) {
beg = memchr(beg, key[0], end - beg);
if (!beg)
break;
if (!strncmp(beg, key, l))
break;
}
return beg;
}
static void
parse(void)
{
unsigned char *current = data;
while (1) {
unsigned char *conn = find(current, "CONNECTION:");
unsigned char *get = find(current, "GET /");
unsigned char *post = find(current, "POST /");
unsigned char *host, *space, *http;
size_t enter;
if (counter) {
unsigned char *min = data + st.st_size;
if (conn)
min = conn;
if (get && get < min)
min = get;
if (post && post < min)
min = post;
tab[counter - 1].length = min - http;
}
if (get && post) {
if (get < post) {
current = get + 4;
} else {
current = post + 5;
}
} else {
if (get) {
current = get + 4;
} else if (post) {
current = post + 5;
} else {
return;
}
}
space = strchr(current, ' ');
if (!space)
return;
host = find(space + 1, "Host: ");
if (!host)
return;
*space = '\0';
tab[counter].string = current;
host += 6;
enter = strcspn(host, "\r\n\0");
host[enter] = '\0';
tab[counter].host = host;
http = find(host + enter + 1, "HTTP/");
if (!http)
return;
tab[counter++].data = http;
}
}
static void
dicts(FILE *f)
{
int i;
fprintf(f, "slownik = {\n");
for (i = 0; i < counter - 1; i++) {
fprintf(f, "\t'http://%s%s' : '%d.txt',\n", tab[i].host, tab[i].string, i);
}
for (; i < counter; i++) {
fprintf(f, "\t'http://%s%s' : '%d.txt'\n", tab[i].host, tab[i].string, i);
}
fprintf(f, "}\n\n");
}
static void
save(void)
{
int i;
FILE *f;
for (i = 0; i < counter; i++) {
char buf[12];
snprintf(buf, 12, "%d.txt", i);
f = fopen(buf, "w");
if (!f)
return;
fwrite(tab[i].data, 1, tab[i].length, f);
fclose(f);
}
f = fopen("proxy.py", "w");
if (!f)
return;
fprintf(f, "%s", header);
dicts(f);
fprintf(f, "%s", footer);
fclose(f);
}
int
main(int argc, char **argv)
{
FILE *f;
if (argc > 1)
file = argv[1];
f = fopen(file, "r");
if (!f)
return 1;
stat(file, &st);
data = calloc(1, st.st_size + 1);
if (!data)
return 2;
fread(data, 1, st.st_size, f);
fclose(f);
parse();
save();
return 0;
}

View File

@ -15,7 +15,7 @@ var smartprefixes = {
// If you want to add a smartprefix for another project's CVSweb, // If you want to add a smartprefix for another project's CVSweb,
// just create a lambda like this. Aren't high-level languages fun? // just create a lambda like this. Aren't high-level languages fun?
cvs: function (x) { return cvsweb ("http://cvsweb.elinks.cz/cvsweb.cgi/", "elinks", x) }, cvs: function (x) { return cvsweb ("http://cvsweb.elinks.cz/cvsweb.cgi/", "elinks", x) },
gitweb: function (x) { return gitweb("http://pasky.or.cz/gitweb.cgi", "elinks.git", x) }, gitweb: function (x) { return gitweb("http://repo.or.cz/gitweb.cgi", "elinks.git", x) },
d: "http://www.dict.org/bin/Dict?Query=%s&Form=Dict1&Strategy=*&Database=*&submit=Submit+query", d: "http://www.dict.org/bin/Dict?Query=%s&Form=Dict1&Strategy=*&Database=*&submit=Submit+query",
debcontents: debian_contents, debcontents: debian_contents,
debfile: debian_file, debfile: debian_file,

View File

@ -55,7 +55,7 @@ function cvsweb (base, project, url)
return base + project + "/" + file return base + project + "/" + file
} }
/* javascript:gitweb("http://pasky.or.cz/gitweb.cgi", "elinks.git", "%s"); */ /* javascript:gitweb("http://repo.or.cz/gitweb.cgi", "elinks.git", "%s"); */
function gitweb(base, project, url) function gitweb(base, project, url)
{ {
var parts = url.match(/^(search|summary|shortlog|log|blob|commit|commitdiff|history|tree|tag)(\s(.*))?/); var parts = url.match(/^(search|summary|shortlog|log|blob|commit|commitdiff|history|tree|tag)(\s(.*))?/);

View File

@ -165,24 +165,11 @@ asciidoc_dep = sed -n 's/[{]builddir}//g;s@include::\(.*\)\[.*@$@: $< \1@p' < $<
-include .deps/*.asciidoc -include .deps/*.asciidoc
# Do a little post-processing of man pages. Inserting title headers and date. # Do a little post-processing of man pages. Inserting title headers and date.
# - Change SYNOPSIS to OVERVIEW in elinkskeys.5 (but not in elinks.1).
# SYNOPSIS isn't supposed to contain running text. But AsciiDoc
# 7.1.2 complains "ERROR: elinkskeys.5.txt: line 10: second section
# must be named SYNOPSIS" so we can't change this in elinkskeys.5.txt.
# - Write backslash as "\e" not "\\", but be careful not to replace
# double-backslashes that actually mean something else. This is
# apparently a bug in db2man, which xmlto runs.
# Run all the hacks together in one sed command so that we get the right
# exit code if there is an error somewhere in the middle.
MAN_DATE = $(shell date -I) MAN_DATE = $(shell date -I)
man_desc = `sed -n 's/:Description:\s*\(.*\)/\1/p' < $(srcdir)$(subst .xml,.txt,$(<F))` man_desc = `sed -n 's/:Description:\s*\(.*\)/\1/p' < $(srcdir)$(subst .xml,.txt,$(<F))`
man_hack = sed -e "s/^\(\.TH \"ELINKS[^\"]*\" [0-9] \).*/\1\"$(1)\" \"$(MAN_DATE)\" \"$(1)\"/" \ man_hack = sed "s/^\(\.TH \"ELINKS[^\"]*\" [0-9] \).*/\1\"$(1)\" \"$(MAN_DATE)\" \"$(1)\"/" < $@ | \
-e 's/\\\\\\\\ /\\e\\e /' \ sed "s/@squote@/\\\\'/g" > $@.tmp && mv $@.tmp $@
-e 's/\(\\fI\)\\\\\(\\fR\)/\1\\e\2/' \
-e "s/@squote@/\\\\'/g" \
$(if $(findstring elinkskeys.5,$(<F)),-e 's/^\.SH "SYNOPSIS"$$/.SH "OVERVIEW"/') \
$(2) < $@ > $@.tmp \
&& mv $@.tmp $@
############################################################################# #############################################################################
# Build recipies # Build recipies

View File

@ -41,7 +41,7 @@ ifndef::installation-webpage[]
See <<lua-scripting,the Elinks - Lua interface>> \ See <<lua-scripting,the Elinks - Lua interface>> \
endif::installation-webpage[] endif::installation-webpage[]
for more info. for more info.
GNU zip For handling compressed documents both locally and \ zlib 1.2.0.2 or later For handling compressed documents both locally and \
sent from server. sent from server.
bzip2 For handling local compressed documents. bzip2 For handling local compressed documents.
OpenSSL or GNU TLS For handling secure HTTP browsing. OpenSSL or GNU TLS For handling secure HTTP browsing.

View File

@ -17,7 +17,7 @@
.el .ne 3 .el .ne 3
.IP "\\$1" \\$2 .IP "\\$1" \\$2
.. ..
.TH "ELINKS.CONF" 5 "ELinks configuration file" "2007-01-06" "ELinks configuration file" .TH "ELINKS.CONF" 5 "ELinks configuration file" "2007-06-21" "ELinks configuration file"
.SH NAME .SH NAME
elinks.conf \- ELinks configuration file elinks.conf \- ELinks configuration file
.SH "SYNOPSIS" .SH "SYNOPSIS"
@ -636,7 +636,7 @@ Ignore Cache\-Control and Pragma server headers\&. When set, the document is cac
.TP .TP
document\&.cache\&.revalidation_interval <num> (default: \-1) document\&.cache\&.revalidation_interval <num> (default: \-1)
Period that a cache entry is considered to be up\-to\-date\&. When a document is loaded and this interval has elapsed since the document was initially loaded or most recently revalidated with the server, the server will be checked in case there is a more up\-to\-date version of the document\&. Period in seconds that a cache entry is considered to be up\-to\-date\&. When a document is loaded and this interval has elapsed since the document was initially loaded or most recently revalidated with the server, the server will be checked in case there is a more up\-to\-date version of the document\&.
.TP .TP
document\&.codepage document\&.codepage
@ -1378,7 +1378,7 @@ Replacement URI for this smartprefix: %c in the string means the current URL %s
.TP .TP
protocol\&.rewrite\&.default_template <str> (default: "") protocol\&.rewrite\&.default_template <str> (default: "")
Default URI template used when the string entered in the goto dialog does not appear to be a URI or a filename (i\&.e\&. contains no '\&.', \fI:\fR or \fI/\fR characters), and does not match any defined prefixes\&. Set the value to "" to disable use of the default template rewrite rule\&. Default URI template used when the string entered in the goto dialog does not appear to be a URI or a filename (i\&.e\&. contains no '\&.', \fI:\fR or \fI/\fR characters), and does not match any defined prefixes\&. Set the value to "" to disable use of the default template rewrite rule\&. %c in the template means the current URL %s in the template means the whole string from the goto dialog %0,%1,...,%9 mean the 1st,2nd,...,10th space\-delimited part of %s %% in the template means '%'
.TP .TP
protocol\&.rewrite\&.enable\-dumb [0|1] (default: 1) protocol\&.rewrite\&.enable\-dumb [0|1] (default: 1)
@ -1438,7 +1438,7 @@ Terminal type; matters mostly only when drawing frames and dialog box borders:
.TP .TP
terminal\&._template_\&.m11_hack [0|1] (default: 0) terminal\&._template_\&.m11_hack [0|1] (default: 0)
Switch fonts when drawing lines, enabling both local characters and lines working at the same time\&. Makes sense only with linux terminal\&. Switch fonts when drawing lines, enabling both local characters and lines working at the same time\&. \fIELinks\fR uses this option only if UTF\-8 I/O is disabled and the terminal type is Linux or FreeBSD\&.
.TP .TP
terminal\&._template_\&.utf_8_io [0|1] (default: 0) terminal\&._template_\&.utf_8_io [0|1] (default: 0)

View File

@ -17,10 +17,10 @@
.el .ne 3 .el .ne 3
.IP "\\$1" \\$2 .IP "\\$1" \\$2
.. ..
.TH "ELINKSKEYS" 5 "ELinks keybindings" "2007-01-06" "ELinks keybindings" .TH "ELINKSKEYS" 5 "ELinks keybindings" "2007-06-21" "ELinks keybindings"
.SH NAME .SH NAME
elinkskeys \- keybindings for ELinks elinkskeys \- keybindings for ELinks
.SH "OVERVIEW" .SH "SYNOPSIS"
Information on how to configure keybinding and overview of the default keybindings\&. Information on how to configure keybinding and overview of the default keybindings\&.
@ -46,7 +46,7 @@ is \fImain\fR, \fIedit\fR, or \fImenu\fR\&. The main keymap is used for general
.TP .TP
<keystroke> <keystroke>
is a case sensitive key, which you can prefix with \fICtrl\-\fR or \fIAlt\-\fR\&. \fICtrl\-\fR must be followed by an uppercase key\&. See below for a list of valid keys\&. is a case sensitive key, which you can prefix with \fICtrl\-\fR, \fIAlt\-\fR, or both\&. \fICtrl\-\fR must be followed by an uppercase key\&. See below for a list of valid keys\&.
.TP .TP
<action> <action>
@ -87,7 +87,7 @@ bind "main" "," = "lua\-console"
Valid keys are: alphanumeric characters, punctuation, \fIEnter\fR, \fIBackspace\fR, \fITab\fR, \fIEscape\fR, \fILeft\fR, \fIRight\fR, \fIUp\fR, \fIDown\fR, \fIInsert\fR, \fIDelete\fR, \fIHome\fR, \fIEnd\fR, \fIPageUp\fR, \fIPageDown\fR, \fIF1\fR to \fIF12\fR\&. Valid keys are: alphanumeric characters, punctuation, \fIEnter\fR, \fIBackspace\fR, \fITab\fR, \fIEscape\fR, \fILeft\fR, \fIRight\fR, \fIUp\fR, \fIDown\fR, \fIInsert\fR, \fIDelete\fR, \fIHome\fR, \fIEnd\fR, \fIPageUp\fR, \fIPageDown\fR, \fIF1\fR to \fIF12\fR\&.
Some keys will need to be quoted or escaped\&. For example, space can be written as " " (quote space quote), and the quote itself as \\" (backslash quote)\&. Backslash can be written as \e\e (double backslash)\&. Some keys will need to be quoted or escaped\&. For example, space can be written as " " (quote space quote), and the quote itself as \\" (backslash quote)\&. Backslash can be written as \\\\ (double backslash)\&.
.SH "KEYMAP ACTIONS" .SH "KEYMAP ACTIONS"
@ -573,7 +573,7 @@ Copy text to clipboard\&.
.TP .TP
cut\-clipboard cut\-clipboard
Delete text from clipboard\&. Cut text to clipboard\&.
.TP .TP
delete delete
@ -893,7 +893,7 @@ Scroll left (\fIscroll\-left\fR)
Go at a specified mark (\fImark\-goto\fR) Go at a specified mark (\fImark\-goto\fR)
.TP .TP
\fI\e\fR \fI\\\fR
Toggle rendering page as HTML / plain text (\fItoggle\-html\-plain\fR) Toggle rendering page as HTML / plain text (\fItoggle\-html\-plain\fR)
.TP .TP
@ -1152,7 +1152,7 @@ Attempt to auto\-complete the input (\fIauto\-complete\fR)
.TP .TP
\fICtrl\-X\fR \fICtrl\-X\fR
Delete text from clipboard (\fIcut\-clipboard\fR) Cut text to clipboard (\fIcut\-clipboard\fR)
.TP .TP
\fIAlt\-Backspace\fR \fIAlt\-Backspace\fR

View File

@ -10,6 +10,8 @@ When releasing a new version
Write a small changelog highlighting the most important changes. Changes Write a small changelog highlighting the most important changes. Changes
by new contributors are always important! by new contributors are always important!
- Update NEWS file and commit. Remember to add the new version number! - Update NEWS file and commit. Remember to add the new version number!
Don't add the release date yet though; it will be added after the release,
from the date in the mailing list archives.
- Change VERSION in the top of configure.in to hold the new version number. - Change VERSION in the top of configure.in to hold the new version number.
- Commit only this change. - Commit only this change.
- Create a signed tag having the version ("ELinks X.X.X") as the subject and - Create a signed tag having the version ("ELinks X.X.X") as the subject and

View File

@ -625,12 +625,12 @@ CONFIG_SMALL=no
# Some features are partially supported. Like line breaking between # Some features are partially supported. Like line breaking between
# double-width characters. There is no other detection for determining when to # double-width characters. There is no other detection for determining when to
# break or not. # break or not.
# Character conversions are still incomplete for ECMAScript strings (bug 805),
# local file names, and IRIs (RFC 3987).
# #
# Note: This UTF-8 support is experimental. # Default: enabled
#
# Default: disabled
CONFIG_UTF8=no CONFIG_UTF8=yes

View File

@ -74,7 +74,18 @@ name of your language (in English) so you end up with something like:
{NULL, NULL}, {NULL, NULL},
}; };
1.2 Making the new language file part of ELinks: 1.2 Testing your changes without installing ELinks:
---------------------------------------------------
It is possible to test translation updates without installing ELinks. After
building both ELinks and the po files, simply start ELinks from the top-level
directory in the source tree using:
$ ./src/elinks
It will then load po files from the po/ directory in the source tree.
1.3 Making the new language file part of ELinks:
------------------------------------------------ ------------------------------------------------
Finally to make it part of the ELinks distribution send it to one of the Finally to make it part of the ELinks distribution send it to one of the
@ -340,7 +351,7 @@ mark (e.g. "~/.elinks") and the translated msgstr do not.
If the language file is already added finally run make to compile and check the If the language file is already added finally run make to compile and check the
language file for errors and fix any warnings you get. Then patch your changes language file for errors and fix any warnings you get. Then patch your changes
and send it to one of the mailinglists or file it as a bug at and send it to one of the mailinglists or file it as a bug at
<http://bugzilla.elinks.or.cz>. <http://bugzilla.elinks.cz>.
3. Statistics: 3. Statistics:

463
po/fr.po

File diff suppressed because it is too large Load Diff

617
po/pl.po

File diff suppressed because it is too large Load Diff

2
src/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
ID
TAGS

View File

@ -38,8 +38,13 @@ vernum.o: $(LIB_O_NAME)
elinks: $(LIB_O_NAME) vernum.o elinks: $(LIB_O_NAME) vernum.o
$(call cmd,link) $(call cmd,link)
# Place the TAGS file in the source directory so that, if the same
# source is built for different configurations in different build
# directories, one doesn't have to remember which of those build
# directories has the most recent TAGS.
TAGS: TAGS:
find $(srcdir). \( -name "*.[ch]" -o -name "*.inc" \) -print \ cd $(srcdir) \
&& find . \( -name "*.[ch]" -o -name "*.inc" \) -print \
| etags --regex='{c}/INIT_LIST_HEAD(\([[:alnum:]_]+\))/\1/' \ | etags --regex='{c}/INIT_LIST_HEAD(\([[:alnum:]_]+\))/\1/' \
--regex='{c}/struct_hierbox_browser(\n[ \t]*\([[:alnum:]_]+\),/\1/m' \ --regex='{c}/struct_hierbox_browser(\n[ \t]*\([[:alnum:]_]+\),/\1/m' \
--regex='{c}/^ACTION_(\([[:alnum:]_]+\),[^,]*,[ \t]*\([[:alnum:]_]+\),/ACT_\1_\2/' \ --regex='{c}/^ACTION_(\([[:alnum:]_]+\),[^,]*,[ \t]*\([[:alnum:]_]+\),/ACT_\1_\2/' \

View File

@ -130,7 +130,7 @@ dlg_format_buttons(struct terminal *term,
mw = 0; mw = 0;
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
buttons_width(widget_data1, i2 - i1 + 1, NULL, &mw, buttons_width(widget_data1, i2 - i1 + 1, NULL, &mw,
term->utf8); term->utf8_cp);
#else #else
buttons_width(widget_data1, i2 - i1 + 1, NULL, &mw); buttons_width(widget_data1, i2 - i1 + 1, NULL, &mw);
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
@ -140,7 +140,7 @@ dlg_format_buttons(struct terminal *term,
mw = 0; mw = 0;
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
buttons_width(widget_data1, i2 - i1, NULL, &mw, term->utf8); buttons_width(widget_data1, i2 - i1, NULL, &mw, term->utf8_cp);
#else #else
buttons_width(widget_data1, i2 - i1, NULL, &mw); buttons_width(widget_data1, i2 - i1, NULL, &mw);
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
@ -156,7 +156,7 @@ dlg_format_buttons(struct terminal *term,
for (i = i1; i < i2; i++) { for (i = i1; i < i2; i++) {
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) if (term->utf8_cp)
set_box(&widget_data[i].box, set_box(&widget_data[i].box,
p, *y, p, *y,
utf8_ptr2cells(widget_data[i].widget->text, NULL) utf8_ptr2cells(widget_data[i].widget->text, NULL)
@ -196,7 +196,7 @@ display_button(struct dialog_data *dlg_data, struct widget_data *widget_data)
if (!color || !shortcut_color) return EVENT_PROCESSED; if (!color || !shortcut_color) return EVENT_PROCESSED;
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) { if (term->utf8_cp) {
int button_left_len = utf8_ptr2cells(BUTTON_LEFT, NULL); int button_left_len = utf8_ptr2cells(BUTTON_LEFT, NULL);
int button_right_len = utf8_ptr2cells(BUTTON_RIGHT, NULL); int button_right_len = utf8_ptr2cells(BUTTON_RIGHT, NULL);
@ -222,7 +222,7 @@ display_button(struct dialog_data *dlg_data, struct widget_data *widget_data)
? SCREEN_ATTR_UNDERLINE : 0; ? SCREEN_ATTR_UNDERLINE : 0;
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) { if (term->utf8_cp) {
if (hk_pos >= 0) { if (hk_pos >= 0) {
int hk_bytes = utf8charlen(&text[hk_pos+1]); int hk_bytes = utf8charlen(&text[hk_pos+1]);
int cells_to_hk = utf8_ptr2cells(text, int cells_to_hk = utf8_ptr2cells(text,
@ -286,7 +286,7 @@ display_button(struct dialog_data *dlg_data, struct widget_data *widget_data)
} }
} }
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) { if (term->utf8_cp) {
int text_cells = utf8_ptr2cells(widget_data->widget->text, NULL); int text_cells = utf8_ptr2cells(widget_data->widget->text, NULL);
int hk = (widget_data->widget->info.button.hotkey_pos >= 0); int hk = (widget_data->widget->info.button.hotkey_pos >= 0);

View File

@ -102,7 +102,7 @@ redraw_dialog(struct dialog_data *dlg_data, int layout)
int x, y; int x, y;
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) if (term->utf8_cp)
titlecells = utf8_ptr2cells(title, titlecells = utf8_ptr2cells(title,
&title[titlelen]); &title[titlelen]);
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
@ -110,7 +110,7 @@ redraw_dialog(struct dialog_data *dlg_data, int layout)
titlecells = int_min(box.width - 2, titlecells); titlecells = int_min(box.width - 2, titlecells);
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) if (term->utf8_cp)
titlelen = utf8_cells2bytes(title, titlecells, titlelen = utf8_cells2bytes(title, titlecells,
NULL); NULL);
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
@ -619,7 +619,7 @@ generic_dialog_layouter(struct dialog_data *dlg_data)
int x = 0, y, rw; int x = 0, y, rw;
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) if (term->utf8_cp)
rw = int_min(w, utf8_ptr2cells(dlg_data->dlg->title, NULL)); rw = int_min(w, utf8_ptr2cells(dlg_data->dlg->title, NULL));
else else
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
@ -664,12 +664,12 @@ draw_dialog(struct dialog_data *dlg_data, int width, int height)
draw_shadow(term, &dlg_data->box, draw_shadow(term, &dlg_data->box,
get_bfu_color(term, "dialog.shadow"), 2, 1); get_bfu_color(term, "dialog.shadow"), 2, 1);
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) if (term->utf8_cp)
fix_dwchar_around_box(term, &dlg_data->box, 0, 2, 1); fix_dwchar_around_box(term, &dlg_data->box, 0, 2, 1);
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
} }
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
else if(term->utf8) else if (term->utf8_cp)
fix_dwchar_around_box(term, &dlg_data->box, 0, 0, 0); fix_dwchar_around_box(term, &dlg_data->box, 0, 0, 0);
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
} }

View File

@ -40,7 +40,7 @@ dlg_format_group(struct terminal *term,
int label_padding; int label_padding;
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) { if (term->utf8_cp) {
if (text && *text) if (text && *text)
label_length = utf8_ptr2cells(text, NULL); label_length = utf8_ptr2cells(text, NULL);
else else
@ -55,7 +55,7 @@ dlg_format_group(struct terminal *term,
width = CHECKBOX_LEN; width = CHECKBOX_LEN;
} else if (widget_is_textfield(widget_data)) { } else if (widget_is_textfield(widget_data)) {
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) { if (term->utf8_cp) {
width = utf8_ptr2cells(widget_data->widget->data, width = utf8_ptr2cells(widget_data->widget->data,
NULL); NULL);
} else } else
@ -82,7 +82,7 @@ dlg_format_group(struct terminal *term,
/* Draw text at right of checkbox. */ /* Draw text at right of checkbox. */
if (label_length) { if (label_length) {
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) { if (term->utf8_cp) {
int lb = utf8_cells2bytes( int lb = utf8_cells2bytes(
text, text,
label_length, label_length,
@ -108,7 +108,7 @@ dlg_format_group(struct terminal *term,
/* Draw label at left of widget. */ /* Draw label at left of widget. */
if (label_length) { if (label_length) {
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) { if (term->utf8_cp) {
int lb = utf8_cells2bytes( int lb = utf8_cells2bytes(
text, text,
label_length, label_length,
@ -149,7 +149,7 @@ group_layouter(struct dialog_data *dlg_data)
int n = dlg_data->number_of_widgets - 2; int n = dlg_data->number_of_widgets - 2;
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) if (term->utf8_cp)
rw = int_min(w, utf8_ptr2cells(dlg_data->dlg->title, NULL)); rw = int_min(w, utf8_ptr2cells(dlg_data->dlg->title, NULL));
else else
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */

View File

@ -271,7 +271,7 @@ display_field_do(struct dialog_data *dlg_data, struct widget_data *widget_data,
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) { if (term->utf8_cp) {
unsigned char *t = widget_data->cdata; unsigned char *t = widget_data->cdata;
int p = widget_data->info.field.cpos; int p = widget_data->info.field.cpos;
@ -298,9 +298,9 @@ display_field_do(struct dialog_data *dlg_data, struct widget_data *widget_data,
int len, w; int len, w;
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8 && !hide) if (term->utf8_cp && !hide)
len = utf8_ptr2cells(text, NULL); len = utf8_ptr2cells(text, NULL);
else if (term->utf8) else if (term->utf8_cp)
len = utf8_ptr2chars(text, NULL); len = utf8_ptr2chars(text, NULL);
else else
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
@ -309,7 +309,7 @@ display_field_do(struct dialog_data *dlg_data, struct widget_data *widget_data,
if (!hide) { if (!hide) {
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) if (term->utf8_cp)
w = utf8_cells2bytes(text, w, NULL); w = utf8_cells2bytes(text, w, NULL);
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
draw_text(term, widget_data->box.x, widget_data->box.y, draw_text(term, widget_data->box.x, widget_data->box.y,
@ -328,7 +328,7 @@ display_field_do(struct dialog_data *dlg_data, struct widget_data *widget_data,
int x; int x;
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) if (term->utf8_cp)
x = widget_data->box.x + len - left; x = widget_data->box.x + len - left;
else else
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
@ -474,7 +474,7 @@ kbd_field(struct dialog_data *dlg_data, struct widget_data *widget_data)
case ACT_EDIT_RIGHT: case ACT_EDIT_RIGHT:
if (widget_data->info.field.cpos < strlen(widget_data->cdata)) { if (widget_data->info.field.cpos < strlen(widget_data->cdata)) {
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) { if (term->utf8_cp) {
unsigned char *next = widget_data->cdata + widget_data->info.field.cpos; unsigned char *next = widget_data->cdata + widget_data->info.field.cpos;
unsigned char *end = strchr(next, '\0'); unsigned char *end = strchr(next, '\0');
@ -492,7 +492,7 @@ kbd_field(struct dialog_data *dlg_data, struct widget_data *widget_data)
if (widget_data->info.field.cpos > 0) if (widget_data->info.field.cpos > 0)
widget_data->info.field.cpos--; widget_data->info.field.cpos--;
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (widget_data->info.field.cpos && term->utf8) { if (widget_data->info.field.cpos && term->utf8_cp) {
unsigned char *t = widget_data->cdata; unsigned char *t = widget_data->cdata;
unsigned char *t2 = t; unsigned char *t2 = t;
int p = widget_data->info.field.cpos; int p = widget_data->info.field.cpos;
@ -517,7 +517,7 @@ kbd_field(struct dialog_data *dlg_data, struct widget_data *widget_data)
case ACT_EDIT_BACKSPACE: case ACT_EDIT_BACKSPACE:
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (widget_data->info.field.cpos && term->utf8) { if (widget_data->info.field.cpos && term->utf8_cp) {
/* XXX: stolen from src/viewer/text/form.c */ /* XXX: stolen from src/viewer/text/form.c */
/* FIXME: This isn't nice. We remove last byte /* FIXME: This isn't nice. We remove last byte
* from UTF-8 character to detect * from UTF-8 character to detect
@ -559,7 +559,7 @@ kbd_field(struct dialog_data *dlg_data, struct widget_data *widget_data)
if (widget_data->info.field.cpos >= cdata_len) goto display_field; if (widget_data->info.field.cpos >= cdata_len) goto display_field;
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) { if (term->utf8_cp) {
unsigned char *end = widget_data->cdata + cdata_len; unsigned char *end = widget_data->cdata + cdata_len;
unsigned char *text = widget_data->cdata + widget_data->info.field.cpos; unsigned char *text = widget_data->cdata + widget_data->info.field.cpos;
unsigned char *old = text; unsigned char *old = text;
@ -688,22 +688,11 @@ kbd_field(struct dialog_data *dlg_data, struct widget_data *widget_data)
const unsigned char *ins; const unsigned char *ins;
int inslen; int inslen;
if (term->utf8) { /* get_kbd_key(ev) is UCS-4, and @text
/* get_kbd_key(ev) is in UCS-4, * is in the terminal's charset. */
* and @text is in UTF-8. */ ins = u2cp_no_nbsp(get_kbd_key(ev),
ins = encode_utf8(get_kbd_key(ev)); get_opt_codepage_tree(term->spec,
/* get_kbd_key(ev) cannot be L'\0' "charset"));
* because @check_kbd_textinput_key
* would have rejected it. So it
* is OK to use @strlen below. */
} else {
/* get_kbd_key(ev) is UCS-4, and @text
* is in the terminal's charset. */
int cp = get_opt_codepage_tree(term->spec,
"charset");
ins = u2cp_no_nbsp(get_kbd_key(ev), cp);
}
inslen = strlen(ins); inslen = strlen(ins);
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */

View File

@ -463,7 +463,7 @@ display_listbox_item(struct listbox_item *item, void *data_, int *offset)
len = strlen(text); len = strlen(text);
int_upper_bound(&len, int_max(0, data->widget_data->box.width - depth * 5)); int_upper_bound(&len, int_max(0, data->widget_data->box.width - depth * 5));
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (data->term->utf8) if (data->term->utf8_cp)
len_bytes = utf8_cells2bytes(text, len, NULL); len_bytes = utf8_cells2bytes(text, len, NULL);
else else
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */

View File

@ -201,7 +201,7 @@ get_menuitem_text_width(struct terminal *term, struct menu_item *mi)
if (!text[0]) return 0; if (!text[0]) return 0;
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) if (term->utf8_cp)
return L_TEXT_SPACE + utf8_ptr2cells(text, NULL) return L_TEXT_SPACE + utf8_ptr2cells(text, NULL)
- !!mi->hotkey_pos + R_TEXT_SPACE; - !!mi->hotkey_pos + R_TEXT_SPACE;
else else
@ -383,7 +383,7 @@ draw_menu_left_text(struct terminal *term, unsigned char *text, int len,
if (!len) return; if (!len) return;
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) { if (term->utf8_cp) {
max_len = utf8_cells2bytes(text, w, NULL); max_len = utf8_cells2bytes(text, w, NULL);
if (max_len <= 0) if (max_len <= 0)
return; return;
@ -431,7 +431,7 @@ draw_menu_left_text_hk(struct terminal *term, unsigned char *text,
} }
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) goto utf8; if (term->utf8_cp) goto utf8;
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
for (x = 0; x - !!hk_state < w && (c = text[x]); x++) { for (x = 0; x - !!hk_state < w && (c = text[x]); x++) {
@ -561,12 +561,12 @@ display_menu(struct terminal *term, struct menu *menu)
draw_shadow(term, &menu->box, draw_shadow(term, &menu->box,
get_bfu_color(term, "dialog.shadow"), 2, 1); get_bfu_color(term, "dialog.shadow"), 2, 1);
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) if (term->utf8_cp)
fix_dwchar_around_box(term, &box, 1, 2, 1); fix_dwchar_around_box(term, &box, 1, 2, 1);
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
} }
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
else if(term->utf8) else if (term->utf8_cp)
fix_dwchar_around_box(term, &box, 1, 0, 0); fix_dwchar_around_box(term, &box, 1, 0, 0);
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
@ -1115,7 +1115,7 @@ display_mainmenu(struct terminal *term, struct menu *menu)
textlen = strlen(text) - !!l; textlen = strlen(text) - !!l;
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) if (term->utf8_cp)
screencnt = utf8_ptr2cells(text, NULL) - !!l; screencnt = utf8_ptr2cells(text, NULL) - !!l;
else else
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
@ -1125,7 +1125,7 @@ display_mainmenu(struct terminal *term, struct menu *menu)
color = selected_color; color = selected_color;
box.x = p; box.x = p;
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) if (term->utf8_cp)
box.width = L_MAINTEXT_SPACE + L_TEXT_SPACE box.width = L_MAINTEXT_SPACE + L_TEXT_SPACE
+ screencnt + screencnt
+ R_TEXT_SPACE + R_MAINTEXT_SPACE; + R_TEXT_SPACE + R_MAINTEXT_SPACE;
@ -1164,7 +1164,7 @@ display_mainmenu(struct terminal *term, struct menu *menu)
int_lower_bound(&menu->last, menu->first); int_lower_bound(&menu->last, menu->first);
if (menu->last < menu->size - 1) { if (menu->last < menu->size - 1) {
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) { if (term->utf8_cp) {
struct screen_char *schar; struct screen_char *schar;
schar = get_char(term, term->width - R_MAINMENU_SPACE, 0); schar = get_char(term, term->width - R_MAINMENU_SPACE, 0);

View File

@ -231,7 +231,7 @@ dlg_format_text_do(struct terminal *term, unsigned char *text,
if (!*text) break; if (!*text) break;
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
line_width = split_line(text, width, &cells, term->utf8); line_width = split_line(text, width, &cells, term->utf8_cp);
#else #else
line_width = split_line(text, width, &cells); line_width = split_line(text, width, &cells);
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
@ -290,7 +290,7 @@ dlg_format_text(struct terminal *term, struct widget_data *widget_data,
* split if we don't have to */ * split if we don't have to */
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (widget_data->box.width != width if (widget_data->box.width != width
&& !split_lines(widget_data, width, term->utf8)) && !split_lines(widget_data, width, term->utf8_cp))
return; return;
#else #else
if (widget_data->box.width != width if (widget_data->box.width != width

View File

@ -52,11 +52,10 @@ struct widget {
struct widget_data { struct widget_data {
struct widget *widget; struct widget *widget;
/* For WIDGET_FIELD: If CONFIG_UTF8 is defined and UTF-8 I/O /* For WIDGET_FIELD: @cdata is in the charset of the terminal.
* is enabled for the terminal, then @cdata is in UTF-8; * (That charset can be UTF-8 only if CONFIG_UTF8 is defined,
* otherwise, @cdata is in the charset of the terminal, and * and is assumed to be unibyte otherwise.) The UTF-8 I/O
* the charset is assumed to be unibyte. (Thus, if you choose * option has no effect here.
* UTF-8 as the charset but disable UTF-8 I/O, you lose.)
* *
* For WIDGET_TEXT: @cdata is cast from/to an unsigned char ** * For WIDGET_TEXT: @cdata is cast from/to an unsigned char **
* that points to the first element of an array. Each element * that points to the first element of an array. Each element

View File

@ -816,6 +816,27 @@ static struct option_info config_options_info[] = {
"_template_", 0, "_template_", 0,
N_("Options specific to this terminal type (according to $TERM value).")), N_("Options specific to this terminal type (according to $TERM value).")),
/* TODO: Incorporate some of the following to the option text.
*
* When UTF-8 I/O is disabled:
* 0 (TERM_DUMB) outputs ASCII -+| characters.
* 1 (TERM_VT100) switches charsets with ^N and ^O.
* 2 (TERM_LINUX) outputs CP437 characters without switching
* charsets, so it works correctly only if the terminal uses
* CP437. Can also be made CP850 and CP852 compatible with
* the restrict_852 option.
* 3 (TERM_KOI8) outputs KOI8-R characters without switching
* charsets, so it works correctly only if the terminal uses
* KOI8-R and the user has selected either KOI8-R or ASCII
* in ELinks. It is also mostly compatible with KOI8-U.
* 4 (TERM_FREEBSD) outputs characters in the 0x80...0x9F
* range, which FreeBSD 4.0 (but not 5.0) treated as
* graphical.
*
* When UTF-8 I/O is enabled, ELinks outputs (almost) the same
* characters as above but encodes them in UTF-8 and does not
* switch charsets. So, it will work in any terminal that
* understands UTF-8 and has the characters in its font. */
INIT_OPT_INT("terminal._template_", N_("Type"), INIT_OPT_INT("terminal._template_", N_("Type"),
"type", 0, 0, 4, 0, "type", 0, 0, 4, 0,
N_("Terminal type; matters mostly only when drawing frames and\n" N_("Terminal type; matters mostly only when drawing frames and\n"
@ -829,8 +850,8 @@ static struct option_info config_options_info[] = {
INIT_OPT_BOOL("terminal._template_", N_("Switch fonts for line drawing"), INIT_OPT_BOOL("terminal._template_", N_("Switch fonts for line drawing"),
"m11_hack", 0, 0, "m11_hack", 0, 0,
N_("Switch fonts when drawing lines, enabling both local characters\n" N_("Switch fonts when drawing lines, enabling both local characters\n"
"and lines working at the same time. Makes sense only with linux\n" "and lines working at the same time. ELinks uses this option only if\n"
"terminal.")), "UTF-8 I/O is disabled and the terminal type is Linux or FreeBSD.")),
/* When CONFIG_UTF8 is defined, any code that reads the "utf_8_io" /* When CONFIG_UTF8 is defined, any code that reads the "utf_8_io"
* option should also check whether the "codepage" option is UTF-8, * option should also check whether the "codepage" option is UTF-8,

View File

@ -158,10 +158,6 @@ redir_set(struct option *opt, unsigned char *str)
} }
static int
redir_add(struct option *opt, unsigned char *str)
wrap_or_(add, add(real, str), 0);
/* Support functions for config file parsing. */ /* Support functions for config file parsing. */
@ -400,21 +396,21 @@ tree_dup(struct option *opt, struct option *template)
} }
const struct option_type_info option_types[] = { const struct option_type_info option_types[] = {
{ N_("Boolean"), bool_cmd, num_rd, num_wr, NULL, num_set, NULL, N_("[0|1]") }, { N_("Boolean"), bool_cmd, num_rd, num_wr, NULL, num_set, N_("[0|1]") },
{ N_("Integer"), gen_cmd, num_rd, num_wr, NULL, num_set, NULL, N_("<num>") }, { N_("Integer"), gen_cmd, num_rd, num_wr, NULL, num_set, N_("<num>") },
{ N_("Longint"), gen_cmd, num_rd, long_wr, NULL, long_set, NULL, N_("<num>") }, { N_("Longint"), gen_cmd, num_rd, long_wr, NULL, long_set, N_("<num>") },
{ N_("String"), gen_cmd, str_rd, str_wr, str_dup, str_set, NULL, N_("<str>") }, { N_("String"), gen_cmd, str_rd, str_wr, str_dup, str_set, N_("<str>") },
{ N_("Codepage"), gen_cmd, str_rd, cp_wr, NULL, cp_set, NULL, N_("<codepage>") }, { N_("Codepage"), gen_cmd, str_rd, cp_wr, NULL, cp_set, N_("<codepage>") },
{ N_("Language"), gen_cmd, str_rd, lang_wr, NULL, lang_set, NULL, N_("<language>") }, { N_("Language"), gen_cmd, str_rd, lang_wr, NULL, lang_set, N_("<language>") },
{ N_("Color"), gen_cmd, str_rd, color_wr, NULL, color_set, NULL, N_("<color|#rrggbb>") }, { N_("Color"), gen_cmd, str_rd, color_wr, NULL, color_set, N_("<color|#rrggbb>") },
{ N_("Special"), exec_cmd, NULL, NULL, NULL, NULL, NULL, "" }, { N_("Special"), exec_cmd, NULL, NULL, NULL, NULL, "" },
{ N_("Alias"), redir_cmd, redir_rd, redir_wr, NULL, redir_set, redir_add, "" }, { N_("Alias"), redir_cmd, redir_rd, redir_wr, NULL, redir_set, "" },
/* tree */ /* tree */
{ N_("Folder"), NULL, NULL, NULL, tree_dup, NULL, NULL, "" }, { N_("Folder"), NULL, NULL, NULL, tree_dup, NULL, "" },
}; };
unsigned char * unsigned char *

View File

@ -11,7 +11,6 @@ struct option_type_info {
void (*write)(struct option *, struct string *); void (*write)(struct option *, struct string *);
void (*dup)(struct option *, struct option *); void (*dup)(struct option *, struct option *);
int (*set)(struct option *, unsigned char *); int (*set)(struct option *, unsigned char *);
int (*add)(struct option *, unsigned char *);
unsigned char *help_str; unsigned char *help_str;
}; };

View File

@ -146,7 +146,7 @@ download_dialog_layouter(struct dialog_data *dlg_data)
return; return;
} }
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) if (term->utf8_cp)
decode_uri(url); decode_uri(url);
else else
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
@ -303,7 +303,7 @@ get_file_download_text(struct listbox_item *item, struct terminal *term)
uristring = get_uri_string(file_download->uri, URI_PUBLIC); uristring = get_uri_string(file_download->uri, URI_PUBLIC);
if (uristring) { if (uristring) {
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) if (term->utf8_cp)
decode_uri(uristring); decode_uri(uristring);
else else
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */

View File

@ -586,7 +586,7 @@ query_file(struct session *ses, struct uri *uri, void *data,
/* Remove the %-ugliness for display */ /* Remove the %-ugliness for display */
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (ses->tab->term->utf8) if (ses->tab->term->utf8_cp)
decode_uri_string(&def); decode_uri_string(&def);
else else
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */

View File

@ -427,7 +427,7 @@ display_title_bar(struct session *ses, struct terminal *term)
int titlelen, titlewidth; int titlelen, titlewidth;
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) { if (term->utf8_cp) {
titlewidth = utf8_ptr2cells(document->title, NULL); titlewidth = utf8_ptr2cells(document->title, NULL);
titlewidth = int_min(titlewidth, maxlen); titlewidth = int_min(titlewidth, maxlen);
@ -452,7 +452,7 @@ display_title_bar(struct session *ses, struct terminal *term)
if (title.length) { if (title.length) {
int x; int x;
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) { if (term->utf8_cp) {
x = int_max(term->width - 1 x = int_max(term->width - 1
- utf8_ptr2cells(title.source, - utf8_ptr2cells(title.source,
title.source title.source

View File

@ -186,7 +186,7 @@ examine_element(struct html_context *html_context, struct css_selector *base,
process_found_selector(selector, CST_PSEUDO, base); process_found_selector(selector, CST_PSEUDO, base);
} }
code = get_attr_val(element->options, "class", html_context->options->cp); code = get_attr_val(element->options, "class", html_context->doc_cp);
if (code && seltype <= CST_CLASS) { if (code && seltype <= CST_CLASS) {
unsigned char *class = code; unsigned char *class = code;
@ -203,7 +203,7 @@ examine_element(struct html_context *html_context, struct css_selector *base,
} }
mem_free_if(code); mem_free_if(code);
code = get_attr_val(element->options, "id", html_context->options->cp); code = get_attr_val(element->options, "id", html_context->doc_cp);
if (code && seltype <= CST_ID) { if (code && seltype <= CST_ID) {
selector = find_css_selector(selectors, CST_ID, rel, code, -1); selector = find_css_selector(selectors, CST_ID, rel, code, -1);
process_found_selector(selector, CST_ID, base); process_found_selector(selector, CST_ID, base);
@ -240,7 +240,7 @@ get_css_selector_for_element(struct html_context *html_context,
DBG("Element %.*s applied.", element->namelen, element->name); DBG("Element %.*s applied.", element->namelen, element->name);
#endif #endif
code = get_attr_val(element->options, "style", html_context->options->cp); code = get_attr_val(element->options, "style", html_context->doc_cp);
if (code) { if (code) {
struct css_selector *stylesel; struct css_selector *stylesel;
struct scanner scanner; struct scanner scanner;

View File

@ -86,6 +86,10 @@ struct form_control {
unsigned char *id; /* used by scripts */ unsigned char *id; /* used by scripts */
unsigned char *name; unsigned char *name;
unsigned char *alt; unsigned char *alt;
/* For FC_TEXT, FC_PASSWORD, and FC_TEXTAREA: @default_value
* is in the charset of the document.
*
* For FC_FILE: The parser does not set @default_value. */
unsigned char *default_value; unsigned char *default_value;
int default_state; int default_state;
int size; int size;
@ -94,12 +98,11 @@ struct form_control {
int maxlength; int maxlength;
int nvalues; int nvalues;
unsigned char **values; unsigned char **values;
/* For FC_SELECT: If CONFIG_UTF8 is defined and UTF-8 I/O is /* For FC_SELECT: @labels are in the charset of the terminal.
* enabled for the terminal, then @labels is in UTF-8; * (That charset can be UTF-8 only if CONFIG_UTF8 is defined,
* otherwise, @labels is in the charset of the terminal, and * and is assumed to be unibyte otherwise.) The charset of
* the charset is assumed to be unibyte. (Thus, if you choose * the document and the UTF-8 I/O option have no effect
* UTF-8 as the charset but disable UTF-8 I/O, you lose.) The * here. */
* charset of the document has no effect here. */
unsigned char **labels; unsigned char **labels;
struct menu_item *menu; struct menu_item *menu;
}; };

View File

@ -51,6 +51,10 @@ struct html_context {
struct document_options *options; struct document_options *options;
/* doc_cp is the charset of the document, i.e. part->document->cp.
* It is copied here because part->document is NULL sometimes. */
int doc_cp;
/* For: /* For:
* html/parser/parse.c * html/parser/parse.c
* html/parser/stack.c * html/parser/stack.c

View File

@ -57,7 +57,7 @@ get_color(struct html_context *html_context, unsigned char *a,
if (!use_document_fg_colors(html_context->options)) if (!use_document_fg_colors(html_context->options))
return -1; return -1;
at = get_attr_val(a, c, html_context->options->cp); at = get_attr_val(a, c, html_context->doc_cp);
if (!at) return -1; if (!at) return -1;
r = decode_color(at, strlen(at), rgb); r = decode_color(at, strlen(at), rgb);
@ -78,6 +78,8 @@ get_bgcolor(struct html_context *html_context, unsigned char *a, color_T *rgb)
unsigned char * unsigned char *
get_target(struct document_options *options, unsigned char *a) get_target(struct document_options *options, unsigned char *a)
{ {
/* FIXME (bug 784): options->cp is the terminal charset;
* should use the document charset instead. */
unsigned char *v = get_attr_val(a, "target", options->cp); unsigned char *v = get_attr_val(a, "target", options->cp);
if (!v) return NULL; if (!v) return NULL;
@ -154,7 +156,7 @@ set_fragment_identifier(struct html_context *html_context,
{ {
unsigned char *id_attr; unsigned char *id_attr;
id_attr = get_attr_val(attr_name, attr, html_context->options->cp); id_attr = get_attr_val(attr_name, attr, html_context->doc_cp);
if (id_attr) { if (id_attr) {
html_context->special_f(html_context, SP_TAG, id_attr); html_context->special_f(html_context, SP_TAG, id_attr);
@ -235,7 +237,7 @@ html_focusable(struct html_context *html_context, unsigned char *a)
if (!a) return; if (!a) return;
options = html_context->options; options = html_context->options;
cp = options->cp; cp = html_context->doc_cp;
accesskey = get_attr_val(a, "accesskey", cp); accesskey = get_attr_val(a, "accesskey", cp);
if (accesskey) { if (accesskey) {
@ -243,7 +245,7 @@ html_focusable(struct html_context *html_context, unsigned char *a)
mem_free(accesskey); mem_free(accesskey);
} }
tabindex = get_num(a, "tabindex", options->cp); tabindex = get_num(a, "tabindex", html_context->doc_cp);
if (0 < tabindex && tabindex < 32767) { if (0 < tabindex && tabindex < 32767) {
format.tabindex = (tabindex & 0x7fff) << 16; format.tabindex = (tabindex & 0x7fff) << 16;
} }
@ -450,6 +452,8 @@ look_for_map(unsigned char **pos, unsigned char *eof, struct uri *uri,
if (strlcasecmp(name, namelen, "MAP", 3)) return 1; if (strlcasecmp(name, namelen, "MAP", 3)) return 1;
if (uri && uri->fragment) { if (uri && uri->fragment) {
/* FIXME (bug 784): options->cp is the terminal charset;
* should use the document charset instead. */
al = get_attr_val(attr, "name", options->cp); al = get_attr_val(attr, "name", options->cp);
if (!al) return 1; if (!al) return 1;
@ -548,6 +552,8 @@ look_for_link(unsigned char **pos, unsigned char *eof, struct menu_item **menu,
if (*pos >= eof) return 0; if (*pos >= eof) return 0;
} else if (!strlcasecmp(name, namelen, "AREA", 4)) { } else if (!strlcasecmp(name, namelen, "AREA", 4)) {
/* FIXME (bug 784): options->cp is the terminal charset;
* should use the document charset instead. */
unsigned char *alt = get_attr_val(attr, "alt", options->cp); unsigned char *alt = get_attr_val(attr, "alt", options->cp);
if (alt) { if (alt) {
@ -582,6 +588,8 @@ look_for_link(unsigned char **pos, unsigned char *eof, struct menu_item **menu,
return 1; return 1;
} }
/* FIXME (bug 784): options->cp is the terminal charset;
* should use the document charset instead. */
href = get_url_val(attr, "href", options->cp); href = get_url_val(attr, "href", options->cp);
if (!href) { if (!href) {
mem_free_if(label); mem_free_if(label);
@ -741,6 +749,9 @@ done_html_parser_state(struct html_context *html_context,
} }
/* This function does not set html_context.doc_cp = document.cp,
* because it does not know the document, and because the codepage has
* not even been decided when it is called. */
struct html_context * struct html_context *
init_html_parser(struct uri *uri, struct document_options *options, init_html_parser(struct uri *uri, struct document_options *options,
unsigned char *start, unsigned char *end, unsigned char *start, unsigned char *end,

View File

@ -50,13 +50,13 @@ html_form(struct html_context *html_context, unsigned char *a,
form->method = FORM_METHOD_GET; form->method = FORM_METHOD_GET;
form->form_num = a - html_context->startf; form->form_num = a - html_context->startf;
al = get_attr_val(a, "method", html_context->options->cp); al = get_attr_val(a, "method", html_context->doc_cp);
if (al) { if (al) {
if (!strcasecmp(al, "post")) { if (!strcasecmp(al, "post")) {
unsigned char *enctype; unsigned char *enctype;
enctype = get_attr_val(a, "enctype", enctype = get_attr_val(a, "enctype",
html_context->options->cp); html_context->doc_cp);
form->method = FORM_METHOD_POST; form->method = FORM_METHOD_POST;
if (enctype) { if (enctype) {
@ -69,11 +69,11 @@ html_form(struct html_context *html_context, unsigned char *a,
} }
mem_free(al); mem_free(al);
} }
form->onsubmit = get_attr_val(a, "onsubmit", html_context->options->cp); form->onsubmit = get_attr_val(a, "onsubmit", html_context->doc_cp);
al = get_attr_val(a, "name", html_context->options->cp); al = get_attr_val(a, "name", html_context->doc_cp);
if (al) form->name = al; if (al) form->name = al;
al = get_attr_val(a, "action", html_context->options->cp); al = get_attr_val(a, "action", html_context->doc_cp);
/* The HTML specification at /* The HTML specification at
* http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.3 states * http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.3 states
* that the behavior of an empty action attribute should be undefined. * that the behavior of an empty action attribute should be undefined.
@ -114,10 +114,10 @@ html_form(struct html_context *html_context, unsigned char *a,
static int static int
get_form_mode(struct html_context *html_context, unsigned char *attr) get_form_mode(struct html_context *html_context, unsigned char *attr)
{ {
if (has_attr(attr, "disabled", html_context->options->cp)) if (has_attr(attr, "disabled", html_context->doc_cp))
return FORM_MODE_DISABLED; return FORM_MODE_DISABLED;
if (has_attr(attr, "readonly", html_context->options->cp)) if (has_attr(attr, "readonly", html_context->doc_cp))
return FORM_MODE_READONLY; return FORM_MODE_READONLY;
return FORM_MODE_NORMAL; return FORM_MODE_NORMAL;
@ -146,8 +146,7 @@ html_button(struct html_context *html_context, unsigned char *a,
unsigned char *al; unsigned char *al;
struct form_control *fc; struct form_control *fc;
enum form_type type = FC_SUBMIT; enum form_type type = FC_SUBMIT;
int cp = (html_context->part && html_context->part->document) ? int cp = html_context->doc_cp;
html_context->part->document->cp : html_context->options->cp;
html_focusable(html_context, a); html_focusable(html_context, a);
@ -197,7 +196,7 @@ html_input_format(struct html_context *html_context, unsigned char *a,
html_focusable(html_context, a); html_focusable(html_context, a);
format.form = fc; format.form = fc;
if (format.title) mem_free(format.title); if (format.title) mem_free(format.title);
format.title = get_attr_val(a, "title", html_context->options->cp); format.title = get_attr_val(a, "title", html_context->doc_cp);
switch (fc->type) { switch (fc->type) {
case FC_TEXT: case FC_TEXT:
case FC_PASSWORD: case FC_PASSWORD:
@ -223,10 +222,10 @@ html_input_format(struct html_context *html_context, unsigned char *a,
unsigned char *al; unsigned char *al;
mem_free_set(&format.image, NULL); mem_free_set(&format.image, NULL);
al = get_url_val(a, "src", html_context->options->cp); al = get_url_val(a, "src", html_context->doc_cp);
if (!al) if (!al)
al = get_url_val(a, "dynsrc", al = get_url_val(a, "dynsrc",
html_context->options->cp); html_context->doc_cp);
if (al) { if (al) {
format.image = join_urls(html_context->base_href, al); format.image = join_urls(html_context->base_href, al);
mem_free(al); mem_free(al);
@ -267,8 +266,7 @@ html_input(struct html_context *html_context, unsigned char *a,
{ {
unsigned char *al; unsigned char *al;
struct form_control *fc; struct form_control *fc;
int cp = (html_context->part && html_context->part->document) ? int cp = html_context->doc_cp;
html_context->part->document->cp : html_context->options->cp;
fc = init_form_control(FC_TEXT, a, html_context); fc = init_form_control(FC_TEXT, a, html_context);
if (!fc) return; if (!fc) return;
@ -421,18 +419,18 @@ abort:
if (!closing_tag) { if (!closing_tag) {
unsigned char *value, *label; unsigned char *value, *label;
if (has_attr(t_attr, "disabled", html_context->options->cp)) if (has_attr(t_attr, "disabled", html_context->doc_cp))
goto see; goto see;
if (preselect == -1 if (preselect == -1
&& has_attr(t_attr, "selected", html_context->options->cp)) && has_attr(t_attr, "selected", html_context->doc_cp))
preselect = order; preselect = order;
value = get_attr_val(t_attr, "value", html_context->options->cp); value = get_attr_val(t_attr, "value", html_context->doc_cp);
if (!mem_align_alloc(&values, order, order + 1, 0xFF)) if (!mem_align_alloc(&values, order, order + 1, 0xFF))
goto abort; goto abort;
values[order++] = value; values[order++] = value;
label = get_attr_val(t_attr, "label", html_context->options->cp); label = get_attr_val(t_attr, "label", html_context->doc_cp);
if (label) new_menu_item(&lnk_menu, label, order - 1, 0); if (label) new_menu_item(&lnk_menu, label, order - 1, 0);
if (!value || !label) { if (!value || !label) {
init_string(&lbl); init_string(&lbl);
@ -452,7 +450,7 @@ abort:
if (!closing_tag) { if (!closing_tag) {
unsigned char *label; unsigned char *label;
label = get_attr_val(t_attr, "label", html_context->options->cp); label = get_attr_val(t_attr, "label", html_context->doc_cp);
if (!label) { if (!label) {
label = stracpy(""); label = stracpy("");
@ -479,8 +477,8 @@ end_parse:
goto abort; goto abort;
} }
fc->id = get_attr_val(attr, "id", html_context->options->cp); fc->id = get_attr_val(attr, "id", html_context->doc_cp);
fc->name = get_attr_val(attr, "name", html_context->options->cp); fc->name = get_attr_val(attr, "name", html_context->doc_cp);
fc->default_state = preselect < 0 ? 0 : preselect; fc->default_state = preselect < 0 ? 0 : preselect;
fc->default_value = order ? stracpy(values[fc->default_state]) : stracpy(""); fc->default_value = order ? stracpy(values[fc->default_state]) : stracpy("");
fc->nvalues = order; fc->nvalues = order;
@ -520,13 +518,13 @@ do_html_select_multiple(struct html_context *html_context, unsigned char *a,
unsigned char *html, unsigned char *eof, unsigned char *html, unsigned char *eof,
unsigned char **end) unsigned char **end)
{ {
unsigned char *al = get_attr_val(a, "name", html_context->options->cp); unsigned char *al = get_attr_val(a, "name", html_context->doc_cp);
if (!al) return; if (!al) return;
html_focusable(html_context, a); html_focusable(html_context, a);
html_top->type = ELEMENT_DONT_KILL; html_top->type = ELEMENT_DONT_KILL;
mem_free_set(&format.select, al); mem_free_set(&format.select, al);
format.select_disabled = has_attr(a, "disabled", html_context->options->cp) format.select_disabled = has_attr(a, "disabled", html_context->doc_cp)
? FORM_MODE_DISABLED ? FORM_MODE_DISABLED
: FORM_MODE_NORMAL; : FORM_MODE_NORMAL;
} }
@ -535,7 +533,7 @@ void
html_select(struct html_context *html_context, unsigned char *a, html_select(struct html_context *html_context, unsigned char *a,
unsigned char *html, unsigned char *eof, unsigned char **end) unsigned char *html, unsigned char *eof, unsigned char **end)
{ {
if (has_attr(a, "multiple", html_context->options->cp)) if (has_attr(a, "multiple", html_context->doc_cp))
do_html_select_multiple(html_context, a, html, eof, end); do_html_select_multiple(html_context, a, html, eof, end);
else else
do_html_select(a, html, eof, end, html_context); do_html_select(a, html, eof, end, html_context);
@ -551,7 +549,7 @@ html_option(struct html_context *html_context, unsigned char *a,
if (!format.select) return; if (!format.select) return;
val = get_attr_val(a, "value", html_context->options->cp); val = get_attr_val(a, "value", html_context->doc_cp);
if (!val) { if (!val) {
struct string str; struct string str;
unsigned char *p, *r; unsigned char *p, *r;
@ -602,11 +600,11 @@ end_parse:
return; return;
} }
fc->id = get_attr_val(a, "id", html_context->options->cp); fc->id = get_attr_val(a, "id", html_context->doc_cp);
fc->name = null_or_stracpy(format.select); fc->name = null_or_stracpy(format.select);
fc->default_value = val; fc->default_value = val;
fc->default_state = has_attr(a, "selected", html_context->options->cp); fc->default_state = has_attr(a, "selected", html_context->doc_cp);
fc->mode = has_attr(a, "disabled", html_context->options->cp) fc->mode = has_attr(a, "disabled", html_context->doc_cp)
? FORM_MODE_DISABLED ? FORM_MODE_DISABLED
: format.select_disabled; : format.select_disabled;
@ -648,9 +646,11 @@ pp:
fc = init_form_control(FC_TEXTAREA, attr, html_context); fc = init_form_control(FC_TEXTAREA, attr, html_context);
if (!fc) return; if (!fc) return;
fc->id = get_attr_val(attr, "id", html_context->options->cp); fc->id = get_attr_val(attr, "id", html_context->doc_cp);
fc->name = get_attr_val(attr, "name", html_context->options->cp); fc->name = get_attr_val(attr, "name", html_context->doc_cp);
fc->default_value = memacpy(html, p - html); fc->default_value = convert_string(NULL, html, p - html,
html_context->doc_cp,
CSM_DEFAULT, NULL, NULL, NULL);
for (p = fc->default_value; p && p[0]; p++) { for (p = fc->default_value; p && p[0]; p++) {
/* FIXME: We don't cope well with entities here. Bugzilla uses /* FIXME: We don't cope well with entities here. Bugzilla uses
* &#13; inside of textarea and we fail miserably upon that * &#13; inside of textarea and we fail miserably upon that
@ -658,7 +658,7 @@ pp:
if (p[0] == '\r') { if (p[0] == '\r') {
if (p[1] == '\n' if (p[1] == '\n'
|| (p > fc->default_value && p[-1] == '\n')) { || (p > fc->default_value && p[-1] == '\n')) {
memcpy(p, p + 1, strlen(p)); memmove(p, p + 1, strlen(p));
p--; p--;
} else { } else {
p[0] = '\n'; p[0] = '\n';
@ -666,7 +666,7 @@ pp:
} }
} }
cols = get_num(attr, "cols", html_context->options->cp); cols = get_num(attr, "cols", html_context->doc_cp);
if (cols <= 0) if (cols <= 0)
cols = html_context->options->default_form_input_size; cols = html_context->options->default_form_input_size;
cols++; /* Add 1 column, other browsers may have different cols++; /* Add 1 column, other browsers may have different
@ -675,14 +675,14 @@ pp:
cols = html_context->options->box.width; cols = html_context->options->box.width;
fc->cols = cols; fc->cols = cols;
rows = get_num(attr, "rows", html_context->options->cp); rows = get_num(attr, "rows", html_context->doc_cp);
if (rows <= 0) rows = 1; if (rows <= 0) rows = 1;
if (rows > html_context->options->box.height) if (rows > html_context->options->box.height)
rows = html_context->options->box.height; rows = html_context->options->box.height;
fc->rows = rows; fc->rows = rows;
html_context->options->needs_height = 1; html_context->options->needs_height = 1;
wrap_attr = get_attr_val(attr, "wrap", html_context->options->cp); wrap_attr = get_attr_val(attr, "wrap", html_context->doc_cp);
if (wrap_attr) { if (wrap_attr) {
if (!strcasecmp(wrap_attr, "hard") if (!strcasecmp(wrap_attr, "hard")
|| !strcasecmp(wrap_attr, "physical")) { || !strcasecmp(wrap_attr, "physical")) {
@ -696,14 +696,14 @@ pp:
} }
mem_free(wrap_attr); mem_free(wrap_attr);
} else if (has_attr(attr, "nowrap", html_context->options->cp)) { } else if (has_attr(attr, "nowrap", html_context->doc_cp)) {
fc->wrap = FORM_WRAP_NONE; fc->wrap = FORM_WRAP_NONE;
} else { } else {
fc->wrap = FORM_WRAP_SOFT; fc->wrap = FORM_WRAP_SOFT;
} }
fc->maxlength = get_num(attr, "maxlength", html_context->options->cp); fc->maxlength = get_num(attr, "maxlength", html_context->doc_cp);
if (fc->maxlength == -1) fc->maxlength = INT_MAX; if (fc->maxlength == -1) fc->maxlength = INT_MAX;
if (rows > 1) ln_break(html_context, 1); if (rows > 1) ln_break(html_context, 1);

View File

@ -136,7 +136,7 @@ void
html_font(struct html_context *html_context, unsigned char *a, html_font(struct html_context *html_context, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5) unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{ {
unsigned char *al = get_attr_val(a, "size", html_context->options->cp); unsigned char *al = get_attr_val(a, "size", html_context->doc_cp);
if (al) { if (al) {
int p = 0; int p = 0;
@ -223,7 +223,7 @@ html_script(struct html_context *html_context, unsigned char *a,
/* Ref: /* Ref:
* http://www.ietf.org/internet-drafts/draft-hoehrmann-script-types-03.txt * http://www.ietf.org/internet-drafts/draft-hoehrmann-script-types-03.txt
*/ */
type = get_attr_val(a, "type", html_context->options->cp); type = get_attr_val(a, "type", html_context->doc_cp);
if (type) { if (type) {
unsigned char *pos = type; unsigned char *pos = type;
@ -265,7 +265,7 @@ not_processed:
* language attribute can be JavaScript with optional version digits * language attribute can be JavaScript with optional version digits
* postfixed (like: ``JavaScript1.1''). * postfixed (like: ``JavaScript1.1'').
* That attribute is deprecated in favor of type by HTML 4.01 */ * That attribute is deprecated in favor of type by HTML 4.01 */
language = get_attr_val(a, "language", html_context->options->cp); language = get_attr_val(a, "language", html_context->doc_cp);
if (language) { if (language) {
int languagelen = strlen(language); int languagelen = strlen(language);
@ -280,7 +280,7 @@ not_processed:
} }
if (html_context->part->document if (html_context->part->document
&& (src = get_attr_val(a, "src", html_context->options->cp))) { && (src = get_attr_val(a, "src", html_context->doc_cp))) {
/* External reference. */ /* External reference. */
unsigned char *import_url; unsigned char *import_url;
@ -479,7 +479,7 @@ void
html_linebrk(struct html_context *html_context, unsigned char *a, html_linebrk(struct html_context *html_context, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5) unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{ {
unsigned char *al = get_attr_val(a, "align", html_context->options->cp); unsigned char *al = get_attr_val(a, "align", html_context->doc_cp);
if (al) { if (al) {
if (!strcasecmp(al, "left")) par_format.align = ALIGN_LEFT; if (!strcasecmp(al, "left")) par_format.align = ALIGN_LEFT;
@ -632,7 +632,7 @@ html_hr(struct html_context *html_context, unsigned char *a,
{ {
int i/* = par_format.width - 10*/; int i/* = par_format.width - 10*/;
unsigned char r = (unsigned char) BORDER_DHLINE; unsigned char r = (unsigned char) BORDER_DHLINE;
int q = get_num(a, "size", html_context->options->cp); int q = get_num(a, "size", html_context->doc_cp);
if (q >= 0 && q < 2) r = (unsigned char) BORDER_SHLINE; if (q >= 0 && q < 2) r = (unsigned char) BORDER_SHLINE;
html_stack_dup(html_context, ELEMENT_KILLABLE); html_stack_dup(html_context, ELEMENT_KILLABLE);
@ -714,7 +714,7 @@ html_base(struct html_context *html_context, unsigned char *a,
{ {
unsigned char *al; unsigned char *al;
al = get_url_val(a, "href", html_context->options->cp); al = get_url_val(a, "href", html_context->doc_cp);
if (al) { if (al) {
unsigned char *base = join_urls(html_context->base_href, al); unsigned char *base = join_urls(html_context->base_href, al);
struct uri *uri = base ? get_uri(base, 0) : NULL; struct uri *uri = base ? get_uri(base, 0) : NULL;
@ -743,7 +743,7 @@ html_ul(struct html_context *html_context, unsigned char *a,
par_format.list_number = 0; par_format.list_number = 0;
par_format.flags = P_STAR; par_format.flags = P_STAR;
al = get_attr_val(a, "type", html_context->options->cp); al = get_attr_val(a, "type", html_context->doc_cp);
if (al) { if (al) {
if (!strcasecmp(al, "disc") || !strcasecmp(al, "circle")) if (!strcasecmp(al, "disc") || !strcasecmp(al, "circle"))
par_format.flags = P_O; par_format.flags = P_O;
@ -767,12 +767,12 @@ html_ol(struct html_context *html_context, unsigned char *a,
int st; int st;
par_format.list_level++; par_format.list_level++;
st = get_num(a, "start", html_context->options->cp); st = get_num(a, "start", html_context->doc_cp);
if (st == -1) st = 1; if (st == -1) st = 1;
par_format.list_number = st; par_format.list_number = st;
par_format.flags = P_NUMBER; par_format.flags = P_NUMBER;
al = get_attr_val(a, "type", html_context->options->cp); al = get_attr_val(a, "type", html_context->doc_cp);
if (al) { if (al) {
if (*al && !al[1]) { if (*al && !al[1]) {
if (*al == '1') par_format.flags = P_NUMBER; if (*al == '1') par_format.flags = P_NUMBER;
@ -875,7 +875,7 @@ html_li(struct html_context *html_context, unsigned char *a,
unsigned char n[32]; unsigned char n[32];
int nlen; int nlen;
int t = par_format.flags & P_LISTMASK; int t = par_format.flags & P_LISTMASK;
int s = get_num(a, "value", html_context->options->cp); int s = get_num(a, "value", html_context->doc_cp);
if (s != -1) par_format.list_number = s; if (s != -1) par_format.list_number = s;
@ -932,7 +932,7 @@ html_dl(struct html_context *html_context, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5) unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{ {
par_format.flags &= ~P_COMPACT; par_format.flags &= ~P_COMPACT;
if (has_attr(a, "compact", html_context->options->cp)) if (has_attr(a, "compact", html_context->doc_cp))
par_format.flags |= P_COMPACT; par_format.flags |= P_COMPACT;
if (par_format.list_level) par_format.leftmargin += 5; if (par_format.list_level) par_format.leftmargin += 5;
par_format.list_level++; par_format.list_level++;
@ -954,7 +954,7 @@ html_dt(struct html_context *html_context, unsigned char *a,
par_format.align = ALIGN_LEFT; par_format.align = ALIGN_LEFT;
par_format.leftmargin = par_format.dd_margin; par_format.leftmargin = par_format.dd_margin;
if (!(par_format.flags & P_COMPACT) if (!(par_format.flags & P_COMPACT)
&& !has_attr(a, "compact", html_context->options->cp)) && !has_attr(a, "compact", html_context->doc_cp))
ln_break(html_context, 2); ln_break(html_context, 2);
} }
@ -995,7 +995,7 @@ html_frame(struct html_context *html_context, unsigned char *a,
{ {
unsigned char *name, *src, *url; unsigned char *name, *src, *url;
src = get_url_val(a, "src", html_context->options->cp); src = get_url_val(a, "src", html_context->doc_cp);
if (!src) { if (!src) {
url = stracpy("about:blank"); url = stracpy("about:blank");
} else { } else {
@ -1004,7 +1004,7 @@ html_frame(struct html_context *html_context, unsigned char *a,
} }
if (!url) return; if (!url) return;
name = get_attr_val(a, "name", html_context->options->cp); name = get_attr_val(a, "name", html_context->doc_cp);
if (!name) { if (!name) {
name = stracpy(url); name = stracpy(url);
} else if (!name[0]) { } else if (!name[0]) {
@ -1048,13 +1048,13 @@ html_frameset(struct html_context *html_context, unsigned char *a,
|| !html_context->special_f(html_context, SP_USED, NULL)) || !html_context->special_f(html_context, SP_USED, NULL))
return; return;
cols = get_attr_val(a, "cols", html_context->options->cp); cols = get_attr_val(a, "cols", html_context->doc_cp);
if (!cols) { if (!cols) {
cols = stracpy("100%"); cols = stracpy("100%");
if (!cols) return; if (!cols) return;
} }
rows = get_attr_val(a, "rows", html_context->options->cp); rows = get_attr_val(a, "rows", html_context->doc_cp);
if (!rows) { if (!rows) {
rows = stracpy("100%"); rows = stracpy("100%");
if (!rows) { if (!rows) {

View File

@ -45,7 +45,7 @@ html_a(struct html_context *html_context, unsigned char *a,
{ {
unsigned char *href; unsigned char *href;
href = get_url_val(a, "href", html_context->options->cp); href = get_url_val(a, "href", html_context->doc_cp);
if (href) { if (href) {
unsigned char *target; unsigned char *target;
@ -84,7 +84,7 @@ html_a(struct html_context *html_context, unsigned char *a,
} }
mem_free_set(&format.title, mem_free_set(&format.title,
get_attr_val(a, "title", html_context->options->cp)); get_attr_val(a, "title", html_context->doc_cp));
html_focusable(html_context, a); html_focusable(html_context, a);
@ -215,8 +215,6 @@ html_img_do(unsigned char *a, unsigned char *object_src,
unsigned char *usemap_attr; unsigned char *usemap_attr;
struct document_options *options = html_context->options; struct document_options *options = html_context->options;
int display_style = options->image_link.display_style; int display_style = options->image_link.display_style;
int cp = (html_context->part && html_context->part->document) ?
html_context->part->document->cp : html_context->options->cp;
/* Note about display_style: /* Note about display_style:
* 0 means always display IMG * 0 means always display IMG
@ -224,7 +222,7 @@ html_img_do(unsigned char *a, unsigned char *object_src,
* 2 means display alt/title attribute if possible, IMG if not * 2 means display alt/title attribute if possible, IMG if not
* 3 means display alt/title attribute if possible, filename if not */ * 3 means display alt/title attribute if possible, filename if not */
usemap_attr = get_attr_val(a, "usemap", options->cp); usemap_attr = get_attr_val(a, "usemap", html_context->doc_cp);
if (usemap_attr) { if (usemap_attr) {
unsigned char *joined_urls = join_urls(html_context->base_href, unsigned char *joined_urls = join_urls(html_context->base_href,
usemap_attr); usemap_attr);
@ -245,13 +243,13 @@ html_img_do(unsigned char *a, unsigned char *object_src,
} }
ismap = format.link ismap = format.link
&& has_attr(a, "ismap", options->cp) && has_attr(a, "ismap", html_context->doc_cp)
&& !usemap; && !usemap;
if (display_style == 2 || display_style == 3) { if (display_style == 2 || display_style == 3) {
label = get_attr_val(a, "alt", cp); label = get_attr_val(a, "alt", html_context->doc_cp);
if (!label) if (!label)
label = get_attr_val(a, "title", options->cp); label = get_attr_val(a, "title", html_context->doc_cp);
/* Little hack to preserve rendering of [ ], in directories listing, /* Little hack to preserve rendering of [ ], in directories listing,
* but we still want to drop extra spaces in alt or title attribute * but we still want to drop extra spaces in alt or title attribute
@ -260,8 +258,8 @@ html_img_do(unsigned char *a, unsigned char *object_src,
} }
src = null_or_stracpy(object_src); src = null_or_stracpy(object_src);
if (!src) src = get_url_val(a, "src", options->cp); if (!src) src = get_url_val(a, "src", html_context->doc_cp);
if (!src) src = get_url_val(a, "dynsrc", options->cp); if (!src) src = get_url_val(a, "dynsrc", html_context->doc_cp);
/* If we have no label yet (no title or alt), so /* If we have no label yet (no title or alt), so
* just use default ones, or image filename. */ * just use default ones, or image filename. */
@ -322,7 +320,7 @@ html_img_do(unsigned char *a, unsigned char *object_src,
format.image = join_urls(html_context->base_href, src); format.image = join_urls(html_context->base_href, src);
} }
format.title = get_attr_val(a, "title", options->cp); format.title = get_attr_val(a, "title", html_context->doc_cp);
if (ismap) { if (ismap) {
unsigned char *new_link; unsigned char *new_link;
@ -370,6 +368,14 @@ put_link_line(unsigned char *prefix, unsigned char *linkname,
format.link = join_urls(html_context->base_href, link); format.link = join_urls(html_context->base_href, link);
format.target = stracpy(target); format.target = stracpy(target);
format.style.fg = format.clink; format.style.fg = format.clink;
/* FIXME: linkname typically comes from get_attr_val, which
* has already converted it from the document charset to the
* terminal charset and expanded character entity references.
* The following put_chrs call again converts the characters
* and expands entity references. So if we have
* <meta http-equiv="refresh" content="3; url=foo?&amp;lt" />
* then ELinks will display "foo?<" rather than "foo?&lt".
* This was mentioned in bug 213. */
put_chrs(html_context, linkname, strlen(linkname)); put_chrs(html_context, linkname, strlen(linkname));
ln_break(html_context, 1); ln_break(html_context, 1);
pop_html_element(html_context); pop_html_element(html_context);
@ -382,10 +388,10 @@ html_applet(struct html_context *html_context, unsigned char *a,
{ {
unsigned char *code, *alt; unsigned char *code, *alt;
code = get_url_val(a, "code", html_context->options->cp); code = get_url_val(a, "code", html_context->doc_cp);
if (!code) return; if (!code) return;
alt = get_attr_val(a, "alt", html_context->options->cp); alt = get_attr_val(a, "alt", html_context->doc_cp);
html_focusable(html_context, a); html_focusable(html_context, a);
@ -408,11 +414,11 @@ html_iframe_do(unsigned char *a, unsigned char *object_src,
unsigned char *name, *url = NULL; unsigned char *name, *url = NULL;
url = null_or_stracpy(object_src); url = null_or_stracpy(object_src);
if (!url) url = get_url_val(a, "src", html_context->options->cp); if (!url) url = get_url_val(a, "src", html_context->doc_cp);
if (!url) return; if (!url) return;
name = get_attr_val(a, "name", html_context->options->cp); name = get_attr_val(a, "name", html_context->doc_cp);
if (!name) name = get_attr_val(a, "id", html_context->options->cp); if (!name) name = get_attr_val(a, "id", html_context->doc_cp);
if (!name) name = stracpy(""); if (!name) name = stracpy("");
if (!name) { if (!name) {
mem_free(url); mem_free(url);
@ -450,11 +456,11 @@ html_object(struct html_context *html_context, unsigned char *a,
* this, which is anyway in the spirit of <object> element, unifying * this, which is anyway in the spirit of <object> element, unifying
* <img> and <iframe> etc. */ * <img> and <iframe> etc. */
url = get_url_val(a, "data", html_context->options->cp); url = get_url_val(a, "data", html_context->doc_cp);
if (!url) url = get_url_val(a, "codebase", html_context->options->cp); if (!url) url = get_url_val(a, "codebase", html_context->doc_cp);
if (!url) return; if (!url) return;
type = get_attr_val(a, "type", html_context->options->cp); type = get_attr_val(a, "type", html_context->doc_cp);
if (!type) { mem_free(url); return; } if (!type) { mem_free(url); return; }
if (!strncasecmp(type, "text/", 5)) { if (!strncasecmp(type, "text/", 5)) {
@ -469,7 +475,7 @@ html_object(struct html_context *html_context, unsigned char *a,
} else { } else {
unsigned char *name; unsigned char *name;
name = get_attr_val(a, "standby", html_context->options->cp); name = get_attr_val(a, "standby", html_context->doc_cp);
html_focusable(html_context, a); html_focusable(html_context, a);
@ -501,7 +507,7 @@ html_embed(struct html_context *html_context, unsigned char *a,
* this, which is anyway in the spirit of <object> element, unifying * this, which is anyway in the spirit of <object> element, unifying
* <img> and <iframe> etc. */ * <img> and <iframe> etc. */
object_src = get_url_val(a, "src", html_context->options->cp); object_src = get_url_val(a, "src", html_context->doc_cp);
if (!object_src || !*object_src) { if (!object_src || !*object_src) {
mem_free_set(&object_src, NULL); mem_free_set(&object_src, NULL);
return; return;
@ -730,20 +736,20 @@ html_link_parse(struct html_context *html_context, unsigned char *a,
assert(a && link); assert(a && link);
memset(link, 0, sizeof(*link)); memset(link, 0, sizeof(*link));
link->href = get_url_val(a, "href", html_context->options->cp); link->href = get_url_val(a, "href", html_context->doc_cp);
if (!link->href) return 0; if (!link->href) return 0;
link->lang = get_attr_val(a, "lang", html_context->options->cp); link->lang = get_attr_val(a, "lang", html_context->doc_cp);
link->hreflang = get_attr_val(a, "hreflang", html_context->options->cp); link->hreflang = get_attr_val(a, "hreflang", html_context->doc_cp);
link->title = get_attr_val(a, "title", html_context->options->cp); link->title = get_attr_val(a, "title", html_context->doc_cp);
link->content_type = get_attr_val(a, "type", html_context->options->cp); link->content_type = get_attr_val(a, "type", html_context->doc_cp);
link->media = get_attr_val(a, "media", html_context->options->cp); link->media = get_attr_val(a, "media", html_context->doc_cp);
link->name = get_attr_val(a, "rel", html_context->options->cp); link->name = get_attr_val(a, "rel", html_context->doc_cp);
if (link->name) { if (link->name) {
link->direction = LD_REL; link->direction = LD_REL;
} else { } else {
link->name = get_attr_val(a, "rev", html_context->options->cp); link->name = get_attr_val(a, "rev", html_context->doc_cp);
if (link->name) link->direction = LD_REV; if (link->name) link->direction = LD_REV;
} }

View File

@ -273,7 +273,7 @@ int
get_width(unsigned char *a, unsigned char *name, int limited, get_width(unsigned char *a, unsigned char *name, int limited,
struct html_context *html_context) struct html_context *html_context)
{ {
unsigned char *value = get_attr_val(a, name, html_context->options->cp); unsigned char *value = get_attr_val(a, name, html_context->doc_cp);
unsigned char *str = value; unsigned char *str = value;
unsigned char *end; unsigned char *end;
int percentage = 0; int percentage = 0;
@ -809,7 +809,7 @@ start_element(struct element_info *ei,
{ {
#define ELEMENT_RENDER_PROLOGUE \ #define ELEMENT_RENDER_PROLOGUE \
ln_break(html_context, ei->linebreak); \ ln_break(html_context, ei->linebreak); \
a = get_attr_val(attr, "id", html_context->options->cp); \ a = get_attr_val(attr, "id", html_context->doc_cp); \
if (a) { \ if (a) { \
html_context->special_f(html_context, SP_TAG, a); \ html_context->special_f(html_context, SP_TAG, a); \
mem_free(a); \ mem_free(a); \
@ -883,7 +883,7 @@ start_element(struct element_info *ei,
html_top->linebreak = ei->linebreak; html_top->linebreak = ei->linebreak;
#ifdef CONFIG_ECMASCRIPT #ifdef CONFIG_ECMASCRIPT
if (has_attr(attr, "onClick", html_context->options->cp)) { if (has_attr(attr, "onClick", html_context->doc_cp)) {
/* XXX: Put something better to format.link. --pasky */ /* XXX: Put something better to format.link. --pasky */
mem_free_set(&format.link, stracpy("javascript:void(0);")); mem_free_set(&format.link, stracpy("javascript:void(0);"));
mem_free_set(&format.target, stracpy(html_context->base_target)); mem_free_set(&format.target, stracpy(html_context->base_target));
@ -1093,6 +1093,8 @@ xsp:
} }
if (strlcasecmp(name, namelen, "META", 4)) goto se; if (strlcasecmp(name, namelen, "META", 4)) goto se;
/* FIXME (bug 784): options->cp is the terminal charset;
* should use the document charset instead. */
he = get_attr_val(attr, "charset", options->cp); he = get_attr_val(attr, "charset", options->cp);
if (he) { if (he) {
add_to_string(head, "Charset: "); add_to_string(head, "Charset: ");
@ -1100,12 +1102,16 @@ xsp:
mem_free(he); mem_free(he);
} }
/* FIXME (bug 784): options->cp is the terminal charset;
* should use the document charset instead. */
he = get_attr_val(attr, "http-equiv", options->cp); he = get_attr_val(attr, "http-equiv", options->cp);
if (!he) goto se; if (!he) goto se;
add_to_string(head, he); add_to_string(head, he);
mem_free(he); mem_free(he);
/* FIXME (bug 784): options->cp is the terminal charset;
* should use the document charset instead. */
c = get_attr_val(attr, "content", options->cp); c = get_attr_val(attr, "content", options->cp);
if (c) { if (c) {
add_to_string(head, ": "); add_to_string(head, ": ");

View File

@ -90,7 +90,7 @@ kill_html_stack_item(struct html_context *html_context, struct html_element *e)
* any element, executing it when that element is fully loaded. */ * any element, executing it when that element is fully loaded. */
if (e->options) if (e->options)
onload = get_attr_val(e->options, "onLoad", onload = get_attr_val(e->options, "onLoad",
html_context->options->cp); html_context->doc_cp);
if (html_context->part if (html_context->part
&& html_context->part->document && html_context->part->document
&& onload && *onload && *onload != '^') { && onload && *onload && *onload != '^') {

View File

@ -70,12 +70,12 @@ get_bordercolor(struct html_context *html_context, unsigned char *a, color_T *rg
if (!use_document_fg_colors(html_context->options)) if (!use_document_fg_colors(html_context->options))
return; return;
at = get_attr_val(a, "bordercolor", html_context->options->cp); at = get_attr_val(a, "bordercolor", html_context->doc_cp);
/* Try some other MSIE-specific attributes if any. */ /* Try some other MSIE-specific attributes if any. */
if (!at) if (!at)
at = get_attr_val(a, "bordercolorlight", html_context->options->cp); at = get_attr_val(a, "bordercolorlight", html_context->doc_cp);
if (!at) if (!at)
at = get_attr_val(a, "bordercolordark", html_context->options->cp); at = get_attr_val(a, "bordercolordark", html_context->doc_cp);
if (!at) return; if (!at) return;
decode_color(at, strlen(at), rgb); decode_color(at, strlen(at), rgb);
@ -85,7 +85,7 @@ get_bordercolor(struct html_context *html_context, unsigned char *a, color_T *rg
static void static void
get_align(struct html_context *html_context, unsigned char *attr, int *a) get_align(struct html_context *html_context, unsigned char *attr, int *a)
{ {
unsigned char *al = get_attr_val(attr, "align", html_context->options->cp); unsigned char *al = get_attr_val(attr, "align", html_context->doc_cp);
if (!al) return; if (!al) return;
@ -100,7 +100,7 @@ get_align(struct html_context *html_context, unsigned char *attr, int *a)
static void static void
get_valign(struct html_context *html_context, unsigned char *attr, int *a) get_valign(struct html_context *html_context, unsigned char *attr, int *a)
{ {
unsigned char *al = get_attr_val(attr, "valign", html_context->options->cp); unsigned char *al = get_attr_val(attr, "valign", html_context->doc_cp);
if (!al) return; if (!al) return;
@ -115,7 +115,7 @@ static void
get_column_width(unsigned char *attr, int *width, int sh, get_column_width(unsigned char *attr, int *width, int sh,
struct html_context *html_context) struct html_context *html_context)
{ {
unsigned char *al = get_attr_val(attr, "width", html_context->options->cp); unsigned char *al = get_attr_val(attr, "width", html_context->doc_cp);
int len; int len;
if (!al) return; if (!al) return;
@ -151,7 +151,7 @@ set_table_frame(struct html_context *html_context, struct table *table,
table->frame = TABLE_FRAME_BOX; table->frame = TABLE_FRAME_BOX;
al = get_attr_val(attr, "frame", html_context->options->cp); al = get_attr_val(attr, "frame", html_context->doc_cp);
if (!al) return; if (!al) return;
if (!strcasecmp(al, "void")) table->frame = TABLE_FRAME_VOID; if (!strcasecmp(al, "void")) table->frame = TABLE_FRAME_VOID;
@ -176,7 +176,7 @@ set_table_rules(struct html_context *html_context, struct table *table,
table->rules = table->border ? TABLE_RULE_ALL : TABLE_RULE_NONE; table->rules = table->border ? TABLE_RULE_ALL : TABLE_RULE_NONE;
al = get_attr_val(attr, "rules", html_context->options->cp); al = get_attr_val(attr, "rules", html_context->doc_cp);
if (!al) return; if (!al) return;
if (!strcasecmp(al, "none")) table->rules = TABLE_RULE_NONE; if (!strcasecmp(al, "none")) table->rules = TABLE_RULE_NONE;
@ -191,7 +191,7 @@ static void
parse_table_attributes(struct table *table, unsigned char *attr, int real, parse_table_attributes(struct table *table, unsigned char *attr, int real,
struct html_context *html_context) struct html_context *html_context)
{ {
table->fragment_id = get_attr_val(attr, "id", html_context->options->cp); table->fragment_id = get_attr_val(attr, "id", html_context->doc_cp);
get_bordercolor(html_context, attr, &table->bordercolor); get_bordercolor(html_context, attr, &table->bordercolor);
@ -212,18 +212,18 @@ parse_table_attributes(struct table *table, unsigned char *attr, int real,
* interpreted as the value of the frame attribute. It implies * interpreted as the value of the frame attribute. It implies
* rules="all" and some default (non-zero) value for the border * rules="all" and some default (non-zero) value for the border
* attribute. */ * attribute. */
table->border = get_num(attr, "border", html_context->options->cp); table->border = get_num(attr, "border", html_context->doc_cp);
if (table->border == -1) { if (table->border == -1) {
table->border = table->border =
has_attr(attr, "border", html_context->options->cp) has_attr(attr, "border", html_context->doc_cp)
|| has_attr(attr, "rules", html_context->options->cp) || has_attr(attr, "rules", html_context->doc_cp)
|| has_attr(attr, "frame", html_context->options->cp); || has_attr(attr, "frame", html_context->doc_cp);
} }
if (table->border) { if (table->border) {
int_upper_bound(&table->border, 2); int_upper_bound(&table->border, 2);
table->cellspacing = get_num(attr, "cellspacing", html_context->options->cp); table->cellspacing = get_num(attr, "cellspacing", html_context->doc_cp);
int_bounds(&table->cellspacing, 1, 2); int_bounds(&table->cellspacing, 1, 2);
} }
@ -231,7 +231,7 @@ parse_table_attributes(struct table *table, unsigned char *attr, int real,
/* TODO: cellpadding may be expressed as a percentage, this is not /* TODO: cellpadding may be expressed as a percentage, this is not
* handled yet. */ * handled yet. */
table->cellpadding = get_num(attr, "cellpadding", html_context->options->cp); table->cellpadding = get_num(attr, "cellpadding", html_context->doc_cp);
if (table->cellpadding == -1) { if (table->cellpadding == -1) {
table->vcellpadding = 0; table->vcellpadding = 0;
table->cellpadding = !!table->border; table->cellpadding = !!table->border;
@ -650,7 +650,7 @@ see:
get_align(html_context, t_attr, &c_al); get_align(html_context, t_attr, &c_al);
get_valign(html_context, t_attr, &c_val); get_valign(html_context, t_attr, &c_val);
get_column_width(t_attr, &c_width, sh, html_context); get_column_width(t_attr, &c_width, sh, html_context);
c_span = get_num(t_attr, "span", html_context->options->cp); c_span = get_num(t_attr, "span", html_context->doc_cp);
if (c_span == -1) if (c_span == -1)
c_span = 1; c_span = 1;
else if (c_span > HTML_MAX_COLSPAN) else if (c_span > HTML_MAX_COLSPAN)
@ -668,7 +668,7 @@ see:
add_table_bad_html_end(table, html); add_table_bad_html_end(table, html);
sp = get_num(t_attr, "span", html_context->options->cp); sp = get_num(t_attr, "span", html_context->doc_cp);
if (sp == -1) sp = 1; if (sp == -1) sp = 1;
else if (sp > HTML_MAX_COLSPAN) sp = HTML_MAX_COLSPAN; else if (sp > HTML_MAX_COLSPAN) sp = HTML_MAX_COLSPAN;
@ -745,7 +745,7 @@ see:
get_valign(html_context, t_attr, &l_val); get_valign(html_context, t_attr, &l_val);
get_bgcolor(html_context, t_attr, &last_bgcolor); get_bgcolor(html_context, t_attr, &last_bgcolor);
mem_free_set(&l_fragment_id, mem_free_set(&l_fragment_id,
get_attr_val(t_attr, "id", html_context->options->cp)); get_attr_val(t_attr, "id", html_context->doc_cp));
row++; row++;
col = 0; col = 0;
goto see; goto see;
@ -788,7 +788,7 @@ see:
cell->align = l_al; cell->align = l_al;
cell->valign = l_val; cell->valign = l_val;
cell->fragment_id = get_attr_val(t_attr, "id", html_context->options->cp); cell->fragment_id = get_attr_val(t_attr, "id", html_context->doc_cp);
if (!cell->fragment_id && l_fragment_id) { if (!cell->fragment_id && l_fragment_id) {
cell->fragment_id = l_fragment_id; cell->fragment_id = l_fragment_id;
l_fragment_id = NULL; l_fragment_id = NULL;
@ -812,12 +812,12 @@ see:
get_valign(html_context, t_attr, &cell->valign); get_valign(html_context, t_attr, &cell->valign);
get_bgcolor(html_context, t_attr, &cell->bgcolor); get_bgcolor(html_context, t_attr, &cell->bgcolor);
colspan = get_num(t_attr, "colspan", html_context->options->cp); colspan = get_num(t_attr, "colspan", html_context->doc_cp);
if (colspan == -1) colspan = 1; if (colspan == -1) colspan = 1;
else if (!colspan) colspan = -1; else if (!colspan) colspan = -1;
else if (colspan > HTML_MAX_COLSPAN) colspan = HTML_MAX_COLSPAN; else if (colspan > HTML_MAX_COLSPAN) colspan = HTML_MAX_COLSPAN;
rowspan = get_num(t_attr, "rowspan", html_context->options->cp); rowspan = get_num(t_attr, "rowspan", html_context->doc_cp);
if (rowspan == -1) rowspan = 1; if (rowspan == -1) rowspan = 1;
else if (!rowspan) rowspan = -1; else if (!rowspan) rowspan = -1;
else if (rowspan > HTML_MAX_ROWSPAN) rowspan = HTML_MAX_ROWSPAN; else if (rowspan > HTML_MAX_ROWSPAN) rowspan = HTML_MAX_ROWSPAN;

View File

@ -175,7 +175,8 @@ realloc_line(struct html_context *html_context, struct document *document,
end->data = ' '; end->data = ' ';
end->attr = 0; end->attr = 0;
set_screen_char_color(end, par_format.bgcolor, 0x0, set_screen_char_color(end, par_format.bgcolor, 0x0,
0, document->options.color_mode); COLOR_ENSURE_CONTRAST, /* for bug 461 */
document->options.color_mode);
for (pos = &line->chars[line->length]; pos < end; pos++) { for (pos = &line->chars[line->length]; pos < end; pos++) {
copy_screen_chars(pos, end, 1); copy_screen_chars(pos, end, 1);
@ -257,7 +258,8 @@ clear_hchars(struct html_context *html_context, int x, int y, int width)
end->data = ' '; end->data = ' ';
end->attr = 0; end->attr = 0;
set_screen_char_color(end, par_format.bgcolor, 0x0, set_screen_char_color(end, par_format.bgcolor, 0x0,
0, part->document->options.color_mode); COLOR_ENSURE_CONTRAST, /* for bug 461 */
part->document->options.color_mode);
while (pos < end) while (pos < end)
copy_screen_chars(pos++, end, 1); copy_screen_chars(pos++, end, 1);
@ -406,6 +408,21 @@ set_hline(struct html_context *html_context, unsigned char *chars, int charslen,
if (realloc_spaces(part, x + charslen)) if (realloc_spaces(part, x + charslen))
return 0; return 0;
/* U+00AD SOFT HYPHEN characters in HTML documents are
* supposed to be displayed only if the word is broken at that
* point. ELinks currently does not use them, so it should
* not display them. If the input @chars is in UTF-8, then
* set_hline() discards the characters. If the input is in
* some other charset, then set_hline() does not know which
* byte that charset uses for U+00AD, so it cannot discard
* the characters; instead, the translation table used by
* convert_string() has already discarded the characters.
*
* Likewise, if the input @chars is in UTF-8, then it may
* contain U+00A0 NO-BREAK SPACE characters; but if the input
* is in some other charset, then the translation table
* has mapped those characters to NBSP_CHAR. */
if (part->document) { if (part->document) {
/* Reallocate LINE(y).chars[] to large enough. The /* Reallocate LINE(y).chars[] to large enough. The
* last parameter of realloc_line is the index of the * last parameter of realloc_line is the index of the
@ -424,7 +441,7 @@ set_hline(struct html_context *html_context, unsigned char *chars, int charslen,
if (orig_length < 0) /* error */ if (orig_length < 0) /* error */
return 0; return 0;
if (utf8) { if (utf8) {
unsigned char *end = chars + charslen; unsigned char *const end = chars + charslen;
unicode_val_T data; unicode_val_T data;
if (part->document->buf_length) { if (part->document->buf_length) {
@ -459,7 +476,7 @@ set_hline(struct html_context *html_context, unsigned char *chars, int charslen,
} }
} }
for (; chars < end; x++) { while (chars < end) {
/* ELinks does not use NBSP_CHAR in UTF-8. */ /* ELinks does not use NBSP_CHAR in UTF-8. */
data = utf8_to_unicode(&chars, end); data = utf8_to_unicode(&chars, end);
@ -473,7 +490,7 @@ set_hline(struct html_context *html_context, unsigned char *chars, int charslen,
schar->attr = SCREEN_ATTR_FRAME; schar->attr = SCREEN_ATTR_FRAME;
copy_screen_chars(&POS(x, y), schar, 1); copy_screen_chars(&POS(x, y), schar, 1);
schar->attr = attr; schar->attr = attr;
part->char_width[x] = 0; part->char_width[x++] = 0;
continue; continue;
} else { } else {
unsigned char i; unsigned char i;
@ -484,26 +501,31 @@ set_hline(struct html_context *html_context, unsigned char *chars, int charslen,
part->document->buf_length = i; part->document->buf_length = i;
break; break;
} }
} else { /* not reached */
good_char:
if (data == UCS_NO_BREAK_SPACE
&& html_context->options->wrap_nbsp)
data = UCS_SPACE;
part->spaces[x] = (data == UCS_SPACE);
if (unicode_to_cell(data) == 2) {
schar->data = (unicode_val_T)data;
part->char_width[x] = 2;
copy_screen_chars(&POS(x++, y), schar, 1);
schar->data = UCS_NO_CHAR;
part->spaces[x] = 0;
part->char_width[x] = 0;
} else {
part->char_width[x] = unicode_to_cell(data);
schar->data = (unicode_val_T)data;
}
} }
copy_screen_chars(&POS(x, y), schar, 1);
} good_char:
if (data == UCS_SOFT_HYPHEN)
continue;
if (data == UCS_NO_BREAK_SPACE
&& html_context->options->wrap_nbsp)
data = UCS_SPACE;
part->spaces[x] = (data == UCS_SPACE);
if (unicode_to_cell(data) == 2) {
schar->data = (unicode_val_T)data;
part->char_width[x] = 2;
copy_screen_chars(&POS(x++, y), schar, 1);
schar->data = UCS_NO_CHAR;
part->spaces[x] = 0;
part->char_width[x] = 0;
} else {
part->char_width[x] = unicode_to_cell(data);
schar->data = (unicode_val_T)data;
}
copy_screen_chars(&POS(x++, y), schar, 1);
} /* while chars < end */
} else { /* not UTF-8 */ } else { /* not UTF-8 */
for (; charslen > 0; charslen--, x++, chars++) { for (; charslen > 0; charslen--, x++, chars++) {
part->char_width[x] = 1; part->char_width[x] = 1;
@ -535,13 +557,20 @@ good_char:
len = x - x2; len = x - x2;
} else { /* part->document == NULL */ } else { /* part->document == NULL */
if (utf8) { if (utf8) {
unsigned char *end; unsigned char *const end = chars + charslen;
for (end = chars + charslen; chars < end; x++) { while (chars < end) {
unicode_val_T data; unicode_val_T data;
part->spaces[x] = (*chars == ' ');
data = utf8_to_unicode(&chars, end); data = utf8_to_unicode(&chars, end);
if (data == UCS_SOFT_HYPHEN)
continue;
if (data == UCS_NO_BREAK_SPACE
&& html_context->options->wrap_nbsp)
data = UCS_SPACE;
part->spaces[x] = (data == UCS_SPACE);
part->char_width[x] = unicode_to_cell(data); part->char_width[x] = unicode_to_cell(data);
if (part->char_width[x] == 2) { if (part->char_width[x] == 2) {
x++; x++;
@ -552,12 +581,17 @@ good_char:
/* this is at the end only */ /* this is at the end only */
return x - x2; return x - x2;
} }
} x++;
} /* while chars < end */
len = x - x2; len = x - x2;
} else { /* not UTF-8 */ } else { /* not UTF-8 */
for (; charslen > 0; charslen--, x++, chars++) { for (; charslen > 0; charslen--, x++, chars++) {
part->spaces[x] = (*chars == ' ');
part->char_width[x] = 1; part->char_width[x] = 1;
if (*chars == NBSP_CHAR) {
part->spaces[x] = html_context->options->wrap_nbsp;
} else {
part->spaces[x] = (*chars == ' ');
}
} }
} }
} /* end of part->document check */ } /* end of part->document check */
@ -600,7 +634,11 @@ set_hline(struct html_context *html_context, unsigned char *chars, int charslen,
} }
} else { } else {
for (; charslen > 0; charslen--, x++, chars++) { for (; charslen > 0; charslen--, x++, chars++) {
part->spaces[x] = (*chars == ' '); if (*chars == NBSP_CHAR) {
part->spaces[x] = html_context->options->wrap_nbsp;
} else {
part->spaces[x] = (*chars == ' ');
}
} }
} }
} }
@ -1773,18 +1811,6 @@ html_special_form_control(struct part *part, struct form_control *fc)
fc->g_ctrl_num = renderer_context.g_ctrl_num++; fc->g_ctrl_num = renderer_context.g_ctrl_num++;
/* We don't want to recode hidden fields. */
if (fc->type == FC_TEXT || fc->type == FC_PASSWORD ||
fc->type == FC_TEXTAREA) {
unsigned char *dv = convert_string(renderer_context.convert_table,
fc->default_value,
strlen(fc->default_value),
part->document->options.cp,
CSM_QUERY, NULL, NULL, NULL);
if (dv) mem_free_set(&fc->default_value, dv);
}
if (list_empty(part->document->forms)) { if (list_empty(part->document->forms)) {
/* No forms encountered yet, that means a homeless form /* No forms encountered yet, that means a homeless form
* control. Generate a dummy form for those Flying * control. Generate a dummy form for those Flying
@ -2210,6 +2236,7 @@ render_html_document(struct cache_entry *cached, struct document *document,
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
html_context->options->utf8 = is_cp_utf8(document->options.cp); html_context->options->utf8 = is_cp_utf8(document->options.cp);
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
html_context->doc_cp = document->cp;
if (title.length) { if (title.length) {
document->title = convert_string(renderer_context.convert_table, document->title = convert_string(renderer_context.convert_table,

View File

@ -22,6 +22,9 @@ struct active_link_options {
* whether they satisfy the current state of the document options. */ * whether they satisfy the current state of the document options. */
struct document_options { struct document_options {
enum color_mode color_mode; enum color_mode color_mode;
/* cp is the codepage for which the document is being formatted;
* typically it is the codepage of a terminal. It is set in
* render_document_frames. */
int cp, assume_cp, hard_assume; int cp, assume_cp, hard_assume;
int margin; int margin;
int num_links_key; int num_links_key;

View File

@ -1,7 +1,7 @@
top_builddir=../.. top_builddir=../..
include $(top_builddir)/Makefile.config include $(top_builddir)/Makefile.config
SUBDIRS = css sgml SUBDIRS = css sgml test
OBJS = configuration.o node.o select.o stack.o scanner.o OBJS = configuration.o node.o select.o stack.o scanner.o
SUBDIRS-$(CONFIG_DEBUG) += test SUBDIRS-$(CONFIG_DEBUG) += test

View File

@ -8,11 +8,6 @@ TEST_PROGS = \
sgml-parser sgml-parser
TESTDEPS = \ TESTDEPS = \
$(top_builddir)/src/dom/$(LIB_O_NAME) \ $(top_builddir)/src/dom/$(LIB_O_NAME)
$(top_builddir)/src/util/error.o \
$(top_builddir)/src/osdep/stub.o \
$(top_builddir)/src/util/hash.o \
$(top_builddir)/src/util/string.o \
$(top_builddir)/src/util/memory.o
include $(top_srcdir)/Makefile.lib include $(top_srcdir)/Makefile.lib

View File

@ -242,7 +242,8 @@ sgml_error_function(struct sgml_parser *parser, struct dom_string *string,
return DOM_CODE_OK; return DOM_CODE_OK;
} }
void die(const char *msg, ...) static void
die(const char *msg, ...)
{ {
va_list args; va_list args;
@ -256,6 +257,29 @@ void die(const char *msg, ...)
exit(!!NULL); exit(!!NULL);
} }
static int
get_opt(char **argref, const char *name, int *argi, int argc, char *argv[],
const char *expect_msg)
{
char *arg = *argref;
int namelen = strlen(name);
if (strncmp(arg, name, namelen))
return 0;
arg += namelen;
if (*arg == '=') {
(*argref) = arg + 1;
} else {
(*argi)++;
if ((*argi) >= argc)
die("--%s expects %s", name, expect_msg);
(*argref) = argv[(*argi)];
}
return 1;
}
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
@ -281,54 +305,17 @@ main(int argc, char *argv[])
arg += 2; arg += 2;
if (!strncmp(arg, "uri", 3)) { if (get_opt(&arg, "uri", &i, argc, argv, "a URI")) {
arg += 3; set_dom_string(&uri, arg, strlen(arg));
if (*arg == '=') {
arg++;
set_dom_string(&uri, arg, strlen(arg));
} else {
i++;
if (i >= argc)
die("--uri expects a URI");
set_dom_string(&uri, argv[i], strlen(argv[i]));
}
} else if (!strncmp(arg, "src", 3)) { } else if (get_opt(&arg, "src", &i, argc, argv, "a string")) {
arg += 3; set_dom_string(&source, arg, strlen(arg));
if (*arg == '=') {
arg++;
set_dom_string(&source, arg, strlen(arg));
} else {
i++;
if (i >= argc)
die("--src expects a string");
set_dom_string(&source, argv[i], strlen(argv[i]));
}
} else if (!strncmp(arg, "stdin", 5)) { } else if (get_opt(&arg, "stdin", &i, argc, argv, "a number")) {
arg += 5; read_stdin = atoi(arg);
if (*arg == '=') {
arg++;
read_stdin = atoi(arg);
set_dom_string(&source, arg, strlen(arg));
} else {
i++;
if (i >= argc)
die("--stdin expects a number");
read_stdin = atoi(argv[i]);
}
flags |= SGML_PARSER_INCREMENTAL; flags |= SGML_PARSER_INCREMENTAL;
} else if (!strncmp(arg, "normalize", 9)) { } else if (get_opt(&arg, "normalize", &i, argc, argv, "a string")) {
arg += 9;
if (*arg == '=') {
arg++;
} else {
i++;
if (i >= argc)
die("--normalize expects a string");
arg = argv[i];
}
normalize = 1; normalize = 1;
normalize_flags = parse_dom_config(arg, ','); normalize_flags = parse_dom_config(arg, ',');
type = SGML_PARSER_TREE; type = SGML_PARSER_TREE;

View File

@ -20,7 +20,7 @@ test_output_equals () {
sgml-parser --uri "$URI" --src "$src" > output sgml-parser --uri "$URI" --src "$src" > output
echo "#document: $URI" > expected echo "#document: $URI" > expected
echo "$out" | sed -n '2,$p' | sed 's/^/ /' >> expected printf "%s\n" "$out" | sed -n '2,$p' | sed 's/^/ /' >> expected
test_expect_success "$desc" 'cmp output expected' test_expect_success "$desc" 'cmp output expected'
} }

View File

@ -19,10 +19,10 @@ test_incremental_parsing () {
URI="test:$(normalize "$desc")" URI="test:$(normalize "$desc")"
echo "#document: $URI" > expected echo "#document: $URI" > expected
echo "$out" | sed -n '2,$p' | sed -e 's/^/ /' >> expected printf "%s\n" "$out" | sed -n '2,$p' | sed -e 's/^/ /' >> expected
for size in 1 2 3 4 5 6 7 8 9 10 15 20 25 50; do for size in 1 2 3 4 5 6 7 8 9 10 15 20 25 50; do
echo -n "$src" | sgml-parser --uri "$URI" --stdin "$size" > output printf "%s" "$src" | sgml-parser --uri "$URI" --stdin "$size" > output
test_run_ 'cmp output expected' test_run_ 'cmp output expected'
if [ "$?" != 0 -o "$eval_ret" != 0 ] if [ "$?" != 0 -o "$eval_ret" != 0 ]

View File

@ -55,10 +55,10 @@ test_output_line_numbers \
7 7
8' \ 8' \
8 8
test_output_line_numbers \ test_output_line_numbers \
'Check line numbers. (IIII)' \ 'Check line numbers. (IIII)' \
$'1\r\f 2\v\n 3\r\n 4\t\f 5' \ "$(printf "1\r\f 2\v\n 3\r\n 4\t\f 5")" \
5 5
test_done test_done

View File

@ -125,6 +125,7 @@ ecmascript_get_interpreter(struct view_state *vs)
return NULL; return NULL;
interpreter->vs = vs; interpreter->vs = vs;
interpreter->vs->ecmascript_fragile = 0;
init_list(interpreter->onload_snippets); init_list(interpreter->onload_snippets);
#ifdef CONFIG_ECMASCRIPT_SEE #ifdef CONFIG_ECMASCRIPT_SEE
see_get_interpreter(interpreter); see_get_interpreter(interpreter);
@ -139,6 +140,11 @@ void
ecmascript_put_interpreter(struct ecmascript_interpreter *interpreter) ecmascript_put_interpreter(struct ecmascript_interpreter *interpreter)
{ {
assert(interpreter); assert(interpreter);
assert(interpreter->backend_nesting == 0);
/* If the assertion fails, it is better to leak the
* interpreter than to corrupt memory. */
if_assert_failed return;
#ifdef CONFIG_ECMASCRIPT_SEE #ifdef CONFIG_ECMASCRIPT_SEE
see_put_interpreter(interpreter); see_put_interpreter(interpreter);
#else #else
@ -150,6 +156,7 @@ ecmascript_put_interpreter(struct ecmascript_interpreter *interpreter)
if (interpreter->vs->doc_view) if (interpreter->vs->doc_view)
kill_timer(&interpreter->vs->doc_view->document->timeout); kill_timer(&interpreter->vs->doc_view->document->timeout);
interpreter->vs->ecmascript = NULL; interpreter->vs->ecmascript = NULL;
interpreter->vs->ecmascript_fragile = 1;
mem_free(interpreter); mem_free(interpreter);
} }
@ -160,39 +167,51 @@ ecmascript_eval(struct ecmascript_interpreter *interpreter,
if (!get_ecmascript_enable()) if (!get_ecmascript_enable())
return; return;
assert(interpreter); assert(interpreter);
interpreter->backend_nesting++;
#ifdef CONFIG_ECMASCRIPT_SEE #ifdef CONFIG_ECMASCRIPT_SEE
see_eval(interpreter, code, ret); see_eval(interpreter, code, ret);
#else #else
spidermonkey_eval(interpreter, code, ret); spidermonkey_eval(interpreter, code, ret);
#endif #endif
interpreter->backend_nesting--;
} }
unsigned char * unsigned char *
ecmascript_eval_stringback(struct ecmascript_interpreter *interpreter, ecmascript_eval_stringback(struct ecmascript_interpreter *interpreter,
struct string *code) struct string *code)
{ {
unsigned char *result;
if (!get_ecmascript_enable()) if (!get_ecmascript_enable())
return NULL; return NULL;
assert(interpreter); assert(interpreter);
interpreter->backend_nesting++;
#ifdef CONFIG_ECMASCRIPT_SEE #ifdef CONFIG_ECMASCRIPT_SEE
return see_eval_stringback(interpreter, code); result = see_eval_stringback(interpreter, code);
#else #else
return spidermonkey_eval_stringback(interpreter, code); result = spidermonkey_eval_stringback(interpreter, code);
#endif #endif
interpreter->backend_nesting--;
return result;
} }
int int
ecmascript_eval_boolback(struct ecmascript_interpreter *interpreter, ecmascript_eval_boolback(struct ecmascript_interpreter *interpreter,
struct string *code) struct string *code)
{ {
int result;
if (!get_ecmascript_enable()) if (!get_ecmascript_enable())
return -1; return -1;
assert(interpreter); assert(interpreter);
interpreter->backend_nesting++;
#ifdef CONFIG_ECMASCRIPT_SEE #ifdef CONFIG_ECMASCRIPT_SEE
return see_eval_boolback(interpreter, code); result = see_eval_boolback(interpreter, code);
#else #else
return spidermonkey_eval_boolback(interpreter, code); result = spidermonkey_eval_boolback(interpreter, code);
#endif #endif
interpreter->backend_nesting--;
return result;
} }

View File

@ -18,6 +18,12 @@ struct view_state;
struct ecmascript_interpreter { struct ecmascript_interpreter {
struct view_state *vs; struct view_state *vs;
void *backend_data; void *backend_data;
/* Nesting level of calls to backend functions. When this is
* nonzero, there are references to backend_data in the C
* stack, so it is not safe to free the data yet. */
int backend_nesting;
/* Used by document.write() */ /* Used by document.write() */
struct string *ret; struct string *ret;

View File

@ -104,7 +104,7 @@ see_eval(struct ecmascript_interpreter *interpreter,
struct SEE_interpreter *interp = interpreter->backend_data; struct SEE_interpreter *interp = interpreter->backend_data;
struct global_object *g = (struct global_object *)interp; struct global_object *g = (struct global_object *)interp;
struct SEE_input *input = SEE_input_elinks(interp, code->source); struct SEE_input *input = see_input_elinks(interp, code->source);
SEE_try_context_t try_ctxt; SEE_try_context_t try_ctxt;
struct SEE_value result; struct SEE_value result;
@ -125,7 +125,7 @@ see_eval_stringback(struct ecmascript_interpreter *interpreter,
{ {
struct SEE_interpreter *interp = interpreter->backend_data; struct SEE_interpreter *interp = interpreter->backend_data;
struct global_object *g = (struct global_object *)interp; struct global_object *g = (struct global_object *)interp;
struct SEE_input *input = SEE_input_elinks(interp, code->source); struct SEE_input *input = see_input_elinks(interp, code->source);
SEE_try_context_t try_ctxt; SEE_try_context_t try_ctxt;
struct SEE_value result; struct SEE_value result;
/* 'volatile' qualifier prevents register allocation which fixes: /* 'volatile' qualifier prevents register allocation which fixes:
@ -138,7 +138,7 @@ see_eval_stringback(struct ecmascript_interpreter *interpreter,
SEE_TRY(interp, try_ctxt) { SEE_TRY(interp, try_ctxt) {
SEE_Global_eval(interp, input, &result); SEE_Global_eval(interp, input, &result);
if (SEE_VALUE_GET_TYPE(&result) == SEE_STRING) if (SEE_VALUE_GET_TYPE(&result) == SEE_STRING)
string = SEE_value_to_unsigned_char(interp, &result); string = see_value_to_unsigned_char(interp, &result);
} }
SEE_INPUT_CLOSE(input); SEE_INPUT_CLOSE(input);
@ -154,7 +154,8 @@ see_eval_boolback(struct ecmascript_interpreter *interpreter,
{ {
struct SEE_interpreter *interp = interpreter->backend_data; struct SEE_interpreter *interp = interpreter->backend_data;
struct global_object *g = (struct global_object *)interp; struct global_object *g = (struct global_object *)interp;
struct SEE_input *input = SEE_input_elinks(interp, code->source); struct SEE_input *input = see_input_elinks(interp, code->source);
struct SEE_object *fun;
SEE_try_context_t try_ctxt; SEE_try_context_t try_ctxt;
struct SEE_value result; struct SEE_value result;
/* 'volatile' qualifier prevents register allocation which fixes: /* 'volatile' qualifier prevents register allocation which fixes:
@ -165,7 +166,8 @@ see_eval_boolback(struct ecmascript_interpreter *interpreter,
g->exec_start = time(NULL); g->exec_start = time(NULL);
g->ret = NULL; g->ret = NULL;
SEE_TRY(interp, try_ctxt) { SEE_TRY(interp, try_ctxt) {
SEE_Global_eval(interp, input, &result); fun = SEE_Function_new(interp, NULL, NULL, input);
SEE_OBJECT_CALL(interp, fun, NULL, 0, NULL, &result);
/* history.back() returns SEE_NULL */ /* history.back() returns SEE_NULL */
if (SEE_VALUE_GET_TYPE(&result) == SEE_NULL) if (SEE_VALUE_GET_TYPE(&result) == SEE_NULL)
res = 0; res = 0;

View File

@ -64,7 +64,7 @@ struct SEE_objectclass js_document_object_class = {
document_hasproperty, document_hasproperty,
SEE_no_delete, SEE_no_delete,
SEE_no_defaultvalue, SEE_no_defaultvalue,
NULL, SEE_no_enumerator,
NULL, NULL,
NULL, NULL,
NULL NULL
@ -145,7 +145,7 @@ document_get(struct SEE_interpreter *interp, struct SEE_object *o,
SEE_SET_OBJECT(res, doc->writeln); SEE_SET_OBJECT(res, doc->writeln);
} else { } else {
struct form *form; struct form *form;
unsigned char *string = SEE_string_to_unsigned_char(p); unsigned char *string = see_string_to_unsigned_char(p);
struct form_view *form_view; struct form_view *form_view;
struct js_form *form_object; struct js_form *form_object;
@ -179,7 +179,7 @@ document_put(struct SEE_interpreter *interp, struct SEE_object *o,
SEE_ToObject(interp, val, &res); SEE_ToObject(interp, val, &res);
doc->forms = res.u.object; doc->forms = res.u.object;
} else if (p == s_title) { } else if (p == s_title) {
string = SEE_value_to_unsigned_char(interp, val); string = see_value_to_unsigned_char(interp, val);
mem_free_set(&document->title, string); mem_free_set(&document->title, string);
print_screen_status(doc_view->session); print_screen_status(doc_view->session);
} else if (p == s_location || p == s_url) { } else if (p == s_location || p == s_url) {
@ -187,12 +187,12 @@ document_put(struct SEE_interpreter *interp, struct SEE_object *o,
* broken sites still assign to it (i.e. * broken sites still assign to it (i.e.
* http://www.e-handelsfonden.dk/validering.asp?URL=www.polyteknisk.dk). * http://www.e-handelsfonden.dk/validering.asp?URL=www.polyteknisk.dk).
* So emulate window.location. */ * So emulate window.location. */
string = SEE_value_to_unsigned_char(interp, val); string = see_value_to_unsigned_char(interp, val);
location_goto(doc_view, string); location_goto(doc_view, string);
mem_free_if(string); mem_free_if(string);
} else if (p == s_cookie) { } else if (p == s_cookie) {
#ifdef CONFIG_COOKIES #ifdef CONFIG_COOKIES
string = SEE_value_to_unsigned_char(interp, val); string = see_value_to_unsigned_char(interp, val);
set_cookie(vs->uri, string); set_cookie(vs->uri, string);
mem_free_if(string); mem_free_if(string);
#endif #endif
@ -218,7 +218,7 @@ js_document_write_do(struct SEE_interpreter *interp, struct SEE_object *self,
for (; i < argc; ++i) { for (; i < argc; ++i) {
unsigned char *code; unsigned char *code;
code = SEE_value_to_unsigned_char(interp, argv[i]); code = see_value_to_unsigned_char(interp, argv[i]);
if (code) { if (code) {
add_to_string(ret, code); add_to_string(ret, code);

View File

@ -56,8 +56,8 @@ static void js_input_focus(struct SEE_interpreter *, struct SEE_object *, struct
static void js_input_select(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_canput(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
static int input_hasproperty(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_input_object(struct SEE_interpreter *, struct js_form *, int);
static struct js_input *js_get_form_control_object(struct SEE_interpreter *, struct js_form *, enum form_type, struct form_state *); static struct js_input *js_get_form_control_object(struct SEE_interpreter *, struct js_form *, enum form_type, int);
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_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 js_form_elems_namedItem(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
@ -85,7 +85,7 @@ struct SEE_objectclass js_input_object_class = {
input_hasproperty, input_hasproperty,
SEE_no_delete, SEE_no_delete,
SEE_no_defaultvalue, SEE_no_defaultvalue,
NULL, SEE_no_enumerator,
NULL, NULL,
NULL, NULL,
NULL NULL
@ -99,7 +99,7 @@ struct SEE_objectclass js_form_elems_class = {
form_elems_hasproperty, form_elems_hasproperty,
SEE_no_delete, SEE_no_delete,
SEE_no_defaultvalue, SEE_no_defaultvalue,
NULL, SEE_no_enumerator,
NULL, NULL,
NULL, NULL,
NULL NULL
@ -113,7 +113,7 @@ struct SEE_objectclass js_forms_object_class = {
forms_hasproperty, forms_hasproperty,
SEE_no_delete, SEE_no_delete,
SEE_no_defaultvalue, SEE_no_defaultvalue,
NULL, SEE_no_enumerator,
NULL, NULL,
NULL, NULL,
NULL NULL
@ -127,7 +127,7 @@ struct SEE_objectclass js_form_class = {
form_hasproperty, form_hasproperty,
SEE_no_delete, SEE_no_delete,
SEE_no_defaultvalue, SEE_no_defaultvalue,
NULL, SEE_no_enumerator,
NULL, NULL,
NULL, NULL,
NULL NULL
@ -136,11 +136,11 @@ struct SEE_objectclass js_form_class = {
struct js_input { struct js_input {
struct SEE_object object; struct SEE_object object;
struct js_form *parent; struct js_form *parent;
struct form_state *fs;
struct SEE_object *blur; struct SEE_object *blur;
struct SEE_object *click; struct SEE_object *click;
struct SEE_object *focus; struct SEE_object *focus;
struct SEE_object *select; struct SEE_object *select;
int form_number;
}; };
struct js_forms_object { struct js_forms_object {
@ -158,6 +158,15 @@ struct js_form_elems {
}; };
static inline struct form_state *
form_state_of_js_input(struct view_state *vs, const struct js_input *input)
{
assert(input->form_number >= 0);
assert(input->form_number < vs->form_info_len);
if_assert_failed return NULL;
return &vs->form_info[input->form_number];
}
static void static void
input_get(struct SEE_interpreter *interp, struct SEE_object *o, input_get(struct SEE_interpreter *interp, struct SEE_object *o,
struct SEE_string *p, struct SEE_value *res) struct SEE_string *p, struct SEE_value *res)
@ -168,7 +177,7 @@ input_get(struct SEE_interpreter *interp, struct SEE_object *o,
struct document *document = doc_view->document; struct document *document = doc_view->document;
struct js_input *input = (struct js_input *)o; struct js_input *input = (struct js_input *)o;
struct js_form *parent = input->parent; struct js_form *parent = input->parent;
struct form_state *fs = input->fs; struct form_state *fs = form_state_of_js_input(vs, input);
struct form_control *fc = find_form_control(document, fs); struct form_control *fc = find_form_control(document, fs);
int linknum; int linknum;
struct link *link = NULL; struct link *link = NULL;
@ -200,6 +209,7 @@ input_get(struct SEE_interpreter *interp, struct SEE_object *o,
} else if (p == s_defaultChecked) { } else if (p == s_defaultChecked) {
SEE_SET_BOOLEAN(res, fc->default_state); SEE_SET_BOOLEAN(res, fc->default_state);
} else if (p == s_defaultValue) { } else if (p == s_defaultValue) {
/* FIXME (bug 805): convert from the charset of the document */
str = string_to_SEE_string(interp, fc->default_value); str = string_to_SEE_string(interp, fc->default_value);
SEE_SET_STRING(res, str); SEE_SET_STRING(res, str);
} else if (p == s_disabled) { } else if (p == s_disabled) {
@ -270,7 +280,7 @@ input_put(struct SEE_interpreter *interp, struct SEE_object *o,
struct document_view *doc_view = vs->doc_view; struct document_view *doc_view = vs->doc_view;
struct document *document = doc_view->document; struct document *document = doc_view->document;
struct js_input *input = (struct js_input *)o; struct js_input *input = (struct js_input *)o;
struct form_state *fs = input->fs; struct form_state *fs = form_state_of_js_input(vs, input);
struct form_control *fc = find_form_control(document, fs); struct form_control *fc = find_form_control(document, fs);
int linknum; int linknum;
struct link *link = NULL; struct link *link = NULL;
@ -289,14 +299,14 @@ input_put(struct SEE_interpreter *interp, struct SEE_object *o,
SEE_ToString(interp, val, &conv); SEE_ToString(interp, val, &conv);
if (conv.u.string->length) if (conv.u.string->length)
accesskey = SEE_string_to_unicode(interp, conv.u.string); accesskey = see_string_to_unicode(interp, conv.u.string);
else else
accesskey = 0; accesskey = 0;
if (link) if (link)
link->accesskey = accesskey; link->accesskey = accesskey;
} else if (p == s_alt) { } else if (p == s_alt) {
string = SEE_value_to_unsigned_char(interp, val); string = see_value_to_unsigned_char(interp, val);
mem_free_set(&fc->alt, string); mem_free_set(&fc->alt, string);
} else if (p == s_checked) { } else if (p == s_checked) {
if (fc->type != FC_CHECKBOX && fc->type != FC_RADIO) if (fc->type != FC_CHECKBOX && fc->type != FC_RADIO)
@ -309,13 +319,13 @@ input_put(struct SEE_interpreter *interp, struct SEE_object *o,
: (fc->mode == FORM_MODE_READONLY ? FORM_MODE_READONLY : (fc->mode == FORM_MODE_READONLY ? FORM_MODE_READONLY
: FORM_MODE_NORMAL)); : FORM_MODE_NORMAL));
} else if (p == s_maxLength) { } else if (p == s_maxLength) {
string = SEE_value_to_unsigned_char(interp, val); string = see_value_to_unsigned_char(interp, val);
if (!string) if (!string)
return; return;
fc->maxlength = atol(string); fc->maxlength = atol(string);
mem_free(string); mem_free(string);
} else if (p == s_name) { } else if (p == s_name) {
string = SEE_value_to_unsigned_char(interp, val); string = see_value_to_unsigned_char(interp, val);
mem_free_set(&fc->name, string); mem_free_set(&fc->name, string);
} else if (p == s_readonly) { } else if (p == s_readonly) {
SEE_uint32_t boo = SEE_ToUint32(interp, val); SEE_uint32_t boo = SEE_ToUint32(interp, val);
@ -324,13 +334,13 @@ input_put(struct SEE_interpreter *interp, struct SEE_object *o,
: FORM_MODE_NORMAL); : FORM_MODE_NORMAL);
} else if (p == s_src) { } else if (p == s_src) {
if (link) { if (link) {
string = SEE_value_to_unsigned_char(interp, val); string = see_value_to_unsigned_char(interp, val);
mem_free_set(&link->where_img, string); mem_free_set(&link->where_img, string);
} }
} else if (p == s_value) { } else if (p == s_value) {
if (fc->type == FC_FILE) if (fc->type == FC_FILE)
return; return;
string = SEE_value_to_unsigned_char(interp, val); string = see_value_to_unsigned_char(interp, val);
mem_free_set(&fs->value, string); mem_free_set(&fs->value, string);
if (fc->type == FC_TEXT || fc->type == FC_PASSWORD) if (fc->type == FC_TEXT || fc->type == FC_PASSWORD)
fs->state = strlen(fs->value); fs->state = strlen(fs->value);
@ -370,7 +380,7 @@ js_input_click(struct SEE_interpreter *interp, struct SEE_object *self,
struct js_input *input = ( struct js_input *input = (
see_check_class(interp, thisobj, &js_input_object_class), see_check_class(interp, thisobj, &js_input_object_class),
(struct js_input *)thisobj); (struct js_input *)thisobj);
struct form_state *fs = input->fs; struct form_state *fs = form_state_of_js_input(vs, input);
struct form_control *fc; struct form_control *fc;
int linknum; int linknum;
@ -405,7 +415,7 @@ js_input_focus(struct SEE_interpreter *interp, struct SEE_object *self,
struct js_input *input = ( struct js_input *input = (
see_check_class(interp, thisobj, &js_input_object_class), see_check_class(interp, thisobj, &js_input_object_class),
(struct js_input *)thisobj); (struct js_input *)thisobj);
struct form_state *fs = input->fs; struct form_state *fs = form_state_of_js_input(vs, input);
struct form_control *fc; struct form_control *fc;
int linknum; int linknum;
@ -450,8 +460,7 @@ input_hasproperty(struct SEE_interpreter *interp, struct SEE_object *o,
} }
static struct js_input * static struct js_input *
js_get_input_object(struct SEE_interpreter *interp, struct js_form *jsform, js_get_input_object(struct SEE_interpreter *interp, struct js_form *jsform, int num)
struct form_state *fs)
{ {
struct js_input *jsinput; struct js_input *jsinput;
@ -473,16 +482,14 @@ js_get_input_object(struct SEE_interpreter *interp, struct js_form *jsform,
jsinput->focus = SEE_cfunction_make(interp, js_input_focus, s_focus, 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->select = SEE_cfunction_make(interp, js_input_select, s_select, 0);
jsinput->fs = fs; jsinput->form_number = num;
jsinput->parent = jsform; jsinput->parent = jsform;
fs->ecmascript_obj = jsinput;
return jsinput; return jsinput;
} }
static struct js_input * static struct js_input *
js_get_form_control_object(struct SEE_interpreter *interp, struct js_form *jsform, js_get_form_control_object(struct SEE_interpreter *interp, struct js_form *jsform,
enum form_type type, struct form_state *fs) enum form_type type, int num)
{ {
switch (type) { switch (type) {
case FC_TEXT: case FC_TEXT:
@ -496,7 +503,7 @@ js_get_form_control_object(struct SEE_interpreter *interp, struct js_form *jsfor
case FC_BUTTON: case FC_BUTTON:
case FC_HIDDEN: case FC_HIDDEN:
case FC_SELECT: case FC_SELECT:
return js_get_input_object(interp, jsform, fs); return js_get_input_object(interp, jsform, num);
case FC_TEXTAREA: case FC_TEXTAREA:
/* TODO */ /* TODO */
@ -534,7 +541,7 @@ js_form_elems_item(struct SEE_interpreter *interp, struct SEE_object *self,
SEE_SET_UNDEFINED(res); SEE_SET_UNDEFINED(res);
if (argc < 1) if (argc < 1)
return; return;
string = SEE_value_to_unsigned_char(interp, argv[0]); string = see_value_to_unsigned_char(interp, argv[0]);
if (!string) if (!string)
return; return;
index = atol(string); index = atol(string);
@ -543,10 +550,13 @@ js_form_elems_item(struct SEE_interpreter *interp, struct SEE_object *self,
foreach (fc, form->items) { foreach (fc, form->items) {
counter++; counter++;
if (counter == index) { if (counter == index) {
struct js_input *fcobj = js_get_form_control_object(interp, parent_form, fc->type, find_form_state(doc_view, fc)); struct form_state *fs = find_form_state(doc_view, fc);
if (fcobj) { if (fs) {
SEE_SET_OBJECT(res, (struct SEE_object *)fcobj); struct js_input *fcobj = js_get_form_control_object(interp, parent_form, fc->type, fc->g_ctrl_num);
if (fcobj)
SEE_SET_OBJECT(res, (struct SEE_object *)fcobj);
} }
break; break;
} }
@ -575,16 +585,19 @@ js_form_elems_namedItem(struct SEE_interpreter *interp, struct SEE_object *self,
SEE_SET_UNDEFINED(res); SEE_SET_UNDEFINED(res);
if (argc < 1) if (argc < 1)
return; return;
string = SEE_value_to_unsigned_char(interp, argv[0]); string = see_value_to_unsigned_char(interp, argv[0]);
if (!string) if (!string)
return; return;
foreach (fc, form->items) { foreach (fc, form->items) {
if ((fc->id && !strcasecmp(string, fc->id)) || (fc->name && !strcasecmp(string, fc->name))) { if ((fc->id && !strcasecmp(string, fc->id)) || (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)); struct form_state *fs = find_form_state(doc_view, fc);
if (fcobj) { if (fs) {
SEE_SET_OBJECT(res, (struct SEE_object *)fcobj); struct js_input *fcobj = js_get_form_control_object(interp, parent_form, fc->type, fc->g_ctrl_num);
if (fcobj)
SEE_SET_OBJECT(res, (struct SEE_object *)fcobj);
} }
break; break;
} }
@ -613,20 +626,21 @@ form_elems_get(struct SEE_interpreter *interp, struct SEE_object *o,
} else if (p == s_namedItem) { } else if (p == s_namedItem) {
SEE_SET_OBJECT(res, jsfe->namedItem); SEE_SET_OBJECT(res, jsfe->namedItem);
} else { } else {
unsigned char *string = SEE_string_to_unsigned_char(p); unsigned char *string = see_string_to_unsigned_char(p);
struct SEE_value argv; struct SEE_value arg0;
struct SEE_value *argv[1] = { &arg0 };
if (!string) { if (!string) {
SEE_SET_UNDEFINED(res); SEE_SET_UNDEFINED(res);
return; return;
} }
SEE_SET_STRING(&argv, p); SEE_SET_STRING(&arg0, p);
if (string[0] >= '0' && string[1] <= '9') { if (string[0] >= '0' && string[0] <= '9') {
js_form_elems_item(interp, jsfe->item, o, 1, js_form_elems_item(interp, jsfe->item, o, 1,
(struct SEE_value **)&argv, res); argv, res);
} else { } else {
js_form_elems_namedItem(interp, jsfe->namedItem, o, 1, js_form_elems_namedItem(interp, jsfe->namedItem, o, 1,
(struct SEE_value **)&argv, res); argv, res);
} }
mem_free(string); mem_free(string);
} }
@ -661,7 +675,7 @@ js_forms_item(struct SEE_interpreter *interp, struct SEE_object *self,
if (argc < 1) if (argc < 1)
return; return;
string = SEE_value_to_unsigned_char(interp, argv[0]); string = see_value_to_unsigned_char(interp, argv[0]);
if (!string) if (!string)
return; return;
index = atol(string); index = atol(string);
@ -698,7 +712,7 @@ js_forms_namedItem(struct SEE_interpreter *interp, struct SEE_object *self,
if (argc < 1) if (argc < 1)
return; return;
string = SEE_value_to_unsigned_char(interp, argv[0]); string = see_value_to_unsigned_char(interp, argv[0]);
if (!string) if (!string)
return; return;
foreach (form, document->forms) { foreach (form, document->forms) {
@ -733,21 +747,19 @@ forms_get(struct SEE_interpreter *interp, struct SEE_object *o,
} else if (p == s_namedItem) { } else if (p == s_namedItem) {
SEE_SET_OBJECT(res, fo->namedItem); SEE_SET_OBJECT(res, fo->namedItem);
} else { } else {
unsigned char *string = SEE_string_to_unsigned_char(p); unsigned char *string = see_string_to_unsigned_char(p);
struct SEE_value argv; struct SEE_value arg0;
struct SEE_value *argv1 = &argv; struct SEE_value *argv[1] = { &arg0 };
if (!string) { if (!string) {
SEE_SET_UNDEFINED(res); SEE_SET_UNDEFINED(res);
return; return;
} }
SEE_SET_STRING(argv1, p); SEE_SET_STRING(&arg0, p);
if (string[0] >= '0' && string[0] <= '9') { if (string[0] >= '0' && string[0] <= '9') {
js_forms_item(interp, fo->item, o, 1, js_forms_item(interp, fo->item, o, 1, argv, res);
(struct SEE_value **)&argv1, res);
} else { } else {
js_forms_namedItem(interp, fo->namedItem, o, 1, js_forms_namedItem(interp, fo->namedItem, o, 1, argv, res);
(struct SEE_value **)&argv1, res);
} }
mem_free(string); mem_free(string);
} }
@ -831,7 +843,7 @@ form_get(struct SEE_interpreter *interp, struct SEE_object *o,
} else if (p == s_reset) { } else if (p == s_reset) {
SEE_SET_OBJECT(res, js_form->reset); SEE_SET_OBJECT(res, js_form->reset);
} else { } else {
unsigned char *string = SEE_string_to_unsigned_char(p); unsigned char *string = see_string_to_unsigned_char(p);
struct form_control *fc; struct form_control *fc;
if (!string) if (!string)
@ -839,13 +851,16 @@ form_get(struct SEE_interpreter *interp, struct SEE_object *o,
foreach(fc, form->items) { foreach(fc, form->items) {
struct js_input *fcobj = NULL; struct js_input *fcobj = NULL;
struct form_state *fs;
if ((!fc->id || strcasecmp(string, fc->id)) && (!fc->name || strcasecmp(string, fc->name))) if ((!fc->id || strcasecmp(string, fc->id)) && (!fc->name || strcasecmp(string, fc->name)))
continue; continue;
fcobj = js_get_form_control_object(interp, js_form, fc->type, find_form_state(doc_view, fc)); fs = find_form_state(doc_view, fc);
if (fs) {
fcobj = js_get_form_control_object(interp, js_form, fc->type, fc->g_ctrl_num);
if (fcobj) { if (fcobj)
SEE_SET_OBJECT(res, (struct SEE_object *)fcobj); SEE_SET_OBJECT(res, (struct SEE_object *)fcobj);
} }
break; break;
} }
@ -863,7 +878,7 @@ form_put(struct SEE_interpreter *interp, struct SEE_object *o,
struct js_form *js_form = (struct js_form *)o; struct js_form *js_form = (struct js_form *)o;
struct form_view *fv = js_form->fv; struct form_view *fv = js_form->fv;
struct form *form = find_form_by_form_view(doc_view->document, fv); struct form *form = find_form_by_form_view(doc_view->document, fv);
unsigned char *string = SEE_value_to_unsigned_char(interp, val); unsigned char *string = see_value_to_unsigned_char(interp, val);
if (!string) if (!string)
return; return;

View File

@ -49,7 +49,7 @@ input_elinks_close(struct SEE_input *inp)
} }
struct SEE_input * struct SEE_input *
SEE_input_elinks(struct SEE_interpreter *interp, unsigned char *s) see_input_elinks(struct SEE_interpreter *interp, unsigned char *s)
{ {
struct input_elinks *input; struct input_elinks *input;
@ -64,7 +64,7 @@ SEE_input_elinks(struct SEE_interpreter *interp, unsigned char *s)
} }
unsigned char * unsigned char *
SEE_string_to_unsigned_char(struct SEE_string *S) see_string_to_unsigned_char(struct SEE_string *S)
{ {
int i; int i;
unsigned char *str = mem_alloc(S->length + 1); unsigned char *str = mem_alloc(S->length + 1);
@ -79,12 +79,12 @@ SEE_string_to_unsigned_char(struct SEE_string *S)
} }
unsigned char * unsigned char *
SEE_value_to_unsigned_char(struct SEE_interpreter *interp, struct SEE_value *val) see_value_to_unsigned_char(struct SEE_interpreter *interp, struct SEE_value *val)
{ {
struct SEE_value result; struct SEE_value result;
SEE_ToString(interp, val, &result); SEE_ToString(interp, val, &result);
return SEE_string_to_unsigned_char(result.u.string); return see_string_to_unsigned_char(result.u.string);
} }
struct SEE_string * struct SEE_string *
@ -127,7 +127,7 @@ append_unicode_to_SEE_string(struct SEE_interpreter *interp,
} }
unicode_val_T unicode_val_T
SEE_string_to_unicode(struct SEE_interpreter *interp, struct SEE_string *S) see_string_to_unicode(struct SEE_interpreter *interp, struct SEE_string *S)
{ {
/* This implementation ignores extra characters in the string. */ /* This implementation ignores extra characters in the string. */
if (S->length < 1) { if (S->length < 1) {

View File

@ -7,12 +7,12 @@ struct SEE_interpreter;
struct SEE_string; struct SEE_string;
struct SEE_value; struct SEE_value;
struct SEE_input *SEE_input_elinks(struct SEE_interpreter *, unsigned char *); struct SEE_input *see_input_elinks(struct SEE_interpreter *, unsigned char *);
unsigned char *SEE_string_to_unsigned_char(struct SEE_string *); unsigned char *see_string_to_unsigned_char(struct SEE_string *);
unsigned char *SEE_value_to_unsigned_char(struct SEE_interpreter *, struct SEE_value *); 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 *); struct SEE_string *string_to_SEE_string(struct SEE_interpreter *, unsigned char *);
void append_unicode_to_SEE_string(struct SEE_interpreter *, struct SEE_string *, void append_unicode_to_SEE_string(struct SEE_interpreter *, struct SEE_string *,
unicode_val_T); unicode_val_T);
unicode_val_T SEE_string_to_unicode(struct SEE_interpreter *, struct SEE_string *); unicode_val_T see_string_to_unicode(struct SEE_interpreter *, struct SEE_string *);
#endif #endif

View File

@ -88,7 +88,7 @@ struct SEE_objectclass js_history_object_class = {
history_hasproperty, history_hasproperty,
SEE_no_delete, SEE_no_delete,
SEE_no_defaultvalue, SEE_no_defaultvalue,
NULL, SEE_no_enumerator,
NULL, NULL,
NULL, NULL,
NULL NULL
@ -102,7 +102,7 @@ struct SEE_objectclass js_location_object_class = {
location_hasproperty, location_hasproperty,
SEE_no_delete, SEE_no_delete,
SEE_no_defaultvalue, SEE_no_defaultvalue,
NULL, SEE_no_enumerator,
NULL, NULL,
NULL, NULL,
NULL NULL
@ -232,7 +232,7 @@ js_history_go(struct SEE_interpreter *interp, struct SEE_object *self,
if (argc < 1) if (argc < 1)
return; return;
str = SEE_value_to_unsigned_char(interp, argv[0]); str = see_value_to_unsigned_char(interp, argv[0]);
if (!str) if (!str)
return; return;
@ -297,7 +297,7 @@ location_put(struct SEE_interpreter *interp, struct SEE_object *o,
struct global_object *g = (struct global_object *)interp; struct global_object *g = (struct global_object *)interp;
struct view_state *vs = g->win->vs; struct view_state *vs = g->win->vs;
struct document_view *doc_view = vs->doc_view; struct document_view *doc_view = vs->doc_view;
unsigned char *url = SEE_value_to_unsigned_char(interp, val); unsigned char *url = see_value_to_unsigned_char(interp, val);
location_goto(doc_view, url); location_goto(doc_view, url);
mem_free(url); mem_free(url);

View File

@ -57,7 +57,7 @@ struct SEE_objectclass js_navigator_object_class = {
navigator_hasproperty, navigator_hasproperty,
SEE_no_delete, SEE_no_delete,
SEE_no_defaultvalue, SEE_no_defaultvalue,
NULL, SEE_no_enumerator,
NULL, NULL,
NULL, NULL,
NULL NULL

View File

@ -64,7 +64,7 @@ struct SEE_objectclass js_menubar_object_class = {
unibar_hasproperty, unibar_hasproperty,
SEE_no_delete, SEE_no_delete,
SEE_no_defaultvalue, SEE_no_defaultvalue,
NULL, SEE_no_enumerator,
NULL, NULL,
NULL, NULL,
NULL NULL
@ -78,7 +78,7 @@ struct SEE_objectclass js_statusbar_object_class = {
unibar_hasproperty, unibar_hasproperty,
SEE_no_delete, SEE_no_delete,
SEE_no_defaultvalue, SEE_no_defaultvalue,
NULL, SEE_no_enumerator,
NULL, NULL,
NULL, NULL,
NULL NULL

View File

@ -67,7 +67,7 @@ struct SEE_objectclass js_window_object_class = {
window_hasproperty, window_hasproperty,
SEE_no_delete, SEE_no_delete,
SEE_no_defaultvalue, SEE_no_defaultvalue,
NULL, SEE_no_enumerator,
NULL, NULL,
NULL, NULL,
NULL NULL
@ -143,7 +143,7 @@ window_get(struct SEE_interpreter *interp, struct SEE_object *o,
} else if (p == s_navigator) { } else if (p == s_navigator) {
SEE_OBJECT_GET(interp, interp->Global, s_navigator, res); SEE_OBJECT_GET(interp, interp->Global, s_navigator, res);
} else { } else {
unsigned char *frame = SEE_string_to_unsigned_char(p); unsigned char *frame = see_string_to_unsigned_char(p);
struct document_view *doc_view = vs->doc_view; struct document_view *doc_view = vs->doc_view;
struct js_window_object *obj; struct js_window_object *obj;
@ -164,7 +164,7 @@ window_put(struct SEE_interpreter *interp, struct SEE_object *o,
struct js_window_object *win = (struct js_window_object *)o; struct js_window_object *win = (struct js_window_object *)o;
struct view_state *vs = win->vs; struct view_state *vs = win->vs;
struct document_view *doc_view = vs->doc_view; struct document_view *doc_view = vs->doc_view;
unsigned char *str = SEE_value_to_unsigned_char(interp, val); unsigned char *str = see_value_to_unsigned_char(interp, val);
if (str) { if (str) {
location_goto(doc_view, str); location_goto(doc_view, str);
@ -176,7 +176,7 @@ window_put(struct SEE_interpreter *interp, struct SEE_object *o,
struct view_state *vs = win->vs; struct view_state *vs = win->vs;
struct document_view *doc_view = vs->doc_view; struct document_view *doc_view = vs->doc_view;
struct session *ses = doc_view->session; struct session *ses = doc_view->session;
unsigned char *stat = SEE_value_to_unsigned_char(interp, val); unsigned char *stat = see_value_to_unsigned_char(interp, val);
mem_free_set(&ses->status.window_status, stat); mem_free_set(&ses->status.window_status, stat);
print_screen_status(ses); print_screen_status(ses);
@ -217,7 +217,7 @@ js_window_alert(struct SEE_interpreter *interp, struct SEE_object *self,
if (argc < 1) if (argc < 1)
return; return;
string = SEE_value_to_unsigned_char(interp, argv[0]); string = see_value_to_unsigned_char(interp, argv[0]);
if (!string || !*string) { if (!string || !*string) {
mem_free_if(string); mem_free_if(string);
return; return;
@ -274,14 +274,14 @@ js_window_open(struct SEE_interpreter *interp, struct SEE_object *self,
} }
#endif #endif
SEE_ToString(interp, argv[0], &url_value); SEE_ToString(interp, argv[0], &url_value);
url = SEE_string_to_unsigned_char(url_value.u.string); url = see_string_to_unsigned_char(url_value.u.string);
if (!url) return; if (!url) return;
trim_chars(url, ' ', 0); trim_chars(url, ' ', 0);
if (argc > 1) { if (argc > 1) {
struct SEE_value target_value; struct SEE_value target_value;
SEE_ToString(interp, argv[1], &target_value); SEE_ToString(interp, argv[1], &target_value);
frame = SEE_string_to_unsigned_char(target_value.u.string); frame = see_string_to_unsigned_char(target_value.u.string);
if (!frame) { if (!frame) {
mem_free(url); mem_free(url);
return; return;
@ -345,7 +345,7 @@ js_setTimeout(struct SEE_interpreter *interp, struct SEE_object *self,
if (argc != 2) return; if (argc != 2) return;
ei = ((struct global_object *)interp)->interpreter; ei = ((struct global_object *)interp)->interpreter;
code = SEE_value_to_unsigned_char(interp, argv[0]); code = see_value_to_unsigned_char(interp, argv[0]);
timeout = SEE_ToInt32(interp, argv[1]); timeout = SEE_ToInt32(interp, argv[1]);
ecmascript_set_timeout(ei, code, timeout); ecmascript_set_timeout(ei, code, timeout);
} }

View File

@ -288,6 +288,7 @@ spidermonkey_eval_boolback(struct ecmascript_interpreter *interpreter,
struct string *code) struct string *code)
{ {
JSContext *ctx; JSContext *ctx;
JSFunction *fun;
jsval rval; jsval rval;
int ret; int ret;
@ -295,8 +296,12 @@ spidermonkey_eval_boolback(struct ecmascript_interpreter *interpreter,
ctx = interpreter->backend_data; ctx = interpreter->backend_data;
setup_safeguard(interpreter, ctx); setup_safeguard(interpreter, ctx);
interpreter->ret = NULL; interpreter->ret = NULL;
ret = JS_EvaluateScript(ctx, JS_GetGlobalObject(ctx), fun = JS_CompileFunction(ctx, NULL, "", 0, NULL, code->source,
code->source, code->length, "", 0, &rval); code->length, "", 0);
if (!fun)
return -1;
ret = JS_CallFunction(ctx, NULL, fun, 0, NULL, &rval);
if (ret == 2) { /* onClick="history.back()" */ if (ret == 2) { /* onClick="history.back()" */
return 0; return 0;
} }

View File

@ -98,7 +98,8 @@ document_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL)); assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL));
if_assert_failed return JS_FALSE; if_assert_failed return JS_FALSE;
vs = JS_GetPrivate(ctx, parent_win); /* from @window_class */ vs = JS_GetInstancePrivate(ctx, parent_win,
(JSClass *) &window_class, NULL);
doc_view = vs->doc_view; doc_view = vs->doc_view;
document = doc_view->document; document = doc_view->document;
ses = doc_view->session; ses = doc_view->session;
@ -173,8 +174,8 @@ document_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
astring_to_jsval(ctx, vp, get_uri_string(document->uri, URI_ORIGINAL)); astring_to_jsval(ctx, vp, get_uri_string(document->uri, URI_ORIGINAL));
break; break;
default: default:
/* Unrecognized property ID; someone is using the /* Unrecognized integer property ID; someone is using
* object as an array. SMJS builtin classes (e.g. * the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return JS_TRUE in this case * js_RegExpClass) just return JS_TRUE in this case
* and leave *@vp unchanged. Do the same here. * and leave *@vp unchanged. Do the same here.
* (Actually not quite the same, as we already used * (Actually not quite the same, as we already used
@ -203,7 +204,8 @@ document_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL)); assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL));
if_assert_failed return JS_FALSE; if_assert_failed return JS_FALSE;
vs = JS_GetPrivate(ctx, parent_win); /* from @window_class */ vs = JS_GetInstancePrivate(ctx, parent_win,
(JSClass *) &window_class, NULL);
doc_view = vs->doc_view; doc_view = vs->doc_view;
document = doc_view->document; document = doc_view->document;

View File

@ -57,10 +57,24 @@ static const JSClass form_class; /* defined below */
static JSBool input_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp); static JSBool input_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp);
static JSBool input_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp); static JSBool input_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp);
/* Indexes of reserved slots in instances of @input_class. */
enum {
/* The slot contains an integer used as an index to
* view_state.form_info[]. This allows ELinks to reallocate
* form_info[] without keeping track of SMJS objects that
* refer to its elements. We do not use JSCLASS_HAS_PRIVATE
* for that because SMJS expects the private data to be an
* aligned pointer. */
JSRS_INPUT_FSINDEX,
/* Number of reserved slots. */
JSRS_INPUT_COUNT
};
/* Each @input_class object must have a @form_class parent. */ /* Each @input_class object must have a @form_class parent. */
static const JSClass input_class = { static const JSClass input_class = {
"input", /* here, we unleash ourselves */ "input", /* here, we unleash ourselves */
JSCLASS_HAS_PRIVATE, /* struct form_state * */ JSCLASS_HAS_RESERVED_SLOTS(JSRS_INPUT_COUNT),
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
input_get_property, input_set_property, input_get_property, input_set_property,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
@ -130,6 +144,27 @@ static const JSFunctionSpec input_funcs[] = {
static JSString *unicode_to_jsstring(JSContext *ctx, unicode_val_T u); static JSString *unicode_to_jsstring(JSContext *ctx, unicode_val_T u);
static unicode_val_T jsval_to_accesskey(JSContext *ctx, jsval *vp); static unicode_val_T jsval_to_accesskey(JSContext *ctx, jsval *vp);
static struct form_state *
input_get_form_state(JSContext *ctx, JSObject *obj, struct view_state *vs)
{
jsval val;
int n;
JSBool ok;
ok = JS_GetReservedSlot(ctx, obj, JSRS_INPUT_FSINDEX, &val);
assert(ok);
assert(JSVAL_IS_INT(val));
if_assert_failed return NULL;
n = JSVAL_TO_INT(val);
assert(n >= 0);
assert(n < vs->form_info_len);
if_assert_failed return NULL;
return &vs->form_info[n];
}
/* @input_class.getProperty */ /* @input_class.getProperty */
static JSBool static JSBool
input_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) input_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
@ -160,10 +195,11 @@ input_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL)); assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL));
if_assert_failed return JS_FALSE; if_assert_failed return JS_FALSE;
vs = JS_GetPrivate(ctx, parent_win); /* from @window_class */ vs = JS_GetInstancePrivate(ctx, parent_win,
(JSClass *) &window_class, NULL);
doc_view = vs->doc_view; doc_view = vs->doc_view;
document = doc_view->document; document = doc_view->document;
fs = JS_GetPrivate(ctx, obj); /* from @input_class */ fs = input_get_form_state(ctx, obj, vs);
fc = find_form_control(document, fs); fc = find_form_control(document, fs);
assert(fc); assert(fc);
@ -206,6 +242,7 @@ input_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
boolean_to_jsval(ctx, vp, fc->default_state); boolean_to_jsval(ctx, vp, fc->default_state);
break; break;
case JSP_INPUT_DEFAULT_VALUE: case JSP_INPUT_DEFAULT_VALUE:
/* FIXME (bug 805): convert from the charset of the document */
string_to_jsval(ctx, vp, fc->default_value); string_to_jsval(ctx, vp, fc->default_value);
break; break;
case JSP_INPUT_DISABLED: case JSP_INPUT_DISABLED:
@ -266,8 +303,8 @@ input_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
if (fc->type == FC_SELECT) int_to_jsval(ctx, vp, fs->state); if (fc->type == FC_SELECT) int_to_jsval(ctx, vp, fs->state);
break; break;
default: default:
/* Unrecognized property ID; someone is using the /* Unrecognized integer property ID; someone is using
* object as an array. SMJS builtin classes (e.g. * the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return JS_TRUE in this case * js_RegExpClass) just return JS_TRUE in this case
* and leave *@vp unchanged. Do the same here. * and leave *@vp unchanged. Do the same here.
* (Actually not quite the same, as we already used * (Actually not quite the same, as we already used
@ -309,10 +346,11 @@ input_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL)); assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL));
if_assert_failed return JS_FALSE; if_assert_failed return JS_FALSE;
vs = JS_GetPrivate(ctx, parent_win); /* from @window_class */ vs = JS_GetInstancePrivate(ctx, parent_win,
(JSClass *) &window_class, NULL);
doc_view = vs->doc_view; doc_view = vs->doc_view;
document = doc_view->document; document = doc_view->document;
fs = JS_GetPrivate(ctx, obj); /* from @input_class */ fs = input_get_form_state(ctx, obj, vs);
fc = find_form_control(document, fs); fc = find_form_control(document, fs);
assert(fc); assert(fc);
@ -348,7 +386,8 @@ input_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
: FORM_MODE_NORMAL); : FORM_MODE_NORMAL);
break; break;
case JSP_INPUT_MAX_LENGTH: case JSP_INPUT_MAX_LENGTH:
fc->maxlength = atol(jsval_to_string(ctx, vp)); if (!JS_ValueToInt32(ctx, *vp, &fc->maxlength))
return JS_FALSE;
break; break;
case JSP_INPUT_NAME: case JSP_INPUT_NAME:
mem_free_set(&fc->name, stracpy(jsval_to_string(ctx, vp))); mem_free_set(&fc->name, stracpy(jsval_to_string(ctx, vp)));
@ -373,7 +412,10 @@ input_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
break; break;
case JSP_INPUT_SELECTED_INDEX: case JSP_INPUT_SELECTED_INDEX:
if (fc->type == FC_SELECT) { if (fc->type == FC_SELECT) {
int item = atoi(jsval_to_string(ctx, vp)); int item;
if (!JS_ValueToInt32(ctx, *vp, &item))
return JS_FALSE;
if (item >= 0 && item < fc->nvalues) { if (item >= 0 && item < fc->nvalues) {
fs->state = item; fs->state = item;
@ -383,8 +425,8 @@ input_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
break; break;
default: default:
/* Unrecognized property ID; someone is using the /* Unrecognized integer property ID; someone is using
* object as an array. SMJS builtin classes (e.g. * the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return JS_TRUE in this case. * js_RegExpClass) just return JS_TRUE in this case.
* Do the same here. */ * Do the same here. */
return JS_TRUE; return JS_TRUE;
@ -428,11 +470,12 @@ input_click(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL)); assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL));
if_assert_failed return JS_FALSE; if_assert_failed return JS_FALSE;
vs = JS_GetPrivate(ctx, parent_win); /* from @window_class */ vs = JS_GetInstancePrivate(ctx, parent_win,
(JSClass *) &window_class, NULL);
doc_view = vs->doc_view; doc_view = vs->doc_view;
document = doc_view->document; document = doc_view->document;
ses = doc_view->session; ses = doc_view->session;
fs = JS_GetPrivate(ctx, obj); /* from @input_class */ fs = input_get_form_state(ctx, obj, vs);
assert(fs); assert(fs);
fc = find_form_control(document, fs); fc = find_form_control(document, fs);
@ -480,11 +523,12 @@ input_focus(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL)); assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL));
if_assert_failed return JS_FALSE; if_assert_failed return JS_FALSE;
vs = JS_GetPrivate(ctx, parent_win); /* from @window_class */ vs = JS_GetInstancePrivate(ctx, parent_win,
(JSClass *) &window_class, NULL);
doc_view = vs->doc_view; doc_view = vs->doc_view;
document = doc_view->document; document = doc_view->document;
ses = doc_view->session; ses = doc_view->session;
fs = JS_GetPrivate(ctx, obj); /* from @input_class */ fs = input_get_form_state(ctx, obj, vs);
assert(fs); assert(fs);
fc = find_form_control(document, fs); fc = find_form_control(document, fs);
@ -511,7 +555,7 @@ input_select(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval
} }
static JSObject * static JSObject *
get_input_object(JSContext *ctx, JSObject *jsform, struct form_state *fs) get_input_object(JSContext *ctx, JSObject *jsform, long number)
{ {
#if 0 #if 0
if (fs->ecmascript_obj) if (fs->ecmascript_obj)
@ -524,14 +568,13 @@ get_input_object(JSContext *ctx, JSObject *jsform, struct form_state *fs)
JS_DefineProperties(ctx, jsinput, (JSPropertySpec *) input_props); JS_DefineProperties(ctx, jsinput, (JSPropertySpec *) input_props);
JS_DefineFunctions(ctx, jsinput, (JSFunctionSpec *) input_funcs); JS_DefineFunctions(ctx, jsinput, (JSFunctionSpec *) input_funcs);
JS_SetPrivate(ctx, jsinput, fs); /* to @input_class */ JS_SetReservedSlot(ctx, jsinput, JSRS_INPUT_FSINDEX, INT_TO_JSVAL(number));
fs->ecmascript_obj = jsinput; return jsinput;;
return fs->ecmascript_obj;
} }
static JSObject * static JSObject *
get_form_control_object(JSContext *ctx, JSObject *jsform, enum form_type type, struct form_state *fs) get_form_control_object(JSContext *ctx, JSObject *jsform, enum form_type type, int number)
{ {
switch (type) { switch (type) {
case FC_TEXT: case FC_TEXT:
@ -545,7 +588,7 @@ get_form_control_object(JSContext *ctx, JSObject *jsform, enum form_type type, s
case FC_BUTTON: case FC_BUTTON:
case FC_HIDDEN: case FC_HIDDEN:
case FC_SELECT: case FC_SELECT:
return get_input_object(ctx, jsform, fs); return get_input_object(ctx, jsform, (long)number);
case FC_TEXTAREA: case FC_TEXTAREA:
/* TODO */ /* TODO */
@ -619,10 +662,12 @@ form_elements_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL)); assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL));
if_assert_failed return JS_FALSE; if_assert_failed return JS_FALSE;
vs = JS_GetPrivate(ctx, parent_win); /* from @window_class */ vs = JS_GetInstancePrivate(ctx, parent_win,
(JSClass *) &window_class, NULL);
doc_view = vs->doc_view; doc_view = vs->doc_view;
document = doc_view->document; document = doc_view->document;
form_view = JS_GetPrivate(ctx, parent_form); /* from @form_class */ form_view = JS_GetInstancePrivate(ctx, parent_form,
(JSClass *) &form_class, NULL);
form = find_form_by_form_view(document, form_view); form = find_form_by_form_view(document, form_view);
if (JSVAL_IS_STRING(id)) { if (JSVAL_IS_STRING(id)) {
@ -675,26 +720,31 @@ form_elements_item(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval
assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL)); assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL));
if_assert_failed return JS_FALSE; if_assert_failed return JS_FALSE;
vs = JS_GetPrivate(ctx, parent_win); /* from @window_class */ vs = JS_GetInstancePrivate(ctx, parent_win,
(JSClass *) &window_class, NULL);
doc_view = vs->doc_view; doc_view = vs->doc_view;
document = doc_view->document; document = doc_view->document;
form_view = JS_GetPrivate(ctx, parent_form); /* from @form_class */ form_view = JS_GetInstancePrivate(ctx, parent_form,
(JSClass *) &form_class, NULL);
form = find_form_by_form_view(document, form_view); form = find_form_by_form_view(document, form_view);
if (argc != 1) if (argc != 1)
return JS_TRUE; return JS_TRUE;
index = atol(jsval_to_string(ctx, &argv[0])); if (!JS_ValueToInt32(ctx, argv[0], &index))
return JS_FALSE;
undef_to_jsval(ctx, rval); undef_to_jsval(ctx, rval);
foreach (fc, form->items) { foreach (fc, form->items) {
counter++; counter++;
if (counter == index) { if (counter == index) {
JSObject *fcobj = get_form_control_object(ctx, parent_form, fc->type, find_form_state(doc_view, fc)); struct form_state *fs = find_form_state(doc_view, fc);
if (fcobj) { if (fs) {
object_to_jsval(ctx, rval, fcobj); JSObject *fcobj = get_form_control_object(ctx, parent_form, fc->type, fc->g_ctrl_num);
if (fcobj)
object_to_jsval(ctx, rval, fcobj);
} }
break; break;
} }
@ -729,10 +779,12 @@ form_elements_namedItem(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv,
assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL)); assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL));
if_assert_failed return JS_FALSE; if_assert_failed return JS_FALSE;
vs = JS_GetPrivate(ctx, parent_win); /* from @window_class */ vs = JS_GetInstancePrivate(ctx, parent_win,
(JSClass *) &window_class, NULL);
doc_view = vs->doc_view; doc_view = vs->doc_view;
document = doc_view->document; document = doc_view->document;
form_view = JS_GetPrivate(ctx, parent_form); /* from @form_class */ form_view = JS_GetInstancePrivate(ctx, parent_form,
(JSClass *) &form_class, NULL);
form = find_form_by_form_view(document, form_view); form = find_form_by_form_view(document, form_view);
if (argc != 1) if (argc != 1)
@ -746,10 +798,13 @@ form_elements_namedItem(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv,
foreach (fc, form->items) { foreach (fc, form->items) {
if ((fc->id && !strcasecmp(string, fc->id)) || (fc->name && !strcasecmp(string, fc->name))) { if ((fc->id && !strcasecmp(string, fc->id)) || (fc->name && !strcasecmp(string, fc->name))) {
JSObject *fcobj = get_form_control_object(ctx, parent_form, fc->type, find_form_state(doc_view, fc)); struct form_state *fs = find_form_state(doc_view, fc);
if (fcobj) { if (fs) {
object_to_jsval(ctx, rval, fcobj); JSObject *fcobj = get_form_control_object(ctx, parent_form, fc->type, fc->g_ctrl_num);
if (fcobj)
object_to_jsval(ctx, rval, fcobj);
} }
break; break;
} }
@ -830,9 +885,10 @@ form_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL)); assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL));
if_assert_failed return JS_FALSE; if_assert_failed return JS_FALSE;
vs = JS_GetPrivate(ctx, parent_win); /* from @window_class */ vs = JS_GetInstancePrivate(ctx, parent_win,
(JSClass *) &window_class, NULL);
doc_view = vs->doc_view; doc_view = vs->doc_view;
fv = JS_GetPrivate(ctx, obj); /* from @form_class */ fv = JS_GetInstancePrivate(ctx, obj, (JSClass *) &form_class, NULL);
form = find_form_by_form_view(doc_view->document, fv); form = find_form_by_form_view(doc_view->document, fv);
assert(form); assert(form);
@ -844,15 +900,17 @@ form_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
string = jsval_to_string(ctx, &id); string = jsval_to_string(ctx, &id);
foreach (fc, form->items) { foreach (fc, form->items) {
JSObject *fcobj = NULL; JSObject *fcobj = NULL;
struct form_state *fs;
if ((!fc->id || strcasecmp(string, fc->id)) && (!fc->name || strcasecmp(string, fc->name))) if ((!fc->id || strcasecmp(string, fc->id)) && (!fc->name || strcasecmp(string, fc->name)))
continue; continue;
fcobj = get_form_control_object(ctx, obj, fc->type, find_form_state(doc_view, fc)); undef_to_jsval(ctx, vp);
if (fcobj) { fs = find_form_state(doc_view, fc);
object_to_jsval(ctx, vp, fcobj); if (fs) {
} else { fcobj = get_form_control_object(ctx, obj, fc->type, fc->g_ctrl_num);
undef_to_jsval(ctx, vp); if (fcobj)
object_to_jsval(ctx, vp, fcobj);
} }
break; break;
} }
@ -924,8 +982,8 @@ form_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
break; break;
default: default:
/* Unrecognized property ID; someone is using the /* Unrecognized integer property ID; someone is using
* object as an array. SMJS builtin classes (e.g. * the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return JS_TRUE in this case * js_RegExpClass) just return JS_TRUE in this case
* and leave *@vp unchanged. Do the same here. * and leave *@vp unchanged. Do the same here.
* (Actually not quite the same, as we already used * (Actually not quite the same, as we already used
@ -960,9 +1018,10 @@ form_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL)); assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL));
if_assert_failed return JS_FALSE; if_assert_failed return JS_FALSE;
vs = JS_GetPrivate(ctx, parent_win); /* from @window_class */ vs = JS_GetInstancePrivate(ctx, parent_win,
(JSClass *) &window_class, NULL);
doc_view = vs->doc_view; doc_view = vs->doc_view;
fv = JS_GetPrivate(ctx, obj); /* from @form_class */ fv = JS_GetInstancePrivate(ctx, obj, (JSClass *) &form_class, NULL);
form = find_form_by_form_view(doc_view->document, fv); form = find_form_by_form_view(doc_view->document, fv);
assert(form); assert(form);
@ -1010,8 +1069,8 @@ form_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
break; break;
default: default:
/* Unrecognized property ID; someone is using the /* Unrecognized integer property ID; someone is using
* object as an array. SMJS builtin classes (e.g. * the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return JS_TRUE in this case. * js_RegExpClass) just return JS_TRUE in this case.
* Do the same here. */ * Do the same here. */
break; break;
@ -1039,9 +1098,10 @@ form_reset(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL)); assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL));
if_assert_failed return JS_FALSE; if_assert_failed return JS_FALSE;
vs = JS_GetPrivate(ctx, parent_win); /* from @window_class */ vs = JS_GetInstancePrivate(ctx, parent_win,
(JSClass *) &window_class, NULL);
doc_view = vs->doc_view; doc_view = vs->doc_view;
fv = JS_GetPrivate(ctx, obj); /* from @form_class */ fv = JS_GetInstancePrivate(ctx, obj, (JSClass *) &form_class, argv);
form = find_form_by_form_view(doc_view->document, fv); form = find_form_by_form_view(doc_view->document, fv);
assert(form); assert(form);
@ -1074,10 +1134,11 @@ form_submit(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL)); assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL));
if_assert_failed return JS_FALSE; if_assert_failed return JS_FALSE;
vs = JS_GetPrivate(ctx, parent_win); /* from @window_class */ vs = JS_GetInstancePrivate(ctx, parent_win,
(JSClass *) &window_class, NULL);
doc_view = vs->doc_view; doc_view = vs->doc_view;
ses = doc_view->session; ses = doc_view->session;
fv = JS_GetPrivate(ctx, obj); /* from @form_class */ fv = JS_GetInstancePrivate(ctx, obj, (JSClass *) &form_class, argv);
form = find_form_by_form_view(doc_view->document, fv); form = find_form_by_form_view(doc_view->document, fv);
assert(form); assert(form);
@ -1138,6 +1199,29 @@ const JSPropertySpec forms_props[] = {
{ NULL } { NULL }
}; };
/* Find the form whose name is @name, which should normally be a
* string (but might not be). If found, set *rval = the DOM
* object. If not found, leave *rval unchanged. */
static void
find_form_by_name(JSContext *ctx, JSObject *jsdoc,
struct document_view *doc_view,
jsval name, jsval *rval)
{
unsigned char *string = jsval_to_string(ctx, &name);
struct form *form;
if (!*string)
return;
foreach (form, doc_view->document->forms) {
if (form->name && !strcasecmp(string, form->name)) {
object_to_jsval(ctx, rval, get_form_object(ctx, jsdoc,
find_form_view(doc_view, form)));
break;
}
}
}
/* @forms_class.getProperty */ /* @forms_class.getProperty */
static JSBool static JSBool
forms_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) forms_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
@ -1160,12 +1244,19 @@ forms_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL)); assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL));
if_assert_failed return JS_FALSE; if_assert_failed return JS_FALSE;
vs = JS_GetPrivate(ctx, parent_win); /* from @window_class */ vs = JS_GetInstancePrivate(ctx, parent_win,
(JSClass *) &window_class, NULL);
doc_view = vs->doc_view; doc_view = vs->doc_view;
document = doc_view->document; document = doc_view->document;
if (JSVAL_IS_STRING(id)) { if (JSVAL_IS_STRING(id)) {
forms_namedItem(ctx, obj, 1, &id, vp); /* When SMJS evaluates forms.namedItem("foo"), it first
* calls forms_get_property with id = JSString "namedItem"
* and *vp = JSObject JSFunction forms_namedItem.
* If we don't find a form whose name is id,
* we must leave *vp unchanged here, to avoid
* "TypeError: forms.namedItem is not a function". */
find_form_by_name(ctx, parent_doc, doc_view, id, vp);
return JS_TRUE; return JS_TRUE;
} }
@ -1204,13 +1295,14 @@ forms_item(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL)); assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL));
if_assert_failed return JS_FALSE; if_assert_failed return JS_FALSE;
vs = JS_GetPrivate(ctx, parent_win); /* from @window_class */ vs = JS_GetInstancePrivate(ctx, parent_win,
(JSClass *) &window_class, NULL);
if (argc != 1) if (argc != 1)
return JS_TRUE; return JS_TRUE;
index = atol(jsval_to_string(ctx, &argv[0])); if (!JS_ValueToInt32(ctx, argv[0], &index))
return JS_FALSE;
undef_to_jsval(ctx, rval); undef_to_jsval(ctx, rval);
foreach (fv, vs->forms) { foreach (fv, vs->forms) {
@ -1232,9 +1324,6 @@ forms_namedItem(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *r
JSObject *parent_win; /* instance of @window_class */ JSObject *parent_win; /* instance of @window_class */
struct view_state *vs; struct view_state *vs;
struct document_view *doc_view; struct document_view *doc_view;
struct document *document;
struct form *form;
unsigned char *string;
if (!JS_InstanceOf(ctx, obj, (JSClass *) &forms_class, argv)) return JS_FALSE; if (!JS_InstanceOf(ctx, obj, (JSClass *) &forms_class, argv)) return JS_FALSE;
parent_doc = JS_GetParent(ctx, obj); parent_doc = JS_GetParent(ctx, obj);
@ -1244,27 +1333,15 @@ forms_namedItem(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *r
assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL)); assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL));
if_assert_failed return JS_FALSE; if_assert_failed return JS_FALSE;
vs = JS_GetPrivate(ctx, parent_win); /* from @window_class */ vs = JS_GetInstancePrivate(ctx, parent_win,
(JSClass *) &window_class, NULL);
doc_view = vs->doc_view; doc_view = vs->doc_view;
document = doc_view->document;
if (argc != 1) if (argc != 1)
return JS_TRUE; return JS_TRUE;
undef_to_jsval(ctx, rval); undef_to_jsval(ctx, rval);
find_form_by_name(ctx, parent_doc, doc_view, argv[0], rval);
string = jsval_to_string(ctx, &argv[0]);
if (!*string)
return JS_TRUE;
foreach (form, document->forms) {
if (form->name && !strcasecmp(string, form->name)) {
object_to_jsval(ctx, rval, get_form_object(ctx, parent_doc,
find_form_view(doc_view, form)));
break;
}
}
return JS_TRUE; return JS_TRUE;
} }

View File

@ -164,7 +164,8 @@ location_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL)); assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL));
if_assert_failed return JS_FALSE; if_assert_failed return JS_FALSE;
vs = JS_GetPrivate(ctx, parent_win); /* from @window_class */ vs = JS_GetInstancePrivate(ctx, parent_win,
(JSClass *) &window_class, NULL);
if (!JSVAL_IS_INT(id)) if (!JSVAL_IS_INT(id))
return JS_TRUE; return JS_TRUE;
@ -176,8 +177,8 @@ location_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
astring_to_jsval(ctx, vp, get_uri_string(vs->uri, URI_ORIGINAL)); astring_to_jsval(ctx, vp, get_uri_string(vs->uri, URI_ORIGINAL));
break; break;
default: default:
/* Unrecognized property ID; someone is using the /* Unrecognized integer property ID; someone is using
* object as an array. SMJS builtin classes (e.g. * the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return JS_TRUE in this case * js_RegExpClass) just return JS_TRUE in this case
* and leave *@vp unchanged. Do the same here. * and leave *@vp unchanged. Do the same here.
* (Actually not quite the same, as we already used * (Actually not quite the same, as we already used
@ -205,7 +206,8 @@ location_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL)); assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL));
if_assert_failed return JS_FALSE; if_assert_failed return JS_FALSE;
vs = JS_GetPrivate(ctx, parent_win); /* from @window_class */ vs = JS_GetInstancePrivate(ctx, parent_win,
(JSClass *) &window_class, NULL);
doc_view = vs->doc_view; doc_view = vs->doc_view;
if (!JSVAL_IS_INT(id)) if (!JSVAL_IS_INT(id))

View File

@ -138,8 +138,8 @@ navigator_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
} }
break; break;
default: default:
/* Unrecognized property ID; someone is using the /* Unrecognized integer property ID; someone is using
* object as an array. SMJS builtin classes (e.g. * the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return JS_TRUE in this case * js_RegExpClass) just return JS_TRUE in this case
* and leave *@vp unchanged. Do the same here. * and leave *@vp unchanged. Do the same here.
* (Actually not quite the same, as we already used * (Actually not quite the same, as we already used

View File

@ -98,7 +98,8 @@ unibar_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL)); assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL));
if_assert_failed return JS_FALSE; if_assert_failed return JS_FALSE;
vs = JS_GetPrivate(ctx, parent_win); /* from @window_class */ vs = JS_GetInstancePrivate(ctx, parent_win,
(JSClass *) &window_class, NULL);
doc_view = vs->doc_view; doc_view = vs->doc_view;
status = &doc_view->session->status; status = &doc_view->session->status;
bar = JS_GetPrivate(ctx, obj); /* from @menubar_class or @statusbar_class */ bar = JS_GetPrivate(ctx, obj); /* from @menubar_class or @statusbar_class */
@ -126,8 +127,8 @@ unibar_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
#undef unibar_fetch #undef unibar_fetch
break; break;
default: default:
/* Unrecognized property ID; someone is using the /* Unrecognized integer property ID; someone is using
* object as an array. SMJS builtin classes (e.g. * the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return JS_TRUE in this case * js_RegExpClass) just return JS_TRUE in this case
* and leave *@vp unchanged. Do the same here. */ * and leave *@vp unchanged. Do the same here. */
break; break;
@ -156,7 +157,8 @@ unibar_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL)); assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL));
if_assert_failed return JS_FALSE; if_assert_failed return JS_FALSE;
vs = JS_GetPrivate(ctx, parent_win); /* from @window_class */ vs = JS_GetInstancePrivate(ctx, parent_win,
(JSClass *) &window_class, NULL);
doc_view = vs->doc_view; doc_view = vs->doc_view;
status = &doc_view->session->status; status = &doc_view->session->status;
bar = JS_GetPrivate(ctx, obj); /* from @menubar_class or @statusbar_class */ bar = JS_GetPrivate(ctx, obj); /* from @menubar_class or @statusbar_class */
@ -179,8 +181,8 @@ unibar_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
register_bottom_half(update_status, NULL); register_bottom_half(update_status, NULL);
break; break;
default: default:
/* Unrecognized property ID; someone is using the /* Unrecognized integer property ID; someone is using
* object as an array. SMJS builtin classes (e.g. * the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return JS_TRUE in this case. * js_RegExpClass) just return JS_TRUE in this case.
* Do the same here. */ * Do the same here. */
return JS_TRUE; return JS_TRUE;

View File

@ -132,7 +132,7 @@ window_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
if (!JS_InstanceOf(ctx, obj, (JSClass *) &window_class, NULL)) if (!JS_InstanceOf(ctx, obj, (JSClass *) &window_class, NULL))
return JS_FALSE; return JS_FALSE;
vs = JS_GetPrivate(ctx, obj); /* from @window_class */ vs = JS_GetInstancePrivate(ctx, obj, (JSClass *) &window_class, NULL);
/* No need for special window.location measurements - when /* No need for special window.location measurements - when
* location is then evaluated in string context, toString() * location is then evaluated in string context, toString()
@ -238,8 +238,8 @@ found_parent:
break; break;
} }
default: default:
/* Unrecognized property ID; someone is using the /* Unrecognized integer property ID; someone is using
* object as an array. SMJS builtin classes (e.g. * the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return JS_TRUE in this case * js_RegExpClass) just return JS_TRUE in this case
* and leave *@vp unchanged. Do the same here. * and leave *@vp unchanged. Do the same here.
* (Actually not quite the same, as we already used * (Actually not quite the same, as we already used
@ -264,7 +264,7 @@ window_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
if (!JS_InstanceOf(ctx, obj, (JSClass *) &window_class, NULL)) if (!JS_InstanceOf(ctx, obj, (JSClass *) &window_class, NULL))
return JS_FALSE; return JS_FALSE;
vs = JS_GetPrivate(ctx, obj); /* from @window_class */ vs = JS_GetInstancePrivate(ctx, obj, (JSClass *) &window_class, NULL);
if (JSVAL_IS_STRING(id)) { if (JSVAL_IS_STRING(id)) {
if (!strcmp(jsval_to_string(ctx, &id), "location")) { if (!strcmp(jsval_to_string(ctx, &id), "location")) {
@ -287,8 +287,8 @@ window_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
print_screen_status(vs->doc_view->session); print_screen_status(vs->doc_view->session);
return JS_TRUE; return JS_TRUE;
default: default:
/* Unrecognized property ID; someone is using the /* Unrecognized integer property ID; someone is using
* object as an array. SMJS builtin classes (e.g. * the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return JS_TRUE in this case. * js_RegExpClass) just return JS_TRUE in this case.
* Do the same here. */ * Do the same here. */
return JS_TRUE; return JS_TRUE;
@ -318,7 +318,7 @@ window_alert(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval
if (!JS_InstanceOf(ctx, obj, (JSClass *) &window_class, argv)) return JS_FALSE; if (!JS_InstanceOf(ctx, obj, (JSClass *) &window_class, argv)) return JS_FALSE;
vs = JS_GetPrivate(ctx, obj); /* from @window_class */ vs = JS_GetInstancePrivate(ctx, obj, (JSClass *) &window_class, argv);
if (argc != 1) if (argc != 1)
return JS_TRUE; return JS_TRUE;
@ -349,7 +349,7 @@ window_open(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
if (!JS_InstanceOf(ctx, obj, (JSClass *) &window_class, argv)) return JS_FALSE; if (!JS_InstanceOf(ctx, obj, (JSClass *) &window_class, argv)) return JS_FALSE;
vs = JS_GetPrivate(ctx, obj); /* from @window_class */ vs = JS_GetInstancePrivate(ctx, obj, (JSClass *) &window_class, argv);
doc_view = vs->doc_view; doc_view = vs->doc_view;
ses = doc_view->session; ses = doc_view->session;

View File

@ -185,11 +185,11 @@ u2cp_(unicode_val_T u, int to, enum nbsp_mode nbsp_mode)
/* To mark non breaking spaces in non-UTF-8 strings, we use a /* To mark non breaking spaces in non-UTF-8 strings, we use a
* special char NBSP_CHAR. */ * special char NBSP_CHAR. */
if (u == 0xa0) { if (u == UCS_NO_BREAK_SPACE) {
if (nbsp_mode == NBSP_MODE_HACK) return NBSP_CHAR_STRING; if (nbsp_mode == NBSP_MODE_HACK) return NBSP_CHAR_STRING;
else /* NBSP_MODE_ASCII */ return " "; else /* NBSP_MODE_ASCII */ return " ";
} }
if (u == 0xad) return ""; if (u == UCS_SOFT_HYPHEN) return "";
if (u < 0xa0) { if (u < 0xa0) {
unicode_val_T strange = strange_chars[u - 0x80]; unicode_val_T strange = strange_chars[u - 0x80];
@ -909,6 +909,10 @@ get_translation_table(int from, int to)
if (is_cp_ptr_utf8(&codepages[from])) { if (is_cp_ptr_utf8(&codepages[from])) {
int i; int i;
/* Map U+00A0 and U+00AD the same way as u2cp() would. */
add_utf8(table, UCS_NO_BREAK_SPACE, strings[NBSP_CHAR]);
add_utf8(table, UCS_SOFT_HYPHEN, "");
for (i = 0x80; i <= 0xFF; i++) for (i = 0x80; i <= 0xFF; i++)
if (codepages[to].highhalf[i - 0x80] != 0xFFFF) if (codepages[to].highhalf[i - 0x80] != 0xFFFF)
add_utf8(table, add_utf8(table,
@ -1125,7 +1129,17 @@ skip:
end: end:
/* Take care of potential buffer overflow. */ /* Take care of potential buffer overflow. */
if (strlen < sizeof(entity_cache[slen][0].str)) { if (strlen < sizeof(entity_cache[slen][0].str)) {
struct entity_cache *ece = &entity_cache[slen][nb_entity_cache[slen]]; struct entity_cache *ece;
/* Sort entries by hit order. */
if (nb_entity_cache[slen] > 1)
qsort(&entity_cache[slen][0], nb_entity_cache[slen],
sizeof(entity_cache[slen][0]), (void *) hits_cmp);
/* Increment number of cache entries if possible.
* Else, just replace the least used entry. */
if (nb_entity_cache[slen] < ENTITY_CACHE_SIZE) nb_entity_cache[slen]++;
ece = &entity_cache[slen][nb_entity_cache[slen] - 1];
/* Copy new entry to cache. */ /* Copy new entry to cache. */
ece->hits = 1; ece->hits = 1;
@ -1135,21 +1149,11 @@ end:
memcpy(ece->str, str, strlen); memcpy(ece->str, str, strlen);
ece->str[strlen] = '\0'; ece->str[strlen] = '\0';
/* Increment number of cache entries if possible. */
if (nb_entity_cache[slen] < ENTITY_CACHE_SIZE) nb_entity_cache[slen]++;
#ifdef DEBUG_ENTITY_CACHE #ifdef DEBUG_ENTITY_CACHE
fprintf(stderr, "Added in [%u]: l=%d st='%s'\n", slen, fprintf(stderr, "Added in [%u]: l=%d st='%s'\n", slen,
entity_cache[slen][0].strlen, entity_cache[slen][0].str); entity_cache[slen][0].strlen, entity_cache[slen][0].str);
#endif
/* Sort entries by hit order. */
if (nb_entity_cache[slen] > 1)
qsort(&entity_cache[slen][0], nb_entity_cache[slen],
sizeof(entity_cache[slen][0]), (void *) hits_cmp);
#ifdef DEBUG_ENTITY_CACHE
{ {
unsigned int i; unsigned int i;
@ -1160,7 +1164,7 @@ end:
entity_cache[slen][i].str); entity_cache[slen][i].str);
fprintf(stderr, "-----------------\n"); fprintf(stderr, "-----------------\n");
} }
#endif #endif /* DEBUG_ENTITY_CACHE */
} }
return result; return result;
} }

View File

@ -10,6 +10,9 @@ typedef uint32_t unicode_val_T;
/* U+00A0 NO-BREAK SPACE. */ /* U+00A0 NO-BREAK SPACE. */
#define UCS_NO_BREAK_SPACE ((unicode_val_T) 0x00A0) #define UCS_NO_BREAK_SPACE ((unicode_val_T) 0x00A0)
/* U+00AD SOFT HYPHEN. */
#define UCS_SOFT_HYPHEN ((unicode_val_T) 0x00AD)
/* U+FFFD REPLACEMENT CHARACTER. Used when no Unicode mapping is /* U+FFFD REPLACEMENT CHARACTER. Used when no Unicode mapping is
* known for a byte in a codepage, or when invalid UTF-8 is received * known for a byte in a codepage, or when invalid UTF-8 is received
* from a terminal. After generating the character, ELinks then * from a terminal. After generating the character, ELinks then

View File

@ -15,6 +15,8 @@
along with this program; if not, write to the Free Software Foundation, along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Modified on 2007-07-02 by Kalle Olavi Niemitalo. */
/* Tell glibc's <string.h> to provide a prototype for mempcpy(). /* Tell glibc's <string.h> to provide a prototype for mempcpy().
This must come before <config.h> because <config.h> may include This must come before <config.h> because <config.h> may include
<features.h>, and once <features.h> has been included, it's too late. */ <features.h>, and once <features.h> has been included, it's too late. */
@ -41,10 +43,15 @@
#if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP)
#include <sys/mman.h> #include <sys/mman.h>
#undef HAVE_MMAP /* Use a custom macro instead of overloading HAVE_MMAP, because the
#define HAVE_MMAP 1 * following #include directives may cause "config.h" to be included
* again (bug 960). It might be good to remove #include "config.h"
* directives from header files and keep them in *.c files only, but
* that seems too risky for the stable elinks-0.11 branch. */
#undef LOADMSGCAT_USE_MMAP
#define LOADMSGCAT_USE_MMAP 1
#else #else
#undef HAVE_MMAP #undef LOADMSGCAT_USE_MMAP
#endif #endif
#include "elinks.h" #include "elinks.h"
@ -212,6 +219,11 @@ add_filename_to_string(struct string *str, struct loaded_l10nfile *domain_file)
unsigned char *slash = strrchr(program.path, '/'); unsigned char *slash = strrchr(program.path, '/');
size_t dirnamelen = (slash ? slash - program.path + 1 : 0); size_t dirnamelen = (slash ? slash - program.path + 1 : 0);
/* Check if elinks is being run from the source tree. */
if (dirnamelen < 4
|| strncmp(program.path + dirnamelen - 4, "src", 3))
return NULL;
if ((dirnamelen && !add_bytes_to_string(str, program.path, dirnamelen)) if ((dirnamelen && !add_bytes_to_string(str, program.path, dirnamelen))
|| !add_to_string(str, "../po/") || !add_to_string(str, "../po/")
|| !add_bytes_to_string(str, || !add_bytes_to_string(str,
@ -280,7 +292,7 @@ source_success:
close(fd); close(fd);
return; return;
} }
#ifdef HAVE_MMAP #ifdef LOADMSGCAT_USE_MMAP
/* Now we are ready to load the file. If mmap() is available we try /* Now we are ready to load the file. If mmap() is available we try
this first. If not available or it failed we try to load it. */ this first. If not available or it failed we try to load it. */
data = (struct mo_file_header *) mmap(NULL, size, PROT_READ, data = (struct mo_file_header *) mmap(NULL, size, PROT_READ,
@ -323,7 +335,7 @@ source_success:
catalog file. */ catalog file. */
if (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED) { if (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED) {
/* The magic number is wrong: not a message catalog file. */ /* The magic number is wrong: not a message catalog file. */
#ifdef HAVE_MMAP #ifdef LOADMSGCAT_USE_MMAP
if (use_mmap) if (use_mmap)
munmap((void *) data, size); munmap((void *) data, size);
else else
@ -360,7 +372,7 @@ source_success:
break; break;
default: default:
/* This is an invalid revision. */ /* This is an invalid revision. */
#ifdef HAVE_MMAP #ifdef LOADMSGCAT_USE_MMAP
if (use_mmap) if (use_mmap)
munmap((void *) data, size); munmap((void *) data, size);
else else

View File

@ -16,17 +16,8 @@ mailcap-cache.o: mailcap.c
TESTDEPS = \ TESTDEPS = \
common.o \ common.o \
$(top_builddir)/src/osdep/osdep.o \ $(top_builddir)/src/osdep/osdep.o
$(top_builddir)/src/osdep/stub.o \
$(top_builddir)/src/util/conv.o \
$(top_builddir)/src/util/error.o \
$(top_builddir)/src/util/file.o \
$(top_builddir)/src/util/hash.o \
$(top_builddir)/src/util/memory.o \
$(top_builddir)/src/util/string.o \
$(top_builddir)/src/util/time.o
TESTDEPS-$(CONFIG_NLS) += $(top_builddir)/src/intl/gettext/lib.o TESTDEPS-$(CONFIG_NLS) += $(top_builddir)/src/intl/gettext/lib.o
TESTDEPS-$(CONFIG_DEBUG) += $(top_builddir)/src/util/memdebug.o
include $(top_srcdir)/Makefile.lib include $(top_srcdir)/Makefile.lib

View File

@ -1078,6 +1078,10 @@ move_download(struct download *old, struct download *new,
conn->pri[new->pri]++; conn->pri[new->pri]++;
add_to_list(conn->downloads, new); add_to_list(conn->downloads, new);
/* In principle, we need to sort_queue() only if conn->pri[new->pri]
* just changed from 0 to 1. But the risk of bugs is smaller if we
* sort every time. */
sort_queue();
cancel_download(old, 0); cancel_download(old, 0);
} }

View File

@ -67,7 +67,7 @@ struct connection {
* the struct download it got to the connection, _and_ updates its @pri * the struct download it got to the connection, _and_ updates its @pri
* array by the priority it has thus, sum of values in all fields of * array by the priority it has thus, sum of values in all fields of
* @pri is also kinda refcount of the connection. */ * @pri is also kinda refcount of the connection. */
enum connection_priority pri[PRIORITIES]; int pri[PRIORITIES];
/* Private protocol specific info. If non-NULL it is free()d when /* Private protocol specific info. If non-NULL it is free()d when
* stopping the connection. */ * stopping the connection. */

View File

@ -580,23 +580,24 @@ connect_socket(struct socket *csocket, enum connection_state state)
* will fail, as we will use it only when it will be successfully * will fail, as we will use it only when it will be successfully
* established. At least I hope that noone else will want to do * established. At least I hope that noone else will want to do
* something else ;-). --pasky */ * something else ;-). --pasky */
/* And in fact we must set it early, because of EINPROGRESS. */
#ifdef CONFIG_IPV6 #ifdef CONFIG_IPV6
if (family == AF_INET6) { if (family == AF_INET6) {
csocket->protocol_family = EL_PF_INET6;
if (connect(sock, (struct sockaddr *) &addr, if (connect(sock, (struct sockaddr *) &addr,
sizeof(struct sockaddr_in6)) == 0) { sizeof(struct sockaddr_in6)) == 0) {
/* Success */ /* Success */
csocket->protocol_family = EL_PF_INET6;
complete_connect_socket(csocket, NULL, NULL); complete_connect_socket(csocket, NULL, NULL);
return; return;
} }
} else } else
#endif #endif
{ {
csocket->protocol_family = EL_PF_INET;
if (connect(sock, (struct sockaddr *) &addr, if (connect(sock, (struct sockaddr *) &addr,
sizeof(struct sockaddr_in)) == 0) { sizeof(struct sockaddr_in)) == 0) {
/* Success */ /* Success */
csocket->protocol_family = EL_PF_INET;
complete_connect_socket(csocket, NULL, NULL); complete_connect_socket(csocket, NULL, NULL);
return; return;
} }

View File

@ -575,7 +575,7 @@ bittorrent_message_dialog(struct session *ses, void *data)
uristring = get_uri_string(message->uri, URI_PUBLIC); uristring = get_uri_string(message->uri, URI_PUBLIC);
if (uristring) { if (uristring) {
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (ses->tab->term->utf8) if (ses->tab->term->utf8_cp)
decode_uri(uristring); decode_uri(uristring);
else else
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
@ -725,7 +725,7 @@ bittorrent_query_callback(void *data, enum connection_state state,
/* Let's make the filename pretty for display & save */ /* Let's make the filename pretty for display & save */
/* TODO: The filename can be the empty string here. See bug 396. */ /* TODO: The filename can be the empty string here. See bug 396. */
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) if (term->utf8_cp)
decode_uri_string(&filename); decode_uri_string(&filename);
else else
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */

View File

@ -3,17 +3,11 @@ include $(top_builddir)/Makefile.config
OBJS = ftp.o parse.o OBJS = ftp.o parse.o
TEST_PROGS = ftp-parser TEST_PROGS = \
ftp-parser
TESTDEPS = \ TESTDEPS = \
$(top_builddir)/src/osdep/stub.o \
$(top_builddir)/src/protocol/date.o \ $(top_builddir)/src/protocol/date.o \
$(top_builddir)/src/protocol/ftp/parse.o \ $(top_builddir)/src/protocol/ftp/parse.o
$(top_builddir)/src/util/conv.o \
$(top_builddir)/src/util/error.o \
$(top_builddir)/src/util/hash.o \
$(top_builddir)/src/util/memory.o \
$(top_builddir)/src/util/string.o \
$(top_builddir)/src/util/time.o
include $(top_srcdir)/Makefile.lib include $(top_srcdir)/Makefile.lib

View File

@ -145,15 +145,6 @@ check_whether_file_exists(unsigned char *name)
return -1; return -1;
} }
static int
check_uri_file(const unsigned char *name)
{
/* Check POST_CHAR etc ... */
static const unsigned char chars[] = POST_CHAR_S "#?";
return strcspn(name, chars);
}
/* Encodes URIs without encoding stuff like fragments and query separators. */ /* Encodes URIs without encoding stuff like fragments and query separators. */
static void static void
encode_file_uri_string(struct string *string, unsigned char *uristring) encode_file_uri_string(struct string *string, unsigned char *uristring)
@ -240,7 +231,7 @@ parse_uri(struct uri *uri, unsigned char *uristring)
return URI_ERRNO_OK; return URI_ERRNO_OK;
} else if (uri->protocol == PROTOCOL_FILE) { } else if (uri->protocol == PROTOCOL_FILE) {
int datalen = check_uri_file(prefix_end); int datalen = strcspn(prefix_end, "#" POST_CHAR_S);
unsigned char *frag_or_post = prefix_end + datalen; unsigned char *frag_or_post = prefix_end + datalen;
/* Extract the fragment part. */ /* Extract the fragment part. */

View File

@ -32,7 +32,8 @@ smjs_action_fn_finalize(JSContext *ctx, JSObject *obj)
assert(JS_InstanceOf(ctx, obj, (JSClass *) &action_fn_class, NULL)); assert(JS_InstanceOf(ctx, obj, (JSClass *) &action_fn_class, NULL));
if_assert_failed return; if_assert_failed return;
hop = JS_GetPrivate(ctx, obj); /* from @action_fn_class */ hop = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &action_fn_class, NULL);
if (hop) mem_free(hop); if (hop) mem_free(hop);
} }
@ -55,7 +56,8 @@ smjs_action_fn_callback(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv,
assert(JS_InstanceOf(ctx, fn_obj, (JSClass *) &action_fn_class, NULL)); assert(JS_InstanceOf(ctx, fn_obj, (JSClass *) &action_fn_class, NULL));
if_assert_failed return JS_FALSE; if_assert_failed return JS_FALSE;
hop = JS_GetPrivate(ctx, fn_obj); /* from @action_fn_class */ hop = JS_GetInstancePrivate(ctx, fn_obj,
(JSClass *) &action_fn_class, NULL);
if (!hop) return JS_TRUE; if (!hop) return JS_TRUE;
if (argc >= 1) { if (argc >= 1) {

View File

@ -90,7 +90,8 @@ bookmark_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
if (!JS_InstanceOf(ctx, obj, (JSClass *) &bookmark_class, NULL)) if (!JS_InstanceOf(ctx, obj, (JSClass *) &bookmark_class, NULL))
return JS_FALSE; return JS_FALSE;
bookmark = JS_GetPrivate(ctx, obj); /* from @bookmark_class */ bookmark = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &bookmark_class, NULL);
if (!bookmark) return JS_FALSE; if (!bookmark) return JS_FALSE;
@ -115,8 +116,8 @@ bookmark_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
return JS_TRUE; return JS_TRUE;
default: default:
/* Unrecognized property ID; someone is using the /* Unrecognized integer property ID; someone is using
* object as an array. SMJS builtin classes (e.g. * the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return JS_TRUE in this case * js_RegExpClass) just return JS_TRUE in this case
* and leave *@vp unchanged. Do the same here. * and leave *@vp unchanged. Do the same here.
* (Actually not quite the same, as we already used * (Actually not quite the same, as we already used
@ -137,7 +138,8 @@ bookmark_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
if (!JS_InstanceOf(ctx, obj, (JSClass *) &bookmark_class, NULL)) if (!JS_InstanceOf(ctx, obj, (JSClass *) &bookmark_class, NULL))
return JS_FALSE; return JS_FALSE;
bookmark = JS_GetPrivate(ctx, obj); /* from @bookmark_class */ bookmark = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &bookmark_class, NULL);
if (!bookmark) return JS_FALSE; if (!bookmark) return JS_FALSE;
@ -162,8 +164,8 @@ bookmark_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
return JS_TRUE; return JS_TRUE;
} }
default: default:
/* Unrecognized property ID; someone is using the /* Unrecognized integer property ID; someone is using
* object as an array. SMJS builtin classes (e.g. * the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return JS_TRUE in this case. * js_RegExpClass) just return JS_TRUE in this case.
* Do the same here. */ * Do the same here. */
return JS_TRUE; return JS_TRUE;
@ -211,7 +213,8 @@ bookmark_folder_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
if (!JS_InstanceOf(ctx, obj, (JSClass *) &bookmark_folder_class, NULL)) if (!JS_InstanceOf(ctx, obj, (JSClass *) &bookmark_folder_class, NULL))
return JS_FALSE; return JS_FALSE;
folder = JS_GetPrivate(ctx, obj); /* from @bookmark_folder_class */ folder = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &bookmark_folder_class, NULL);
*vp = JSVAL_NULL; *vp = JSVAL_NULL;

View File

@ -49,7 +49,8 @@ cache_entry_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
if (!JS_InstanceOf(ctx, obj, (JSClass *) &cache_entry_class, NULL)) if (!JS_InstanceOf(ctx, obj, (JSClass *) &cache_entry_class, NULL))
return JS_FALSE; return JS_FALSE;
cached = JS_GetPrivate(ctx, obj); /* from @cache_entry_class */ cached = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &cache_entry_class, NULL);
if (!cache_entry_is_valid(cached)) return JS_FALSE; if (!cache_entry_is_valid(cached)) return JS_FALSE;
@ -90,8 +91,8 @@ cache_entry_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
return JS_TRUE; return JS_TRUE;
default: default:
/* Unrecognized property ID; someone is using the /* Unrecognized integer property ID; someone is using
* object as an array. SMJS builtin classes (e.g. * the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return JS_TRUE in this case * js_RegExpClass) just return JS_TRUE in this case
* and leave *@vp unchanged. Do the same here. * and leave *@vp unchanged. Do the same here.
* (Actually not quite the same, as we already used * (Actually not quite the same, as we already used
@ -112,7 +113,8 @@ cache_entry_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
if (!JS_InstanceOf(ctx, obj, (JSClass *) &cache_entry_class, NULL)) if (!JS_InstanceOf(ctx, obj, (JSClass *) &cache_entry_class, NULL))
return JS_FALSE; return JS_FALSE;
cached = JS_GetPrivate(ctx, obj); /* from @cache_entry_class */ cached = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &cache_entry_class, NULL);
if (!cache_entry_is_valid(cached)) return JS_FALSE; if (!cache_entry_is_valid(cached)) return JS_FALSE;
@ -147,8 +149,8 @@ cache_entry_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
return JS_TRUE; return JS_TRUE;
} }
default: default:
/* Unrecognized property ID; someone is using the /* Unrecognized integer property ID; someone is using
* object as an array. SMJS builtin classes (e.g. * the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return JS_TRUE in this case. * js_RegExpClass) just return JS_TRUE in this case.
* Do the same here. */ * Do the same here. */
return JS_TRUE; return JS_TRUE;
@ -164,7 +166,8 @@ cache_entry_finalize(JSContext *ctx, JSObject *obj)
assert(JS_InstanceOf(ctx, obj, (JSClass *) &cache_entry_class, NULL)); assert(JS_InstanceOf(ctx, obj, (JSClass *) &cache_entry_class, NULL));
if_assert_failed return; if_assert_failed return;
cached = JS_GetPrivate(ctx, obj); /* from @cache_entry_class */ cached = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &cache_entry_class, NULL);
if (!cached) return; if (!cached) return;

View File

@ -25,7 +25,9 @@ smjs_globhist_item_finalize(JSContext *ctx, JSObject *obj)
assert(JS_InstanceOf(ctx, obj, (JSClass *) &smjs_globhist_item_class, NULL)); assert(JS_InstanceOf(ctx, obj, (JSClass *) &smjs_globhist_item_class, NULL));
if_assert_failed return; if_assert_failed return;
history_item = JS_GetPrivate(ctx, obj); /* from @smjs_globhist_item_class */ history_item = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &smjs_globhist_item_class,
NULL);
if (history_item) object_unlock(history_item); if (history_item) object_unlock(history_item);
} }
@ -60,7 +62,9 @@ smjs_globhist_item_get_property(JSContext *ctx, JSObject *obj, jsval id,
if (!JS_InstanceOf(ctx, obj, (JSClass *) &smjs_globhist_item_class, NULL)) if (!JS_InstanceOf(ctx, obj, (JSClass *) &smjs_globhist_item_class, NULL))
return JS_FALSE; return JS_FALSE;
history_item = JS_GetPrivate(ctx, obj); /* from @smjs_globhist_item_class */ history_item = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &smjs_globhist_item_class,
NULL);
if (!history_item) return JS_FALSE; if (!history_item) return JS_FALSE;
@ -101,8 +105,8 @@ smjs_globhist_item_get_property(JSContext *ctx, JSObject *obj, jsval id,
return JS_TRUE; return JS_TRUE;
default: default:
/* Unrecognized property ID; someone is using the /* Unrecognized integer property ID; someone is using
* object as an array. SMJS builtin classes (e.g. * the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return JS_TRUE in this case * js_RegExpClass) just return JS_TRUE in this case
* and leave *@vp unchanged. Do the same here. * and leave *@vp unchanged. Do the same here.
* (Actually not quite the same, as we already used * (Actually not quite the same, as we already used
@ -123,7 +127,9 @@ smjs_globhist_item_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *
if (!JS_InstanceOf(ctx, obj, (JSClass *) &smjs_globhist_item_class, NULL)) if (!JS_InstanceOf(ctx, obj, (JSClass *) &smjs_globhist_item_class, NULL))
return JS_FALSE; return JS_FALSE;
history_item = JS_GetPrivate(ctx, obj); /* from @smjs_globhist_item_class */ history_item = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &smjs_globhist_item_class,
NULL);
if (!history_item) return JS_FALSE; if (!history_item) return JS_FALSE;
@ -157,8 +163,8 @@ smjs_globhist_item_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *
return JS_TRUE; return JS_TRUE;
} }
default: default:
/* Unrecognized property ID; someone is using the /* Unrecognized integer property ID; someone is using
* object as an array. SMJS builtin classes (e.g. * the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return JS_TRUE in this case. * js_RegExpClass) just return JS_TRUE in this case.
* Do the same here. */ * Do the same here. */
return JS_TRUE; return JS_TRUE;

View File

@ -29,7 +29,8 @@ keymap_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
if (!JS_InstanceOf(ctx, obj, (JSClass *) &keymap_class, NULL)) if (!JS_InstanceOf(ctx, obj, (JSClass *) &keymap_class, NULL))
return JS_FALSE; return JS_FALSE;
data = JS_GetPrivate(ctx, obj); /* from @keymap_class */ data = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &keymap_class, NULL);
keystroke_str = JS_GetStringBytes(JS_ValueToString(ctx, id)); keystroke_str = JS_GetStringBytes(JS_ValueToString(ctx, id));
if (!keystroke_str) goto ret_null; if (!keystroke_str) goto ret_null;
@ -83,7 +84,8 @@ keymap_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
if (!JS_InstanceOf(ctx, obj, (JSClass *) &keymap_class, NULL)) if (!JS_InstanceOf(ctx, obj, (JSClass *) &keymap_class, NULL))
return JS_FALSE; return JS_FALSE;
data = JS_GetPrivate(ctx, obj); /* from @keymap_class */ data = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &keymap_class, NULL);
/* Ugly fact: we need to get the string from the id to give to bind_do, /* Ugly fact: we need to get the string from the id to give to bind_do,
* which will of course then convert the string back to an id... */ * which will of course then convert the string back to an id... */
@ -155,7 +157,8 @@ keymap_finalize(JSContext *ctx, JSObject *obj)
assert(JS_InstanceOf(ctx, obj, (JSClass *) &keymap_class, NULL)); assert(JS_InstanceOf(ctx, obj, (JSClass *) &keymap_class, NULL));
if_assert_failed return; if_assert_failed return;
data = JS_GetPrivate(ctx, obj); /* from @keymap_class */ data = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &keymap_class, NULL);
mem_free(data); mem_free(data);
} }

View File

@ -49,7 +49,8 @@ view_state_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
if (!JS_InstanceOf(ctx, obj, (JSClass *) &view_state_class, NULL)) if (!JS_InstanceOf(ctx, obj, (JSClass *) &view_state_class, NULL))
return JS_FALSE; return JS_FALSE;
vs = JS_GetPrivate(ctx, obj); /* from @view_state_class */ vs = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &view_state_class, NULL);
undef_to_jsval(ctx, vp); undef_to_jsval(ctx, vp);
@ -67,8 +68,8 @@ view_state_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
return JS_TRUE; return JS_TRUE;
default: default:
/* Unrecognized property ID; someone is using the /* Unrecognized integer property ID; someone is using
* object as an array. SMJS builtin classes (e.g. * the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return JS_TRUE in this case * js_RegExpClass) just return JS_TRUE in this case
* and leave *@vp unchanged. Do the same here. * and leave *@vp unchanged. Do the same here.
* (Actually not quite the same, as we already used * (Actually not quite the same, as we already used
@ -89,7 +90,8 @@ view_state_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
if (!JS_InstanceOf(ctx, obj, (JSClass *) &view_state_class, NULL)) if (!JS_InstanceOf(ctx, obj, (JSClass *) &view_state_class, NULL))
return JS_FALSE; return JS_FALSE;
vs = JS_GetPrivate(ctx, obj); /* from @view_state_class */ vs = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &view_state_class, NULL);
if (!JSVAL_IS_INT(id)) if (!JSVAL_IS_INT(id))
return JS_FALSE; return JS_FALSE;
@ -101,8 +103,8 @@ view_state_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
return JS_TRUE; return JS_TRUE;
} }
default: default:
/* Unrecognized property ID; someone is using the /* Unrecognized integer property ID; someone is using
* object as an array. SMJS builtin classes (e.g. * the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return JS_TRUE in this case. * js_RegExpClass) just return JS_TRUE in this case.
* Do the same here. */ * Do the same here. */
return JS_TRUE; return JS_TRUE;

View File

@ -1158,7 +1158,7 @@ do_type_query(struct type_query *type_query, unsigned char *ct, struct mime_hand
/* Let's make the filename pretty for display & save */ /* Let's make the filename pretty for display & save */
/* TODO: The filename can be the empty string here. See bug 396. */ /* TODO: The filename can be the empty string here. See bug 396. */
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) if (term->utf8_cp)
decode_uri_string(&filename); decode_uri_string(&filename);
else else
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */

View File

@ -267,7 +267,7 @@ print_error_dialog(struct session *ses, enum connection_state state,
uristring = uri ? get_uri_string(uri, URI_PUBLIC) : NULL; uristring = uri ? get_uri_string(uri, URI_PUBLIC) : NULL;
if (uristring) { if (uristring) {
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (ses->tab->term->utf8) if (ses->tab->term->utf8_cp)
decode_uri(uristring); decode_uri(uristring);
else else
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */

View File

@ -13,7 +13,7 @@
#define ELINKS_HOMEPAGE "http://elinks.cz/" #define ELINKS_HOMEPAGE "http://elinks.cz/"
#define ELINKS_DOC_URL "http://elinks.cz/documentation/" #define ELINKS_DOC_URL "http://elinks.cz/documentation/"
#define ELINKS_BUGS_URL "http://bugzilla.elinks.cz/" #define ELINKS_BUGS_URL "http://bugzilla.elinks.cz/"
#define ELINKS_GITWEB_URL "http://pasky.or.cz/gitweb.cgi" #define ELINKS_GITWEB_URL "http://repo.or.cz/w/elinks.git"
#define ELINKS_SOCK_NAME "socket" #define ELINKS_SOCK_NAME "socket"
#define ELINKS_PORT 23456 #define ELINKS_PORT 23456

View File

@ -104,6 +104,9 @@ draw_char_color(struct terminal *term, int x, int y, struct color_pair *color)
set_screen_dirty(term->screen, y, y); set_screen_dirty(term->screen, y, y);
} }
/* The data parameter here is like screen_char.data: UCS-4 if the
* charset of the terminal is UTF-8 (possible only if CONFIG_UTF8 is
* defined), and a byte otherwise. */
void void
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
draw_char_data(struct terminal *term, int x, int y, unicode_val_T data) draw_char_data(struct terminal *term, int x, int y, unicode_val_T data)
@ -120,10 +123,10 @@ draw_char_data(struct terminal *term, int x, int y, unsigned char data)
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
#ifdef CONFIG_DEBUG #ifdef CONFIG_DEBUG
/* Detect attempt to draw double-width char on the last /* Detect attempt to draw double-width char on the last
* column of terminal. The unicode_to_cell(data) call * column of terminal. The unicode_to_cell(data) call is
* is in principle wrong if CONFIG_UTF8 is defined but * in principle wrong if CONFIG_UTF8 is defined but the
* UTF-8 I/O is disabled, because @data is then a byte * charset of the terminal is not UTF-8, because @data
* in the charset of the terminal; but unicode_to_cell * is then a byte in that charset; but unicode_to_cell
* returns 1 for U+0000...U+00FF so it's not a problem. */ * returns 1 for U+0000...U+00FF so it's not a problem. */
if (unicode_to_cell(data) == 2 && x + 1 > term->width) if (unicode_to_cell(data) == 2 && x + 1 > term->width)
INTERNAL("Attempt to draw double-width glyph on last column!"); INTERNAL("Attempt to draw double-width glyph on last column!");
@ -152,7 +155,7 @@ draw_line(struct terminal *term, int x, int y, int l, struct screen_char *line)
if (size == 0) return; if (size == 0) return;
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) { if (term->utf8_cp) {
struct screen_char *sc; struct screen_char *sc;
if (line[0].data == UCS_NO_CHAR && x == 0) { if (line[0].data == UCS_NO_CHAR && x == 0) {
@ -272,7 +275,7 @@ fix_dwchar_around_box(struct terminal *term, struct box *box, int border,
struct screen_char *schar; struct screen_char *schar;
int height, x, y; int height, x, y;
if (!term->utf8) if (!term->utf8_cp)
return; return;
/* 1 */ /* 1 */
@ -499,7 +502,7 @@ draw_text(struct terminal *term, int x, int y,
if (x >= term->width || y >= term->height) return; if (x >= term->width || y >= term->height) return;
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (term->utf8) { if (term->utf8_cp) {
draw_text_utf8(term, x, y, text, length, attr, color); draw_text_utf8(term, x, y, text, length, attr, color);
return; return;
} }

View File

@ -33,11 +33,11 @@ struct screen_char {
/* Contains either character value or frame data. /* Contains either character value or frame data.
* If @attr includes SCREEN_ATTR_FRAME, then @data is enum * If @attr includes SCREEN_ATTR_FRAME, then @data is enum
* border_char; otherwise, @data is a character value. * border_char; otherwise, @data is a character value.
* If CONFIG_UTF8 is defined, and UTF-8 I/O is enabled for the * If the charset of the terminal is UTF-8 (which is possible
* terminal, then the character value is in UCS-4; otherwise, * only if CONFIG_UTF8 is defined), then the character value
* it is in the charset of the terminal, and the charset is * is in UCS-4; otherwise, the charset is assumed to be
* assumed to be unibyte. (Thus, if you choose UTF-8 as the * unibyte, and the character value is a byte in that
* charset but disable UTF-8 I/O, you lose.) */ * charset. */
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
unicode_val_T data; unicode_val_T data;
#else #else

View File

@ -182,11 +182,13 @@ check_terminal_name(struct terminal *term, struct terminal_info *info)
/* Probably not best place for set this. But now we finally have /* Probably not best place for set this. But now we finally have
* term->spec and term->utf8 should be set before decode session info. * term->spec and term->utf8 should be set before decode session info.
* --Scrool */ * --Scrool */
term->utf8_cp = is_cp_utf8(get_opt_codepage_tree(term->spec,
"charset"));
/* Force UTF-8 I/O if the UTF-8 charset is selected. Various /* Force UTF-8 I/O if the UTF-8 charset is selected. Various
* places assume that the terminal's charset is unibyte if * places assume that the terminal's charset is unibyte if
* UTF-8 I/O is disabled. (bug 827) */ * UTF-8 I/O is disabled. (bug 827) */
term->utf8 = get_opt_bool_tree(term->spec, "utf_8_io") term->utf8_io = term->utf8_cp
|| is_cp_utf8(get_opt_codepage_tree(term->spec, "charset")); || get_opt_bool_tree(term->spec, "utf_8_io");
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
} }
@ -302,13 +304,13 @@ handle_interlink_event(struct terminal *term, struct interlink_event *ilev)
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
/* struct term_event_keyboard carries UCS-4. /* struct term_event_keyboard carries UCS-4.
* - If the "utf_8_io" option is true or the "charset" * - If the "utf_8_io" option is true or the "charset"
* option refers to UTF-8, then term->utf8 is true, * option refers to UTF-8, then term->utf8_io is true,
* and handle_interlink_event() converts from UTF-8 * and handle_interlink_event() converts from UTF-8
* to UCS-4. * to UCS-4.
* - Otherwise, handle_interlink_event() converts from * - Otherwise, handle_interlink_event() converts from
* the codepage specified with the "charset" option * the codepage specified with the "charset" option
* to UCS-4. */ * to UCS-4. */
utf8_io = term->utf8; utf8_io = term->utf8_io;
#else #else
/* struct term_event_keyboard carries bytes in the /* struct term_event_keyboard carries bytes in the
* charset of the terminal. * charset of the terminal.

View File

@ -31,8 +31,7 @@
const unsigned char frame_dumb[48] = " ||||++||++++++--|-+||++--|-+----++++++++ "; const unsigned char frame_dumb[48] = " ||||++||++++++--|-+||++--|-+----++++++++ ";
static const unsigned char frame_vt100[48] = "aaaxuuukkuxkjjjkmvwtqnttmlvwtqnvvwwmmllnnjla "; static const unsigned char frame_vt100[48] = "aaaxuuukkuxkjjjkmvwtqnttmlvwtqnvvwwmmllnnjla ";
#ifndef CONFIG_UTF8 /* For UTF-8 I/O */
/* For UTF8 I/O */
static const unsigned char frame_vt100_u[48] = { static const unsigned char frame_vt100_u[48] = {
177, 177, 177, 179, 180, 180, 180, 191, 177, 177, 177, 179, 180, 180, 180, 191,
191, 180, 179, 191, 217, 217, 217, 191, 191, 180, 179, 191, 217, 217, 217, 191,
@ -41,8 +40,55 @@ static const unsigned char frame_vt100_u[48] = {
193, 194, 194, 192, 192, 218, 218, 197, 193, 194, 194, 192, 192, 218, 218, 197,
197, 217, 218, 177, 32, 32, 32, 32 197, 217, 218, 177, 32, 32, 32, 32
}; };
#endif /* CONFIG_UTF8 */
/* This is for FreeBSD fonts that place graphics characters in the
* 0x80...0x9F range, which ISO 8859 does not use. The characters are
* supposed to be sorted according to the codes used in VT100 or in
* the terminfo "acsc" capability:
*
* 0x80 U+2588 '0' ACS_BLOCK
* 0x81 U+25C6 '`' ACS_DIAMOND
* 0x82 U+2592 'a' ACS_CKBOARD
* 0x83 U+2409 'b' -
* 0x84 U+240C 'c' -
* 0x85 U+240D 'd' -
* 0x86 U+240A 'e' -
* 0x87 U+00B0 'f' ACS_DEGREE
* 0x88 U+00B1 'g' ACS_PLMINUS
* 0x89 U+2424 'h' -
* 0x8A U+240B 'i' -
* 0x8B U+2518 'j' ACS_LRCORNER
* 0x8C U+2510 'k' ACS_URCORNER
* 0x8D U+250C 'l' ACS_ULCORNER
* 0x8E U+2514 'm' ACS_LLCORNER
* 0x8F U+253C 'n' ACS_PLUS
* 0x90 - 'o' ACS_S1
* 0x91 - 'p' ACS_S3
* 0x92 U+2500 'q' ACS_HLINE
* 0x93 - 'r' ACS_S7
* 0x94 - 's' ACS_S9
* 0x95 U+251C 't' ACS_LTEE
* 0x96 U+2524 'u' ACS_RTEE
* 0x97 U+2534 'v' ACS_BTEE
* 0x98 U+252C 'w' ACS_TTEE
* 0x99 U+2502 'x' ACS_VLINE
* 0x9A U+2264 'y' ACS_LEQUAL
* 0x9B U+2265 'z' ACS_GEQUAL
* 0x9C U+03C0 '{' ACS_PI
* 0x9D U+2260 '|' ACS_NEQUAL
* 0x9E U+00A3 '}' ACS_STERLING
* 0x9F U+00B7 '~' ACS_BULLET
*
* (Ncurses 5.5 defines ACS_BOARD using 'h' and ACS_LANTERN using 'i',
* but those are not the characters meant above.)
*
* In FreeBSD CVS, src/share/syscons/fonts/iso-8x16.fnt revision 1.1
* includes these characters, except it has a space at 0x80. In
* revision 1.2 however, all the characters not defined by ISO 8859-1
* have been blanked out. This change was made on 2001-11-22 and
* included in FreeBSD 4.6.0, which was then released in June 2002.
* Yet, support for these characters was added to Links on 2003-11-18
* and to ELinks on 2003-12-07, so perhaps we should keep it for now. */
static const unsigned char frame_freebsd[48] = { static const unsigned char frame_freebsd[48] = {
130, 138, 128, 153, 150, 150, 150, 140, 130, 138, 128, 153, 150, 150, 150, 140,
140, 150, 153, 140, 139, 139, 139, 140, 140, 150, 153, 140, 139, 139, 139, 140,
@ -52,6 +98,19 @@ static const unsigned char frame_freebsd[48] = {
143, 139, 141, 128, 128, 128, 128, 128, 143, 139, 141, 128, 128, 128, 128, 128,
}; };
/* For UTF-8 I/O. Derived from frame_freebsd[] by converting the
* characters to Unicode and back to CP437. frame_freebsd[1] = 138 =
* 0x8a = U+240B SYMBOL FOR VERTICAL TABULATION does not exist in
* CP437, so we substitute U+2592 MEDIUM SHADE. */
static const unsigned char frame_freebsd_u[48] = {
177, 177, 219, 179, 180, 180, 180, 191,
191, 180, 179, 191, 217, 217, 217, 191,
192, 193, 194, 195, 196, 197, 195, 195,
192, 218, 193, 194, 195, 196, 197, 193,
193, 194, 194, 192, 192, 218, 218, 197,
197, 217, 218, 219, 219, 219, 219, 219,
};
static const unsigned char frame_koi[48] = { static const unsigned char frame_koi[48] = {
144, 145, 146, 129, 135, 178, 180, 167, 144, 145, 146, 129, 135, 178, 180, 167,
166, 181, 161, 168, 174, 173, 172, 131, 166, 181, 161, 168, 174, 173, 172, 131,
@ -77,18 +136,14 @@ static const unsigned char frame_restrict[48] = {
#define add_term_string(str, tstr) \ #define add_term_string(str, tstr) \
add_bytes_to_string(str, (tstr).source, (tstr).length) add_bytes_to_string(str, (tstr).source, (tstr).length)
/* ECMA-48: CSI Ps... 06/13 = SGR - SELECT GRAPHIC RENDITION
* Ps = 10 = primary (default) font
* Ps = 11 = first alternative font */
static const struct string m11_hack_frame_seqs[] = { static const struct string m11_hack_frame_seqs[] = {
/* end border: */ TERM_STRING("\033[10m"), /* end border: */ TERM_STRING("\033[10m"),
/* begin border: */ TERM_STRING("\033[11m"), /* begin border: */ TERM_STRING("\033[11m"),
}; };
#ifdef CONFIG_UTF8
static const struct string utf8_linux_frame_seqs[] = {
/* end border: */ TERM_STRING("\033[10m\033%G"),
/* begin border: */ TERM_STRING("\033%@\033[11m"),
};
#endif /* CONFIG_UTF8 */
static const struct string vt100_frame_seqs[] = { static const struct string vt100_frame_seqs[] = {
/* end border: */ TERM_STRING("\x0f"), /* end border: */ TERM_STRING("\x0f"),
/* begin border: */ TERM_STRING("\x0e"), /* begin border: */ TERM_STRING("\x0e"),
@ -110,214 +165,202 @@ struct screen_driver {
* uniquely identify the screen_driver. */ * uniquely identify the screen_driver. */
enum term_mode_type type; enum term_mode_type type;
#ifndef CONFIG_UTF8 struct screen_driver_opt {
/* Charsets when doing UTF8 I/O. */ /* Charsets when doing UTF8 I/O. */
/* [0] is the common charset and [1] is the frame charset. /* [0] is the common charset and [1] is the frame charset.
* Test whether to use UTF8 I/O using the use_utf8_io() macro. */ * Test whether to use UTF8 I/O using the use_utf8_io() macro. */
int charsets[2]; int charsets[2];
#endif /* CONFIG_UTF8 */
/* The frame translation table. May be NULL. */ /* The frame translation table. May be NULL. */
const unsigned char *frame; const unsigned char *frame;
/* The frame mode setup and teardown sequences. May be NULL. */ /* The frame mode setup and teardown sequences. May be NULL. */
const struct string *frame_seqs; const struct string *frame_seqs;
/* The underline mode setup and teardown sequences. May be NULL. */ /* The underline mode setup and teardown sequences. May be NULL. */
const struct string *underline; const struct string *underline;
/* The color mode */ /* The color mode */
enum color_mode color_mode; enum color_mode color_mode;
/* These are directly derived from the terminal options. */ /* These are directly derived from the terminal options. */
unsigned int transparent:1; unsigned int transparent:1;
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
/* UTF-8 I/O. Forced on if the UTF-8 charset is selected. (bug 827) */ /* Whether the charset of the terminal is UTF-8. This
unsigned int utf8:1; * is the same as is_cp_utf8(charsets[0]), except the
* latter might crash if UTF-8 I/O is disabled. */
unsigned int utf8_cp:1;
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
} opt;
/* The terminal._template_ name. */ /* The terminal._template_ name. */
unsigned char name[1]; /* XXX: Keep last! */ unsigned char name[1]; /* XXX: Keep last! */
}; };
static const struct screen_driver dumb_screen_driver = { static const struct screen_driver_opt dumb_screen_driver_opt = {
NULL_LIST_HEAD,
/* type: */ TERM_DUMB,
#ifndef CONFIG_UTF8
/* charsets: */ { -1, -1 }, /* No UTF8 I/O */ /* charsets: */ { -1, -1 }, /* No UTF8 I/O */
#endif /* CONFIG_UTF8 */
/* frame: */ frame_dumb, /* frame: */ frame_dumb,
/* frame_seqs: */ NULL, /* frame_seqs: */ NULL,
/* underline: */ underline_seqs, /* underline: */ underline_seqs,
/* color_mode: */ COLOR_MODE_16, /* color_mode: */ COLOR_MODE_16,
/* transparent: */ 1, /* transparent: */ 1,
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
/* utf-8: */ 0, /* utf8_cp: */ 0,
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
}; };
static const struct screen_driver vt100_screen_driver = { static const struct screen_driver_opt vt100_screen_driver_opt = {
NULL_LIST_HEAD,
/* type: */ TERM_VT100,
#ifndef CONFIG_UTF8
/* charsets: */ { -1, -1 }, /* No UTF8 I/O */ /* charsets: */ { -1, -1 }, /* No UTF8 I/O */
#endif /* CONFIG_UTF8 */
/* frame: */ frame_vt100, /* frame: */ frame_vt100,
/* frame_seqs: */ vt100_frame_seqs, /* frame_seqs: */ vt100_frame_seqs,
/* underline: */ underline_seqs, /* underline: */ underline_seqs,
/* color_mode: */ COLOR_MODE_16, /* color_mode: */ COLOR_MODE_16,
/* transparent: */ 1, /* transparent: */ 1,
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
/* utf-8: */ 0, /* utf8_cp: */ 0,
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
}; };
static const struct screen_driver linux_screen_driver = { static const struct screen_driver_opt linux_screen_driver_opt = {
NULL_LIST_HEAD,
/* type: */ TERM_LINUX,
#ifndef CONFIG_UTF8
/* charsets: */ { -1, -1 }, /* No UTF8 I/O */ /* charsets: */ { -1, -1 }, /* No UTF8 I/O */
#endif /* CONFIG_UTF8 */
/* frame: */ NULL, /* No restrict_852 */ /* frame: */ NULL, /* No restrict_852 */
/* frame_seqs: */ NULL, /* No m11_hack */ /* frame_seqs: */ NULL, /* No m11_hack */
/* underline: */ underline_seqs, /* underline: */ underline_seqs,
/* color_mode: */ COLOR_MODE_16, /* color_mode: */ COLOR_MODE_16,
/* transparent: */ 1, /* transparent: */ 1,
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
/* utf-8: */ 0, /* utf8_cp: */ 0,
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
}; };
static const struct screen_driver koi8_screen_driver = { static const struct screen_driver_opt koi8_screen_driver_opt = {
NULL_LIST_HEAD,
/* type: */ TERM_KOI8,
#ifndef CONFIG_UTF8
/* charsets: */ { -1, -1 }, /* No UTF8 I/O */ /* charsets: */ { -1, -1 }, /* No UTF8 I/O */
#endif /* CONFIG_UTF8 */
/* frame: */ frame_koi, /* frame: */ frame_koi,
/* frame_seqs: */ NULL, /* frame_seqs: */ NULL,
/* underline: */ underline_seqs, /* underline: */ underline_seqs,
/* color_mode: */ COLOR_MODE_16, /* color_mode: */ COLOR_MODE_16,
/* transparent: */ 1, /* transparent: */ 1,
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
/* utf-8: */ 0, /* utf8_cp: */ 0,
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
}; };
static const struct screen_driver freebsd_screen_driver = { static const struct screen_driver_opt freebsd_screen_driver_opt = {
NULL_LIST_HEAD,
/* type: */ TERM_FREEBSD,
#ifndef CONFIG_UTF8
/* charsets: */ { -1, -1 }, /* No UTF8 I/O */ /* charsets: */ { -1, -1 }, /* No UTF8 I/O */
#endif /* CONFIG_UTF8 */
/* frame: */ frame_freebsd, /* frame: */ frame_freebsd,
/* frame_seqs: */ NULL, /* No m11_hack */ /* frame_seqs: */ NULL, /* No m11_hack */
/* underline: */ underline_seqs, /* underline: */ underline_seqs,
/* color_mode: */ COLOR_MODE_16, /* color_mode: */ COLOR_MODE_16,
/* transparent: */ 1, /* transparent: */ 1,
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
/* utf-8: */ 0, /* utf8_cp: */ 0,
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
}; };
/* XXX: Keep in sync with enum term_mode_type. */ /* XXX: Keep in sync with enum term_mode_type. */
static const struct screen_driver *const screen_drivers[] = { static const struct screen_driver_opt *const screen_driver_opts[] = {
/* TERM_DUMB: */ &dumb_screen_driver, /* TERM_DUMB: */ &dumb_screen_driver_opt,
/* TERM_VT100: */ &vt100_screen_driver, /* TERM_VT100: */ &vt100_screen_driver_opt,
/* TERM_LINUX: */ &linux_screen_driver, /* TERM_LINUX: */ &linux_screen_driver_opt,
/* TERM_KOI8: */ &koi8_screen_driver, /* TERM_KOI8: */ &koi8_screen_driver_opt,
/* TERM_FREEBSD: */ &freebsd_screen_driver, /* TERM_FREEBSD: */ &freebsd_screen_driver_opt,
}; };
#ifdef CONFIG_UTF8 #define use_utf8_io(driver) ((driver)->opt.charsets[0] != -1)
#define use_utf8_io(driver) ((driver)->utf8)
#else
#define use_utf8_io(driver) ((driver)->charsets[0] != -1)
#endif /* CONFIG_UTF8 */
static INIT_LIST_HEAD(active_screen_drivers); static INIT_LIST_HEAD(active_screen_drivers);
/* Set driver->opt according to driver->type and term_spec.
* Other members of *driver need not have been initialized.
*
* If you modify anything here, check whether option descriptions
* should be updated. */
static void static void
update_screen_driver(struct screen_driver *driver, struct option *term_spec) set_screen_driver_opt(struct screen_driver *driver, struct option *term_spec)
{ {
const int cp = get_opt_codepage_tree(term_spec, "charset");
int utf8_io = get_opt_bool_tree(term_spec, "utf_8_io");
/* Copy all the original options from constants, so that this
* function need not carefully restore options one by one. */
copy_struct(&driver->opt, screen_driver_opts[driver->type]);
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
/* Force UTF-8 I/O if the UTF-8 charset is selected. Various /* Force UTF-8 I/O if the UTF-8 charset is selected. Various
* places assume that the terminal's charset is unibyte if * places assume that the terminal's charset is unibyte if
* UTF-8 I/O is disabled. (bug 827) */ * UTF-8 I/O is disabled. (bug 827) */
driver->utf8 = get_opt_bool_tree(term_spec, "utf_8_io") if (is_cp_utf8(cp)) {
|| is_cp_utf8(get_opt_codepage_tree(term_spec, "charset")); driver->opt.utf8_cp = 1;
#else utf8_io = 1;
int utf8_io = get_opt_bool_tree(term_spec, "utf_8_io"); } else {
driver->opt.utf8_cp = 0;
}
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
driver->color_mode = get_opt_int_tree(term_spec, "colors"); driver->opt.color_mode = get_opt_int_tree(term_spec, "colors");
driver->transparent = get_opt_bool_tree(term_spec, "transparency"); driver->opt.transparent = get_opt_bool_tree(term_spec, "transparency");
if (get_opt_bool_tree(term_spec, "underline")) { if (get_opt_bool_tree(term_spec, "underline")) {
driver->underline = underline_seqs; driver->opt.underline = underline_seqs;
} else { } else {
driver->underline = NULL; driver->opt.underline = NULL;
} }
#ifdef CONFIG_UTF8
if (driver->type == TERM_LINUX) {
if (get_opt_bool_tree(term_spec, "restrict_852"))
driver->frame = frame_restrict;
if (get_opt_bool_tree(term_spec, "m11_hack"))
driver->frame_seqs = m11_hack_frame_seqs;
if (driver->utf8)
driver->frame_seqs = utf8_linux_frame_seqs;
} else if (driver->type == TERM_FREEBSD) {
if (get_opt_bool_tree(term_spec, "m11_hack"))
driver->frame_seqs = m11_hack_frame_seqs;
} else if (driver->type == TERM_VT100) {
driver->frame = frame_vt100;
}
#else
if (utf8_io) { if (utf8_io) {
driver->charsets[0] = get_opt_codepage_tree(term_spec, "charset"); driver->opt.charsets[0] = cp;
/* When we're using UTF-8 I/O, we never need to switch
* charsets or fonts for drawing frames, because the
* characters encoded in UTF-8 are already unambiguous. */
driver->opt.frame_seqs = NULL;
if (driver->type == TERM_LINUX) { if (driver->type == TERM_LINUX) {
if (get_opt_bool_tree(term_spec, "restrict_852")) if (get_opt_bool_tree(term_spec, "restrict_852"))
driver->frame = frame_restrict; driver->opt.frame = frame_restrict;
driver->opt.charsets[1] = get_cp_index("cp437");
driver->charsets[1] = get_cp_index("cp437");
} else if (driver->type == TERM_FREEBSD) { } else if (driver->type == TERM_FREEBSD) {
driver->charsets[1] = get_cp_index("cp437"); driver->opt.frame = frame_freebsd_u;
driver->opt.charsets[1] = get_cp_index("cp437");
} else if (driver->type == TERM_VT100) { } else if (driver->type == TERM_VT100) {
driver->frame = frame_vt100_u; driver->opt.frame = frame_vt100_u;
driver->charsets[1] = get_cp_index("cp437"); driver->opt.charsets[1] = get_cp_index("cp437");
} else if (driver->type == TERM_KOI8) { } else if (driver->type == TERM_KOI8) {
driver->charsets[1] = get_cp_index("koi8-r"); driver->opt.charsets[1] = get_cp_index("koi8-r");
} else { } else {
driver->charsets[1] = driver->charsets[0]; #ifdef CONFIG_UTF8
/* Don't let driver->opt.charsets[1] become
* UTF-8, because it is passed to cp2u(),
* which supports only unibyte characters. */
if (driver->opt.utf8_cp)
driver->opt.charsets[1] = get_cp_index("US-ASCII");
else
#endif /* CONFIG_UTF8 */
driver->opt.charsets[1] = driver->opt.charsets[0];
} }
} else { } else { /* !utf8_io */
driver->charsets[0] = -1; driver->opt.charsets[0] = -1;
if (driver->type == TERM_LINUX) { if (driver->type == TERM_LINUX) {
if (get_opt_bool_tree(term_spec, "restrict_852")) if (get_opt_bool_tree(term_spec, "restrict_852"))
driver->frame = frame_restrict; driver->opt.frame = frame_restrict;
if (get_opt_bool_tree(term_spec, "m11_hack")) if (get_opt_bool_tree(term_spec, "m11_hack"))
driver->frame_seqs = m11_hack_frame_seqs; driver->opt.frame_seqs = m11_hack_frame_seqs;
} else if (driver->type == TERM_FREEBSD) { } else if (driver->type == TERM_FREEBSD) {
if (get_opt_bool_tree(term_spec, "m11_hack")) if (get_opt_bool_tree(term_spec, "m11_hack"))
driver->frame_seqs = m11_hack_frame_seqs; driver->opt.frame_seqs = m11_hack_frame_seqs;
} else if (driver->type == TERM_VT100) { } else if (driver->type == TERM_VT100) {
driver->frame = frame_vt100; driver->opt.frame = frame_vt100;
} }
} } /* !utf8_io */
#endif /* CONFIG_UTF8 */
} }
static int static int
@ -327,11 +370,10 @@ screen_driver_change_hook(struct session *ses, struct option *term_spec,
enum term_mode_type type = get_opt_int_tree(term_spec, "type"); enum term_mode_type type = get_opt_int_tree(term_spec, "type");
struct screen_driver *driver; struct screen_driver *driver;
unsigned char *name = term_spec->name; unsigned char *name = term_spec->name;
int len = strlen(name);
foreach (driver, active_screen_drivers) foreach (driver, active_screen_drivers)
if (driver->type == type && !memcmp(driver->name, name, len)) { if (driver->type == type && !strcmp(driver->name, name)) {
update_screen_driver(driver, term_spec); set_screen_driver_opt(driver, term_spec);
break; break;
} }
@ -347,17 +389,17 @@ add_screen_driver(enum term_mode_type type, struct terminal *term, int env_len)
driver = mem_alloc(sizeof(*driver) + env_len); driver = mem_alloc(sizeof(*driver) + env_len);
if (!driver) return NULL; if (!driver) return NULL;
memcpy(driver, screen_drivers[type], sizeof(*driver) - 1); /* These four operations fully initialize *driver. */
memcpy(driver->name, term->spec->name, env_len + 1);
add_to_list(active_screen_drivers, driver); add_to_list(active_screen_drivers, driver);
driver->type = type;
update_screen_driver(driver, term->spec); set_screen_driver_opt(driver, term->spec);
memcpy(driver->name, term->spec->name, env_len + 1);
term->spec->change_hook = screen_driver_change_hook; term->spec->change_hook = screen_driver_change_hook;
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
term->utf8 = use_utf8_io(driver); term->utf8_cp = driver->opt.utf8_cp;
term->utf8_io = use_utf8_io(driver);
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
return driver; return driver;
@ -373,13 +415,14 @@ get_screen_driver(struct terminal *term)
foreach (driver, active_screen_drivers) { foreach (driver, active_screen_drivers) {
if (driver->type != type) continue; if (driver->type != type) continue;
if (memcmp(driver->name, name, len + 1)) continue; if (strcmp(driver->name, name)) continue;
/* Some simple probably useless MRU ;) */ /* Some simple probably useless MRU ;) */
move_to_top_of_list(active_screen_drivers, driver); move_to_top_of_list(active_screen_drivers, driver);
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
term->utf8 = use_utf8_io(driver); term->utf8_cp = driver->opt.utf8_cp;
term->utf8_io = use_utf8_io(driver);
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
return driver; return driver;
} }
@ -527,46 +570,48 @@ copy_color_16(unsigned char *a, unsigned char *b)
static inline void static inline void
add_char_data(struct string *screen, struct screen_driver *driver, add_char_data(struct string *screen, struct screen_driver *driver,
unicode_val_T data, unsigned char border) unicode_val_T data, unsigned char border)
#else #else /* !CONFIG_UTF8 */
static inline void static inline void
add_char_data(struct string *screen, struct screen_driver *driver, add_char_data(struct string *screen, struct screen_driver *driver,
unsigned char data, unsigned char border) unsigned char data, unsigned char border)
#endif /* CONFIG_UTF8 */ #endif /* !CONFIG_UTF8 */
{ {
/* CONFIG_UTF8 use_utf8_io border data add_to_string /* charset use_utf8_io border data add_to_string
* ----------- ----------- ------ ---------------- ---------------- * ------- ----------- ------ ---------------- ----------------
* not defined 0 0 terminal unibyte terminal unibyte * unibyte 0 0 terminal unibyte terminal unibyte
* not defined 0 1 enum border_char border unibyte * unibyte 0 1 enum border_char border unibyte
* not defined 1 0 terminal unibyte UTF-8 * unibyte 1 0 terminal unibyte UTF-8
* not defined 1 1 enum border_char UTF-8 * unibyte 1 1 enum border_char UTF-8
* defined 0 0 terminal unibyte terminal unibyte * UTF-8 1 0 UTF-32 (*) UTF-8
* defined 0 1 enum border_char border unibyte * UTF-8 1 1 enum border_char UTF-8
* defined 1 0 UTF-32 UTF-8
* defined 1 1 enum border_char border unibyte
* *
* For "UTF-32" above, the data can also be UCS_NO_CHAR. * (*) For "UTF-32" above, data can also be UCS_NO_CHAR,
* in which case this function must not alter *screen.
*/ */
if (border && driver->frame && data >= 176 && data < 224) if (border && driver->opt.frame && data >= 176 && data < 224)
data = driver->frame[data - 176]; data = driver->opt.frame[data - 176];
if (use_utf8_io(driver)) {
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
if (border) if (driver->opt.utf8_cp) {
add_char_to_string(screen, (unsigned char)data); if (border) {
else if (data != UCS_NO_CHAR) { data = cp2u(driver->opt.charsets[1],
if (!isscreensafe_ucs(data)) (unsigned char) data);
data = UCS_SPACE;
add_to_string(screen, encode_utf8(data));
} }
#else if (data == UCS_NO_CHAR)
int charset = driver->charsets[!!border]; return;
if (!isscreensafe_ucs(data))
data = UCS_SPACE;
add_to_string(screen, encode_utf8(data));
} else
#endif /* CONFIG_UTF8 */
if (use_utf8_io(driver)) {
int charset = driver->opt.charsets[!!border];
if (border || isscreensafe(data)) if (border || isscreensafe(data))
add_to_string(screen, cp2utf8(charset, data)); add_to_string(screen, cp2utf8(charset, data));
else /* UCS_SPACE <= 0x7F and so fits in one UTF-8 byte */ else /* UCS_SPACE <= 0x7F and so fits in one UTF-8 byte */
add_char_to_string(screen, UCS_SPACE); add_char_to_string(screen, UCS_SPACE);
#endif /* CONFIG_UTF8 */
} else { } else {
if (border || isscreensafe(data)) if (border || isscreensafe(data))
add_char_to_string(screen, (unsigned char)data); add_char_to_string(screen, (unsigned char)data);
@ -586,27 +631,27 @@ add_char16(struct string *screen, struct screen_driver *driver,
if ( if (
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
(!use_utf8_io(driver) || ch->data != UCS_NO_CHAR) && !(driver->opt.utf8_cp && ch->data == UCS_NO_CHAR) &&
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
border != state->border && driver->frame_seqs border != state->border && driver->opt.frame_seqs
) { ) {
state->border = border; state->border = border;
add_term_string(screen, driver->frame_seqs[!!border]); add_term_string(screen, driver->opt.frame_seqs[!!border]);
} }
if ( if (
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
(!use_utf8_io(driver) || ch->data != UCS_NO_CHAR) && !(driver->opt.utf8_cp && ch->data == UCS_NO_CHAR) &&
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
underline != state->underline && driver->underline underline != state->underline && driver->opt.underline
) { ) {
state->underline = underline; state->underline = underline;
add_term_string(screen, driver->underline[!!underline]); add_term_string(screen, driver->opt.underline[!!underline]);
} }
if ( if (
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
(!use_utf8_io(driver) || ch->data != UCS_NO_CHAR) && !(driver->opt.utf8_cp && ch->data == UCS_NO_CHAR) &&
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
bold != state->bold bold != state->bold
) { ) {
@ -621,7 +666,7 @@ add_char16(struct string *screen, struct screen_driver *driver,
if ( if (
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
(!use_utf8_io(driver) || ch->data != UCS_NO_CHAR) && !(driver->opt.utf8_cp && ch->data == UCS_NO_CHAR) &&
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
!compare_color_16(ch->color, state->color) !compare_color_16(ch->color, state->color)
) { ) {
@ -629,7 +674,7 @@ add_char16(struct string *screen, struct screen_driver *driver,
add_bytes_to_string(screen, "\033[0", 3); add_bytes_to_string(screen, "\033[0", 3);
/* @update_screen_driver has set @driver->color_mode /* @set_screen_driver_opt has set @driver->opt.color_mode
* according to terminal-type-specific options. * according to terminal-type-specific options.
* The caller of @add_char16 has already partially * The caller of @add_char16 has already partially
* checked it, but there are still these possibilities: * checked it, but there are still these possibilities:
@ -637,13 +682,13 @@ add_char16(struct string *screen, struct screen_driver *driver,
* perhaps use the standout attribute. * perhaps use the standout attribute.
* - COLOR_MODE_16. Use 16 colors. * - COLOR_MODE_16. Use 16 colors.
* - An unsupported color mode. Use 16 colors. */ * - An unsupported color mode. Use 16 colors. */
if (driver->color_mode != COLOR_MODE_MONO) { if (driver->opt.color_mode != COLOR_MODE_MONO) {
unsigned char code[6] = ";30;40"; unsigned char code[6] = ";30;40";
unsigned char bgcolor = TERM_COLOR_BACKGROUND_16(ch->color); unsigned char bgcolor = TERM_COLOR_BACKGROUND_16(ch->color);
code[2] += TERM_COLOR_FOREGROUND_16(ch->color); code[2] += TERM_COLOR_FOREGROUND_16(ch->color);
if (!driver->transparent || bgcolor != 0) { if (!driver->opt.transparent || bgcolor != 0) {
code[5] += bgcolor; code[5] += bgcolor;
add_bytes_to_string(screen, code, 6); add_bytes_to_string(screen, code, 6);
} else { } else {
@ -656,7 +701,7 @@ add_char16(struct string *screen, struct screen_driver *driver,
add_bytes_to_string(screen, ";7", 2); add_bytes_to_string(screen, ";7", 2);
} }
if (underline && driver->underline) { if (underline && driver->opt.underline) {
add_bytes_to_string(screen, ";4", 2); add_bytes_to_string(screen, ";4", 2);
} }
@ -736,18 +781,18 @@ add_char256(struct string *screen, struct screen_driver *driver,
if ( if (
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
(!use_utf8_io(driver) || ch->data != UCS_NO_CHAR) && !(driver->opt.utf8_cp && ch->data == UCS_NO_CHAR) &&
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
attr_delta attr_delta
) { ) {
if ((attr_delta & SCREEN_ATTR_FRAME) && driver->frame_seqs) { if ((attr_delta & SCREEN_ATTR_FRAME) && driver->opt.frame_seqs) {
state->border = !!(ch->attr & SCREEN_ATTR_FRAME); state->border = !!(ch->attr & SCREEN_ATTR_FRAME);
add_term_string(screen, driver->frame_seqs[state->border]); add_term_string(screen, driver->opt.frame_seqs[state->border]);
} }
if ((attr_delta & SCREEN_ATTR_UNDERLINE) && driver->underline) { if ((attr_delta & SCREEN_ATTR_UNDERLINE) && driver->opt.underline) {
state->underline = !!(ch->attr & SCREEN_ATTR_UNDERLINE); state->underline = !!(ch->attr & SCREEN_ATTR_UNDERLINE);
add_term_string(screen, driver->underline[state->underline]); add_term_string(screen, driver->opt.underline[state->underline]);
} }
if (attr_delta & SCREEN_ATTR_BOLD) { if (attr_delta & SCREEN_ATTR_BOLD) {
@ -764,23 +809,23 @@ add_char256(struct string *screen, struct screen_driver *driver,
if ( if (
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
(!use_utf8_io(driver) || ch->data != UCS_NO_CHAR) && !(driver->opt.utf8_cp && ch->data == UCS_NO_CHAR) &&
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
!compare_color_256(ch->color, state->color) !compare_color_256(ch->color, state->color)
) { ) {
copy_color_256(state->color, ch->color); copy_color_256(state->color, ch->color);
add_foreground_color(screen, color256_seqs, ch); add_foreground_color(screen, color256_seqs, ch);
if (!driver->transparent || ch->color[1] != 0) { if (!driver->opt.transparent || ch->color[1] != 0) {
add_background_color(screen, color256_seqs, ch); add_background_color(screen, color256_seqs, ch);
} }
if (ch->attr & SCREEN_ATTR_BOLD) if (ch->attr & SCREEN_ATTR_BOLD)
add_bytes_to_string(screen, "\033[1m", 4); add_bytes_to_string(screen, "\033[1m", 4);
if (ch->attr & SCREEN_ATTR_UNDERLINE && driver->underline) { if (ch->attr & SCREEN_ATTR_UNDERLINE && driver->opt.underline) {
state->underline = !!(ch->attr & SCREEN_ATTR_UNDERLINE); state->underline = !!(ch->attr & SCREEN_ATTR_UNDERLINE);
add_term_string(screen, driver->underline[state->underline]); add_term_string(screen, driver->opt.underline[state->underline]);
} }
} }
@ -851,18 +896,18 @@ add_char_true(struct string *screen, struct screen_driver *driver,
if ( if (
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
(!use_utf8_io(driver) || ch->data != UCS_NO_CHAR) && !(driver->opt.utf8_cp && ch->data == UCS_NO_CHAR) &&
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
attr_delta attr_delta
) { ) {
if ((attr_delta & SCREEN_ATTR_FRAME) && driver->frame_seqs) { if ((attr_delta & SCREEN_ATTR_FRAME) && driver->opt.frame_seqs) {
state->border = !!(ch->attr & SCREEN_ATTR_FRAME); state->border = !!(ch->attr & SCREEN_ATTR_FRAME);
add_term_string(screen, driver->frame_seqs[state->border]); add_term_string(screen, driver->opt.frame_seqs[state->border]);
} }
if ((attr_delta & SCREEN_ATTR_UNDERLINE) && driver->underline) { if ((attr_delta & SCREEN_ATTR_UNDERLINE) && driver->opt.underline) {
state->underline = !!(ch->attr & SCREEN_ATTR_UNDERLINE); state->underline = !!(ch->attr & SCREEN_ATTR_UNDERLINE);
add_term_string(screen, driver->underline[state->underline]); add_term_string(screen, driver->opt.underline[state->underline]);
} }
if (attr_delta & SCREEN_ATTR_BOLD) { if (attr_delta & SCREEN_ATTR_BOLD) {
@ -879,23 +924,23 @@ add_char_true(struct string *screen, struct screen_driver *driver,
if ( if (
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
(!use_utf8_io(driver) || ch->data != UCS_NO_CHAR) && !(driver->opt.utf8_cp && ch->data == UCS_NO_CHAR) &&
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
!compare_color_true(ch->color, state->color) !compare_color_true(ch->color, state->color)
) { ) {
copy_color_true(state->color, ch->color); copy_color_true(state->color, ch->color);
add_true_foreground_color(screen, color_true_seqs, ch); add_true_foreground_color(screen, color_true_seqs, ch);
if (!driver->transparent || !background_is_black(ch->color)) { if (!driver->opt.transparent || !background_is_black(ch->color)) {
add_true_background_color(screen, color_true_seqs, ch); add_true_background_color(screen, color_true_seqs, ch);
} }
if (ch->attr & SCREEN_ATTR_BOLD) if (ch->attr & SCREEN_ATTR_BOLD)
add_bytes_to_string(screen, "\033[1m", 4); add_bytes_to_string(screen, "\033[1m", 4);
if (ch->attr & SCREEN_ATTR_UNDERLINE && driver->underline) { if (ch->attr & SCREEN_ATTR_UNDERLINE && driver->opt.underline) {
state->underline = !!(ch->attr & SCREEN_ATTR_UNDERLINE); state->underline = !!(ch->attr & SCREEN_ATTR_UNDERLINE);
add_term_string(screen, driver->underline[state->underline]); add_term_string(screen, driver->opt.underline[state->underline]);
} }
} }
@ -980,7 +1025,7 @@ redraw_screen(struct terminal *term)
if (!init_string(&image)) return; if (!init_string(&image)) return;
switch (driver->color_mode) { switch (driver->opt.color_mode) {
default: default:
/* If the desired color mode was not compiled in, /* If the desired color mode was not compiled in,
* use 16 colors. */ * use 16 colors. */
@ -1005,19 +1050,19 @@ redraw_screen(struct terminal *term)
#endif #endif
case COLOR_MODES: case COLOR_MODES:
case COLOR_MODE_DUMP: case COLOR_MODE_DUMP:
INTERNAL("Invalid color mode (%d).", driver->color_mode); INTERNAL("Invalid color mode (%d).", driver->opt.color_mode);
return; return;
} }
if (image.length) { if (image.length) {
if (driver->color_mode != COLOR_MODE_MONO) if (driver->opt.color_mode != COLOR_MODE_MONO)
add_bytes_to_string(&image, "\033[37;40m", 8); add_bytes_to_string(&image, "\033[37;40m", 8);
add_bytes_to_string(&image, "\033[0m", 4); add_bytes_to_string(&image, "\033[0m", 4);
/* If we ended in border state end the frame mode. */ /* If we ended in border state end the frame mode. */
if (state.border && driver->frame_seqs) if (state.border && driver->opt.frame_seqs)
add_term_string(&image, driver->frame_seqs[0]); add_term_string(&image, driver->opt.frame_seqs[0]);
} }

View File

@ -127,9 +127,12 @@ struct terminal {
unsigned int master:1; unsigned int master:1;
#ifdef CONFIG_UTF8 #ifdef CONFIG_UTF8
/* Indicates whether the charset of the terminal is UTF-8. */
unsigned int utf8_cp:1;
/* Indicates whether UTF-8 I/O is used. Forced on if the /* Indicates whether UTF-8 I/O is used. Forced on if the
* UTF-8 charset is selected. (bug 827) */ * UTF-8 charset is selected. (bug 827) */
unsigned int utf8:1; unsigned int utf8_io:1;
#endif /* CONFIG_UTF8 */ #endif /* CONFIG_UTF8 */
/* The current tab number. */ /* The current tab number. */

View File

@ -3,10 +3,6 @@ include $(top_builddir)/Makefile.config
INCLUDES += $(GNUTLS_CFLAGS) $(OPENSSL_CFLAGS) INCLUDES += $(GNUTLS_CFLAGS) $(OPENSSL_CFLAGS)
# Reverse a CONFIG_* string
# Usage $(call not,$(CONFIG_FOO))
not = $(if $(findstring yes,$(1)),no,yes)
OBJS-$(call not,$(CONFIG_SMALL)) += fastfind.o OBJS-$(call not,$(CONFIG_SMALL)) += fastfind.o
OBJS-$(CONFIG_CSS) += scanner.o OBJS-$(CONFIG_CSS) += scanner.o
OBJS-$(CONFIG_DEBUG) += memdebug.o OBJS-$(CONFIG_DEBUG) += memdebug.o

Some files were not shown because too many files have changed in this diff Show More