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

📄 terminal.c

📁 this is the file used to browse web
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "links.h"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(){	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;	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 clear_terminal(struct terminal *term){	fill_area(term, 0, 0, term->x, term->y, ' ');	set_cursor(term, 0, 0, 0, 0);}void redraw_terminal_ev(struct terminal *term, int e){	struct window *win;	struct event ev = {0, 0, 0, 0};	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){	redraw_terminal_ev(term, EV_REDRAW);}void redraw_terminal_all(struct terminal *term){	redraw_terminal_ev(term, EV_RESIZE);}void erase_screen(struct terminal *term){	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){	erase_screen(term);	alloc_term_screen(term, term->x, term->y);	redraw_terminal_all(term);}void cls_redraw_all_terminals(){	struct terminal *term;	foreach(term, terminals) redraw_terminal_cls(term);}void redraw_from_window(struct window *win){	struct terminal *term = win->term;	struct window *end = (void *)&term->windows;	struct event ev = {EV_REDRAW, 0, 0, 0};	ev.x = term->x;	ev.y = term->y;	if (term->redrawing) return;	term->redrawing = 1;	for (win = win->prev; win != end; win = win->prev) {		win->handler(win, &ev, 0);	}	term->redrawing = 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};	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 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_alloc(sizeof (struct window));	win->handler = handler;	win->data = data;	win->term = term;	win->xp = win->yp = 0;	add_at_pos(at, win);	win->handler(win, &ev, 0);}void add_window(struct terminal *term, void (*handler)(struct window *, struct event *, int), void *data){	add_window_at_pos(term, handler, data, (struct window *)(void *)&term->windows);}void delete_window(struct window *win){	struct event ev = {EV_ABORT, 0, 0, 0};	win->handler(win, &ev, 1);	del_from_list(win);	if (win->data) mem_free(win->data);	redraw_terminal(win->term);	mem_free(win);}void delete_window_ev(struct window *win, struct event *ev){	struct window *w = win->next;	if ((void *)w == &win->term->windows) w = NULL;	delete_window(win);	if (ev && w && w->next != w) w->handler(w, ev, 1);}void set_window_ptr(struct window *win, int x, int y){	win->xp = x;	win->yp = y;}void get_parent_ptr(struct window *win, int *x, int *y){	if ((void *)win->next != &win->term->windows) {		*x = win->next->xp;		*y = win->next->yp;	} else {		*x = *y = 0;	}}struct window *get_root_window(struct terminal *term){	if (list_empty(term->windows)) {		internal("terminal has no windows");		return NULL;	}	return (struct window *)term->windows.prev;}struct ewd {	void (*fn)(void *);	void *data;	int b;};void empty_window_handler(struct window *win, struct event *ev, int fwd){	struct window *n;	struct ewd *ewd = win->data;	int x, y;	void (*fn)(void *) = ewd->fn;	void *data = ewd->data;	if (ewd->b) return;	switch (ev->ev) {		case EV_INIT:		case EV_RESIZE:		case EV_REDRAW:			get_parent_ptr(win, &x, &y);			set_window_ptr(win, x, y);			return;		case EV_ABORT:			fn(data);			return;	}	ewd->b = 1;	n = win->next;	delete_window(win);	fn(data);	if (n->next != n) n->handler(n, ev, fwd);}void add_empty_window(struct terminal *term, void (*fn)(void *), void *data){	struct ewd *ewd;	ewd = mem_alloc(sizeof(struct ewd));	ewd->fn = fn;	ewd->data = data;	ewd->b = 0;	add_window(term, empty_window_handler, ewd);}void free_term_specs(){	free_list(term_specs);}struct list_head term_specs = {&term_specs, &term_specs};struct term_spec dumb_term = { NULL, NULL, "", 0, 1, 0, 0, 0, 0 };struct term_spec *get_term_spec(unsigned char *term){	struct term_spec *t;	foreach(t, term_specs) if (!strcasecmp(t->term, term)) return t;	return &dumb_term;}struct term_spec *new_term_spec(unsigned char *term){	struct term_spec *t;	foreach(t, term_specs) if (!strcasecmp(t->term, term)) return t;	t = mem_alloc(sizeof(struct term_spec));	memcpy(t, &dumb_term, sizeof(struct term_spec));	if (strlen(term) < MAX_TERM_LEN) strcpy(t->term, term);	else memcpy(t->term, term, MAX_TERM_LEN - 1), t->term[MAX_TERM_LEN - 1] = 0;	add_to_list(term_specs, t);	sync_term_specs();	return t;}void sync_term_specs(){	struct terminal *term;	foreach (term, terminals) term->spec = get_term_spec(term->term);}struct terminal *init_term(int fdin, int fdout, void (*root_window)(struct window *, struct event *, int)){	struct terminal *term;	struct window *win;	term = mem_alloc(sizeof (struct terminal));	memset(term, 0, sizeof(struct terminal));	term->fdin = fdin;	term->fdout = fdout;	term->master = term->fdout == get_output_handle();	/*term->x = 0;	term->y = 0;	term->cx = 0;	term->cy = 0;*/	term->lcx = -1;	term->lcy = -1;	term->dirty = 1;	term->redrawing = 0;	term->blocked = -1;	term->screen = DUMMY;	term->last_screen = DUMMY;	term->spec = &dumb_term;	term->term[0] = 0;	term->cwd[0] = 0;	term->input_queue = DUMMY;	term->qlen = 0;	init_list(term->windows);	win = mem_alloc(sizeof (struct window));	win->handler = root_window;	win->data = NULL;	win->term = term;	add_to_list(term->windows, win);	/*alloc_term_screen(term, 80, 25);*/	add_to_list(terminals, term);	set_handlers(fdin, (void (*)(void *))in_term, NULL, (void (*)(void *))destroy_terminal, term);	return term;}void in_term(struct terminal *term){	struct event *ev;	int r;	unsigned char *iq;	if ((unsigned)term->qlen + ALLOC_GR > MAXINT) overalloc();	iq = mem_realloc(term->input_queue, term->qlen + ALLOC_GR);	term->input_queue = iq;	if ((r = read(term->fdin, iq + term->qlen, ALLOC_GR)) <= 0) {		if (r == -1 && errno != ECONNRESET) error("ERROR: error %d on terminal: could not read event", errno);		destroy_terminal(term);		return;	}	term->qlen += r;	test_queue:	if ((size_t)term->qlen < sizeof(struct event)) return;	ev = (struct event *)iq;	r = sizeof(struct event);	if (ev->ev != EV_INIT && ev->ev != EV_RESIZE && ev->ev != EV_REDRAW && ev->ev != EV_KBD && ev->ev != EV_MOUSE && ev->ev != EV_ABORT) {		error("ERROR: error on terminal: bad event %d", ev->ev);		goto mm;	}	if (ev->ev == EV_INIT) {		int init_len;		if ((size_t)term->qlen < sizeof(struct event) + MAX_TERM_LEN + MAX_CWD_LEN + 2 * sizeof(int)) return;		init_len = *(int *)(iq + sizeof(struct event) + MAX_TERM_LEN + MAX_CWD_LEN + sizeof(int));		if ((size_t)term->qlen < sizeof(struct event) + MAX_TERM_LEN + MAX_CWD_LEN + 2 * sizeof(int) + init_len) return;		memcpy(term->term, iq + sizeof(struct event), MAX_TERM_LEN);		term->term[MAX_TERM_LEN - 1] = 0;		memcpy(term->cwd, iq + sizeof(struct event) + MAX_TERM_LEN, MAX_CWD_LEN);		term->cwd[MAX_CWD_LEN - 1] = 0;		term->environment = *(int *)(iq + sizeof(struct event) + MAX_TERM_LEN + MAX_CWD_LEN);		ev->b = (long)(iq + sizeof(struct event) + MAX_TERM_LEN + MAX_CWD_LEN + sizeof(int));		r = sizeof(struct event) + MAX_TERM_LEN + MAX_CWD_LEN + 2 * sizeof(int) + init_len;		sync_term_specs();	}	if (ev->ev == EV_REDRAW || ev->ev == EV_RESIZE || ev->ev == EV_INIT) {		struct window *win;		send_redraw:		if (ev->x < 0 || ev->y < 0) {			error("ERROR: bad terminal size: %d, %d", (int)ev->x, (int)ev->y);			goto mm;		}		alloc_term_screen(term, ev->x, ev->y);		clear_terminal(term);		erase_screen(term);		term->redrawing = 1;		foreachback(win, term->windows) win->handler(win, ev, 0);		term->redrawing = 0;	}	if (ev->ev == EV_KBD || ev->ev == EV_MOUSE) {		if (ev->ev == EV_KBD && upcase(ev->x) == 'L' && ev->y == KBD_CTRL) {			ev->ev = EV_REDRAW;			ev->x = term->x;			ev->y = term->y;			goto send_redraw;		}		else if (ev->ev == EV_KBD && ev->x == KBD_CTRL_C) ((struct window *)(void *)&term->windows)->prev->handler(term->windows.prev, ev, 0);		else ((struct window *)(void *)&term->windows)->next->handler(term->windows.next, ev, 0);	}

⌨️ 快捷键说明

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