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

📄 renderer.c

📁 一个很有名的浏览器
💻 C
📖 第 1 页 / 共 2 页
字号:
/* HTML renderer *//* $Id: renderer.c,v 1.140.2.3 2005/04/05 21:08:41 jonas Exp $ */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <ctype.h>#include <stdarg.h>#include <stdlib.h>#include <string.h>#include "elinks.h"#include "cache/cache.h"#include "config/options.h"#include "document/document.h"#include "document/dom/renderer.h"#include "document/html/frames.h"#include "document/html/renderer.h"#include "document/plain/renderer.h"#include "document/renderer.h"#include "document/view.h"#include "ecmascript/ecmascript.h"#include "intl/charsets.h"#include "main.h"#include "protocol/header.h"#include "protocol/protocol.h"#include "protocol/uri.h"#include "sched/session.h"#include "terminal/terminal.h"#include "terminal/window.h"#include "util/error.h"#include "util/memory.h"#include "util/object.h"#include "util/string.h"#include "viewer/text/view.h"#include "viewer/text/vs.h"static void sort_links(struct document *document);#ifdef CONFIG_ECMASCRIPT/* XXX: This function is de facto obsolete, since we do not need to copy * snippets around anymore (we process them in one go after the document is * loaded; gradual processing was practically impossible because the snippets * could reorder randomly during the loading - consider i.e. * <body onLoad><script></body>: first just <body> is loaded, but then the * rest of the document is loaded and <script> gets before <body>; do not even * imagine the trouble with rewritten (through scripting hooks) documents; * besides, implementing document.write() will be much simpler). * But I want to take no risk by reworking that now. --pasky */static voidadd_snippets(struct ecmascript_interpreter *interpreter,             struct list_head *doc_snippets, struct list_head *queued_snippets){	struct string_list_item *doc_current = doc_snippets->next;#ifdef CONFIG_LEDS	if (list_empty(*queued_snippets) && interpreter->vs->doc_view->session)		interpreter->vs->doc_view->session->status.ecmascript_led->value = '-';#endif	if (list_empty(*doc_snippets) || !get_opt_bool("ecmascript.enable"))		return;	/* We do this all only once per view_state now. */	if (!list_empty(*queued_snippets)) {		/* So if we already did it, we shouldn't need to do it again.		 * This is the case of moving around in history - we have all		 * what happenned recorded in the view_state and needn't bother		 * again. */#ifdef CONFIG_DEBUG		/* Hopefully. */		struct string_list_item *iterator = queued_snippets->next;		while (iterator != (struct string_list_item *) queued_snippets) {			if (doc_current == (struct string_list_item *) doc_snippets) {				INTERNAL("add_snippets(): doc_snippets shorter than queued_snippets!");				return;			}#if 0			DBG("Comparing snippets\n%.*s\n###### vs #####\n%.*s\n #####",			    iterator->string.length, iterator->string.source,			    doc_current->string.length, doc_current->string.source);#endif			assert(!strlcmp(iterator->string.source,			                iterator->string.length,			                doc_current->string.source,			                doc_current->string.length));			doc_current = doc_current->next;			iterator = iterator->next;		}#endif		return;	}	assert(doc_current);	for (; doc_current != (struct string_list_item *) doc_snippets;	     doc_current = doc_current->next) {		add_to_string_list(queued_snippets, doc_current->string.source,		                   doc_current->string.length);#if 0		DBG("Adding snippet\n%.*s\n #####",		    doc_current->string.length,		    doc_current->string.source);#endif	}}static voidprocess_snippets(struct ecmascript_interpreter *interpreter,                 struct list_head *snippets, struct string_list_item **current){	if (!*current)		*current = snippets->next;	for (; *current != (struct string_list_item *) snippets;	     (*current) = (*current)->next) {		struct string *string = &(*current)->string;		unsigned char *uristring;		struct uri *uri;		struct cache_entry *cached;		struct fragment *fragment;		if (string->length == 0)			continue;		if (*string->source != '^') {			/* Evaluate <script>code</script> snippet */			ecmascript_eval(interpreter, string);			continue;		}		/* Eval external <script src="reference"></script> snippet */		uristring = string->source + 1;		if (!*uristring) continue;		uri = get_uri(uristring, URI_BASE);		if (!uri) continue;		cached = get_redirected_cache_entry(uri);		done_uri(uri);		if (!cached) {			/* At this time (!gradual_rerendering), we should've			 * already retrieved this though. So it must've been			 * that it went away because unused and the cache was			 * already too full. */#if 0			/* Disabled because gradual rerendering can be triggered			 * by numerous events other than a ecmascript reference			 * completing like the original document and CSS. Problem			 * is that we should never continue this loop but rather			 * break out if that is the case. Somehow we need to			 * be able to derive URI loading problems at this point			 * or maybe remove reference snippets if they fail to load.			 *			 * This FIFO queue handling should be used for also CSS			 * imports so it would be cool if it could be general			 * enough for that. Using it for frames with the FIFOing			 * disabled probably wouldn't hurt either.			 *			 * To top this thing off it would be nice if it also			 * handled dependency tracking between references so that			 * CSS documents will not disappear from the cache			 * before all referencing HTML documents has been deleted			 * from it.			 *			 * Reported as bug 533. */			/* Pasky's explanation: If we get the doc in a single			 * shot, before calling draw_formatted() we didn't have			 * anything additional queued for loading and the cache			 * entry was already loaded, so we didn't get			 * gradual_loading set. But then while parsing the			 * document we got some external references and trying			 * to process them right now. Boom.			 *			 * The obvious solution would be to always call			 * draw_formatted() with gradual_loading in			 * doc_loading_callback() and if we are sure the			 * loading is really over, call it one more time			 * without gradual_loading set. I'm not sure about			 * the implications though so I won't do it before			 * 0.10.0. --pasky */			ERROR("The script of %s was lost in too full a cache!",			      uristring);#endif			continue;		}		fragment = get_cache_fragment(cached);		if (fragment) {			struct string code = INIT_STRING(fragment->data, fragment->length);			ecmascript_eval(interpreter, &code);		}	}}#endifstatic voidrender_encoded_document(struct cache_entry *cached, struct document *document){	struct uri *uri = cached->uri;	enum stream_encoding encoding = ENCODING_NONE;	unsigned char *extension;	struct fragment *fragment = get_cache_fragment(cached);	struct string buffer = INIT_STRING("", 0);	/* Even empty documents have to be rendered so that info in the protocol	 * header, such as refresh info, get processed. (bug 625) */	if (fragment) {		buffer.source = fragment->data;		buffer.length = fragment->length;	}	extension = get_extension_from_uri(uri);	if (extension) {		encoding = guess_encoding(extension);		mem_free(extension);	}	if (encoding != ENCODING_NONE) {		int length = 0;		unsigned char *source;		source = decode_encoded_buffer(encoding, buffer.source,					       buffer.length, &length);		if (source) {			buffer.source = source;			buffer.length = length;		} else {			encoding = ENCODING_NONE;		}	}	if (document->options.plain) {#ifdef CONFIG_DOM		if (cached->content_type		    && !strlcasecmp("text/html", 9, cached->content_type, -1))			render_dom_document(cached, document, &buffer);		else#endif			render_plain_document(cached, document, &buffer);	} else {		render_html_document(cached, document, &buffer);	}	if (encoding != ENCODING_NONE) {		done_string(&buffer);	}}voidrender_document(struct view_state *vs, struct document_view *doc_view,		struct document_options *options){	unsigned char *name;	struct document *document;	struct cache_entry *cached;	assert(vs && doc_view && options);	if_assert_failed return;#if 0	DBG("(Re%d)Rendering %s on doc_view %p [%s] while attaching it to %p",	    options->gradual_rerendering, struri(vs->uri),	    doc_view, doc_view->name, vs);#endif	name = doc_view->name;	doc_view->name = NULL;	detach_formatted(doc_view);	doc_view->name = name;	doc_view->vs = vs;	doc_view->last_x = doc_view->last_y = -1;#if 0	/* This is a nice idea, but doesn't always work: in particular when	 * there's a frame name conflict. You loaded something to the vs'	 * frame, but later something tried to get loaded to a frame with	 * the same name and we got back this frame again, so we are now	 * overriding the original document with a cuckoo. This assert()ion	 * should be re-enabled when we start to get this right (which is	 * very complex, but someone should rewrite the frames support	 * anyway). --pasky */	assert(!vs->doc_view);#else	if (vs->doc_view) {		/* It will be still detached, no worries - hopefully it still		 * resides in ses->scrn_frames. */

⌨️ 快捷键说明

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