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

📄 html_gr.c

📁 ELinks is an advanced and well-established feature-rich text mode web (HTTP/FTP/..) browser. ELinks
💻 C
📖 第 1 页 / 共 3 页
字号:
/* html_gr.c * HTML parser in graphics mode * (c) 2002 Mikulas Patocka * This file is a part of the Links program, released under GPL. */#include "cfg.h"#define format format_#ifdef G#include "links.h"/* prototypes */int gray (int, int, int);int too_near(int, int, int, int, int, int);void separate_fg_bg(int *, int *, int *, int, int, int);unsigned char *make_html_font_name(int);int get_real_font_size(int size);struct style *get_style_by_ta(struct text_attrib *);void split_line_object(struct g_part *, struct g_object_text *, unsigned char *);void g_line_break(struct g_part *);void g_html_form_control(struct g_part *, struct form_control *);void do_image(struct g_part *, struct image_description *);void g_hr(struct g_part *p, struct hr_param *hr);void *g_html_special(struct g_part *, int, ...);void g_do_format(char *, char *, struct g_part *, unsigned char *);void g_scan_width(struct g_object **, int, int *);void g_scan_lines(struct g_object_line **, int, int *);int g_put_chars_conv(struct g_part *, unsigned char *, int);int g_nobreak;int get_real_font_size(int size){	int fs=d_opt->font_size;		if (size < 1) size = 1;	if (size > 7) size = 7;	switch (size) {		case 1:	return (14*fs)>>4;		case 2: return (15*fs)>>4;		case 3: return (16*fs)>>4;		case 4: return (19*fs)>>4;		case 5: return (22*fs)>>4;		case 6: return (25*fs)>>4;		case 7: return (28*fs)>>4;	}	return 0;}struct background *get_background(unsigned char *bg, unsigned char *bgcolor){	struct background *b;	struct rgb r;	b = mem_alloc(sizeof(struct background));	/* !!! FIXME: background image */	{		b->img = 0;		if (bgcolor && !decode_color(bgcolor, &r)) {			b->u.sRGB=(r.r << 16) + (r.g << 8) + r.b;		} else {			b->u.sRGB=(d_opt->default_bg.r << 16) + (d_opt->default_bg.g << 8) + d_opt->default_bg.b;		}	}	return b;}void g_put_chars(struct g_part *, unsigned char *, int);#define CH_BUF	256int g_put_chars_conv(struct g_part *p, unsigned char *c, int l){	static char buffer[CH_BUF];	int bp = 0;	int pp = 0;	int total = 0;	if (format.attr & AT_GRAPHICS) {		g_put_chars(p, c, l);		return l;	}	/*{		debug("\"%.*s\"", l, c);	}*/	if (!l) g_put_chars(p, NULL, 0);	while (pp < l) {		unsigned char *e;		if (c[pp] < 128 && c[pp] != '&') {			put_c:			if (!(buffer[bp++] = c[pp++])) buffer[bp - 1] = ' ';			if (bp < CH_BUF) continue;			goto flush;		}		if (c[pp] != '&') {			struct conv_table *t;			int i;			if (!convert_table) goto put_c;			t = convert_table;			i = pp;			decode:			if (!t[c[i]].t) {				e = t[c[i]].u.str;			} else {				t = t[c[i++]].u.tbl;				if (i >= l) goto put_c;				goto decode;			}			pp = i + 1;		} else {			int i = pp + 1;			if (d_opt->plain & 1) goto put_c;			while (i < l && c[i] != ';' && c[i] != '&' && c[i] > ' ') i++;			if (!(e = get_entity_string(&c[pp + 1], i - pp - 1, d_opt->cp))) goto put_c;			pp = i + (i < l && c[i] == ';');		}		if (!e[0]) continue;		if (!e[1]) {			buffer[bp++] = e[0];			if (bp < CH_BUF) continue;			flush:			e = "";			goto flush1;		}		while (*e) {			buffer[bp++] = *(e++);			if (bp < CH_BUF) continue;			flush1:			g_put_chars(p, buffer, bp);			while (bp) if ((buffer[--bp] & 0xc0) != 0x80) total++;		}	}	if (bp) g_put_chars(p, buffer, bp);	while (bp) if ((buffer[--bp] & 0xc0) != 0x80) total++;	return total;}/* Returns 0 to 2550 */int gray (int r, int g, int b){	return r*3+g*6+b;}/* Tells if two colors are too near to be legible one on another *//* 1=too near 0=not too near */int too_near(int r1, int g1, int b1, int r2, int g2, int b2){	int gray1,gray2;	gray1=gray(r1, g1, b1);	gray2=gray(r2, g2, b2);	if (gray1<=gray2)		return gray2-gray1<=400;	else		return gray1-gray2<=400;}/* Fixes foreground based on background */void separate_fg_bg(int *fgr, int *fgg, int *fgb	, int bgr, int bgg, int bgb){	if (too_near(*fgr, *fgg, *fgb, bgr, bgg, bgb)){		*fgr=255-bgr;		*fgg=255-bgg;		*fgb=255-bgb;	}else return;	if (too_near(*fgr, *fgg, *fgb, bgr, bgg, bgb)){		if (gray(bgr, bgg, bgb)<=1275)			*fgr=*fgg=*fgb=255;		else			*fgr=*fgg=*fgb=0;	}}unsigned char *make_html_font_name(int attr){	unsigned char *str;	int len;		str=init_str();len=0;	add_to_str(&str, &len, G_HTML_DEFAULT_FAMILY);	add_to_str(&str, &len, attr & AT_BOLD ? "-bold" : "-medium");	add_to_str(&str, &len, attr & AT_ITALIC ? "-italic-serif" :			"-roman-serif");	add_to_str(&str, &len, attr & AT_FIXED ? "-mono" : "-vari");	return str;}struct style *get_style_by_ta(struct text_attrib *ta){	int fg_r,fg_g,fg_b; /* sRGB 0-255 values */	int fs = get_real_font_size(ta->fontsize);	struct style*stl;	unsigned char *fontname;	fg_r=ta->fg.r;	fg_g=ta->fg.g;	fg_b=ta->fg.b;	separate_fg_bg(&fg_r,&fg_g,&fg_b,ta->bg.r,ta->bg.g,ta->bg.b);	stl = g_get_style((fg_r << 16) + (fg_g << 8) + fg_b, (ta->bg.r << 16) +			(ta->bg.g << 8) + ta->bg.b, fs, 			fontname=make_html_font_name(ta->attr),			ta->attr & AT_UNDERLINE ? FF_UNDERLINE : 0);	mem_free(fontname);	return stl;}#define rm(x) ((x).width - (x).rightmargin * G_HTML_MARGIN > 0 ? (x).width - (x).rightmargin * G_HTML_MARGIN : 0)#ifndef SPADstatic inline int pw2(int a){	int x = 1;	while (x < a && x) {		if ((unsigned)x > MAXINT / 2) overalloc();		x <<= 1;	}	return x;}#elsestatic inline int pw2(int a){	return a;}#endifvoid flush_pending_line_to_obj(struct g_part *p, int minheight){	int i, pp, pos, w, lbl;	struct g_object_line *l = p->line;	struct g_object_area *a;	if (!l) {		return;	}	for (i = l->n_entries - 1; i >= 0; i--) {		struct g_object_text *go = (struct g_object_text *)l->entries[i];		if (go->draw == g_text_draw) {			int l;			while ((l = strlen(go->text)) && go->text[l - 1] == ' ') go->text[l - 1] = 0, go->xw -= g_char_width(go->style, ' ');			if (go->xw < 0) internal("xw(%d) < 0", go->xw);		}		if (!go->xw) continue;		break;	}	scan_again:	pp = 0;	w = minheight;	lbl = 0;	for (i = 0; i < l->n_entries; i++) {		int yy = l->entries[i]->y;		if (yy >= G_OBJ_ALIGN_SPECIAL) yy = 0;		pp += l->entries[i]->xw;		if (l->entries[i]->xw && l->entries[i]->yw + yy > w) w = l->entries[i]->yw + yy;		if (yy < lbl) lbl = yy;	}	if (lbl < 0) {		for (i = 0; i < l->n_entries; i++) {			if (l->entries[i]->y < G_OBJ_ALIGN_SPECIAL) l->entries[i]->y -= lbl;		}		goto scan_again;	}	if (par_format.align == AL_CENTER) pos = (rm(par_format) + par_format.leftmargin * G_HTML_MARGIN - pp) / 2;	else if (par_format.align == AL_RIGHT) pos = rm(par_format) - pp;	else pos = par_format.leftmargin * G_HTML_MARGIN;	if (pos < par_format.leftmargin * G_HTML_MARGIN) pos = par_format.leftmargin * G_HTML_MARGIN;	pp = pos;	for (i = 0; i < l->n_entries; i++) {		l->entries[i]->x = pp;		pp += l->entries[i]->xw;		if (l->entries[i]->y < G_OBJ_ALIGN_SPECIAL) {			l->entries[i]->y = w - l->entries[i]->yw - l->entries[i]->y;		} else if (l->entries[i]->y == G_OBJ_ALIGN_TOP) {			l->entries[i]->y = 0;		} else if (l->entries[i]->y == G_OBJ_ALIGN_MIDDLE) {			l->entries[i]->y = (w - l->entries[i]->yw + 1) / 2;		}	}	l->x = 0;	l->xw = par_format.width;	l->yw = w;	l->y = p->cy;	if (l->xw > p->root->xw) p->root->xw = l->xw;	p->root->yw = p->cy += w;	p->root->n_lines++;	if ((unsigned)p->root->n_lines > (MAXINT - sizeof(struct g_object_area)) / 2 / sizeof(struct g_object_text *) + 1) overalloc();	a = mem_realloc(p->root, sizeof(struct g_object_area) + sizeof(struct g_object_text *) * pw2(p->root->n_lines + 1));		/* note: +1 is for extend_area */	p->root = a;	p->root->lines[p->root->n_lines - 1] = l;	p->line = NULL;	p->w.pos = 0;	p->w.last_wrap = NULL;	p->w.last_wrap_obj = NULL;}void add_object_to_line(struct g_part *pp, struct g_object_line **lp, struct g_object *go){	struct g_object_line *l;	if (go && (go->xw < 0 || go->yw < 0)) {		internal("object has negative size: %d,%d", go->xw, go->yw);		return;	}	if (!*lp) {		l = mem_calloc(sizeof(struct g_object_line) + sizeof(struct g_object_text *));		l->mouse_event = g_line_mouse;		l->draw = g_line_draw;		l->destruct = g_line_destruct;		l->get_list = g_line_get_list;		/*l->x = 0;		l->y = 0;		l->xw = 0;		l->yw = 0;*/		l->bg = pp->root->bg;		if (!go) {			*lp = l;			return;		}		l->n_entries = 1;	} else {		if (!go) return;		(*lp)->n_entries++;		if ((unsigned)(*lp)->n_entries > (MAXINT - sizeof(struct g_object_line)) / sizeof(struct g_object *)) overalloc();		l = mem_realloc(*lp, sizeof(struct g_object_line) + sizeof(struct g_object *) * (*lp)->n_entries);		*lp = l;	}	l->entries[l->n_entries - 1] = go;	*lp = l;	if (pp->cx == -1) pp->cx = par_format.leftmargin * G_HTML_MARGIN;	pp->cx += go->xw;}void flush_pending_text_to_line(struct g_part *p){	if (!p->text) return;	add_object_to_line(p, &p->line, (struct g_object *)p->text);	p->text = NULL;}void split_line_object(struct g_part *p, struct g_object_text *text, unsigned char *ptr){	struct g_object_text *t2;	struct g_object_line *l2;	int n;	int esp;	if (!ptr) {		if (p->line && p->line->n_entries && (struct g_object *)text == p->line->entries[p->line->n_entries - 1]) {			flush_pending_line_to_obj(p, 0);			goto wwww;		}		t2 = NULL;		goto nt2;	}	t2 = mem_calloc(sizeof(struct g_object_text) + strlen(ptr) + 1);	t2->mouse_event = g_text_mouse;	t2->draw = g_text_draw;	t2->destruct = g_text_destruct;	t2->get_list = NULL;	esp = 1;	if (*ptr == ' ') {		strcpy(t2->text, ptr + 1);		*ptr = 0;		/*debug("split: (%s)(%s)", text->text, ptr + 1);*/	} else {		strcpy(t2->text, ptr);		ptr[0] = '-';		ptr[1] = 0;		esp = 0;	}	t2->y = text->y;	t2->style = g_clone_style(text->style);	t2->bg = text->bg;	t2->link_num = text->link_num;	t2->link_order = text->link_order;	text->xw = g_text_width(text->style, text->text);	nt2:	if (p->line) for (n = 0; n < p->line->n_entries; n++) if (p->line->entries[n] == (struct g_object *)text) goto found;	if (text != p->text) {		internal("split_line_object: bad wrap");		t2->destruct(t2);		mem_free(t2);		return;

⌨️ 快捷键说明

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