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

📄 kbd.c

📁 ELinks is an advanced and well-established feature-rich text mode web (HTTP/FTP/..) browser. ELinks
💻 C
📖 第 1 页 / 共 2 页
字号:
/* kbd.c * (c) 2002 Mikulas Patocka * This file is a part of the Links program, released under GPL. */#include "links.h"#define OUT_BUF_SIZE	16384#define IN_BUF_SIZE	16#define USE_TWIN_MOUSE	1#define TW_BUTT_LEFT	1#define TW_BUTT_MIDDLE	2#define TW_BUTT_RIGHT	4struct itrm {	int std_in;	int std_out;	int sock_in;	int sock_out;	int ctl_in;	int blocked;	struct termios t;	int flags;	unsigned char kqueue[IN_BUF_SIZE];	int qlen;	int tm;	void (*queue_event)(struct itrm *, unsigned char *, int);	unsigned char *ev_queue;	int eqlen;	void *mouse_h;	unsigned char *orig_title;	void (*free_trm)(struct itrm *);};void free_trm(struct itrm *);void in_kbd(struct itrm *);void in_sock(struct itrm *);struct itrm *ditrm = NULL;/* prototypes */void write_ev_queue(struct itrm *);void mouse_queue_event(struct itrm *, unsigned char *, int);void queue_event(struct itrm *, unsigned char *, int);void send_init_sequence(int, int);void send_term_sequence(int, int);int setraw(int, struct termios *);void unblock_itrm_x(void *);void resize_terminal_x(unsigned char *);void kbd_timeout(struct itrm *);int get_esc_code(char *, int, char *, int *, int *);int ttcgetattr(int, struct termios *);int ttcsetattr(int, int, struct termios *);int is_blocked(void){	return ditrm && ditrm->blocked;}void free_all_itrms(void){	if (ditrm) ditrm->free_trm(ditrm);}void write_ev_queue(struct itrm *itrm){	int l;	if (!itrm->eqlen) internal("event queue empty");	if ((l = write(itrm->sock_out, itrm->ev_queue, itrm->eqlen > 128 ? 128 : itrm->eqlen)) == -1) {		itrm->free_trm(itrm);		return;	}	memmove(itrm->ev_queue, itrm->ev_queue + l, itrm->eqlen -= l);	if (!itrm->eqlen) set_handlers(itrm->sock_out, get_handler(itrm->sock_out, H_READ), NULL, get_handler(itrm->sock_out, H_ERROR), get_handler(itrm->sock_out, H_DATA));}void mouse_queue_event(struct itrm *itrm, unsigned char *data, int len){	if (itrm->blocked) return;	queue_event(itrm, data, len);}void queue_event(struct itrm *itrm, unsigned char *data, int len){	int w = 0;	if (!len) return;	if (!itrm->eqlen && can_write(itrm->sock_out) && (w = write(itrm->sock_out, data, len)) <= 0) {		/*free_trm(itrm);*/		register_bottom_half((void (*)(void *))itrm->free_trm, itrm);		return;	}	if (w < len) {		if ((unsigned)itrm->eqlen + (unsigned)(len - w) > MAXINT) overalloc();		itrm->ev_queue = mem_realloc(itrm->ev_queue, itrm->eqlen + len - w);		memcpy(itrm->ev_queue + itrm->eqlen, data + w, len - w);		itrm->eqlen += len - w;		set_handlers(itrm->sock_out, get_handler(itrm->sock_out, H_READ), (void (*)(void *))write_ev_queue, (void (*)(void *))itrm->free_trm, itrm);	}}void kbd_ctrl_c(void){	struct event ev = { EV_KBD, KBD_CTRL_C, 0, 0 };	if (ditrm) ditrm->queue_event(ditrm, (unsigned char *)&ev, sizeof(struct event));}/*unsigned char *init_seq = "\033[?1000h\033[?47h\0337";unsigned char *term_seq = "\033[2J\033[?1000l\033[?47l\0338\b \b";*/unsigned char init_seq[] = "\033)0\0337";unsigned char init_seq_x_mouse[] = "\033[?1000h";unsigned char init_seq_tw_mouse[] = "\033[?9h";unsigned char term_seq[] = "\033[2J\0338\r \b";unsigned char term_seq_x_mouse[] = "\033[?1000l\015       \015";unsigned char term_seq_tw_mouse[] = "\033[?9l";/*unsigned char *term_seq = "\033[2J\033[?1000l\0338\b \b";*/void send_init_sequence(int h, int flags){	want_draw();	hard_write(h, init_seq, strlen(init_seq));	if (flags & USE_TWIN_MOUSE) {		hard_write(h, init_seq_tw_mouse, strlen(init_seq_tw_mouse));	} else {		hard_write(h, init_seq_x_mouse, strlen(init_seq_x_mouse));	}	done_draw();}void send_term_sequence(int h,int flags){	want_draw();	hard_write(h, term_seq, strlen(term_seq));	if (flags & USE_TWIN_MOUSE) {		hard_write(h, term_seq_tw_mouse, strlen(term_seq_tw_mouse));	} else {		hard_write(h, term_seq_x_mouse, strlen(term_seq_x_mouse));	}	done_draw();}void resize_terminal(void){	struct event ev = { EV_RESIZE, 0, 0, 0 };	int x, y;	if (get_terminal_size(ditrm->std_out, &x, &y)) return;	ev.x = x;	ev.y = y;	queue_event(ditrm, (char *)&ev, sizeof(struct event));}int ttcgetattr(int fd, struct termios *t){	int r;#ifdef SIGTTOU	interruptible_signal(SIGTTOU, 1);#endif#ifdef SIGTTIN	interruptible_signal(SIGTTIN, 1);#endif	r = tcgetattr(fd, t);#ifdef SIGTTOU	interruptible_signal(SIGTTOU, 0);#endif#ifdef SIGTTIN	interruptible_signal(SIGTTIN, 0);#endif	return r;}int ttcsetattr(int fd, int a, struct termios *t){	int r;#ifdef SIGTTOU	interruptible_signal(SIGTTOU, 1);#endif#ifdef SIGTTIN	interruptible_signal(SIGTTIN, 1);#endif	r = tcsetattr(fd, a, t);#ifdef SIGTTOU	interruptible_signal(SIGTTOU, 0);#endif#ifdef SIGTTIN	interruptible_signal(SIGTTIN, 0);#endif	return r;}int setraw(int fd, struct termios *p){	struct termios t;	memset(&t, 0, sizeof(struct termios));	if (ttcgetattr(fd, &t)) return -1;	if (p) memcpy(p, &t, sizeof(struct termios));	os_cfmakeraw(&t);	t.c_lflag |= ISIG;#ifdef TOSTOP	t.c_lflag |= TOSTOP;#endif	t.c_oflag |= OPOST;	if (ttcsetattr(fd, TCSANOW, &t)) return -1;	return 0;}void handle_trm(int std_in, int std_out, int sock_in, int sock_out, int ctl_in, void *init_string, int init_len){	int x, y;	struct itrm *itrm;	struct event ev = { EV_INIT, 80, 24, 0 };	unsigned char *ts;	int xwin;	if (get_terminal_size(ctl_in, &x, &y)) {		error("ERROR: could not get terminal size");		return;	}	itrm = mem_alloc(sizeof(struct itrm));	itrm->queue_event = queue_event;	itrm->free_trm = free_trm;	ditrm = itrm;	itrm->std_in = std_in;	itrm->std_out = std_out;	itrm->sock_in = sock_in;	itrm->sock_out = sock_out;	itrm->ctl_in = ctl_in;	itrm->blocked = 0;	itrm->qlen = 0;	itrm->tm = -1;	itrm->ev_queue = DUMMY;	itrm->eqlen = 0;	if (ctl_in >= 0) setraw(ctl_in, &itrm->t);	set_handlers(std_in, (void (*)(void *))in_kbd, NULL, (void (*)(void *))itrm->free_trm, itrm);	if (sock_in != std_out) set_handlers(sock_in, (void (*)(void *))in_sock, NULL, (void (*)(void *))itrm->free_trm, itrm);	ev.x = x;	ev.y = y;	handle_terminal_resize(ctl_in, resize_terminal);	queue_event(itrm, (char *)&ev, sizeof(struct event));	xwin = is_xterm() * ENV_XWIN + can_twterm() * ENV_TWIN + (!!getenv("STY")) * ENV_SCREEN + get_system_env();	itrm->flags = 0;	if (!(ts = getenv("TERM"))) ts = "";	if ((xwin & ENV_TWIN) && !strcmp(ts, "linux")) itrm->flags |= USE_TWIN_MOUSE;	if (strlen(ts) >= MAX_TERM_LEN) queue_event(itrm, ts, MAX_TERM_LEN);	else {		unsigned char *mm;		int ll = MAX_TERM_LEN - strlen(ts);		queue_event(itrm, ts, strlen(ts));		mm = mem_calloc(ll);		queue_event(itrm, mm, ll);		mem_free(mm);	}	if (!(ts = get_cwd())) ts = stracpy("");	if (strlen(ts) >= MAX_CWD_LEN) queue_event(itrm, ts, MAX_CWD_LEN);	else {		unsigned char *mm;		int ll = MAX_CWD_LEN - strlen(ts);		queue_event(itrm, ts, strlen(ts));		mm = mem_calloc(ll);		queue_event(itrm, mm, ll);		mem_free(mm);	}	mem_free(ts);	queue_event(itrm, (char *)&xwin, sizeof(int));	queue_event(itrm, (char *)&init_len, sizeof(int));	queue_event(itrm, (char *)init_string, init_len);	itrm->mouse_h = handle_mouse(0, (void (*)(void *, unsigned char *, int))mouse_queue_event, itrm);	itrm->orig_title = get_window_title();	set_window_title("Links");	send_init_sequence(std_out,itrm->flags);}void unblock_itrm_x(void *h){	NO_GFX;	close_handle(h);	if (!ditrm) return;	unblock_itrm(0);}int unblock_itrm(int fd){	struct itrm *itrm = ditrm;	if (!itrm) return -1;	if (itrm->ctl_in >= 0 && setraw(itrm->ctl_in, NULL)) return -1;	if (itrm->blocked != fd + 1) return -2;	itrm->blocked = 0;	send_init_sequence(itrm->std_out,itrm->flags);	set_handlers(itrm->std_in, (void (*)(void *))in_kbd, NULL, (void (*)(void *))itrm->free_trm, itrm);	handle_terminal_resize(itrm->ctl_in, resize_terminal);	unblock_stdin();	itrm->mouse_h = handle_mouse(0, (void (*)(void *, unsigned char *, int))mouse_queue_event, itrm);	resize_terminal();	return 0;}void block_itrm(int fd){	struct itrm *itrm = ditrm;	NO_GFX;	if (!itrm) return;	if (itrm->blocked) return;	itrm->blocked = fd + 1;	block_stdin();	unhandle_terminal_resize(itrm->ctl_in);	send_term_sequence(itrm->std_out,itrm->flags);	ttcsetattr(itrm->ctl_in, TCSANOW, &itrm->t);	if (itrm->mouse_h) unhandle_mouse(itrm->mouse_h), itrm->mouse_h = NULL;	set_handlers(itrm->std_in, NULL, NULL, (void (*)(void *))itrm->free_trm, itrm);}void free_trm(struct itrm *itrm){	if (!itrm) return;	set_window_title(itrm->orig_title);	if (itrm->orig_title) mem_free(itrm->orig_title), itrm->orig_title = NULL;	unhandle_terminal_resize(itrm->ctl_in);	send_term_sequence(itrm->std_out,itrm->flags);	ttcsetattr(itrm->ctl_in, TCSANOW, &itrm->t);	if (itrm->mouse_h) unhandle_mouse(itrm->mouse_h);	set_handlers(itrm->std_in, NULL, NULL, NULL, NULL);	set_handlers(itrm->sock_in, NULL, NULL, NULL, NULL);	set_handlers(itrm->std_out, NULL, NULL, NULL, NULL);	set_handlers(itrm->sock_out, NULL, NULL, NULL, NULL);	if (itrm->tm != -1) kill_timer(itrm->tm);	mem_free(itrm->ev_queue);	mem_free(itrm);	if (itrm == ditrm) ditrm = NULL;}void fatal_tty_exit(void){	if (ditrm) ttcsetattr(ditrm->ctl_in, TCSANOW, &ditrm->t);}void resize_terminal_x(unsigned char *text){	int x, y;	unsigned char *p;	if (!(p = strchr(text, ','))) return;	*p++ = 0;	x = atoi(text);	y = atoi(p);	resize_window(x, y);	resize_terminal();}void dispatch_special(unsigned char *text){	switch (text[0]) {		case TERM_FN_TITLE:			set_window_title(text + 1);			break;		case TERM_FN_RESIZE:			resize_terminal_x(text + 1);			break;	}}unsigned char buf[OUT_BUF_SIZE];/*#define RD ({ char cc; if (p < c) cc = buf[p++]; else if ((dl = hard_read(itrm->sock_in, &cc, 1)) <= 0) {debug("%d %d", dl, errno);goto fr;} cc; })*//*udefine RD ({ char cc; if (p < c) cc = buf[p++]; else if ((hard_read(itrm->sock_in, &cc, 1)) <= 0) goto fr; cc; })*/#define RD(xx) { unsigned char cc; if (p < c) cc = buf[p++]; else if ((hard_read(itrm->sock_in, &cc, 1)) <= 0) goto fr; xx = cc; }void in_sock(struct itrm *itrm){	unsigned char *path, *delete;	int pl, dl;	char ch;	int fg;	int c, i, p;	if ((c = read(itrm->sock_in, buf, OUT_BUF_SIZE)) <= 0) {		fr:		itrm->free_trm(itrm);		terminate_loop = 1;		return;	}	qwerty:	for (i = 0; i < c; i++) if (!buf[i]) goto ex;	if (!is_blocked()) {		want_draw();		hard_write(itrm->std_out, buf, c);		done_draw();	}	return;	ex:	if (!is_blocked()) {		want_draw();		hard_write(itrm->std_out, buf, i);		done_draw();	}	i++;	memmove(buf, buf + i, OUT_BUF_SIZE - i);	c -= i;	p = 0;	/*fg = RD;*/	RD(fg);	path = init_str();	delete = init_str();	pl = dl = 0;	while (1) {		RD(ch);		if (!ch) break;		add_chr_to_str(&path, &pl, ch);	}	while (1) {		RD(ch);		if (!ch) break;		add_chr_to_str(&delete, &dl, ch);	}	if (!*path) {		dispatch_special(delete);	} else {		long blockh;		unsigned char *param;		if (is_blocked() && fg) {			if (*delete) unlink(delete);			goto to_je_ale_hnus;		}		param = mem_alloc(strlen(path) + strlen(delete) + 3);		param[0] = fg;		strcpy(param + 1, path);		strcpy(param + 1 + strlen(path) + 1, delete);		if (fg == 1) block_itrm(0);		if ((blockh = start_thread((void (*)(void *, int))exec_thread, param, strlen(path) + strlen(delete) + 3)) == -1) {			if (fg == 1) unblock_itrm(0);			mem_free(param);			goto to_je_ale_hnus;		}		mem_free(param);		if (fg == 1) {			set_handlers(blockh, (void (*)(void *))unblock_itrm_x, NULL, (void (*)(void *))unblock_itrm_x, (void *)blockh);		} else {			set_handlers(blockh, close_handle, NULL, close_handle, (void *)blockh);		}	}	to_je_ale_hnus:	mem_free(path);	mem_free(delete);	memmove(buf, buf + p, OUT_BUF_SIZE - p);	c -= p;	goto qwerty;}int process_queue(struct itrm *);void kbd_timeout(struct itrm *itrm){	struct event ev = {EV_KBD, KBD_ESC, 0, 0};	char code;	int num;	int len;	itrm->tm = -1;	if (can_read(itrm->std_in)) {		in_kbd(itrm);		return;	}	if (!itrm->qlen) {		internal("timeout on empty queue");		return;	}	itrm->queue_event(itrm, (char *)&ev, sizeof(struct event));	if (get_esc_code(itrm->kqueue, itrm->qlen, &code, &num, &len)) len = 1;	itrm->qlen -= len;	memmove(itrm->kqueue, itrm->kqueue + len, itrm->qlen);	while (process_queue(itrm)) ;}int get_esc_code(char *str, int len, char *code, int *num, int *el){	int pos;	*num = 0;	for (pos = 2; pos < len; pos++) {		if (str[pos] < '0' || str[pos] > '9' || pos > 7) {			*el = pos + 1;			*code = str[pos];			return 0;		}		*num = *num * 10 + str[pos] - '0';	}	return -1;}/*struct os2_key {	int x, y;};*/struct os2_key os2xtd[256] = {/* 0 */{0,0},{0,0},{' ',KBD_CTRL},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},

⌨️ 快捷键说明

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