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

📄 apply.c

📁 一个很有名的浏览器
💻 C
字号:
/* CSS style applier *//* $Id: apply.c,v 1.90.4.2 2005/01/29 01:01:21 jonas Exp $ */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <stdlib.h>#include <string.h>#include "elinks.h"#include "document/css/apply.h"#include "document/css/css.h"#include "document/css/parser.h"#include "document/css/property.h"#include "document/css/scanner.h"#include "document/css/stylesheet.h"#include "document/html/parser/parse.h"#include "document/options.h"#include "util/align.h"#include "util/color.h"#include "util/lists.h"#include "util/error.h"#include "util/memory.h"#include "util/string.h"/* #define DEBUG_CSS *//* TODO: A way to disable CSS completely, PLUS a way to stop various property * groups from taking effect. (Ie. way to turn out effect of 'display: none' * or aligning or colors but keeping all the others.) --pasky */typedef void (*css_applier_t)(struct html_element *element,			      struct css_property *prop);static voidcss_apply_color(struct html_element *element, struct css_property *prop){	assert(prop->value_type == CSS_VT_COLOR);	if (use_document_fg_colors(global_doc_opts))		element->attr.style.fg = prop->value.color;}static voidcss_apply_background_color(struct html_element *element,			   struct css_property *prop){	assert(prop->value_type == CSS_VT_COLOR);	if (use_document_bg_colors(global_doc_opts))		element->attr.style.bg = prop->value.color;}static voidcss_apply_font_attribute(struct html_element *element, struct css_property *prop){	assert(prop->value_type == CSS_VT_FONT_ATTRIBUTE);	element->attr.style.attr |= prop->value.font_attribute.add;	element->attr.style.attr &= ~prop->value.font_attribute.rem;}/* FIXME: Because the current CSS doesn't provide reasonable defaults for each * HTML element this applier will cause bad rendering of <pre> tags. */static voidcss_apply_text_align(struct html_element *element, struct css_property *prop){	assert(prop->value_type == CSS_VT_TEXT_ALIGN);	element->parattr.align = prop->value.text_align;}/* XXX: Sort like the css_property_type */static css_applier_t css_appliers[CSS_PT_LAST] = {	/* CSS_PT_NONE */		NULL,	/* CSS_PT_BACKGROUND */		css_apply_background_color,	/* CSS_PT_BACKGROUND_COLOR */	css_apply_background_color,	/* CSS_PT_COLOR */		css_apply_color,	/* CSS_PT_FONT_STYLE */		css_apply_font_attribute,	/* CSS_PT_FONT_WEIGHT */	css_apply_font_attribute,	/* CSS_PT_TEXT_ALIGN */		css_apply_text_align,	/* CSS_PT_TEXT_DECORATION */	css_apply_font_attribute,	/* CSS_PT_WHITE_SPACE */	css_apply_font_attribute,};/* This looks for a match in list of selectors. */static voidexamine_element(struct css_selector *base,		enum css_selector_type seltype, enum css_selector_relation rel,                struct list_head *selectors, struct html_element *element,                struct list_head *html_stack){	struct css_selector *selector;	unsigned char *code;#ifdef DEBUG_CSS 	DBG("examine_element(%s, %d, %d, %p, %.*s);", base->name, seltype, rel, selectors, element->namelen, element->name);#define dbginfo(sel, type_, base) \	DBG("Matched selector %s (rel %d type %d [m%d])! Children %p !!%d, props !!%d", sel->name, sel->relation, sel->type, sel->type == type_, &sel->leaves, !list_empty(sel->leaves), !list_empty(sel->properties))#else#define dbginfo(sel, type, base)#endif#define process_found_selector(sel, type, base) \	if (selector) { \		dbginfo(sel, type, base); \		merge_css_selectors(base, sel); \		/* Ancestor matches? */ \		if ((struct list_head *) element->next != html_stack) { \			struct html_element *ancestor; \			/* This is less effective than doing reverse iterations,			 * first over sel->leaves and then over the HTML stack,			 * which shines in the most common case where there are			 * no CSR_ANCESTOR selector leaves. However we would			 * have to duplicate the whole examine_element(), so if			 * profiles won't show it really costs... */ \			for (ancestor = element->next; \			     (struct list_head *) ancestor != html_stack;\			     ancestor = ancestor->next) \				examine_element(base,CST_ELEMENT,CSR_ANCESTOR, \						&sel->leaves, ancestor, \						html_stack); \			examine_element(base, CST_ELEMENT, CSR_PARENT, \			                &sel->leaves, element->next, \			                html_stack); \		} \		/* More specific matches? */ \		examine_element(base, type + 1, CSR_SPECIFITY, \		                &sel->leaves, element, html_stack); \	}	if (seltype <= CST_ELEMENT && element->namelen) {		selector = find_css_selector(selectors, CST_ELEMENT, rel,		                             "*", 1);		process_found_selector(selector, CST_ELEMENT, base);		selector = find_css_selector(selectors, CST_ELEMENT, rel,		                             element->name, element->namelen);		process_found_selector(selector, CST_ELEMENT, base);	}	if (!element->options)		return;	/* TODO: More pseudo-classess. --pasky */	if (element->pseudo_class & ELEMENT_LINK) {		selector = find_css_selector(selectors, CST_PSEUDO, rel, "link", -1);		process_found_selector(selector, CST_PSEUDO, base);	}	if (element->pseudo_class & ELEMENT_VISITED) {		selector = find_css_selector(selectors, CST_PSEUDO, rel, "visited", -1);		process_found_selector(selector, CST_PSEUDO, base);	}	code = get_attr_val(element->options, "class");	if (code && seltype <= CST_CLASS) {		selector = find_css_selector(selectors, CST_CLASS, rel, code, -1);		process_found_selector(selector, CST_CLASS, base);	}	if (code) mem_free(code);	code = get_attr_val(element->options, "id");	if (code && seltype <= CST_ID) {		selector = find_css_selector(selectors, CST_ID, rel, code, -1);		process_found_selector(selector, CST_ID, base);	}	if (code) mem_free(code);#undef process_found_selector#undef dbginfo}struct css_selector *get_css_selector_for_element(struct html_element *element, struct css_stylesheet *css,			     struct list_head *html_stack){	unsigned char *code;	struct css_selector *selector;	assert(element && element->options && css);	selector = init_css_selector(NULL, CST_ELEMENT, NULL, 0);	if (!selector)		return NULL;#ifdef DEBUG_CSS	DBG("Applying to element %.*s...", element->namelen, element->name);#endif	examine_element(selector, CST_ELEMENT, CSR_ROOT,	                &css->selectors, element, html_stack);#ifdef DEBUG_CSS	DBG("Element %.*s applied.", element->namelen, element->name);#endif	code = get_attr_val(element->options, "style");	if (code) {		struct css_selector *stylesel;		struct scanner scanner;		stylesel = init_css_selector(NULL, CST_ELEMENT, NULL, 0);		if (stylesel) {			init_scanner(&scanner, &css_scanner_info, code, NULL);			css_parse_properties(&stylesel->properties, &scanner);			merge_css_selectors(selector, stylesel);			done_css_selector(stylesel);		}		mem_free(code);	}	return selector;}voidapply_css_selector_style(struct html_element *element, struct css_selector *selector){	struct css_property *property;	foreach (property, selector->properties) {		assert(property->type < CSS_PT_LAST);		/* We don't assert general prop->value_type here because I		 * don't want hinder properties' ability to potentially make		 * use of multiple value types. */		assert(css_appliers[property->type]);		css_appliers[property->type](element, property);	}}voidcss_apply(struct html_element *element, struct css_stylesheet *css,	  struct list_head *html_stack){	struct css_selector *selector;	selector = get_css_selector_for_element(element, css, html_stack);	if (!selector) return;	apply_css_selector_style(element, selector);	done_css_selector(selector);}

⌨️ 快捷键说明

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