mirror of
https://github.com/rkd77/elinks.git
synced 2024-12-04 14:46:47 -05: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:
commit
822e9d6921
22
NEWS
22
NEWS
@ -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.
|
||||
|
39
configure.in
39
configure.in
@ -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=
|
||||
|
@ -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
|
||||
|
@ -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 "
|
||||
|
46
src/viewer/dump/dump-color-mode.h
Normal file
46
src/viewer/dump/dump-color-mode.h
Normal 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);
|
||||
}
|
163
src/viewer/dump/dump-specialized.h
Normal file
163
src/viewer/dump/dump-specialized.h
Normal 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;
|
||||
}
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user