⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dump.c

📁 一个很有名的浏览器
💻 C
字号:
/* Support for dumping to the file on startup (w/o bfu) *//* $Id: dump.c,v 1.150.2.3 2005/04/05 21:08:43 jonas Exp $ */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <errno.h>#include <stdio.h>#include <string.h>#include <sys/types.h> /* NetBSD flavour */#ifdef HAVE_SYS_SIGNAL_H#include <sys/signal.h>#endif#ifdef HAVE_FCNTL_H#include <fcntl.h> /* OS/2 needs this after sys/types.h */#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include "elinks.h"#include "cache/cache.h"#include "config/options.h"#include "document/document.h"#include "document/options.h"#include "document/renderer.h"#include "document/view.h"#include "intl/gettext/libintl.h"#include "lowlevel/select.h"#include "main.h"#include "osdep/ascii.h"#include "osdep/osdep.h"#include "protocol/protocol.h"#include "protocol/uri.h"#include "sched/connection.h"#include "sched/error.h"#include "terminal/color.h"#include "terminal/hardio.h"#include "terminal/terminal.h"#include "util/memory.h"#include "util/string.h"#include "viewer/dump/dump.h"#include "viewer/text/view.h"#include "viewer/text/vs.h"static int dump_pos;static struct download dump_download;static int dump_redir_count = 0;/* 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. */static intdump_source(int fd, struct download *status, struct cache_entry *cached){	struct fragment *frag;	if (!cached) return 0;nextfrag:	foreach (frag, cached->frag) {		int d = dump_pos - frag->offset;		int l, w;		if (d < 0 || frag->length <= d)			continue;		l = frag->length - d;		w = hard_write(fd, frag->data + d, l);		if (w != l) {			detach_connection(status, dump_pos);			if (w < 0)				ERROR(gettext("Can't write to stdout: %s"),				      (unsigned char *) strerror(errno));			else				ERROR(gettext("Can't write to stdout."));			retval = RET_ERROR;			return 1;		}		dump_pos += w;		detach_connection(status, dump_pos);		goto nextfrag;	}	return 0;}/* This dumps the given @cached's formatted output onto @fd. */static voiddump_formatted(int fd, struct download *status, struct cache_entry *cached){	struct document_options o;	struct document_view formatted;	struct view_state vs;	int width;	if (!cached) return;	memset(&vs, 0, sizeof(vs));	memset(&formatted, 0, sizeof(formatted));	get_opt_bool("document.browse.links.numbering") =		!get_cmd_opt_bool("no-numbering");	init_document_options(&o);	width = get_opt_int("document.dump.width");	set_box(&o.box, 0, 1, width, DEFAULT_TERMINAL_HEIGHT);	o.cp = get_opt_codepage("document.dump.codepage");	o.color_mode = COLOR_MODE_DUMP;	o.plain = 0;	o.frames = 0;	init_vs(&vs, cached->uri, -1);	render_document(&vs, &formatted, &o);	dump_to_file(formatted.document, fd);	detach_formatted(&formatted);	destroy_vs(&vs, 1);}static unsigned char *subst_url(unsigned char *str, struct string *url){	struct string string;	if (!init_string(&string)) return NULL;	while (*str) {		int p;		for (p = 0; str[p] && str[p] != '%' && str[p] != '\\'; p++);		add_bytes_to_string(&string, str, p);		str += p;		if (*str == '\\') {			unsigned char ch;			str++;			switch (*str) {				case 'f':					ch = '\f';					break;				case 'n':					ch = '\n';					break;				case 't':					ch = '\t';					break;				default:					ch = *str;			}			if (*str) {				add_char_to_string(&string, ch);				str++;			}			continue;		} else if (*str != '%') {			break;		}		str++;		switch (*str) {			case 'u':				if (url) add_string_to_string(&string, url);				break;		}		if (*str) str++;	}	return string.source;}static voiddump_print(unsigned char *option, struct string *url){	unsigned char *str = get_opt_str(option);	if (str) {		unsigned char *realstr = subst_url(str, url);		if (realstr) {			printf("%s", realstr);			fflush(stdout);			mem_free(realstr);		}	}}static voiddump_loading_callback(struct download *status, void *p){	struct cache_entry *cached = status->cached;	int fd = get_output_handle();	if (fd == -1) return;	if (cached && cached->redirect && dump_redir_count++ < MAX_REDIRECTS) {		struct uri *uri = cached->redirect;		if (is_in_progress_state(status->state))			change_connection(status, NULL, PRI_CANCEL, 0);		load_uri(uri, cached->uri, status, PRI_MAIN, 0, -1);		return;	}	if (is_in_queued_state(status->state)) return;	if (get_cmd_opt_bool("dump")) {		if (is_in_transfering_state(status->state))			return;		dump_formatted(fd, status, cached);	} else {		if (dump_source(fd, status, cached) > 0)			goto terminate;		if (is_in_progress_state(status->state))			return;	}	if (status->state != S_OK) {		usrerror(get_err_msg(status->state, NULL));		retval = RET_ERROR;		goto terminate;	}terminate:	terminate = 1;	dump_next(NULL);}static voiddump_start(unsigned char *url){	unsigned char *wd = get_cwd();	struct uri *uri = get_translated_uri(url, wd);	mem_free_if(wd);	if (!uri || get_protocol_external_handler(uri->protocol)) {		usrerror(gettext("URL protocol not supported (%s)."), url);		goto terminate;	}	dump_download.callback = dump_loading_callback;	dump_pos = 0;	if (load_uri(uri, NULL, &dump_download, PRI_MAIN, 0, -1)) {terminate:		dump_next(NULL);		terminate = 1;		retval = RET_SYNTAX;	}	if (uri) done_uri(uri);}voiddump_next(struct list_head *url_list){	static INIT_LIST_HEAD(todo_list);	static INIT_LIST_HEAD(done_list);	struct string_list_item *item;	if (url_list) {		/* Steal all them nice list items but keep the same order */		while (!list_empty(*url_list)) {			item = url_list->next;			del_from_list(item);			add_to_list_end(todo_list, item);		}	}	/* Dump each url list item one at a time */	if (!list_empty(todo_list)) {		static int first = 1;		terminate = 0;		item = todo_list.next;		del_from_list(item);		add_to_list(done_list, item);		if (!first) {			dump_print("document.dump.separator", NULL);		} else {			first = 0;		}		dump_print("document.dump.header", &item->string);		dump_start(item->string.source);		/* XXX: I think it ought to print footer at the end of		 * the whole dump (not only this file). Testing required.		 * --pasky */		dump_print("document.dump.footer", &item->string);	} else {		free_string_list(&done_list);		terminate = 1;	}}/* Using this function in dump_to_file() is unfortunately slightly slower than * the current code.  However having this here instead of in the scripting * backends is better. */struct string *add_document_to_string(struct string *string, struct document *document){	int y;	assert(string && document);	if_assert_failed return NULL;	for (y = 0; y < document->height; y++) {		struct screen_char *pos = document->data[y].chars;		int white = 0;		int x;		for (x = 0; x < document->data[y].length; x++) {			unsigned char data = pos->data;			unsigned int frame = (pos->attr & SCREEN_ATTR_FRAME);			if (!isscreensafe(data)) {				white++;				continue;			} else if (frame && data >= 176 && data < 224) {				data = frame_dumb[data - 176];				if (data <= ' ') {					/* Count spaces. */					white++;				} else {					/* Print spaces if any. */					if (white) {						add_xchar_to_string(string, ' ', white);						white = 0;					}					add_char_to_string(string, data);				}			}		}		add_char_to_string(string, '\n');	}	return string;}#define D_BUF	65536static intwrite_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;}intdump_to_file(struct document *document, int fd){	int y;	int bptr = 0;	unsigned char *buf = mem_alloc(D_BUF);	if (!buf) return -1;	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;	}	if (hard_write(fd, buf, bptr) != bptr) {fail:		mem_free(buf);		return -1;	}	if (document->nlinks && !get_cmd_opt_bool("no-references")) {		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 (get_opt_bool("document.browse.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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -