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

📄 renderer.c

📁 一个很有名的浏览器
💻 C
📖 第 1 页 / 共 4 页
字号:
				continue;			matched = 1;			if (link->points[i].x < X(xf))				continue;			if (yt >= 0) {				link->points[i].y = Y(yt);				link->points[i].x += -xf + xt;			} else {				int to_move = link->npoints - (i + 1);				assert(to_move >= 0);				if (to_move > 0) {					memmove(&link->points[i],						&link->points[i + 1],						to_move *						sizeof(*link->points));					i--;				}				link->npoints--;			}		}		if (!matched) {			renderer_context.last_link_to_move = nlink;		}	}	/* Don't move tags when removing links. */	if (yt < 0) return;	matched = 0;	tag = renderer_context.last_tag_to_move;	while (list_has_next(part->document->tags, tag)) {		tag = tag->next;		if (tag->y == Y(yf)) {			matched = 1;			if (tag->x >= X(xf)) {				tag->y = Y(yt);				tag->x += -xf + xt;			}		} else if (!matched && tag->y > Y(yf)) {			/* Fix for bug 479 (part two) */			matched = 1;		}		if (!matched) renderer_context.last_tag_to_move = tag;	}}static inline voidcopy_chars(struct part *part, int x, int y, int width, struct screen_char *d){	assert(width > 0 && part && part->document && part->document->data);	if_assert_failed return;	if (realloc_line(part->document, Y(y), X(x) + width - 1))		return;	copy_screen_chars(&POS(x, y), d, width);}static inline voidmove_chars(struct part *part, int x, int y, int nx, int ny){	assert(part && part->document && part->document->data);	if_assert_failed return;	if (LEN(y) - x <= 0) return;	copy_chars(part, nx, ny, LEN(y) - x, &POS(x, y));	LINE(y).length = X(x);	move_links(part, x, y, nx, ny);}static inline voidshift_chars(struct part *part, int y, int shift){	struct screen_char *a;	int len;	assert(part && part->document && part->document->data);	if_assert_failed return;	len = LEN(y);	a = mem_alloc(len * sizeof(*a));	if (!a) return;	copy_screen_chars(a, &POS(0, y), len);	clear_hchars(part, 0, y, shift);	copy_chars(part, shift, y, len, a);	mem_free(a);	move_links(part, 0, y, shift, y);}static inline voiddel_chars(struct part *part, int x, int y){	assert(part && part->document && part->document->data);	if_assert_failed return;	LINE(y).length = X(x);	move_links(part, x, y, -1, -1);}#define overlap(x) int_max((x).width - (x).rightmargin, 0)static int inlinesplit_line_at(struct part *part, int width){	int tmp;	int new_width = width + par_format.rightmargin;	assert(part);	if_assert_failed return 0;	/* Make sure that we count the right margin to the total	 * actual box width. */	int_lower_bound(&part->box.width, new_width);	if (part->document) {		assert(part->document->data);		if_assert_failed return 0;		assertm(POS(width, part->cy).data == ' ',			"bad split: %c", POS(width, part->cy).data);		move_chars(part, width + 1, part->cy, par_format.leftmargin, part->cy + 1);		del_chars(part, width, part->cy);	}	width++; /* Since we were using (x + 1) only later... */	tmp = part->spaces_len - width;	if (tmp > 0) {		/* 0 is possible and I'm paranoid ... --Zas */		memmove(part->spaces, part->spaces + width, tmp);	}	assert(tmp >= 0);	if_assert_failed tmp = 0;	memset(part->spaces + tmp, 0, width);	if (par_format.leftmargin > 0) {		tmp = part->spaces_len - par_format.leftmargin;		assertm(tmp > 0, "part->spaces_len - par_format.leftmargin == %d", tmp);		/* So tmp is zero, memmove() should survive that. Don't recover. */		memmove(part->spaces + par_format.leftmargin, part->spaces, tmp);	}	part->cy++;	if (part->cx == width) {		part->cx = -1;		int_lower_bound(&part->box.height, part->cy);		return 2;	} else {		part->cx -= width - par_format.leftmargin;		int_lower_bound(&part->box.height, part->cy + 1);		return 1;	}}/* Here, we scan the line for a possible place where we could split it into two * (breaking it, because it is too long), if it is overlapping from the maximal * box width. *//* Returns 0 if there was found no spot suitable for breaking the line. *         1 if the line was split into two. *         2 if the (second) splitted line is blank (that is useful to determine *           ie. if the next line_break() should really break the line; we don't *           want to see any blank lines to pop up, do we?). */static intsplit_line(struct part *part){	int x;	assert(part);	if_assert_failed return 0;	for (x = overlap(par_format); x >= par_format.leftmargin; x--)		if (x < part->spaces_len && part->spaces[x])			return split_line_at(part, x);	for (x = par_format.leftmargin; x < part->cx ; x++)		if (x < part->spaces_len && part->spaces[x])			return split_line_at(part, x);	/* Make sure that we count the right margin to the total	 * actual box width. */	int_lower_bound(&part->box.width, part->cx + par_format.rightmargin);	return 0;}/* Insert @new_spaces spaces before the coordinates @x and @y, * adding those spaces to whatever link is at those coordinates. *//* TODO: Integrate with move_links. */static voidinsert_spaces_in_link(struct part *part, int x, int y, int new_spaces){	int i = part->document->nlinks;	x = X(x);	y = Y(y);	while (i--) {		struct link *link = &part->document->links[i];		int j = link->npoints;		while (j-- > 1) {			struct point *point = &link->points[j];			if (point->x != x || point->y != y)				continue;			if (!realloc_points(link, link->npoints + new_spaces))				return;			link->npoints += new_spaces;			point = &link->points[link->npoints - 1];			while (new_spaces--) {				point->x = --x;				point->y = y;				point--;			}			return;		}	}}/* This function is very rare exemplary of clean and beautyful code here. * Please handle with care. --pasky */static voidjustify_line(struct part *part, int y){	struct screen_char *line; /* we save original line here */	int len;	int pos;	int *space_list;	int spaces;	assert(part && part->document && part->document->data);	if_assert_failed return;	len = LEN(y);	assert(len > 0);	if_assert_failed return;	line = fmem_alloc(len * sizeof(*line));	if (!line) return;	/* It may sometimes happen that the line is only one char long and that	 * char is space - then we're going to write to both [0] and [1], but	 * we allocated only one field. Thus, we've to do (len + 1). --pasky */	space_list = fmem_alloc((len + 1) * sizeof(*space_list));	if (!space_list) {		fmem_free(line);		return;	}	copy_screen_chars(line, &POS(0, y), len);	/* Skip leading spaces */	spaces = 0;	pos = 0;	while (line[pos].data == ' ')		pos++;	/* Yes, this can be negative, we know. But we add one to it always	 * anyway, so it's ok. */	space_list[spaces++] = pos - 1;	/* Count spaces */	for (; pos < len; pos++)		if (line[pos].data == ' ')			space_list[spaces++] = pos;	space_list[spaces] = len;	/* Realign line */	if (spaces > 1) {		int insert = overlap(par_format) - len;		int prev_end = 0;		int word;		clear_hchars(part, 0, y, overlap(par_format));		for (word = 0; word < spaces; word++) {			/* We have to increase line length by 'insert' num. of			 * characters, so we move 'word'th word 'word_shift'			 * characters right. */			int word_start = space_list[word] + 1;			int word_len = space_list[word + 1] - word_start;			int word_shift;			int new_start;			int new_spaces;			assert(word_len >= 0);			if_assert_failed continue;			if (!word_len) continue;			word_shift = (word * insert) / (spaces - 1);			new_start = word_start + word_shift;			copy_chars(part, new_start, y, word_len,				   &line[word_start]);			new_spaces = new_start - prev_end - 1;			if (word && new_spaces) {				move_links(part, prev_end + 1, y, new_start, y);				insert_spaces_in_link(part,						      new_start, y, new_spaces);			}			prev_end = new_start + word_len;		}	}	fmem_free(space_list);	fmem_free(line);}static voidalign_line(struct part *part, int y, int last){	int shift;	int len;	assert(part && part->document && part->document->data);	if_assert_failed return;	len = LEN(y);	if (!len || par_format.align == ALIGN_LEFT)		return;	if (par_format.align == ALIGN_JUSTIFY) {		if (!last)			justify_line(part, y);		return;	}	shift = overlap(par_format) - len;	if (par_format.align == ALIGN_CENTER)		shift /= 2;	if (shift > 0)		shift_chars(part, y, shift);}static struct link *new_link(struct document *document, int link_number,	 unsigned char *name, int namelen){	struct link *link;	assert(document);	if_assert_failed return NULL;	if (!ALIGN_LINK(&document->links, document->nlinks, document->nlinks + 1))		return NULL;	link = &document->links[document->nlinks++];	link->number = link_number - 1;	if (document->options.use_tabindex) link->number += format.tabindex;	link->accesskey = format.accesskey;	link->title = null_or_stracpy(format.title);	link->where_img = null_or_stracpy(format.image);	if (!format.form) {		link->target = null_or_stracpy(format.target);		link->data.name = memacpy(name, namelen);		/* if (strlen(url) > 4 && !strncasecmp(url, "MAP@", 4)) { */		if (format.link		    && ((format.link[0]|32) == 'm')		    && ((format.link[1]|32) == 'a')		    && ((format.link[2]|32) == 'p')		    && 	(format.link[3]     == '@')		    &&   format.link[4]) {			link->type = LINK_MAP;			link->where = stracpy(format.link + 4);		} else {			link->type = LINK_HYPERTEXT;			link->where = null_or_stracpy(format.link);		}	} else {		struct form_control *fc = format.form;		struct form *form;		switch (fc->type) {		case FC_TEXT:		case FC_PASSWORD:		case FC_FILE:			link->type = LINK_FIELD;			break;		case FC_TEXTAREA:			link->type = LINK_AREA;			break;		case FC_CHECKBOX:		case FC_RADIO:			link->type = LINK_CHECKBOX;			break;		case FC_SELECT:			link->type = LINK_SELECT;			break;		case FC_SUBMIT:		case FC_IMAGE:		case FC_RESET:		case FC_BUTTON:		case FC_HIDDEN:			link->type = LINK_BUTTON;		}		link->data.form_control = fc;		/* At this point, format.form might already be set but		 * the form_control not registered through SP_CONTROL		 * yet, therefore without fc->form set. It is always		 * after the "good" last form was already processed,		 * though, so we can safely just take that. */		form = fc->form;		if (!form && !list_empty(document->forms))			form = document->forms.next;		link->target = null_or_stracpy(form ? form->target : NULL);	}	link->color.background = format.style.bg;	link->color.foreground = link_is_textinput(link)				? format.style.fg : format.clink;	link->event_hooks = mem_calloc(1, sizeof(*link->event_hooks));	if (link->event_hooks) {		init_list(*link->event_hooks);#define add_evhook(list_, type_, src_) \do { \	struct script_event_hook *evhook = mem_calloc(1, sizeof(*evhook)); \	\	if (evhook) { \		evhook->type = type_; \		evhook->src = stracpy(src_); \		add_to_list(*list_, evhook); \	} \} while (0)		if (format.onclick) add_evhook(link->event_hooks, SEVHOOK_ONCLICK, format.onclick);		if (format.ondblclick) add_evhook(link->event_hooks, SEVHOOK_ONDBLCLICK, format.ondblclick);		if (format.onmouseover) add_evhook(link->event_hooks, SEVHOOK_ONMOUSEOVER, format.onmouseover);		if (format.onhover) add_evhook(link->event_hooks, SEVHOOK_ONHOVER, format.onhover);		if (format.onfocus) add_evhook(link->event_hooks, SEVHOOK_ONFOCUS, format.onfocus);		if (format.onmouseout) add_evhook(link->event_hooks, SEVHOOK_ONMOUSEOUT, format.onmouseout);		if (format.onblur) add_evhook(link->event_hooks, SEVHOOK_ONBLUR, format.onblur);#undef add_evhook	}	return link;}static voidhtml_special_tag(struct document *document, unsigned char *t, int x, int y){	struct tag *tag;	int tag_len;	assert(document);	if_assert_failed return;	tag_len = strlen(t);	/* One byte is reserved for name in struct tag. */	tag = mem_alloc(sizeof(*tag) + tag_len);

⌨️ 快捷键说明

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