1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-06-20 00:15:31 +00:00

Merge branch 'elinks-0.12' into elinks-0.13

Conflicts:
	NEWS
	po/fr.po: kept version from elinks-0.13
	src/viewer/dump/dump.c
This commit is contained in:
Kalle Olavi Niemitalo 2009-06-12 23:18:21 +03:00 committed by Kalle Olavi Niemitalo
commit 822e9d6921
7 changed files with 521 additions and 630 deletions

22
NEWS
View File

@ -72,11 +72,29 @@ have already been considered.
(mostly reverted)
//////////////////////////////////////////////////////////////////////
ELinks 0.12pre4.GIT now:
------------------------
To be released as 0.12pre5, 0.12rc1, or even 0.12.0. This branch also
includes the changes listed under ``ELinks 0.11.6.GIT now'' below.
* bug 1080: Support ``--dump-color-mode'' with ``--dump-charset UTF-8''.
* minor bug 1017: To work around HTTP server bugs, disable
protocol.http.compression by default, until ELinks can report
decompression errors or automatically retry the connection.
Bugs that should be removed from NEWS before the 0.12.0 release:
* critical bug 1081: To fix crashes caused by different definitions of
regfree() in TRE and in the system libc, link with TRE before any
other libraries. ELinks 0.12pre4 was the first release that had
this bug.
ELinks 0.12pre4:
----------------
Released on 2009-05-31. This release also included the changes listed
under ``ELinks 0.11.6.GIT now'' below.
under ``ELinks 0.11.6'' below.
Incompatibilities:
@ -87,6 +105,8 @@ Incompatibilities:
Other changes:
* critical bug 1077: Fix crash opening a ``javascript:'' link in a new
tab.
* Debian bug 528661: If using GNUTLS 2.1.7 or later, disable various
TLS extensions (including CERT and SERVERNAME) to help handshaking
with the SSLv3-only bugzilla.novell.com.

View File

