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

📄 edit.c

📁 一个开放源代码的 AT&T 的 Korn Shell 的复制品, 支持大多数 ksh89 的特性。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Command line editing - common code * */#include "config.h"#ifdef EDIT#include "sh.h"#include "tty.h"#define EXTERN#include "edit.h"#undef EXTERN#ifdef OS_SCO	/* SCO Unix 3.2v4.1 */# include <sys/stream.h>	/* needed for <sys/ptem.h> */# include <sys/ptem.h>		/* needed for struct winsize */#endif /* OS_SCO */#include <ctype.h>#include "ksh_stat.h"#if defined(TIOCGWINSZ)static RETSIGTYPE x_sigwinch ARGS((int sig));static int got_sigwinch;static void check_sigwinch ARGS((void));#endif /* TIOCGWINSZ */static int	x_file_glob ARGS((int flags, const char *str, int slen,				  char ***wordsp));static int	x_command_glob ARGS((int flags, const char *str, int slen,				     char ***wordsp));static int	x_locate_word ARGS((const char *buf, int buflen, int pos,				    int *startp, int *is_command));static char vdisable_c;/* Called from main */voidx_init(){	/* set to -2 to force initial binding */	edchars.erase = edchars.kill = edchars.intr = edchars.quit		= edchars.eof = -2;	/* default value for deficient systems */	edchars.werase = 027;	/* ^W */#ifdef TIOCGWINSZ# ifdef SIGWINCH	if (setsig(&sigtraps[SIGWINCH], x_sigwinch, SS_RESTORE_ORIG|SS_SHTRAP))		sigtraps[SIGWINCH].flags |= TF_SHELL_USES;# endif /* SIGWINCH */	got_sigwinch = 1; /* force initial check */	check_sigwinch();#endif /* TIOCGWINSZ */#ifdef EMACS	x_init_emacs();#endif /* EMACS */	/* Bizarreness to figure out how to disable	 * a struct termios.c_cc[] char	 */#ifdef _POSIX_VDISABLE	if (_POSIX_VDISABLE >= 0)		vdisable_c = (char) _POSIX_VDISABLE;	else		/* `feature not available' */		vdisable_c = (char) 0377;#else# if defined(HAVE_PATHCONF) && defined(_PC_VDISABLE)	vdisable_c = fpathconf(tty_fd, _PC_VDISABLE);# else	vdisable_c = (char) 0377;	/* default to old BSD value */# endif#endif /* _POSIX_VDISABLE */}#if defined(TIOCGWINSZ)static RETSIGTYPEx_sigwinch(sig)    	int sig;{	got_sigwinch = 1;	return RETSIGVAL;}static voidcheck_sigwinch ARGS((void)){	if (got_sigwinch) {		struct winsize ws;		got_sigwinch = 0;		if (procpid == kshpid && ioctl(tty_fd, TIOCGWINSZ, &ws) >= 0) {			struct tbl *vp;			/* Do NOT export COLUMNS/LINES.  Many applications			 * check COLUMNS/LINES before checking ws.ws_col/row,			 * so if the app is started with C/L in the environ			 * and the window is then resized, the app won't			 * see the change cause the environ doesn't change.			 */			if (ws.ws_col) {				x_cols = ws.ws_col < MIN_COLS ? MIN_COLS						: ws.ws_col;								if ((vp = typeset("COLUMNS", 0, 0, 0, 0)))					setint(vp, (long) ws.ws_col);			}			if (ws.ws_row			    && (vp = typeset("LINES", 0, 0, 0, 0)))				setint(vp, (long) ws.ws_row);		}	}}#endif /* TIOCGWINSZ *//* * read an edited command line */intx_read(buf, len)	char *buf;	size_t len;{	int	i;#if defined(TIOCGWINSZ)	if (got_sigwinch)		check_sigwinch();#endif /* TIOCGWINSZ */	x_mode(TRUE);#ifdef EMACS	if (Flag(FEMACS) || Flag(FGMACS))		i = x_emacs(buf, len);	else#endif#ifdef VI	if (Flag(FVI))		i = x_vi(buf, len);	else#endif		i = -1;		/* internal error */	x_mode(FALSE);	return i;}/* tty I/O */intx_getc(){#ifdef OS2	unsigned char c = _read_kbd(0, 1, 0);	return c == 0 ? 0xE0 : c;#else /* OS2 */	char c;	int n;	while ((n = blocking_read(0, &c, 1)) < 0 && errno == EINTR)		if (trap) {			x_mode(FALSE);			runtraps(0);			x_mode(TRUE);		}	if (n != 1)		return -1;	return (int) (unsigned char) c;#endif /* OS2 */}voidx_flush(){	shf_flush(shl_out);}voidx_putc(c)	int c;{	shf_putc(c, shl_out);}voidx_puts(s)	const char *s;{	while (*s != 0)		shf_putc(*s++, shl_out);}bool_tx_mode(onoff)	bool_t	onoff;{	static bool_t	x_cur_mode;	bool_t		prev;	if (x_cur_mode == onoff)		return x_cur_mode;	prev = x_cur_mode;	x_cur_mode = onoff;	if (onoff) {		TTY_state	cb;		X_chars		oldchars;				oldchars = edchars;		cb = tty_state;#if defined(HAVE_TERMIOS_H) || defined(HAVE_TERMIO_H)		edchars.erase = cb.c_cc[VERASE];		edchars.kill = cb.c_cc[VKILL];		edchars.intr = cb.c_cc[VINTR];		edchars.quit = cb.c_cc[VQUIT];		edchars.eof = cb.c_cc[VEOF];# ifdef VWERASE		edchars.werase = cb.c_cc[VWERASE];# endif# ifdef _CRAY2		/* brain-damaged terminal handler */		cb.c_lflag &= ~(ICANON|ECHO);		/* rely on print routine to map '\n' to CR,LF */# else		cb.c_iflag &= ~(INLCR|ICRNL);#  ifdef _BSD_SYSV	/* need to force CBREAK instead of RAW (need CRMOD on output) */		cb.c_lflag &= ~(ICANON|ECHO);#  else#   ifdef SWTCH	/* need CBREAK to handle swtch char */		cb.c_lflag &= ~(ICANON|ECHO);		cb.c_lflag |= ISIG;		cb.c_cc[VINTR] = vdisable_c;		cb.c_cc[VQUIT] = vdisable_c;#   else		cb.c_lflag &= ~(ISIG|ICANON|ECHO);#   endif#  endif#  ifdef VLNEXT		/* osf/1 processes lnext when ~icanon */		cb.c_cc[VLNEXT] = vdisable_c;#  endif /* VLNEXT */#  ifdef VDISCARD		/* sunos 4.1.x & osf/1 processes discard(flush) when ~icanon */		cb.c_cc[VDISCARD] = vdisable_c;#  endif /* VDISCARD */		cb.c_cc[VTIME] = 0;		cb.c_cc[VMIN] = 1;# endif	/* _CRAY2 */#else	/* Assume BSD tty stuff. */		edchars.erase = cb.sgttyb.sg_erase;		edchars.kill = cb.sgttyb.sg_kill;		cb.sgttyb.sg_flags &= ~ECHO;		cb.sgttyb.sg_flags |= CBREAK;#  ifdef TIOCGATC		edchars.intr = cb.lchars.tc_intrc;		edchars.quit = cb.lchars.tc_quitc;		edchars.eof = cb.lchars.tc_eofc;		edchars.werase = cb.lchars.tc_werasc;		cb.lchars.tc_suspc = -1;		cb.lchars.tc_dsuspc = -1;		cb.lchars.tc_lnextc = -1;		cb.lchars.tc_statc = -1;		cb.lchars.tc_intrc = -1;		cb.lchars.tc_quitc = -1;		cb.lchars.tc_rprntc = -1;#  else		edchars.intr = cb.tchars.t_intrc;		edchars.quit = cb.tchars.t_quitc;		edchars.eof = cb.tchars.t_eofc;		cb.tchars.t_intrc = -1;		cb.tchars.t_quitc = -1;#   ifdef TIOCGLTC		edchars.werase = cb.ltchars.t_werasc;		cb.ltchars.t_suspc = -1;		cb.ltchars.t_dsuspc = -1;		cb.ltchars.t_lnextc = -1;		cb.ltchars.t_rprntc = -1;#   endif#  endif /* TIOCGATC */#endif /* HAVE_TERMIOS_H || HAVE_TERMIO_H */		set_tty(tty_fd, &cb, TF_WAIT);#ifdef __CYGWIN__		if (edchars.eof == '\0')			edchars.eof = '\4';#endif /* __CYGWIN__ */		/* Convert unset values to internal `unset' value */		if (edchars.erase == vdisable_c)			edchars.erase = -1;		if (edchars.kill == vdisable_c)			edchars.kill = -1;		if (edchars.intr == vdisable_c)			edchars.intr = -1;		if (edchars.quit == vdisable_c)			edchars.quit = -1;		if (edchars.eof == vdisable_c)			edchars.eof = -1;		if (edchars.werase == vdisable_c)			edchars.werase = -1;		if (memcmp(&edchars, &oldchars, sizeof(edchars)) != 0) {#ifdef EMACS			x_emacs_keys(&edchars);#endif		}	} else {		/* TF_WAIT doesn't seem to be necessary when leaving xmode */		set_tty(tty_fd, &tty_state, TF_NONE);	}	return prev;}/* NAME: *      promptlen - calculate the length of PS1 etc. * * DESCRIPTION: *      This function is based on a fix from guy@demon.co.uk *      It fixes a bug in that if PS1 contains '!', the length  *      given by strlen() is probably wrong. * * RETURN VALUE: *      length */intpromptlen(cp, spp)    const char  *cp;    const char **spp;{    int count = 0;    const char *sp = cp;    char delimiter = 0;    int indelimit = 0;    /* Undocumented AT&T ksh feature:     * If the second char in the prompt string is \r then the first char     * is taken to be a non-printing delimiter and any chars between two     * instances of the delimiter are not considered to be part of the     * prompt length     */    if (*cp && cp[1] == '\r') {	delimiter = *cp;	cp += 2;    }    for (; *cp; cp++) {	if (indelimit && *cp != delimiter)	    ;	else if (*cp == '\n' || *cp == '\r') {	    count = 0;	    sp = cp + 1;	} else if (*cp == '\t') {	    count = (count | 7) + 1;	} else if (*cp == '\b') {	    if (count > 0)		count--;	} else if (*cp == delimiter)	    indelimit = !indelimit;	else	    count++;    }    if (spp)	*spp = sp;    return count;}voidset_editmode(ed)	const char *ed;{	static const enum sh_flag edit_flags[] = {#ifdef EMACS			FEMACS, FGMACS,#endif#ifdef VI			FVI,#endif		    };	char *rcp;	int i;  	if ((rcp = ksh_strrchr_dirsep(ed)))		ed = ++rcp;	for (i = 0; i < NELEM(edit_flags); i++)		if (strstr(ed, options[(int) edit_flags[i]].name)) {			change_flag(edit_flags[i], OF_SPECIAL, 1);			return;		}}/* ------------------------------------------------------------------------- *//*           Misc common code for vi/emacs				     *//* Handle the commenting/uncommenting of a line. * Returns: *	1 if a carriage return is indicated (comment added) *	0 if no return (comment removed) *	-1 if there is an error (not enough room for comment chars) * If successful, *lenp contains the new length.  Note: cursor should be * moved to the start of the line after (un)commenting. */intx_do_comment(buf, bsize, lenp)	char *buf;	int bsize;	int *lenp;{	int i, j;	int len = *lenp;	if (len == 0)		return 1; /* somewhat arbitrary - it's what at&t ksh does */	/* Already commented? */	if (buf[0] == '#') {		int saw_nl = 0;		for (j = 0, i = 1; i < len; i++) {			if (!saw_nl || buf[i] != '#')				buf[j++] = buf[i];			saw_nl = buf[i] == '\n';		}		*lenp = j;		return 0;	} else {		int n = 1;		/* See if there's room for the #'s - 1 per \n */		for (i = 0; i < len; i++)			if (buf[i] == '\n')				n++;		if (len + n >= bsize)			return -1;		/* Now add them... */		for (i = len, j = len + n; --i >= 0; ) {			if (buf[i] == '\n')				buf[--j] = '#';			buf[--j] = buf[i];		}		buf[0] = '#';		*lenp += n;		return 1;	}}/* ------------------------------------------------------------------------- *//*           Common file/command completion code for vi/emacs	             */static char	*add_glob ARGS((const char *str, int slen));static void	glob_table ARGS((const char *pat, XPtrV *wp, struct table *tp));static void	glob_path ARGS((int flags, const char *pat, XPtrV *wp,				const char *path));#if 0 /* not used... */int	x_complete_word ARGS((const char *str, int slen, int is_command,			      int *multiple, char **ret));intx_complete_word(str, slen, is_command, nwordsp, ret)	const char *str;	int slen;	int is_command;	int *nwordsp;	char **ret;{	int nwords;	int prefix_len;	char **words;	nwords = (is_command ? x_command_glob : x_file_glob)(XCF_FULLPATH,				str, slen, &words);	*nwordsp = nwords;	if (nwords == 0) {		*ret = (char *) 0;		return -1;	}	prefix_len = x_longest_prefix(nwords, words);	*ret = str_nsave(words[0], prefix_len, ATEMP);	x_free_words(nwords, words);	return prefix_len;}#endif /* 0 */voidx_print_expansions(nwords, words, is_command)	int nwords;	char *const *words;	int is_command;{	int use_copy = 0;	int prefix_len;	XPtrV l;	/* Check if all matches are in the same directory (in this	 * case, we want to omitt the directory name)	 */	if (!is_command	    && (prefix_len = x_longest_prefix(nwords, words)) > 0)	{		int i;		/* Special case for 1 match (prefix is whole word) */		if (nwords == 1)			prefix_len = x_basename(words[0], (char *) 0);		/* Any (non-trailing) slashes in non-common word suffixes? */		for (i = 0; i < nwords; i++)

⌨️ 快捷键说明

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