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

📄 term.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/*- * Copyright (c) 1991, 1993, 1994 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char sccsid[] = "@(#)term.c	8.64 (Berkeley) 4/17/94";#endif /* not lint */#include <sys/types.h>#include <sys/queue.h>#include <sys/time.h>#include <bitstring.h>#include <ctype.h>#include <errno.h>#include <limits.h>#include <locale.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <termios.h>#include <unistd.h>#include "compat.h"#include <curses.h>#include <db.h>#include <regex.h>#include "vi.h"#include "seq.h"static int	 keycmp __P((const void *, const void *));static int	 term_key_queue __P((SCR *));static void	 term_key_set __P((GS *, int, int));/* * If we're reading less than 20 characters, up the size of the tty buffer. * This shouldn't ever happen, other than the first time through, but it's * possible if a map is large enough. */#define	term_read_grow(sp, tty)					\	(tty)->nelem - (tty)->cnt >= 20 ? 0 : __term_read_grow(sp, tty, 64)static int __term_read_grow __P((SCR *, IBUF *, int));/* * XXX * THIS REQUIRES THAT ALL SCREENS SHARE A TERMINAL TYPE. */typedef struct _tklist {	char	*ts;			/* Key's termcap string. */	char	*output;		/* Corresponding vi command. */	char	*name;			/* Name. */	u_char	 value;			/* Special value (for lookup). */} TKLIST;static TKLIST const c_tklist[] = {	/* Command mappings. */	{"kA",    "O",	"insert line"},	{"kD",    "x",	"delete character"},	{"kd",    "j",	"cursor down"},	{"kE",    "D",	"delete to eol"},	{"kF", "\004",	"scroll down"},	{"kH",    "$",	"go to eol"},	{"kh",    "^",	"go to sol"},	{"kI",    "i",	"insert at cursor"},	{"kL",   "dd",	"delete line"},	{"kl",    "h",	"cursor left"},	{"kN", "\006",	"page down"},	{"kP", "\002",	"page up"},	{"kR", "\025",	"scroll up"},	{"kS",	 "dG",	"delete to end of screen"},	{"kr",    "l",	"cursor right"},	{"ku",    "k",	"cursor up"},	{NULL},};static TKLIST const m1_tklist[] = {	/* Input mappings (lookup). */	{"kl",   NULL,	"cursor erase", K_VERASE},	{NULL},};static TKLIST const m2_tklist[] = {	/* Input mappings (set or delete). */	{"kd",   NULL,	"cursor down"},	{"ku",   NULL,	"cursor up"},	{"kr",    " ",	"cursor space"},	{NULL},};/* * !!! * Historic ex/vi always used: * *	^D: autoindent deletion *	^H: last character deletion *	^W: last word deletion *	^Q: quote the next character (if not used in flow control). *	^V: quote the next character * * regardless of the user's choices for these characters.  The user's erase * and kill characters worked in addition to these characters.  Ex was not * completely consistent with this scheme, as it did map the scroll command * to the user's current EOF character.  This implementation wires down the * above characters, but in addition uses the VERASE, VINTR, VKILL and VWERASE * characters described by the user's termios structure.  We don't do the EOF * mapping for ex, but I think I'm unlikely to get caught on that one. * * XXX * THIS REQUIRES THAT ALL SCREENS SHARE A SPECIAL KEY SET. */typedef struct _keylist {	u_char	value;			/* Special value. */	CHAR_T	ch;			/* Key. */} KEYLIST;static KEYLIST keylist[] = {	{K_CARAT,	   '^'},	/*  ^ */	{K_CNTRLD,	'\004'},	/* ^D */	{K_CNTRLR,	'\022'},	/* ^R */	{K_CNTRLT,	'\024'},	/* ^T */	{K_CNTRLZ,	'\032'},	/* ^Z */	{K_COLON,	   ':'},	/*  : */	{K_CR,		  '\r'},	/* \r */	{K_ESCAPE,	'\033'},	/* ^[ */	{K_FORMFEED,	  '\f'},	/* \f */	{K_HEXCHAR,	'\030'},	/* ^X */	{K_NL,		  '\n'},	/* \n */	{K_RIGHTBRACE,	   '}'},	/*  } */	{K_RIGHTPAREN,	   ')'},	/*  ) */	{K_TAB,		  '\t'},	/* \t */	{K_VERASE,	  '\b'},	/* \b */	{K_VINTR,	'\003'},	/* ^C */	{K_VKILL,	'\025'},	/* ^U */	{K_VLNEXT,	'\021'},	/* ^Q */	{K_VLNEXT,	'\026'},	/* ^V */	{K_VWERASE,	'\027'},	/* ^W */	{K_ZERO,	   '0'},	/*  0 */	{K_NOTUSED, 0},			/* VERASE, VINTR, VKILL, VWERASE */	{K_NOTUSED, 0},	{K_NOTUSED, 0},	{K_NOTUSED, 0},};static int nkeylist = (sizeof(keylist) / sizeof(keylist[0])) - 4;/* * term_init -- *	Initialize the special key lookup table, and the special keys *	defined by the terminal's termcap entry. */intterm_init(sp)	SCR *sp;{	GS *gp;	KEYLIST *kp;	TKLIST const *tkp;	int cnt;	char *sbp, *t, buf[2 * 1024], sbuf[128];	/*	 * XXX	 * 8-bit only, for now.  Recompilation should get you any	 * 8-bit character set, as long as nul isn't a character.	 */	(void)setlocale(LC_ALL, "");	key_init(sp);	gp = sp->gp;#ifdef VERASE	term_key_set(gp, VERASE, K_VERASE);#endif#ifdef VINTR	term_key_set(gp, VINTR, K_VINTR);#endif#ifdef VKILL	term_key_set(gp, VKILL, K_VKILL);#endif#ifdef VWERASE	term_key_set(gp, VWERASE, K_VWERASE);#endif	/* Sort the special key list. */	qsort(keylist, nkeylist, sizeof(keylist[0]), keycmp);	/* Initialize the fast lookup table. */	for (gp->max_special = 0, kp = keylist, cnt = nkeylist; cnt--; ++kp) {		if (gp->max_special < kp->value)			gp->max_special = kp->value;		if (kp->ch <= MAX_FAST_KEY)			gp->special_key[kp->ch] = kp->value;	}	/* Set key sequences found in the termcap entry. */#ifndef SYSV_CURSES	if (term_tgetent(sp, buf, O_STR(sp, O_TERM)))		return (0);#endif	/* Command mappings. */	for (tkp = c_tklist; tkp->name != NULL; ++tkp) {#ifdef SYSV_CURSES		if ((t = tigetstr(tkp->ts)) == (char *)-1)			continue;#else		sbp = sbuf;		if ((t = tgetstr(tkp->ts, &sbp)) == NULL)			continue;#endif		if (seq_set(sp, tkp->name, strlen(tkp->name), t, strlen(t),		    tkp->output, strlen(tkp->output), SEQ_COMMAND, 0))			return (1);	}	/* Input mappings needing to be looked up. */	for (tkp = m1_tklist; tkp->name != NULL; ++tkp) {#ifdef SYSV_CURSES		if ((t = tigetstr(tkp->ts)) == (char *)-1)			continue;#else		sbp = sbuf;		if ((t = tgetstr(tkp->ts, &sbp)) == NULL)			continue;#endif		for (kp = keylist;; ++kp)			if (kp->value == tkp->value)				break;		if (kp == NULL)			continue;		if (seq_set(sp, tkp->name, strlen(tkp->name),		    t, strlen(t), &kp->ch, 1, SEQ_INPUT, 0))			return (1);	}	/* Input mappings that are already set or are text deletions. */	for (tkp = m2_tklist; tkp->name != NULL; ++tkp) {#ifdef SYSV_CURSES		if ((t = tigetstr(tkp->ts)) == (char *)-1)			continue;#else		sbp = sbuf;		if ((t = tgetstr(tkp->ts, &sbp)) == NULL)			continue;#endif		if (tkp->output == NULL) {			if (seq_set(sp, tkp->name, strlen(tkp->name),			    t, strlen(t), NULL, 0, SEQ_INPUT, 0))				return (1);		} else			if (seq_set(sp, tkp->name, strlen(tkp->name),			    t, strlen(t), tkp->output, strlen(tkp->output),			    SEQ_INPUT, 0))				return (1);	}	return (0);}#ifndef SYSV_CURSES/* * term_tgetent -- *	Routine to fill in the tgetent buffer, broken out so that *	the error code isn't endlessly repeated. */intterm_tgetent(sp, buf, term)	SCR *sp;	char *buf, *term;{	if (term == NULL) {		msgq(sp, M_ERR, "No terminal type set.");		return (1);	}	switch (tgetent(buf, term)) {	case -1:		msgq(sp, M_SYSERR, "tgetent: %s", term);		return (1);	case 0:		msgq(sp, M_ERR, "%s: unknown terminal type.", term);		return (1);	}	return (0);}#endif/* * term_key_set -- *	Set keys found in the termios structure.  VERASE, VINTR and VKILL are *	required by POSIX 1003.1-1990, VWERASE is a 4.4BSD extension.  We've *	left four open slots in the keylist table, if these values exist, put *	them into place.  Note, they may reset (or duplicate) values already *	in the table, so we check for that first. */static voidterm_key_set(gp, name, val)	GS *gp;	int name, val;{	KEYLIST *kp;	cc_t ch;	if (!F_ISSET(gp, G_TERMIOS_SET))		return;	if ((ch = gp->original_termios.c_cc[(name)]) == _POSIX_VDISABLE)		return;	/* Check for duplication. */	for (kp = keylist; kp->value != K_NOTUSED; ++kp)		if (kp->ch == ch) {			kp->value = val;			return;		}	/* Add a new entry. */	if (kp->value == K_NOTUSED) {		keylist[nkeylist].ch = ch;		keylist[nkeylist].value = val;		++nkeylist;	}}/* * key_init -- *	Build the fast-lookup key display array. */voidkey_init(sp)	SCR *sp;{	CHAR_T ch;	/*	 * XXX	 * Assume that nul is not a legal character.	 */	for (ch = 0; ch <= MAX_FAST_KEY; ++ch) {		(void)__key_name(sp, ch);		(void)memmove(sp->gp->cname[ch].name,		    sp->cname, sp->gp->cname[ch].len = sp->clen);	}}/* * __key_len -- *	Return the length of the string that will display the key. *	This routine is the backup for the KEY_LEN() macro. */size_t__key_len(sp, ch)	SCR *sp;	ARG_CHAR_T ch;{	(void)__key_name(sp, ch);	return (sp->clen);}/* * __key_name -- *	Return the string that will display the key.  This routine *	is the backup for the KEY_NAME() macro. */CHAR_T *__key_name(sp, ach)	SCR *sp;	ARG_CHAR_T ach;{	static const CHAR_T hexdigit[] = "0123456789abcdef";	static const CHAR_T octdigit[] = "01234567";	CHAR_T ch, *chp, mask;	size_t len;	int cnt, shift;	/*	 * Historical mappings.  Printable characters are left alone.  Control	 * characters less than '\177' are represented as '^' followed by the	 * character offset from the '@' character in the ASCII map.  '\177' is	 * represented as '^' followed by '?'.	 *	 * XXX	 * The following code depends on the current locale being identical to	 * the ASCII map from '\100' to '\076' (\076 since that's the largest	 * character for which we can offset from '@' and get something that's	 * a printable character in ASCII.  I'm told that this is a reasonable	 * assumption...	 *	 * XXX	 * This code will only work with CHAR_T's that are multiples of 8-bit	 * bytes.	 *	 * XXX	 * NB: There's an assumption here that all printable characters take	 * up a single column on the screen.  This is not always correct.	 */	ch = ach;	if (isprint(ch)) {		sp->cname[0] = ch;		len = 1;	} else if (ch <= '\076' && iscntrl(ch)) {		sp->cname[0] = '^';		sp->cname[1] = ch == '\177' ? '?' : '@' + ch;		len = 2;	} else if (O_ISSET(sp, O_OCTAL)) {#define	BITS	(sizeof(CHAR_T) * 8)#define	SHIFT	(BITS - BITS % 3)#define	TOPMASK	(BITS % 3 == 2 ? 3 : 1) << BITS - BITS % 3		sp->cname[0] = '\\';		sp->cname[1] = octdigit[(ch & TOPMASK) >> SHIFT];		shift = SHIFT - 3;		for (len = 2, mask = 7 << SHIFT - 3,		    cnt = BITS / 3; cnt-- > 0; mask >>= 3, shift -= 3)			sp->cname[len++] = octdigit[(ch & mask) >> shift];	} else {		sp->cname[0] = '0';		sp->cname[1] = 'x';		for (len = 2, chp = (u_int8_t *)&ch,		    cnt = sizeof(CHAR_T); cnt-- > 0; ++chp) {			sp->cname[len++] = hexdigit[(*chp & 0xf0) >> 4];			sp->cname[len++] = hexdigit[*chp & 0x0f];		}	}	sp->cname[sp->clen = len] = '\0';	return (sp->cname);}/* * term_push -- *	Push keys onto the front of a buffer. * * There is a single input buffer in ex/vi.  Characters are read onto the * end of the buffer by the terminal input routines, and pushed onto the * front of the buffer by various other functions in ex/vi.  Each key has * an associated flag value, which indicates if it has already been quoted,

⌨️ 快捷键说明

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