@ -961,7 +961,7 @@ else
AC_MSG_CHECKING([[for TRE header and library]])
EL_SAVE_FLAGS
CFLAGS="$TRE_CFLAGS $CFLAGS"
LIBS="$TRE_LIBS $LIBS"
LIBS="$TRE_LIBS $LIBS" # must be first, because of regfree conflict
AC_TRY_LINK([#include <tre/regex.h>],
[regex_t re;
regmatch_t match[1];
@ -1452,6 +1452,9 @@ AC_ARG_ENABLE(weehoofooboomookerchoo,
# This must be done after the CONFIG_UTF8 check above.
# The first part of the TRE check is separate, to get
# the configure --help output in a sensible order.
#
# After this section, nothing else must be added to the
# beginning of $LIBS.
if test "$tre_log" = "available"; then
if test "$CONFIG_UTF8" = "yes"; then
@ -1495,7 +1498,39 @@ if test "$tre_log" = "TRE"; then
AC_DEFINE([CONFIG_TRE], [1],
[Define as 1 to use the TRE library for regular expression searching. This requires the <tre/regex.h> header file. If you define CONFIG_UTF8 too, then wchar_t must be exactly 32-bit so that it matches unicode_val_T.])
# TRE_CFLAGS will be used only where needed.
LIBS="$LIBS $TRE_LIBS"
#
# Bug 1081: If both TRE and libc define the regfree function,
# ELinks needs to use the version defined by TRE because
# that's the one compatible with regex_t initialized by the
# regwcomp function of TRE. Therefore put $TRE_LIBS at the
# very beginning of $LIBS so that the linker hopefully finds
# regfree there before it examines libc. In particular,
# $PERL_LIBS appears to often include "-lc".
#
# This scheme still risks a crash if ELinks is linked with
# some static library that uses GNU <regex.h> extensions that
# TRE does not implement. For example, the library might call
# re_compile_pattern, which is found in GNU libc, and then
# regfree, which is found in TRE and probably crashes with the
# GNU-initialized regex_t. Ways to avoid such crashes:
#
# - Change TRE so it defines only tre_... functions and does
# not attempt to override the POSIX names by default.
#
# - Change ELinks to access TRE only via dlopen and dlsym.
# The problem then is how to find the correct file name.
# There might be libtre.so.4 and libtre.so.5 with different
# ABI. How can this configure script detect which of them
# matches the <tre/regex.h> in the include path?
#
# - Replace the static library with a shared library. At
# least on GNU/Linux, when the shared library is built, the
# linker should note that e.g. regfree is defined in libc
# and has the GLIBC_2.0 version there, and write that
# version string to the shared library as well; because TRE
# does not provide regfree with that version, any regfree
# calls at run time should then get resolved to libc.
LIBS="$TRE_LIBS $LIBS"
else
TRE_LIBS=
TRE_CFLAGS=

View File

@ -106,7 +106,6 @@ tmpdir=$(mktemp -d -t elinks-dist-XXXXXXXX) || exit 1
git --git-dir="$GIT_DIR" archive --format=tar --prefix="elinks/" "$rev" |
(cd -- "$tmpdir" && tar -xf -)
mkdir -- "$tmpdir/elinks/.git"
printf "%s\n" "$commit" > "$tmpdir/elinks/git-commit-id"
(set -e

View File

@ -159,10 +159,17 @@ static struct option_info http_options[] = {
"risk because it tells web-masters and the FBI sniffers "
"about your language preference.")),
/* After the compression support has been tested enough,
* we might wrap this option in #if CFG_DEBUG. */
/* http://www.eweek.com/c/a/Desktops-and-Notebooks/Intel-Psion-End-Dispute-Concerning-Netbook-Trademark-288875/
* responds with "Transfer-Encoding: chunked" and
* "Content-Encoding: gzip" but does not compress the first chunk
* and the last chunk, causing ELinks to display garbage.
* (If User-Agent includes "Gecko" (case sensitive), then
* that server correctly compresses the whole stream.)
* ELinks should instead report the decompression error (bug 1017)
* or perhaps even blacklist the server for compression and retry.
* Until that has been implemented, disable compression by default. */
INIT_OPT_BOOL("protocol.http", N_("Enable on-the-fly compression"),
"compression", 0, 1,
"compression", 0, 0,
N_("If enabled, the capability to receive compressed content "
"(gzip and/or bzip2) is announced to the server, which "
"usually sends the reply compressed, thus saving some "

View File

@ -0,0 +1,46 @@
/* Partially specialized functions for dumping to a file.
*
* This include file defines a function that dumps the document to a
* file. The function is specialized to one color mode. This is
* supposedly faster than runtime checks. The file that includes this
* file must define several macros to select the specialization.
*
* The following macros must be defined as names of functions that
* this file should define:
*
* - DUMP_FUNCTION_COLOR: The main function. It calls one of the others.
* - DUMP_FUNCTION_UNIBYTE: For dumping in unibyte charsets.
* - DUMP_FUNCTION_UTF8: For dumping in the UTF-8 charset.
* (The function names could be generated with the ## preprocessor
* operator, but that would make grepping more difficult.)
*
* At most one of the following macros may be defined:
*
* - DUMP_COLOR_MODE_16
* - DUMP_COLOR_MODE_256
* - DUMP_COLOR_MODE_TRUE
*/
#define DUMP_FUNCTION_SPECIALIZED DUMP_FUNCTION_UNIBYTE
#include "dump-specialized.h"
#undef DUMP_FUNCTION_SPECIALIZED
#ifdef CONFIG_UTF8
# define DUMP_CHARSET_UTF8
# define DUMP_FUNCTION_SPECIALIZED DUMP_FUNCTION_UTF8
# include "dump-specialized.h"
# undef DUMP_FUNCTION_SPECIALIZED
# undef DUMP_CHARSET_UTF8
#endif /* CONFIG_UTF8 */
static int
DUMP_FUNCTION_COLOR(struct document *document, int fd,
unsigned char buf[D_BUF])
{
#ifdef CONFIG_UTF8
if (is_cp_utf8(document->options.cp))
return DUMP_FUNCTION_UTF8(document, fd, buf);
#endif /* CONFIG_UTF8 */
return DUMP_FUNCTION_UNIBYTE(document, fd, buf);
}

View File

@ -0,0 +1,163 @@
/* Fully specialized functions for dumping to a file.
*
* This include file defines a function that dumps the document to a
* file. The function is specialized to one color mode and one kind
* of charset. This is supposedly faster than runtime checks. The
* file that includes this file must define several macros to select
* the specialization.
*
* The following macro must be defined:
*
* - DUMP_FUNCTION_SPECIALIZED: The name of the function that this
* file should define.
*
* At most one of the following macros may be defined:
*
* - DUMP_COLOR_MODE_16
* - DUMP_COLOR_MODE_256
* - DUMP_COLOR_MODE_TRUE
*
* The following macro may be defined:
*
* - DUMP_CHARSET_UTF8
*/
static int
DUMP_FUNCTION_SPECIALIZED(struct document *document, int fd,
unsigned char buf[D_BUF])
{
int y;
int bptr = 0;
#ifdef DUMP_COLOR_MODE_16
unsigned char color = 0;
const int width = get_opt_int("document.dump.width", NULL);
#elif defined(DUMP_COLOR_MODE_256)
unsigned char foreground = 0;
unsigned char background = 0;
const int width = get_opt_int("document.dump.width", NULL);
#elif defined(DUMP_COLOR_MODE_TRUE)
static const unsigned char color[6] = {255, 255, 255, 0, 0, 0};
const unsigned char *foreground = &color[0];
const unsigned char *background = &color[3];
const int width = get_opt_int("document.dump.width", NULL);
#endif /* DUMP_COLOR_MODE_TRUE */
for (y = 0; y < document->height; y++) {
int white = 0;
int x;
#ifdef DUMP_COLOR_MODE_16
write_color_16(color, fd, buf, &bptr);
#elif defined(DUMP_COLOR_MODE_256)
write_color_256("38", foreground, fd, buf, &bptr);
write_color_256("48", background, fd, buf, &bptr);
#elif defined(DUMP_COLOR_MODE_TRUE)
write_true_color("38", foreground, fd, buf, &bptr);
write_true_color("48", background, fd, buf, &bptr);
#endif /* DUMP_COLOR_MODE_TRUE */
for (x = 0; x < document->data[y].length; x++) {
#ifdef DUMP_CHARSET_UTF8
unicode_val_T c;
const unsigned char *utf8_buf;
#else /* !DUMP_CHARSET_UTF8 */
unsigned char c;
#endif /* !DUMP_CHARSET_UTF8 */
const unsigned char attr
= document->data[y].chars[x].attr;
#ifdef DUMP_COLOR_MODE_16
const unsigned char color1
= document->data[y].chars[x].color[0];
if (color != color1) {
color = color1;
if (write_color_16(color, fd, buf, &bptr))
return -1;
}
#elif defined(DUMP_COLOR_MODE_256)
const unsigned char color1
= document->data[y].chars[x].color[0];
const unsigned char color2
= document->data[y].chars[x].color[1];
if (foreground != color1) {
foreground = color1;
if (write_color_256("38", foreground, fd, buf, &bptr))
return -1;
}
if (background != color2) {
background = color2;
if (write_color_256("48", background, fd, buf, &bptr))
return -1;
}
#elif defined(DUMP_COLOR_MODE_TRUE)
const unsigned char *const new_foreground
= &document->data[y].chars[x].color[0];
const unsigned char *const new_background
= &document->data[y].chars[x].color[3];
if (memcmp(foreground, new_foreground, 3)) {
foreground = new_foreground;
if (write_true_color("38", foreground, fd, buf, &bptr))
return -1;
}
if (memcmp(background, new_background, 3)) {
background = new_background;
if (write_true_color("48", background, fd, buf, &bptr))
return -1;
}
#endif /* DUMP_COLOR_MODE_TRUE */
c = document->data[y].chars[x].data;
if ((attr & SCREEN_ATTR_FRAME)
&& c >= 176 && c < 224)
c = frame_dumb[c - 176];
if (c <= ' ') {
/* Count spaces. */
white++;
continue;
}
/* Print spaces if any. */
while (white) {
if (write_char(' ', fd, buf, &bptr))
return -1;
white--;
}
/* Print normal char. */
#ifdef DUMP_CHARSET_UTF8
utf8_buf = encode_utf8(c);
while (*utf8_buf) {
if (write_char(*utf8_buf++,
fd, buf, &bptr)) return -1;
}
x += unicode_to_cell(c) - 1;
#else /* !DUMP_CHARSET_UTF8 */
if (write_char(c, fd, buf, &bptr))
return -1;
#endif /* !DUMP_CHARSET_UTF8 */
}
#if defined(DUMP_COLOR_MODE_16) || defined(DUMP_COLOR_MODE_256) || defined(DUMP_COLOR_MODE_TRUE)
for (;x < width; x++) {
if (write_char(' ', fd, buf, &bptr))
return -1;
}
#endif /* DUMP_COLOR_MODE_16 || DUMP_COLOR_MODE_256 || DUMP_COLOR_MODE_TRUE */
/* Print end of line. */
if (write_char('\n', fd, buf, &bptr))
return -1;
}
if (hard_write(fd, buf, bptr) != bptr)
return -1;
return 0;
}

View File

@ -51,14 +51,254 @@ static int dump_pos;
static struct download dump_download;
static int dump_redir_count = 0;
static int dump_to_file_16(struct document *document, int fd);
#define D_BUF 65536
static int
write_char(unsigned char c, int fd, unsigned char *buf, int *bptr)
{
buf[(*bptr)++] = c;
if ((*bptr) >= D_BUF) {
if (hard_write(fd, buf, (*bptr)) != (*bptr))
return -1;
(*bptr) = 0;
}
return 0;
}
static int
write_color_16(unsigned char color, int fd, unsigned char *buf, int *bptr)
{
unsigned char bufor[] = "\033[0;30;40m";
unsigned char *data = bufor;
int background = (color >> 4) & 7;
int foreground = color & 7;
bufor[5] += foreground;
if (background) bufor[8] += background;
else {
bufor[6] = 'm';
bufor[7] = '\0';
}
while(*data) {
if (write_char(*data++, fd, buf, bptr)) return -1;
}
return 0;
}
#define DUMP_COLOR_MODE_16
#define DUMP_FUNCTION_COLOR dump_16color
#define DUMP_FUNCTION_UTF8 dump_16color_utf8
#define DUMP_FUNCTION_UNIBYTE dump_16color_unibyte
#include "dump-color-mode.h"
#undef DUMP_COLOR_MODE_16
#undef DUMP_FUNCTION_COLOR
#undef DUMP_FUNCTION_UTF8
#undef DUMP_FUNCTION_UNIBYTE
/* configure --enable-debug uses gcc -Wall -Werror, and -Wall includes
* -Wunused-function, so declaring or defining any unused function
* would break the build. */
#if defined(CONFIG_88_COLORS) || defined(CONFIG_256_COLORS)
static int dump_to_file_256(struct document *document, int fd);
#endif
static int
write_color_256(const unsigned char *str, unsigned char color,
int fd, unsigned char *buf, int *bptr)
{
unsigned char bufor[16];
unsigned char *data = bufor;
snprintf(bufor, 16, "\033[%s;5;%dm", str, color);
while(*data) {
if (write_char(*data++, fd, buf, bptr)) return -1;
}
return 0;
}
#define DUMP_COLOR_MODE_256
#define DUMP_FUNCTION_COLOR dump_256color
#define DUMP_FUNCTION_UTF8 dump_256color_utf8
#define DUMP_FUNCTION_UNIBYTE dump_256color_unibyte
#include "dump-color-mode.h"
#undef DUMP_COLOR_MODE_256
#undef DUMP_FUNCTION_COLOR
#undef DUMP_FUNCTION_UTF8
#undef DUMP_FUNCTION_UNIBYTE
#endif /* defined(CONFIG_88_COLORS) || defined(CONFIG_256_COLORS) */
#ifdef CONFIG_TRUE_COLOR
static int dump_to_file_true_color(struct document *document, int fd);
static int
write_true_color(const unsigned char *str, const unsigned char *color,
int fd, unsigned char *buf, int *bptr)
{
unsigned char bufor[24];
unsigned char *data = bufor;
snprintf(bufor, 24, "\033[%s;2;%d;%d;%dm", str, color[0], color[1], color[2]);
while(*data) {
if (write_char(*data++, fd, buf, bptr)) return -1;
}
return 0;
}
#define DUMP_COLOR_MODE_TRUE
#define DUMP_FUNCTION_COLOR dump_truecolor
#define DUMP_FUNCTION_UTF8 dump_truecolor_utf8
#define DUMP_FUNCTION_UNIBYTE dump_truecolor_unibyte
#include "dump-color-mode.h"
#undef DUMP_COLOR_MODE_TRUE
#undef DUMP_FUNCTION_COLOR
#undef DUMP_FUNCTION_UTF8
#undef DUMP_FUNCTION_UNIBYTE
#endif /* CONFIG_TRUE_COLOR */
#define DUMP_FUNCTION_COLOR dump_nocolor
#define DUMP_FUNCTION_UTF8 dump_nocolor_utf8
#define DUMP_FUNCTION_UNIBYTE dump_nocolor_unibyte
#include "dump-color-mode.h"
#undef DUMP_FUNCTION_COLOR
#undef DUMP_FUNCTION_UTF8
#undef DUMP_FUNCTION_UNIBYTE
/*! @return 0 on success, -1 on error */
static int
dump_references(struct document *document, int fd, unsigned char buf[D_BUF])
{
if (document->nlinks
&& get_opt_bool("document.dump.references", NULL)) {
int x;
unsigned char *header = "\nReferences\n\n Visible links\n";
int headlen = strlen(header);
if (hard_write(fd, header, headlen) != headlen)
return -1;
for (x = 0; x < document->nlinks; x++) {
struct link *link = &document->links[x];
unsigned char *where = link->where;
size_t reflen;
if (!where) continue;
if (document->options.links_numbering) {
if (link->title && *link->title)
snprintf(buf, D_BUF, "%4d. %s\n\t%s\n",
x + 1, link->title, where);
else
snprintf(buf, D_BUF, "%4d. %s\n",
x + 1, where);
} else {
if (link->title && *link->title)
snprintf(buf, D_BUF, " . %s\n\t%s\n",
link->title, where);
else
snprintf(buf, D_BUF, " . %s\n", where);
}
reflen = strlen(buf);
if (hard_write(fd, buf, reflen) != reflen)
return -1;
}
}
return 0;
}
int
dump_to_file(struct document *document, int fd)
{
unsigned char *buf = mem_alloc(D_BUF);
int result;
if (!buf) return -1;
result = dump_nocolor(document, fd, buf);
if (!result)
result = dump_references(document, fd, buf);
mem_free(buf);
return result;
}
/* This dumps the given @cached's formatted output onto @fd. */
static void
dump_formatted(int fd, struct download *download, struct cache_entry *cached)
{
struct document_options o;
struct document_view formatted;
struct view_state vs;
int width;
unsigned char *buf;
if (!cached) return;
memset(&formatted, 0, sizeof(formatted));
init_document_options(NULL, &o);
width = get_opt_int("document.dump.width", NULL);
set_box(&o.box, 0, 1, width, DEFAULT_TERMINAL_HEIGHT);
o.cp = get_opt_codepage("document.dump.codepage", NULL);
o.color_mode = get_opt_int("document.dump.color_mode", NULL);
o.plain = 0;
o.frames = 0;
o.links_numbering = get_opt_bool("document.dump.numbering", NULL);
init_vs(&vs, cached->uri, -1);
render_document(&vs, &formatted, &o);
buf = mem_alloc(D_BUF);
if (buf) {
int result;
switch (o.color_mode) {
case COLOR_MODE_DUMP:
case COLOR_MODE_MONO: /* FIXME: inversion */
result = dump_nocolor(formatted.document, fd, buf);
break;
default:
/* If the desired color mode was not compiled in,
* use 16 colors. */
case COLOR_MODE_16:
result = dump_16color(formatted.document, fd, buf);
break;
#ifdef CONFIG_88_COLORS
case COLOR_MODE_88:
result = dump_256color(formatted.document, fd, buf);
break;
#endif
#ifdef CONFIG_256_COLORS
case COLOR_MODE_256:
result = dump_256color(formatted.document, fd, buf);
break;
#endif
#ifdef CONFIG_TRUE_COLOR
case COLOR_MODE_TRUE_COLOR:
result = dump_truecolor(formatted.document, fd, buf);
break;
#endif
}
if (!result)
dump_references(formatted.document, fd, buf);
mem_free(buf);
} /* if buf */
detach_formatted(&formatted);
destroy_vs(&vs, 1);
}
#undef D_BUF
/* This dumps the given @cached's source onto @fd nothing more. It returns 0 if it
* all went fine and 1 if something isn't quite right and we should terminate
* ourselves ASAP. */
@ -101,64 +341,6 @@ nextfrag:
return 0;
}
/* This dumps the given @cached's formatted output onto @fd. */
static void
dump_formatted(int fd, struct download *download, struct cache_entry *cached)
{
struct document_options o;
struct document_view formatted;
struct view_state vs;
int width;
if (!cached) return;
memset(&formatted, 0, sizeof(formatted));
init_document_options(NULL, &o);
width = get_opt_int("document.dump.width", NULL);
set_box(&o.box, 0, 1, width, DEFAULT_TERMINAL_HEIGHT);
o.cp = get_opt_codepage("document.dump.codepage", NULL);
o.color_mode = get_opt_int("document.dump.color_mode", NULL);
o.plain = 0;
o.frames = 0;
o.links_numbering = get_opt_bool("document.dump.numbering", NULL);
init_vs(&vs, cached->uri, -1);
render_document(&vs, &formatted, &o);
switch(o.color_mode) {
case COLOR_MODE_DUMP:
case COLOR_MODE_MONO: /* FIXME: inversion */
dump_to_file(formatted.document, fd);
break;
default:
/* If the desired color mode was not compiled in,
* use 16 colors. */
case COLOR_MODE_16:
dump_to_file_16(formatted.document, fd);
break;
#ifdef CONFIG_88_COLORS
case COLOR_MODE_88:
dump_to_file_256(formatted.document, fd);
break;
#endif
#ifdef CONFIG_256_COLORS
case COLOR_MODE_256:
dump_to_file_256(formatted.document, fd);
break;
#endif
#ifdef CONFIG_TRUE_COLOR
case COLOR_MODE_TRUE_COLOR:
dump_to_file_true_color(formatted.document, fd);
break;
#endif
}
detach_formatted(&formatted);
destroy_vs(&vs, 1);
}
static unsigned char *
subst_url(unsigned char *str, struct string *url)
{
@ -435,564 +617,3 @@ end:
#endif /* CONFIG_UTF8 */
return string;
}
#define D_BUF 65536
static int
write_char(unsigned char c, int fd, unsigned char *buf, int *bptr)
{
buf[(*bptr)++] = c;
if ((*bptr) >= D_BUF) {
if (hard_write(fd, buf, (*bptr)) != (*bptr))
return -1;
(*bptr) = 0;
}
return 0;
}
static int
write_color_16(unsigned char color, int fd, unsigned char *buf, int *bptr)
{
unsigned char bufor[] = "\033[0;30;40m";
unsigned char *data = bufor;
int background = (color >> 4) & 7;
int foreground = color & 7;
bufor[5] += foreground;
if (background) bufor[8] += background;
else {
bufor[6] = 'm';
bufor[7] = '\0';
}
while(*data) {
if (write_char(*data++, fd, buf, bptr)) return -1;
}
return 0;
}
static int
dump_to_file_16(struct document *document, int fd)
{
int y;
int bptr = 0;
unsigned char *buf = mem_alloc(D_BUF);
unsigned char color = 0;
int width = get_opt_int("document.dump.width", NULL);
if (!buf) return -1;
for (y = 0; y < document->height; y++) {
int white = 0;
int x;
write_color_16(color, fd, buf, &bptr);
for (x = 0; x < document->data[y].length; x++) {
unsigned char c;
unsigned char attr = document->data[y].chars[x].attr;
unsigned char color1 = document->data[y].chars[x].color[0];
if (color != color1) {
color = color1;
if (write_color_16(color, fd, buf, &bptr))
goto fail;
}
c = document->data[y].chars[x].data;
if ((attr & SCREEN_ATTR_FRAME)
&& c >= 176 && c < 224)
c = frame_dumb[c - 176];
if (c <= ' ') {
/* Count spaces. */
white++;
continue;
}
/* Print spaces if any. */
while (white) {
if (write_char(' ', fd, buf, &bptr))
goto fail;
white--;
}
/* Print normal char. */
if (write_char(c, fd, buf, &bptr))
goto fail;
}
for (;x < width; x++) {
if (write_char(' ', fd, buf, &bptr))
goto fail;
}
/* Print end of line. */
if (write_char('\n', fd, buf, &bptr))
goto fail;
}
if (hard_write(fd, buf, bptr) != bptr) {
fail:
mem_free(buf);
return -1;
}
if (document->nlinks
&& get_opt_bool("document.dump.references", NULL)) {
int x;
unsigned char *header = "\nReferences\n\n Visible links\n";
int headlen = strlen(header);
if (hard_write(fd, header, headlen) != headlen)
goto fail;
for (x = 0; x < document->nlinks; x++) {
struct link *link = &document->links[x];
unsigned char *where = link->where;
if (!where) continue;
if (document->options.links_numbering) {
if (link->title && *link->title)
snprintf(buf, D_BUF, "%4d. %s\n\t%s\n",
x + 1, link->title, where);
else
snprintf(buf, D_BUF, "%4d. %s\n",
x + 1, where);
} else {
if (link->title && *link->title)
snprintf(buf, D_BUF, " . %s\n\t%s\n",
link->title, where);
else
snprintf(buf, D_BUF, " . %s\n", where);
}
bptr = strlen(buf);
if (hard_write(fd, buf, bptr) != bptr)
goto fail;
}
}
mem_free(buf);
return 0;
}
/* configure --enable-debug uses gcc -Wall -Werror, and -Wall includes
* -Wunused-function, so declaring or defining any unused function
* would break the build. */
#if defined(CONFIG_88_COLORS) || defined(CONFIG_256_COLORS)
static int
write_color_256(unsigned char *str, unsigned char color, int fd, unsigned char *buf, int *bptr)
{
unsigned char bufor[16];
unsigned char *data = bufor;
snprintf(bufor, 16, "\033[%s;5;%dm", str, color);
while(*data) {
if (write_char(*data++, fd, buf, bptr)) return -1;
}
return 0;
}
static int
dump_to_file_256(struct document *document, int fd)
{
int y;
int bptr = 0;
unsigned char *buf = mem_alloc(D_BUF);
unsigned char foreground = 0;
unsigned char background = 0;
int width = get_opt_int("document.dump.width", NULL);
if (!buf) return -1;
for (y = 0; y < document->height; y++) {
int white = 0;
int x;
write_color_256("38", foreground, fd, buf, &bptr);
write_color_256("48", background, fd, buf, &bptr);
for (x = 0; x < document->data[y].length; x++) {
unsigned char c;
unsigned char attr = document->data[y].chars[x].attr;
unsigned char color1 = document->data[y].chars[x].color[0];
unsigned char color2 = document->data[y].chars[x].color[1];
if (foreground != color1) {
foreground = color1;
if (write_color_256("38", foreground, fd, buf, &bptr))
goto fail;
}
if (background != color2) {
background = color2;
if (write_color_256("48", background, fd, buf, &bptr))
goto fail;
}
c = document->data[y].chars[x].data;
if ((attr & SCREEN_ATTR_FRAME)
&& c >= 176 && c < 224)
c = frame_dumb[c - 176];
if (c <= ' ') {
/* Count spaces. */
white++;
continue;
}
/* Print spaces if any. */
while (white) {
if (write_char(' ', fd, buf, &bptr))
goto fail;
white--;
}
/* Print normal char. */
if (write_char(c, fd, buf, &bptr))
goto fail;
}
for (;x < width; x++) {
if (write_char(' ', fd, buf, &bptr))
goto fail;
}
/* Print end of line. */
if (write_char('\n', fd, buf, &bptr))
goto fail;
}
if (hard_write(fd, buf, bptr) != bptr) {
fail:
mem_free(buf);
return -1;
}
if (document->nlinks
&& get_opt_bool("document.dump.references", NULL)) {
int x;
unsigned char *header = "\nReferences\n\n Visible links\n";
int headlen = strlen(header);
if (hard_write(fd, header, headlen) != headlen)
goto fail;
for (x = 0; x < document->nlinks; x++) {
struct link *link = &document->links[x];
unsigned char *where = link->where;
if (!where) continue;
if (document->options.links_numbering) {
if (link->title && *link->title)
snprintf(buf, D_BUF, "%4d. %s\n\t%s\n",
x + 1, link->title, where);
else
snprintf(buf, D_BUF, "%4d. %s\n",
x + 1, where);
} else {
if (link->title && *link->title)
snprintf(buf, D_BUF, " . %s\n\t%s\n",
link->title, where);
else
snprintf(buf, D_BUF, " . %s\n", where);
}
bptr = strlen(buf);
if (hard_write(fd, buf, bptr) != bptr)
goto fail;
}
}
mem_free(buf);
return 0;
}
#endif /* defined(CONFIG_88_COLORS) || defined(CONFIG_256_COLORS) */
#ifdef CONFIG_TRUE_COLOR
static int
write_true_color(unsigned char *str, unsigned char *color, int fd, unsigned char *buf, int *bptr)
{
unsigned char bufor[24];
unsigned char *data = bufor;
snprintf(bufor, 24, "\033[%s;2;%d;%d;%dm", str, color[0], color[1], color[2]);
while(*data) {
if (write_char(*data++, fd, buf, bptr)) return -1;
}
return 0;
}
static int
dump_to_file_true_color(struct document *document, int fd)
{
static unsigned char color[6] = {255, 255, 255, 0, 0, 0};
int y;
int bptr = 0;
unsigned char *buf = mem_alloc(D_BUF);
unsigned char *foreground = &color[0];
unsigned char *background = &color[3];
int width = get_opt_int("document.dump.width", NULL);
if (!buf) return -1;
for (y = 0; y < document->height; y++) {
int white = 0;
int x;
write_true_color("38", foreground, fd, buf, &bptr);
write_true_color("48", background, fd, buf, &bptr);
for (x = 0; x < document->data[y].length; x++) {
unsigned char c;
unsigned char attr = document->data[y].chars[x].attr;
unsigned char *new_foreground = &document->data[y].chars[x].color[0];
unsigned char *new_background = &document->data[y].chars[x].color[3];
if (memcmp(foreground, new_foreground, 3)) {
foreground = new_foreground;
if (write_true_color("38", foreground, fd, buf, &bptr))
goto fail;
}
if (memcmp(background, new_background, 3)) {
background = new_background;
if (write_true_color("48", background, fd, buf, &bptr))
goto fail;
}
c = document->data[y].chars[x].data;
if ((attr & SCREEN_ATTR_FRAME)
&& c >= 176 && c < 224)
c = frame_dumb[c - 176];
if (c <= ' ') {
/* Count spaces. */
white++;
continue;
}
/* Print spaces if any. */
while (white) {
if (write_char(' ', fd, buf, &bptr))
goto fail;
white--;
}
/* Print normal char. */
if (write_char(c, fd, buf, &bptr))
goto fail;
}
for (;x < width; x++) {
if (write_char(' ', fd, buf, &bptr))
goto fail;
}
/* Print end of line. */
if (write_char('\n', fd, buf, &bptr))
goto fail;
}
if (hard_write(fd, buf, bptr) != bptr) {
fail:
mem_free(buf);
return -1;
}
if (document->nlinks
&& get_opt_bool("document.dump.references", NULL)) {
int x;
unsigned char *header = "\nReferences\n\n Visible links\n";
int headlen = strlen(header);
if (hard_write(fd, header, headlen) != headlen)
goto fail;
for (x = 0; x < document->nlinks; x++) {
struct link *link = &document->links[x];
unsigned char *where = link->where;
if (!where) continue;
if (document->options.links_numbering) {
if (link->title && *link->title)
snprintf(buf, D_BUF, "%4d. %s\n\t%s\n",
x + 1, link->title, where);
else
snprintf(buf, D_BUF, "%4d. %s\n",
x + 1, where);
} else {
if (link->title && *link->title)
snprintf(buf, D_BUF, " . %s\n\t%s\n",
link->title, where);
else
snprintf(buf, D_BUF, " . %s\n", where);
}
bptr = strlen(buf);
if (hard_write(fd, buf, bptr) != bptr)
goto fail;
}
}
mem_free(buf);
return 0;
}
#endif /* CONFIG_TRUE_COLOR */
int
dump_to_file(struct document *document, int fd)
{
int y;
int bptr = 0;
unsigned char *buf = mem_alloc(D_BUF);
if (!buf) return -1;
#ifdef CONFIG_UTF8
if (is_cp_utf8(document->options.cp))
goto utf8;
#endif /* CONFIG_UTF8 */
for (y = 0; y < document->height; y++) {
int white = 0;
int x;
for (x = 0; x < document->data[y].length; x++) {
unsigned char c;
unsigned char attr = document->data[y].chars[x].attr;
c = document->data[y].chars[x].data;
if ((attr & SCREEN_ATTR_FRAME)
&& c >= 176 && c < 224)
c = frame_dumb[c - 176];
if (c <= ' ') {
/* Count spaces. */
white++;
continue;
}
/* Print spaces if any. */
while (white) {
if (write_char(' ', fd, buf, &bptr))
goto fail;
white--;
}
/* Print normal char. */
if (write_char(c, fd, buf, &bptr))
goto fail;
}
/* Print end of line. */
if (write_char('\n', fd, buf, &bptr))
goto fail;
}
#ifdef CONFIG_UTF8
goto ref;
utf8:
for (y = 0; y < document->height; y++) {
int white = 0;
int x;
for (x = 0; x < document->data[y].length; x++) {
unicode_val_T c;
unsigned char attr = document->data[y].chars[x].attr;
c = document->data[y].chars[x].data;
if ((attr & SCREEN_ATTR_FRAME)
&& c >= 176 && c < 224)
c = frame_dumb[c - 176];
else {
unsigned char *utf8_buf = encode_utf8(c);
while (*utf8_buf) {
if (write_char(*utf8_buf++,
fd, buf, &bptr)) goto fail;
}
x += unicode_to_cell(c) - 1;
continue;
}
if (c <= ' ') {
/* Count spaces. */
white++;
continue;
}
/* Print spaces if any. */
while (white) {
if (write_char(' ', fd, buf, &bptr))
goto fail;
white--;
}
/* Print normal char. */
if (write_char(c, fd, buf, &bptr))
goto fail;
}
/* Print end of line. */
if (write_char('\n', fd, buf, &bptr))
goto fail;
}
ref:
#endif /* CONFIG_UTF8 */
if (hard_write(fd, buf, bptr) != bptr) {
fail:
mem_free(buf);
return -1;
}
if (document->nlinks
&& get_opt_bool("document.dump.references", NULL)) {
int x;
unsigned char *header = "\nReferences\n\n Visible links\n";
int headlen = strlen(header);
if (hard_write(fd, header, headlen) != headlen)
goto fail;
for (x = 0; x < document->nlinks; x++) {
struct link *link = &document->links[x];
unsigned char *where = link->where;
if (!where) continue;
if (document->options.links_numbering) {
if (link->title && *link->title)
snprintf(buf, D_BUF, "%4d. %s\n\t%s\n",
x + 1, link->title, where);
else
snprintf(buf, D_BUF, "%4d. %s\n",
x + 1, where);
} else {
if (link->title && *link->title)
snprintf(buf, D_BUF, " . %s\n\t%s\n",
link->title, where);
else
snprintf(buf, D_BUF, " . %s\n", where);
}
bptr = strlen(buf);
if (hard_write(fd, buf, bptr) != bptr)
goto fail;
}
}
mem_free(buf);
return 0;
}
#undef D_BUF