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

📄 document.c

📁 一个很有名的浏览器
💻 C
字号:
/* The document base functionality *//* $Id: document.c,v 1.89.2.2 2005/04/05 21:08:40 jonas Exp $ */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include "elinks.h"#include "cache/cache.h"#include "config/options.h"#include "document/document.h"#include "document/forms.h"#include "document/html/frames.h"#include "document/html/parser.h"#include "document/html/parser/parse.h"#include "document/html/renderer.h"#include "document/options.h"#include "document/refresh.h"#include "modules/module.h"#include "protocol/uri.h"#include "terminal/draw.h"#include "util/color.h"#include "util/error.h"#include "util/lists.h"#include "util/memory.h"#include "util/object.h"#include "util/string.h"#include "viewer/text/link.h"static INIT_LIST_HEAD(format_cache);struct document *init_document(struct cache_entry *cached, struct document_options *options){	struct document *document = mem_calloc(1, sizeof(*document));	if (!document) return NULL;	document->uri = get_uri_reference(cached->uri);	object_lock(cached);	document->id = cached->id;	init_list(document->forms);	init_list(document->tags);	init_list(document->nodes);#ifdef CONFIG_ECMASCRIPT	init_list(document->onload_snippets);#endif	object_nolock(document, "document");	object_lock(document);	copy_opt(&document->options, options);	global_doc_opts = &document->options;	add_to_list(format_cache, document);	return document;}static voidfree_frameset_desc(struct frameset_desc *frameset_desc){	int i;	for (i = 0; i < frameset_desc->n; i++) {		struct frame_desc *frame_desc = &frameset_desc->frame_desc[i];		if (frame_desc->subframe)			free_frameset_desc(frame_desc->subframe);		mem_free_if(frame_desc->name);		if (frame_desc->uri)			done_uri(frame_desc->uri);	}	mem_free(frameset_desc);}voiddone_link_members(struct link *link){	if (link->event_hooks) {		struct script_event_hook *evhook, *safety;		foreachsafe (evhook, safety, *link->event_hooks) {			mem_free_if(evhook->src);			mem_free(evhook);		}		mem_free(link->event_hooks);	}	mem_free_if(get_link_name(link));	mem_free_if(link->where);	mem_free_if(link->target);	mem_free_if(link->title);	mem_free_if(link->where_img);	mem_free_if(link->points);}voiddone_document(struct document *document){	struct cache_entry *cached;	int pos;	assert(document);	if_assert_failed return;	assertm(!is_object_used(document), "Attempt to free locked formatted data.");	if_assert_failed return;	cached = find_in_cache(document->uri);	if (!cached)		INTERNAL("no cache entry for document");	else		object_unlock(cached);	if (document->uri) done_uri(document->uri);	mem_free_if(document->title);	if (document->frame_desc) free_frameset_desc(document->frame_desc);	if (document->refresh) done_document_refresh(document->refresh);	for (pos = 0; pos < document->nlinks; pos++) {		done_link_members(&document->links[pos]);	}	mem_free_if(document->links);	if (document->data) {		for (pos = 0; pos < document->height; pos++)			mem_free_if(document->data[pos].chars);		mem_free(document->data);	}	mem_free_if(document->lines1);	mem_free_if(document->lines2);	mem_free_if(document->options.framename);	while (!list_empty(document->forms)) {		done_form(document->forms.next);	}#ifdef CONFIG_CSS	free_uri_list(&document->css_imports);#endif#ifdef CONFIG_ECMASCRIPT	free_string_list(&document->onload_snippets);	free_uri_list(&document->ecmascript_imports);#endif	free_list(document->tags);	free_list(document->nodes);	mem_free_if(document->search);	mem_free_if(document->slines1);	mem_free_if(document->slines2);	/* Blast off global document option pointer if we are the `owner'	 * so we don't have a dangling pointer. */	if (global_doc_opts == &document->options)		global_doc_opts = NULL;	del_from_list(document);	mem_free(document);}voidrelease_document(struct document *document){	assert(document);	if_assert_failed return;	if (document->refresh) kill_document_refresh(document->refresh);	object_unlock(document);	del_from_list(document);	add_to_list(format_cache, document);}/* Formatted document cache management *//* ECMAScript doesn't like anything like CSS since it doesn't modify the * formatted document (yet). */#if CONFIG_CSSunsigned longget_document_css_magic(struct document *document){	unsigned long css_magic = 0;	struct uri *uri;	int index;	foreach_uri (uri, index, &document->css_imports) {		struct cache_entry *cached = find_in_cache(uri);		if (cached) css_magic += cached->id + cached->data_size;	}	return css_magic;}#define check_document_css_magic(document) \	((document)->css_magic == get_document_css_magic(document))#else#define check_document_css_magic(document) 1#endifstruct document *get_cached_document(struct cache_entry *cached, struct document_options *options){	struct document *document, *next;	foreachsafe (document, next, format_cache) {		if (!compare_uri(document->uri, cached->uri, 0)		    || compare_opt(&document->options, options))			continue;		if (options->no_cache		    || cached->id != document->id		    || !check_document_css_magic(document)) {			if (!is_object_used(document)) {				done_document(document);			}			continue;		}		/* Reactivate */		del_from_list(document);		add_to_list(format_cache, document);		object_lock(document);		return document;	}	return NULL;}voidshrink_format_cache(int whole){	struct document *document, *next;	int format_cache_size = get_opt_int("document.cache.format.size");	int format_cache_entries = 0;	foreachsafe (document, next, format_cache) {		struct cache_entry *cached;		if (is_object_used(document)) continue;		format_cache_entries++;		/* Destroy obsolete renderer documents which are already		 * out-of-sync. */		cached = find_in_cache(document->uri);		assertm(cached, "cached formatted document has no cache entry");		if (cached->id == document->id) continue;		done_document(document);		format_cache_entries--;	}	assertm(format_cache_entries >= 0, "format_cache_entries underflow on entry");	if_assert_failed format_cache_entries = 0;	foreachback (document, format_cache) {		if (is_object_used(document)) continue;		/* If we are not purging the whole format cache, stop		 * once we are below the maximum number of entries. */		if (!whole && format_cache_entries <= format_cache_size)			break;		/* Jump back to already processed entry (or list head), and let		 * the foreachback move it to the next entry to go. */		document = document->next;		done_document(document->prev);		format_cache_entries--;	}	assertm(format_cache_entries >= 0, "format_cache_entries underflow");	if_assert_failed format_cache_entries = 0;}longformatted_info(int type){	int i = 0;	struct document *document;	switch (type) {		case INFO_FILES:			foreach (document, format_cache) i++;			return i;		case INFO_LOCKED:			foreach (document, format_cache)				i += is_object_used(document);			return i;		case INFO_TIMERS:			foreach (document, format_cache)				if (document->refresh				    && document->refresh->timer != -1)					i++;			return i;	}	return 0;}static voidinit_documents(struct module *module){	init_tags_lookup();}static voiddone_documents(struct module *module){	free_tags_lookup();	free_table_cache();}struct module document_module = struct_module(	/* name: */		"Document",	/* options: */		NULL,	/* hooks: */		NULL,	/* submodules: */	NULL,	/* data: */		NULL,	/* init: */		init_documents,	/* done: */		done_documents);

⌨️ 快捷键说明

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