Beispiel #1
0
/* re_goto_bottom():
 *	 used to go to last used screen line
 */
libedit_private void
re_goto_bottom(EditLine *el)
{

	terminal_move_to_line(el, el->el_refresh.r_oldcv);
	terminal__putc(el, '\n');
	re_clear_display(el);
	terminal__flush(el);
}
Beispiel #2
0
/* el_push():
 *	Push a macro
 */
void
el_wpush(EditLine *el, const wchar_t *str)
{
	struct macros *ma = &el->el_read->macros;

	if (str != NULL && ma->level + 1 < EL_MAXMACRO) {
		ma->level++;
		if ((ma->macro[ma->level] = wcsdup(str)) != NULL)
			return;
		ma->level--;
	}
	terminal_beep(el);
	terminal__flush(el);
}
Beispiel #3
0
/* el_wgetc():
 *	Read a wide character
 */
int
el_wgetc(EditLine *el, wchar_t *cp)
{
	int num_read;
	c_macro_t *ma = &el->el_chared.c_macro;

	terminal__flush(el);
	for (;;) {
		if (ma->level < 0)
			break;

		if (ma->macro[0][ma->offset] == '\0') {
			read_pop(ma);
			continue;
		}

		*cp = ma->macro[0][ma->offset++];

		if (ma->macro[0][ma->offset] == '\0') {
			/* Needed for QuoteMode On */
			read_pop(ma);
		}

		return 1;
	}

#ifdef DEBUG_READ
	(void) fprintf(el->el_errfile, "Turning raw mode on\n");
#endif /* DEBUG_READ */
	if (tty_rawmode(el) < 0)/* make sure the tty is set up correctly */
		return 0;

#ifdef DEBUG_READ
	(void) fprintf(el->el_errfile, "Reading a character\n");
#endif /* DEBUG_READ */
	num_read = (*el->el_read->read_char)(el, cp);
	if (num_read < 0)
		el->el_errno = errno;
#ifdef DEBUG_READ
	(void) fprintf(el->el_errfile, "Got it %lc\n", *cp);
#endif /* DEBUG_READ */
	return num_read;
}
Beispiel #4
0
/* sig_handler():
 *	This is the handler called for all signals
 *	XXX: we cannot pass any data so we just store the old editline
 *	state in a private variable
 */
static void
sig_handler(int signo)
{
	int i, save_errno;
	sigset_t nset, oset;

	save_errno = errno;
	(void) sigemptyset(&nset);
	(void) sigaddset(&nset, signo);
	(void) sigprocmask(SIG_BLOCK, &nset, &oset);

	sel->el_signal->sig_no = signo;

	switch (signo) {
	case SIGCONT:
		tty_rawmode(sel);
		if (ed_redisplay(sel, 0) == CC_REFRESH)
			re_refresh(sel);
		terminal__flush(sel);
		break;

	case SIGWINCH:
		el_resize(sel);
		break;

	default:
		tty_cookedmode(sel);
		break;
	}

	for (i = 0; sighdl[i] != -1; i++)
		if (signo == sighdl[i])
			break;

	(void) sigaction(signo, &sel->el_signal->sig_action[i], NULL);
	sel->el_signal->sig_action[i].sa_handler = SIG_ERR;
	sel->el_signal->sig_action[i].sa_flags = 0;
	sigemptyset(&sel->el_signal->sig_action[i].sa_mask);
	(void) sigprocmask(SIG_SETMASK, &oset, NULL);
	(void) kill(0, signo);
	errno = save_errno;
}
Beispiel #5
0
libedit_private void
read_prepare(EditLine *el)
{
	if (el->el_flags & HANDLE_SIGNALS)
		sig_set(el);
	if (el->el_flags & NO_TTY)
		return;
	if ((el->el_flags & (UNBUFFERED|EDIT_DISABLED)) == UNBUFFERED)
		tty_rawmode(el);

	/* This is relatively cheap, and things go terribly wrong if
	   we have the wrong size. */
	el_resize(el);
	re_clear_display(el);	/* reset the display stuff */
	ch_reset(el);
	re_refresh(el);		/* print the prompt */

	if (el->el_flags & UNBUFFERED)
		terminal__flush(el);
}
Beispiel #6
0
/* el_wgetc():
 *	Read a wide character
 */
int
el_wgetc(EditLine *el, wchar_t *cp)
{
	struct macros *ma = &el->el_read->macros;
	int num_read;

	terminal__flush(el);
	for (;;) {
		if (ma->level < 0)
			break;

		if (ma->macro[0][ma->offset] == '\0') {
			read_pop(ma);
			continue;
		}

		*cp = ma->macro[0][ma->offset++];

		if (ma->macro[0][ma->offset] == '\0') {
			/* Needed for QuoteMode On */
			read_pop(ma);
		}

		return 1;
	}

	if (tty_rawmode(el) < 0)/* make sure the tty is set up correctly */
		return 0;

	num_read = (*el->el_read->read_char)(el, cp);

	/*
	 * Remember the original reason of a read failure
	 * such that el_wgets() can restore it after doing
	 * various cleanup operation that might change errno.
	 */
	if (num_read < 0)
		el->el_read->read_errno = errno;

	return num_read;
}
Beispiel #7
0
const wchar_t *
el_wgets(EditLine *el, int *nread)
{
	int retval;
	el_action_t cmdnum = 0;
	int num;		/* how many chars we have read at NL */
	wchar_t ch;
	int nrb;

	if (nread == NULL)
		nread = &nrb;
	*nread = 0;
	el->el_read->read_errno = 0;

	if (el->el_flags & NO_TTY) {
		el->el_line.lastchar = el->el_line.buffer;
		return noedit_wgets(el, nread);
	}

#ifdef FIONREAD
	if (el->el_tty.t_mode == EX_IO && el->el_read->macros.level < 0) {
		int chrs = 0;

		(void) ioctl(el->el_infd, FIONREAD, &chrs);
		if (chrs == 0) {
			if (tty_rawmode(el) < 0) {
				errno = 0;
				*nread = 0;
				return NULL;
			}
		}
	}
#endif /* FIONREAD */

	if ((el->el_flags & UNBUFFERED) == 0)
		read_prepare(el);

	if (el->el_flags & EDIT_DISABLED) {
		if ((el->el_flags & UNBUFFERED) == 0)
			el->el_line.lastchar = el->el_line.buffer;
		terminal__flush(el);
		return noedit_wgets(el, nread);
	}

	for (num = -1; num == -1;) {  /* while still editing this line */
		/* if EOF or error */
		if (read_getcmd(el, &cmdnum, &ch) == -1)
			break;
		if ((size_t)cmdnum >= el->el_map.nfunc) /* BUG CHECK command */
			continue;	/* try again */
		/* now do the real command */
		/* vi redo needs these way down the levels... */
		el->el_state.thiscmd = cmdnum;
		el->el_state.thisch = ch;
		if (el->el_map.type == MAP_VI &&
		    el->el_map.current == el->el_map.key &&
		    el->el_chared.c_redo.pos < el->el_chared.c_redo.lim) {
			if (cmdnum == VI_DELETE_PREV_CHAR &&
			    el->el_chared.c_redo.pos != el->el_chared.c_redo.buf
			    && iswprint(el->el_chared.c_redo.pos[-1]))
				el->el_chared.c_redo.pos--;
			else
				*el->el_chared.c_redo.pos++ = ch;
		}
		retval = (*el->el_map.func[cmdnum]) (el, ch);

		/* save the last command here */
		el->el_state.lastcmd = cmdnum;

		/* use any return value */
		switch (retval) {
		case CC_CURSOR:
			re_refresh_cursor(el);
			break;

		case CC_REDISPLAY:
			re_clear_lines(el);
			re_clear_display(el);
			/* FALLTHROUGH */

		case CC_REFRESH:
			re_refresh(el);
			break;

		case CC_REFRESH_BEEP:
			re_refresh(el);
			terminal_beep(el);
			break;

		case CC_NORM:	/* normal char */
			break;

		case CC_ARGHACK:	/* Suggested by Rich Salz */
			/* <*****@*****.**> */
			continue;	/* keep going... */

		case CC_EOF:	/* end of file typed */
			if ((el->el_flags & UNBUFFERED) == 0)
				num = 0;
			else if (num == -1) {
				*el->el_line.lastchar++ = CONTROL('d');
				el->el_line.cursor = el->el_line.lastchar;
				num = 1;
			}
			break;

		case CC_NEWLINE:	/* normal end of line */
			num = (int)(el->el_line.lastchar - el->el_line.buffer);
			break;

		case CC_FATAL:	/* fatal error, reset to known state */
			/* put (real) cursor in a known place */
			re_clear_display(el);	/* reset the display stuff */
			ch_reset(el);	/* reset the input pointers */
			read_clearmacros(&el->el_read->macros);
			re_refresh(el); /* print the prompt again */
			break;

		case CC_ERROR:
		default:	/* functions we don't know about */
			terminal_beep(el);
			terminal__flush(el);
			break;
		}
		el->el_state.argument = 1;
		el->el_state.doingarg = 0;
		el->el_chared.c_vcmd.action = NOP;
		if (el->el_flags & UNBUFFERED)
			break;
	}

	terminal__flush(el);		/* flush any buffered output */
	/* make sure the tty is set up correctly */
	if ((el->el_flags & UNBUFFERED) == 0) {
		read_finish(el);
		*nread = num != -1 ? num : 0;
	} else
		*nread = (int)(el->el_line.lastchar - el->el_line.buffer);

	if (*nread == 0) {
		if (num == -1) {
			*nread = -1;
			if (el->el_read->read_errno)
				errno = el->el_read->read_errno;
		}
		return NULL;
	} else
		return el->el_line.buffer;
}
Beispiel #8
0
const wchar_t *
el_wgets(EditLine *el, int *nread)
{
	int retval;
	el_action_t cmdnum = 0;
	int num;		/* how many chars we have read at NL */
	wchar_t wc;
	wchar_t ch, *cp;
	int crlf = 0;
	int nrb;

	if (nread == NULL)
		nread = &nrb;
	*nread = 0;

	if (el->el_flags & NO_TTY) {
		size_t idx;

		cp = el->el_line.buffer;
		while ((num = (*el->el_read->read_char)(el, &wc)) == 1) {
			*cp = wc;
			/* make sure there is space for next character */
			if (cp + 1 >= el->el_line.limit) {
				idx = (size_t)(cp - el->el_line.buffer);
				if (!ch_enlargebufs(el, (size_t)2))
					break;
				cp = &el->el_line.buffer[idx];
			}
			cp++;
			if (el->el_flags & UNBUFFERED)
				break;
			if (cp[-1] == '\r' || cp[-1] == '\n')
				break;
		}
		if (num == -1) {
			if (errno == EINTR)
				cp = el->el_line.buffer;
			el->el_errno = errno;
		}

		goto noedit;
	}


#ifdef FIONREAD
	if (el->el_tty.t_mode == EX_IO && el->el_chared.c_macro.level < 0) {
		int chrs = 0;

		(void) ioctl(el->el_infd, FIONREAD, &chrs);
		if (chrs == 0) {
			if (tty_rawmode(el) < 0) {
				errno = 0;
				*nread = 0;
				return NULL;
			}
		}
	}
#endif /* FIONREAD */

	if ((el->el_flags & UNBUFFERED) == 0)
		read_prepare(el);

	if (el->el_flags & EDIT_DISABLED) {
		size_t idx;

		if ((el->el_flags & UNBUFFERED) == 0)
			cp = el->el_line.buffer;
		else
			cp = el->el_line.lastchar;

		terminal__flush(el);

		while ((num = (*el->el_read->read_char)(el, &wc)) == 1) {
			*cp = wc;
			/* make sure there is space next character */
			if (cp + 1 >= el->el_line.limit) {
				idx = (size_t)(cp - el->el_line.buffer);
				if (!ch_enlargebufs(el, (size_t)2))
					break;
				cp = &el->el_line.buffer[idx];
			}
			cp++;
			crlf = cp[-1] == '\r' || cp[-1] == '\n';
			if (el->el_flags & UNBUFFERED)
				break;
			if (crlf)
				break;
		}

		if (num == -1) {
			if (errno == EINTR)
				cp = el->el_line.buffer;
			el->el_errno = errno;
		}

		goto noedit;
	}

	for (num = -1; num == -1;) {  /* while still editing this line */
#ifdef DEBUG_EDIT
		read_debug(el);
#endif /* DEBUG_EDIT */
		/* if EOF or error */
		if (read_getcmd(el, &cmdnum, &ch) == -1) {
#ifdef DEBUG_READ
			(void) fprintf(el->el_errfile,
			    "Returning from el_gets\n");
#endif /* DEBUG_READ */
			break;
		}
		if (el->el_errno == EINTR) {
			el->el_line.buffer[0] = '\0';
			el->el_line.lastchar =
			    el->el_line.cursor = el->el_line.buffer;
			break;
		}
		if ((size_t)cmdnum >= el->el_map.nfunc) {	/* BUG CHECK command */
#ifdef DEBUG_EDIT
			(void) fprintf(el->el_errfile,
			    "ERROR: illegal command from key 0%o\r\n", ch);
#endif /* DEBUG_EDIT */
			continue;	/* try again */
		}
		/* now do the real command */
#ifdef DEBUG_READ
		{
			el_bindings_t *b;
			for (b = el->el_map.help; b->name; b++)
				if (b->func == cmdnum)
					break;
			if (b->name)
				(void) fprintf(el->el_errfile,
				    "Executing %ls\n", b->name);
			else
				(void) fprintf(el->el_errfile,
				    "Error command = %d\n", cmdnum);
		}
#endif /* DEBUG_READ */
		/* vi redo needs these way down the levels... */
		el->el_state.thiscmd = cmdnum;
		el->el_state.thisch = ch;
		if (el->el_map.type == MAP_VI &&
		    el->el_map.current == el->el_map.key &&
		    el->el_chared.c_redo.pos < el->el_chared.c_redo.lim) {
			if (cmdnum == VI_DELETE_PREV_CHAR &&
			    el->el_chared.c_redo.pos != el->el_chared.c_redo.buf
			    && iswprint(el->el_chared.c_redo.pos[-1]))
				el->el_chared.c_redo.pos--;
			else
				*el->el_chared.c_redo.pos++ = ch;
		}
		retval = (*el->el_map.func[cmdnum]) (el, ch);
#ifdef DEBUG_READ
		(void) fprintf(el->el_errfile,
			"Returned state %d\n", retval );
#endif /* DEBUG_READ */

		/* save the last command here */
		el->el_state.lastcmd = cmdnum;

		/* use any return value */
		switch (retval) {
		case CC_CURSOR:
			re_refresh_cursor(el);
			break;

		case CC_REDISPLAY:
			re_clear_lines(el);
			re_clear_display(el);
			/* FALLTHROUGH */

		case CC_REFRESH:
			re_refresh(el);
			break;

		case CC_REFRESH_BEEP:
			re_refresh(el);
			terminal_beep(el);
			break;

		case CC_NORM:	/* normal char */
			break;

		case CC_ARGHACK:	/* Suggested by Rich Salz */
			/* <*****@*****.**> */
			continue;	/* keep going... */

		case CC_EOF:	/* end of file typed */
			if ((el->el_flags & UNBUFFERED) == 0)
				num = 0;
			else if (num == -1) {
				*el->el_line.lastchar++ = CONTROL('d');
				el->el_line.cursor = el->el_line.lastchar;
				num = 1;
			}
			break;

		case CC_NEWLINE:	/* normal end of line */
			num = (int)(el->el_line.lastchar - el->el_line.buffer);
			break;

		case CC_FATAL:	/* fatal error, reset to known state */
#ifdef DEBUG_READ
			(void) fprintf(el->el_errfile,
			    "*** editor fatal ERROR ***\r\n\n");
#endif /* DEBUG_READ */
			/* put (real) cursor in a known place */
			re_clear_display(el);	/* reset the display stuff */
			ch_reset(el, 1);	/* reset the input pointers */
			re_refresh(el); /* print the prompt again */
			break;

		case CC_ERROR:
		default:	/* functions we don't know about */
#ifdef DEBUG_READ
			(void) fprintf(el->el_errfile,
			    "*** editor ERROR ***\r\n\n");
#endif /* DEBUG_READ */
			terminal_beep(el);
			terminal__flush(el);
			break;
		}
		el->el_state.argument = 1;
		el->el_state.doingarg = 0;
		el->el_chared.c_vcmd.action = NOP;
		if (el->el_flags & UNBUFFERED)
			break;
	}

	terminal__flush(el);		/* flush any buffered output */
	/* make sure the tty is set up correctly */
	if ((el->el_flags & UNBUFFERED) == 0) {
		read_finish(el);
		*nread = num != -1 ? num : 0;
	} else {
		*nread = (int)(el->el_line.lastchar - el->el_line.buffer);
	}
	goto done;
noedit:
	el->el_line.cursor = el->el_line.lastchar = cp;
	*cp = '\0';
	*nread = (int)(el->el_line.cursor - el->el_line.buffer);
done:
	if (*nread == 0) {
		if (num == -1) {
			*nread = -1;
			errno = el->el_errno;
		}
		return NULL;
	} else
		return el->el_line.buffer;
}