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

📄 terminal.c

📁 ELinks is an advanced and well-established feature-rich text mode web (HTTP/FTP/..) browser. ELinks
💻 C
📖 第 1 页 / 共 3 页
字号:
/* terminal.c * (c) 2002 Mikulas Patocka * This file is a part of the Links program, released under GPL. */#include "links.h"void alloc_term_screen(struct terminal *, int, int);void clear_terminal(struct terminal *);void redraw_terminal_ev(struct terminal *, int);void erase_screen(struct terminal *);void redraw_windows(struct terminal *);void empty_window_handler(struct window *, struct event *, int);struct term_spec *get_term_spec(unsigned char *);void unblock_terminal(struct terminal *);int hard_write(int fd, unsigned char *p, int l){	int w = 1;	int t = 0;	while (l > 0 && w) {		if ((w = write(fd, p, l)) < 0) {			if (errno == EINTR) continue;			return -1;		}		t += w;		p += w;		l -= w;	}	return t;}int hard_read(int fd, unsigned char *p, int l){	int r = 1;	int t = 0;	while (l > 0 && r) {		if ((r = read(fd, p, l)) < 0) {			if (errno == EINTR) continue;			return -1;		}		/*{int ww;for(ww=0;ww<r;ww++)fprintf(stderr," %02x",(int)p[ww]);fflush(stderr);}*/		t += r;		p += r;		l -= r;	}	return t;}unsigned char *get_cwd(void){	int bufsize = 128;	unsigned char *buf;	while (1) {		buf = mem_alloc(bufsize);		if (getcwd(buf, bufsize)) return buf;		mem_free(buf);		if (errno == EINTR) continue;		if (errno != ERANGE) return NULL;		if ((unsigned)bufsize > MAXINT - 128) overalloc();		bufsize += 128;	}	return NULL;}void set_cwd(unsigned char *path){	if (path) while (chdir(path) && errno == EINTR) ;}struct list_head terminals = {&terminals, &terminals};void alloc_term_screen(struct terminal *term, int x, int y){	unsigned *s, *t;	NO_GFX;	if (x && (unsigned)x * (unsigned)y / (unsigned)x != (unsigned)y) overalloc();	if ((unsigned)x * (unsigned)y > MAXINT / sizeof(unsigned)) overalloc();	s = mem_realloc(term->screen, x * y * sizeof(unsigned));	t = mem_realloc(term->last_screen, x * y * sizeof(unsigned));	memset(t, -1, x * y * sizeof(unsigned));	term->x = x;	term->y = y;	term->last_screen = t;	memset(s, 0, x * y * sizeof(unsigned));	term->screen = s;	term->dirty = 1;}void in_term(struct terminal *);void destroy_terminal(struct terminal *);void check_if_no_terminal(void);void clear_terminal(struct terminal *term){	NO_GFX;	fill_area(term, 0, 0, term->x, term->y, ' ');	set_cursor(term, 0, 0, 0, 0);}void redraw_below_window(struct window *win){	int tr;	struct terminal *term = win->term;	struct window *end = win;	struct event ev = {EV_REDRAW, 0, 0, 0};	NO_GFX;	ev.x = term->x;	ev.y = term->y;	if (term->redrawing >= 2) return;	tr = term->redrawing;	win->term->redrawing = 2;	for (win = term->windows.prev; win != end; win = win->prev) {		win->handler(win, &ev, 0);	}	term->redrawing = tr;}void redraw_terminal_ev(struct terminal *term, int e){	struct window *win;	struct event ev = {0, 0, 0, 0};	NO_GFX;	ev.ev = e;	ev.x = term->x;	ev.y = term->y;	clear_terminal(term);	term->redrawing = 2;	foreachback(win, term->windows) win->handler(win, &ev, 0);	term->redrawing = 0;}void redraw_terminal(struct terminal *term){	NO_GFX;	redraw_terminal_ev(term, EV_REDRAW);}void redraw_terminal_all(struct terminal *term){	NO_GFX;	redraw_terminal_ev(term, EV_RESIZE);}void erase_screen(struct terminal *term){	NO_GFX;	if (!term->master || !is_blocked()) {		if (term->master) want_draw();		hard_write(term->fdout, "\033[2J\033[1;1H", 10);		if (term->master) done_draw();	}}void redraw_terminal_cls(struct terminal *term){	NO_GFX;	erase_screen(term);	alloc_term_screen(term, term->x, term->y);	redraw_terminal_all(term);}void cls_redraw_all_terminals(void){	struct terminal *term;	foreach(term, terminals) {		if (!F) redraw_terminal_cls(term);#ifdef G		else {			t_resize(term->dev);		}#endif	}}#ifdef Gint do_rects_intersect(struct rect *r1, struct rect *r2){	return (r1->x1 > r2->x1 ? r1->x1 : r2->x1) < (r1->x2 > r2->x2 ? r2->x2 : r1->x2) && (r1->y1 > r2->y1 ? r1->y1 : r2->y1) < (r1->y2 > r2->y2 ? r2->y2 : r1->y2);}void intersect_rect(struct rect *v, struct rect *r1, struct rect *r2){	v->x1 = r1->x1 > r2->x1 ? r1->x1 : r2->x1;	v->x2 = r1->x2 > r2->x2 ? r2->x2 : r1->x2;	v->y1 = r1->y1 > r2->y1 ? r1->y1 : r2->y1;	v->y2 = r1->y2 > r2->y2 ? r2->y2 : r1->y2;}void unite_rect(struct rect *v, struct rect *r1, struct rect *r2){	if (!is_rect_valid(r1)) {		if (v != r2) memcpy(v, r2, sizeof(struct rect));		return;	}	if (!is_rect_valid(r2)) {		if (v != r1) memcpy(v, r1, sizeof(struct rect));		return;	}	v->x1 = r1->x1 < r2->x1 ? r1->x1 : r2->x1;	v->x2 = r1->x2 < r2->x2 ? r2->x2 : r1->x2;	v->y1 = r1->y1 < r2->y1 ? r1->y1 : r2->y1;	v->y2 = r1->y2 < r2->y2 ? r2->y2 : r1->y2;}int is_rect_valid(struct rect *r1){	return r1->x1 < r1->x2 && r1->y1 < r1->y2;}#define R_GR	8struct rect_set *init_rect_set(void){	struct rect_set *s;	s = mem_calloc(sizeof(struct rect_set) + sizeof(struct rect) * R_GR);	s->rl = R_GR;	s->m = 0;	return s;}void add_to_rect_set(struct rect_set **s, struct rect *r){	struct rect_set *ss = *s;	int i;	if (!is_rect_valid(r)) return;	for (i = 0; i < ss->rl; i++) if (!ss->r[i].x1 && !ss->r[i].x2 && !ss->r[i].y1 && !ss->r[i].y2) {		x:		memcpy(&ss->r[i], r, sizeof(struct rect));		if (i >= ss->m) ss->m = i + 1;		return;	}	if ((unsigned)ss->rl > (MAXINT - sizeof(struct rect_set)) / sizeof(struct rect) - R_GR) overalloc();	ss = mem_realloc(ss, sizeof(struct rect_set) + sizeof(struct rect) * (ss->rl + R_GR));	memset(&(*s = ss)->r[i = (ss->rl += R_GR) - R_GR], 0, sizeof(struct rect) * R_GR);	goto x;}void exclude_rect_from_set(struct rect_set **s, struct rect *r){	int i, a;	struct rect *rr;	do {		a = 0;		for (i = 0; i < (*s)->m; i++) if (do_rects_intersect(rr = &(*s)->r[i], r)) {			struct rect r1, r2, r3, r4;			r1.x1 = rr->x1;			r1.x2 = rr->x2;			r1.y1 = rr->y1;			r1.y2 = r->y1;			r2.x1 = rr->x1;			r2.x2 = r->x1;			r2.y1 = r->y1;			r2.y2 = r->y2;			r3.x1 = r->x2;			r3.x2 = rr->x2;			r3.y1 = r->y1;			r3.y2 = r->y2;			r4.x1 = rr->x1;			r4.x2 = rr->x2;			r4.y1 = r->y2;			r4.y2 = rr->y2;			intersect_rect(&r2, &r2, rr);			intersect_rect(&r3, &r3, rr);			rr->x1 = rr->x2 = rr->y1 = rr->y2 = 0;#ifdef DEBUG			if (is_rect_valid(&r1) && do_rects_intersect(&r1, r)) internal("bad intersection 1");			if (is_rect_valid(&r2) && do_rects_intersect(&r2, r)) internal("bad intersection 2");			if (is_rect_valid(&r3) && do_rects_intersect(&r3, r)) internal("bad intersection 3");			if (is_rect_valid(&r4) && do_rects_intersect(&r4, r)) internal("bad intersection 4");#endif			add_to_rect_set(s, &r1);			add_to_rect_set(s, &r2);			add_to_rect_set(s, &r3);			add_to_rect_set(s, &r4);			a = 1;		}	} while (a);}/* memory address r must contain one struct rect * x1 is leftmost pixel that is still valid * x2 is leftmost pixel that isn't valid any more * y1, y2 analogically */int restrict_clip_area(struct graphics_device *dev, struct rect *r, int x1, int y1, int x2, int y2){	struct rect v, rr;	rr.x1 = x1, rr.x2 = x2, rr.y1 = y1, rr.y2 = y2;	if (r) memcpy(r, &dev->clip, sizeof(struct rect));	intersect_rect(&v, &dev->clip, &rr);	drv->set_clip_area(dev, &v);	return is_rect_valid(&v);}#endifvoid draw_to_window(struct window *win, void (*fn)(struct terminal *term, void *), void *data){	struct terminal *term = win->term;	struct window *end = (void *)&term->windows;	if (!F) {		pr(fn(term, data)) {};		term = win->term;		end = (void *)&term->windows;		if (win->prev == end || term->redrawing) return;		term->redrawing = 1;		{			struct event ev = {EV_REDRAW, 0, 0, 0};			ev.x = term->x;			ev.y = term->y;			for (win = win->prev; win != end; win = win->prev) win->handler(win, &ev, 0);		}		term->redrawing = 0;#ifdef G	} else {		struct rect r1, *r;		struct rect_set *s;		int i, a;		if (win->prev == end || !(s = init_rect_set())) {			pr(fn(term, data)) {};			return;		}		intersect_rect(&r1, &win->pos, &term->dev->clip);		add_to_rect_set(&s, &r1);		for (win = win->prev; win != end; win = win->prev) exclude_rect_from_set(&s, &win->pos);		a = 0;		memcpy(&r1, &term->dev->clip, sizeof(struct rect));		for (i = 0; i < s->m; i++) if (is_rect_valid(r = &s->r[i])) {			drv->set_clip_area(term->dev, r);			pr(fn(term, data)) return;			a = 1;		}		if (!a) {			struct rect empty = { 0, 0, 0, 0 };			drv->set_clip_area(term->dev, &empty);			fn(term, data);		}		drv->set_clip_area(term->dev, &r1);		mem_free(s);#endif	}}#ifdef Gvoid redraw_windows(struct terminal *term){	struct terminal *t1;	struct window *win;	foreach(t1, terminals) if (t1 == term) goto ok;	return;	ok:	foreach(win, term->windows) {		struct event ev = { EV_REDRAW, 0, 0, 0 };		ev.x = term->x;		ev.y = term->y;		drv->set_clip_area(term->dev, &win->redr);		memset(&win->redr, 0, sizeof(struct rect));		win->handler(win, &ev, 0);	}	drv->set_clip_area(term->dev, &term->dev->size);}void set_window_pos(struct window *win, int x1, int y1, int x2, int y2){	struct terminal *term = win->term;	struct rect r;	NO_TXT;	r.x1 = x1, r.y1 = y1, r.x2 = x2, r.y2 = y2;	if (is_rect_valid(&win->pos) && (x1 > win->pos.x1 || x2 < win->pos.x2 || y1 > win->pos.y1 || y2 < win->pos.y2) && term->redrawing < 2) {		struct window *w;		for (w = win->next; w != (void *)&win->term->windows; w = w->next) unite_rect(&w->redr, &win->pos, &w->redr);		register_bottom_half((void (*)(void *))redraw_windows, term);	}	memcpy(&win->pos, &r, sizeof(struct rect));}#endifvoid add_window_at_pos(struct terminal *term, void (*handler)(struct window *, struct event *, int), void *data, struct window *at){	struct event ev = {EV_INIT, 0, 0, 0};	struct window *win;	ev.x = term->x;	ev.y = term->y;	win = mem_calloc(sizeof(struct window));	win->handler = handler;

⌨️ 快捷键说明

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