tcsh with a command line editor (2 of 5)
Paul Placeway
paul at osu-dbs.UUCP
Sat Apr 14 05:27:34 AEST 1984
.
The following code is my changes to Ken Greer's tcsh. I have added a visual
mini-editor to the shell, and cleaned up the expansion routines some what.
note that this is the 4.1 version. When we get 4.2 up I'll repost the new
changes.
Please send any changes back to me so that I can update our version.
Note: this is part 2 of 5, you need all of the parts to make tcsh.
Paul W. Placeway
The Ohio State University IRCC
(UUCP: cbosgd!osu-dbs!paul)
(CSNet: paul at ohio-state)
================ cut here ================
: This is a shar archive. Extract with sh, not csh.
echo x - inputl.c
cat > inputl.c << '!Funky!Stuff!'
/* @(#)inputl.c 1.1 (Ohio State) 6/24/83 Paul Placeway */
/*
* $Compile: cc -DTEST -o foobar -O %f -ltermcap
*/
/*****************************************************************
* inputl() -- get a promped line from the keyboard with input editing
*
* SYNOPSIS:
* char *
* inputl(prompt, string, stringlen)
* char *prompt;
* char *string;
* int stringlen; length of the above string
*
* ilsetup (instr, outstr)
* short instr, outstr; input and output streams - normaly 0 & 1
*
* int
* ilpushback(string)
* char *string;
*
* DESCRIPTION:
* Inputl reads a string from the terminal and allows editing by the
* user. The editing is done by control keys and special use keys such
* as DELETE or BACKSPACE. A list of the controls follows:
*
* ^@ Nothing (becuase some parts won't cope with it)
*
* ^A Moves the cursor to the begining of the line (after
* the prompt)
*
* ^B Moves the cursor back one space. Beeps if it is
* allready in column one.
*
* ^C Sends a SIGINTR to the current process (from the tty
* driver)
*
* ^D Deletes the character that is over the cursor.
*
* ^E Moves the cursor to the end of the line.
*
* ^F Moves the cursor forward one space. Beeps if at the
* end of the line.
*
* ^G Erase entire line and start over.
*
* ^H BS Same as ^B
*
* ^I TAB Inserts a tab character
*
* ^J LF Moves the cursor to the end of the line, inserts a
* newline character, and sends the line.
*
* ^K Delete all characters from the current cursor
* possition to the end inclusive and save them in a
* special buffer to be called back later (see ^Y).
*
* ^L Put a ^L at the end of the line and send it (without
* echoing a newline).
*
* ^M RETURN Same as ^J
*
* ^N Move to the next following word (i.e. skip to the
* end of the current whitespace, then skip to the end
* of the non-whitespace)
*
* ^O Flush tty output until the next tty input request
* (tty driver).
*
* ^P Same as ^N but go backwards.
*
* ^Q Restart output. (see ^S)
*
* ^R Redisplay the current line and move the cursor to
* it's original place.
*
* ^S Stop the tty's output.
*
* ^T Transpose previous two characters.
*
* ^U Same as ^K but kill to the beginning of the line
* exclusive.
*
* ^V Clear the screen and redisplay the line
*
* ^W Delete the previous word.
*
* ^X Delete the next word (see ^W).
*
* ^Y Yank the characters saved (by ^K or ^U) as if they
* were typed on the keyboard.
*
* ^Z Send a SIGTSTP to the current process (tty driver).
*
* ^[ ESC put a ESC at the end of the line and send it
* (without echoing a newline)
*
* ^\ send a SIGQUIT to the current process (tty driver)
*
* ^] Send a SIGTSTP when the program attempts to read the
* NULL. (tty driver) This is usually immeaditly
* because of CBREAK mode, but the assignment is left
* so that cooked mode uses it.
*
* ^^ Insert the next character regardless of it's
* meaning.
*
* ^_ Put an end of file mark at the end and send the
* line. (tty driver)
*
* ^? DELETE Delete the character immeaditely to the left of the
* cursor. Beeps if the cursor is at the beginning of
* the line.
*
* ALL OTHERS All other characters insert themselfs into the line.
*
* Ilpushback pushes the string onto the input line exactly as if it
* had been typed on the console. The next call to inputl will print
* the string and put the cursor at the end of the line. If control
* characters are passed to ilpushback, they will act as if they had
* been quoted.
*
* NOTE
* This program is in the public domain. It may be copied and
* modified, but not sold or included in another product which
* is sold.
*
* If you change anything, PLEASE send me mail describing your changes
* so that I can include them in later versions. A diff listing would
* be very helpful, also.
*
* Also, please send any bug reports to me. Thanks,
*
* Paul W. Placeway
* The Ohio State University IRCC
* (UUCP: cbosgd!osu-dbs!paul)
* (CSNet: paul at ohio-state)
*
*****************************************************************
*/
#define CSH
#define MAKE_INPUTL
/* so that some defines get done */
#include "inputl.h"
/*
Interface to termcap library.
*/
static char *ClearEOL;
static char *ClearScr;
static char *DeleteCh;
static char *StartIns;
static char *EndIns;
static char *FwdCh;
static char *BkdCh;
static char input_line[1024]; /* what i'm getting */
static char kill_buf[1024]; /* for ^K, ^U, ^Y */
static char last_inp[1024]; /* for matching input compleation and ^@ */
static int endptr; /* the last char in the line */
static int cursor; /* The current cursor posisition (0 = beg) */
static int killbuf_len = 0; /* Length of the kill buffer string */
static int lastin_len = 0; /* for last input saving */
static int matching_length = 0; /* for command compleation */
static int pushed_input = FALSE; /* weather some input has been pushed on */
static char *prompt; /* a global pointer to the prompt */
static int prompt_length; /* how long the prompt given is */
static int edit_flags; /* flags that effect the cursor
posisition and other things */
static int do_redisplay = FALSE; /* redraw what you have now */
static int has_been_setup = FALSE; /* for autosetup of the terminal */
static int tty_driver_not_setup = TRUE; /* for autosetup of the tty driver */
static int keybindings[256]; /* the currently assigned keys */
static int bindings_been_inited = FALSE; /* for setup of bindings */
/* the first time */
#ifdef CSH
extern short SHIN, SHOUT;
#else
static short SHIN = 0; /* for input and output munging */
static short SHOUT = 1;
#endif
/* vars for the tty driver */
struct sgttyb old_term;
struct sgttyb new_term;
struct sgttyb none_term;
struct sgttyb test_term; /* for testing wether the modes have been */
/* changed on us so we can compensate */
struct tchars old_tchars; /* INT, QUIT, XON, XOFF, EOF, BRK */
struct tchars new_tchars;
struct tchars none_tchars;
struct ltchars old_ltchars; /* SUSP, DSTOP, RPRNT, FLUSH, WERASE, LNEXT */
struct ltchars new_ltchars;
struct ltchars none_ltchars;
long old_modwd; /* both for testing if things have changed */
long test_modwd; /* on us during proccessing */
/*
* inputl.c -- get an input line from the terminal using full line editing
* and take the line on an escape, control-V , return,
* or line feed.
*/
char
inputl(prompt_str, string_to_get, string_to_get_length)
char *prompt_str; /* prompt string */
char *string_to_get;
int string_to_get_length; /* max length of the input line */
{
register int i;
char c;
int doing_input;
char temp_c1;
char temp_c2;
int old_cursor;
int quoted;
int outputchar();
char retval; /* return value - char typed to send line */
if (isatty (SHIN) == 0) {
if (read (SHIN, string_to_get, 512) <= 0) {
string_to_get[0] = -1;
string_to_get[1] = '\0';
}
return ('\n');
}
if (has_been_setup == FALSE) {
ilsetup();
}
prompt = prompt_str;
prompt_length = strlen (prompt);
if (prompt_length > 70) prompt_length = 70;
set_term(); /* turn on CBREAK and NOECHO */
if (pushed_input == FALSE) {
if (ClearEOL != 0) {
write (SHOUT, "\r", 1); /* start at the beg of line */
write (SHOUT, prompt, prompt_length); /* write the prompt */
tputs (ClearEOL, 0, outputchar);
} else {
write (SHOUT, prompt, prompt_length); /* write the prompt */
}
cursor = 0; /* start cursor off at beginning */
endptr = 0;
} else {
if (do_redisplay == FALSE) {
for (i = matching_length; i < endptr; i++) {
PrintChar (input_line[i], i+1);
}
}
pushed_input = FALSE;
}
doing_input = TRUE;
if (do_redisplay == TRUE) {
Redisplay();
do_redisplay = FALSE;
}
quoted = FALSE;
while (doing_input) {
if (read (SHIN, &c, 1) != 1) { /* get an input character */
input_line[0] = -1; /* fool it into thinking that the */
endptr = 1; /* end-of-file char was typed */
break;
}
if (quoted == TRUE) {
quoted = FALSE;
Insert(c);
set_term(); /* reset the special characters */
}
else switch (keybindings[c]) {
/* and parse it for kbrd commands */
case YANK_LAST_INPUT: /* ^@ -- YANK_LAST_INPUT */
for (i = 0; i < lastin_len; i++) {
Insert(last_inp[i]);
}
break;
case BEGINNING_OF_LINE: /* ^A -- BEGINNING_OF_LINE */
MoveCursor(cursor, 0);
cursor = 0;
break;
case BACKWARD_CHAR: /* ^B -- BACKWARD_CHAR */
if (cursor != 0) {
MoveCursor(cursor, cursor - 1);
cursor--;
}
else beep();
break;
case TTY_SIGINTR: /* ^C -- SIGINTR (tty driver) */
break;
case DELETE_CHAR_FORWARD: /* ^D -- DELETE_CHAR_FORWARD */
Delete();
break;
case END_OF_LINE: /* ^E -- END_OF_LINE */
MoveCursor(cursor, endptr);
cursor = endptr;
break;
case FORWARD_CHAR: /* ^F -- FORWARD_CHAR */
if (cursor != endptr) {
MoveCursor(cursor, cursor +1); /* move the cursor fwd */
cursor++; /* by writing its current */
} /* character */
else beep(); /* at end-of-line */
break;
case START_OVER: /* ^G -- START_OVER */
ClearLine();
(void) write (SHOUT, prompt, prompt_length);
endptr = 0;
cursor = 0;
break;
case KILL_TO_END: /* ^K -- KILL_TO_END */
if (cursor == endptr) {
beep();
break;
}
else {
killbuf_len = endptr - cursor;
for (i = 0; i < killbuf_len; i++) {
kill_buf[i] = input_line[cursor + i];
}
endptr = cursor;
if (ClearEOL != 0) {
tputs (ClearEOL, 0, outputchar);
}
else {
Redisplay();
}
break;
}
case SEND_EOF: /* ^_ -- TTY_EOF */
c = -1; /* sends an EOF */
/* fall through to */
case SEND_LINE: /* ^V -- SEND_LINE */
input_line[endptr] = '\0'; /* just in case */
doing_input = FALSE; /* send it */
MoveCursor(cursor, endptr); /* make sure your at end */
retval = c; /* set the return value */
break;
case NL_SEND_LINE: /* ^J LF -- NL_SEND_LINE */
if (endptr > 0) { /* save the input for ^H */
lastin_len = endptr;
for (i = 0; i <=lastin_len; i++) {
last_inp[i] = input_line[i];
}
}
input_line[endptr] = '\n';
retval = '\n'; /* like the name says: NL... */
doing_input = FALSE; /* send it */
if ((c == '\n') || (c == '\r')) {
outputchar('\n');
}
break;
case FORWARD_WORD: /* ^N -- FORWARD_WORD */
old_cursor = cursor;
while ((IsInWord (input_line[cursor]) == 0)
&& (cursor != endptr)) {
++cursor;
}
while ((IsInWord (input_line[cursor]))
&& (cursor != endptr)) {
++cursor;
}
MoveCursor(old_cursor, cursor);
break;
case ERR: /* beep on this key */
beep(); /* fall through to... */
case NOP: /* no operation */
break;
case TTY_FLUSH_OUTPUT: /* ^O -- TTY_FLUSH_OUTPUT */
break;
case BACKWARD_WORD: /* ^P -- BACKWARD_WORD */
old_cursor = cursor;
while ((IsInWord (input_line[cursor-1]) == 0)
&& (cursor != 0)) {
--cursor;
}
while ((IsInWord (input_line[cursor-1]))
&& (cursor != 0)) {
--cursor;
}
MoveCursor(old_cursor, cursor);
break;
case TTY_START_OUTPUT: /* ^Q -- START_OUTPUT (tty driver) */
break;
case REDISPLAY: /* ^R -- REDISPLAY */
Redisplay();
break;
case TTY_STOP_OUTPUT: /* ^S -- STOP_OUTPUT */
break;
case TRANSPOSE_CHARS: /* ^T -- TRANSPOSE_PREVIOUS_TWO */
if (cursor >= 2) {
temp_c2 = input_line[cursor - 2];
temp_c1 = input_line[cursor - 1];
DelPrev();
DelPrev();
Insert(temp_c1);
Insert(temp_c2);
}
else beep();
break;
case KILL_TO_BEGINNING: /* ^U -- KILL_TO_BEGINNING */
if (cursor == 0) {
beep();
break;
}
else {
killbuf_len = cursor;
for (i = 0; i < cursor; i++) {
kill_buf[i] = input_line[i];
}
while (cursor != 0) {
DelPrev();
}
break;
}
case CLEAR_SCREEN: /* ^L -- CLEAR_SCREEN */
ClearScreen();
Redisplay();
break;
case DELETE_WORD_BACKWARD: /* ^W -- DELETE_WORD_BACKWARD */
while ((IsInWord (input_line[cursor-1]) == 0)
&& (cursor != 0)) {
DelPrev();
}
while ((IsInWord (input_line[cursor-1]))
&& (cursor != 0)) {
DelPrev();
}
break;
case DELETE_WORD_FORWARD: /* ^X -- DELETE_WORD_FORWARD */
while ((IsInWord (input_line[cursor]) == 0)
&& (cursor != endptr)) {
Delete();
}
while ((IsInWord (input_line[cursor]))
&& (cursor != endptr)) {
Delete();
}
break;
case YANK_KILLBUFFER: /* ^Y -- YANK_KILLBUFFER */
for (i = 0; i < killbuf_len; i++) {
Insert(kill_buf[i]);
}
break;
case TTY_SIGTSUSP: /* ^Z -- TTY_SIGTSUSP */
break;
case TTY_SIGQUIT: /* ^\ -- TTY_SIGQUIT */
break;
case TTY_DSUSP: /* ^] -- TTY_DSUSP */
break;
case QUOTE_NEXT: /* ^^ -- QUOTE_NEXT */
quoted = TRUE;
nospecial(); /* this is gross -- turn off all the chars */
break;
case DELETE_CHAR_BACKWARD: /* ^? DEL -- DELETE_CHAR_BACKWARD */
DelPrev();
break;
case AUTO_INSERT: /* it's a normal character, insert it */
Insert(c);
break;
default: /* it's garbage, ignore it */
break;
} /* end of switch (c) */
} /* end of while (doing_input) */
input_line[endptr+1] = NULL;
reset_term();
strncpy(string_to_get, input_line, string_to_get_length- 1);
string_to_get[string_to_get_length] = '\0';
/* string_to_get = input_line */
return (retval);
}
/************************************************************/
#ifdef CSH
ilsetup () {
#else
ilsetup(Shin, Shout)
short Shin, Shout; /* SHIN = input stream, SHOUT = output str. */
{
#endif
static char bp[1024];
static char buffer[1024];
char *area = buffer;
char *getenv();
char *tgetstr();
char *name;
int retcode;
#ifndef CSH
SHIN = Shin;
SHOUT = Shout;
#endif
name = getenv("TERM");
retcode = tgetent(bp, name);
switch(retcode) {
case -1:
printf("can't open termcap file.\n");
exit(1);
break;
case 0:
printf("No termcap entry for %s, using \"dumb\"\n", name);
if ((tgetent(bp, "dumb")) == -1) {
printf("can't open termcap file.\n");
exit (1);
}
break;
}
StartIns = tgetstr("im", &area);
EndIns = tgetstr("ei", &area);
DeleteCh = tgetstr("dc", &area);
ClearEOL = tgetstr("ce", &area);
ClearScr = tgetstr("cl", &area);
FwdCh = tgetstr("nd", &area);
BkdCh = tgetstr("bc", &area);
InitBindings ();
has_been_setup = TRUE;
}
static
InitBindings ()
{
register int i;
if (bindings_been_inited) return;
get_tty_special (); /* get the old chars */
for (i=0; i<128; i++) { /* assign all the keys */
DoBindToKey (AUTO_INSERT, i);
}
DoBindToKey(BEGINNING_OF_LINE, 001);
DoBindToKey(BACKWARD_CHAR, 002);
DoBindToKey(TTY_SIGINTR, 003);
DoBindToKey(DELETE_CHAR_FORWARD, 004);
DoBindToKey(END_OF_LINE, 005);
DoBindToKey(FORWARD_CHAR, 006);
DoBindToKey(START_OVER, 007);
DoBindToKey(YANK_LAST_INPUT, 010);
DoBindToKey(KILL_TO_END, 013);
DoBindToKey(SEND_EOF, 037);
DoBindToKey(SEND_LINE, 000);
DoBindToKey(SEND_LINE, 077);
DoBindToKey(SEND_LINE, 033);
DoBindToKey(NL_SEND_LINE, 012);
DoBindToKey(NL_SEND_LINE, 015);
DoBindToKey(FORWARD_WORD, 016);
DoBindToKey(TTY_FLUSH_OUTPUT, 017);
DoBindToKey(BACKWARD_WORD, 020);
DoBindToKey(TTY_START_OUTPUT, 021);
DoBindToKey(REDISPLAY, 022);
DoBindToKey(TTY_STOP_OUTPUT, 023);
DoBindToKey(TRANSPOSE_CHARS, 024);
DoBindToKey(KILL_TO_BEGINNING, 025);
DoBindToKey(CLEAR_SCREEN, 014);
DoBindToKey(DELETE_WORD_BACKWARD, 027);
DoBindToKey(DELETE_WORD_FORWARD, 030);
DoBindToKey(YANK_KILLBUFFER, 031);
DoBindToKey(TTY_SIGTSUSP, 032);
DoBindToKey(TTY_SIGQUIT, 034);
DoBindToKey(TTY_DSUSP, 035);
DoBindToKey(QUOTE_NEXT, 026); /* ^^ -> ^V (back to normal) */
DoBindToKey(DELETE_CHAR_BACKWARD, 0177);
reset_term (); /* export bindings */
bindings_been_inited = TRUE;
}
static
ClearLine() {
int outputchar();
if (ClearEOL != 0) {
outputchar ('\r');
tputs (ClearEOL, 0, outputchar);
} else {
outputchar ('\n');
}
}
static
ClearScreen() {
int outputchar();
if (ClearScr != 0) {
tputs (ClearScr, 0, outputchar);
}
}
static
DelPrevChar() {
register int distance;
int Count();
MoveCursor(cursor, cursor-1);
distance = Count(cursor) - Count(cursor - 1);
DelScrChar(distance);
}
static
DelChar() {
register int distance;
int Count();
distance = Count(cursor + 1) - Count(cursor);
DelScrChar(distance);
}
static
DelScrChar(distance)
int distance;
{
register int i;
int outputchar();
if (DeleteCh == 0) { /* do a huge pain */
for (i = cursor; i < endptr; i++) {
PrintChar(input_line[i], i+1); /* i+1??? brain-dammage */
}
for (i = 0; i < distance; i++) {
outputchar(' ');
}
/* MoveCursor(endptr + distance, cursor); INCONSISTANT USAGE... */
for (i = distance; i > 0; i--) {
if (BkdCh != 0) {
tputs (BkdCh, 0, outputchar);
}
else {
outputchar ('\b');
}
} /* now I'm at the end... */
MoveCursor(endptr, cursor);
}
else {
for (i = 0; i < distance; i++) {
tputs (DeleteCh, 0, outputchar);
}
}
}
static
InsChar(c)
char c;
{
register int i;
int outputchar();
if (StartIns == 0) {
for (i = cursor-1; i < endptr; i++) {
PrintChar(input_line[i], i+1);
}
MoveCursor(endptr, cursor);
}
else {
if (cursor != endptr) {
tputs (StartIns, 0, outputchar);
}
PrintChar(c, cursor);
if (cursor != endptr) {
tputs (EndIns, 0, outputchar);
}
}
}
static
MoveCursor(where_from, where_to)
int where_from;
int where_to;
{
int diff;
int i;
int Count();
int outputchar();
diff = Count(where_to) - Count(where_from);
if (diff > 0) {
if (FwdCh != 0) {
for (i = 0; i < diff; i++) {
tputs (FwdCh, 0, outputchar);
}
}
else {
for (i = where_from; i < where_to; i++) {
PrintChar(input_line[i], i);
}
}
}
else if (diff < 0) {
diff = -diff;
for (i = 0; i < diff; i++) {
if (BkdCh != 0) {
tputs (BkdCh, 0, outputchar);
}
else {
outputchar ('\b');
}
}
}
}
/*
Set terminal to CBREAK and NOECHO.
*/
static
set_term()
{
if(tty_driver_not_setup == 0) { /* tty driver is set up */
ioctl (SHIN, TIOCGETP, &test_term); /* get the setup */
ioctl (SHIN, TIOCLGET, &test_modwd); /* get local mode word */
if ((old_term.sg_ispeed != test_term.sg_ispeed) ||
(old_term.sg_ospeed != test_term.sg_ospeed) ||
(old_term.sg_flags != test_term.sg_flags) ||
(old_modwd != test_modwd)) {
/* printf ("tty has changed.\n"); */
tty_driver_not_setup = 1;
/* things have changed, fake it */
}
}
if (tty_driver_not_setup) {
/* hasn't been setup yet or reseting do to a change */
get_tty_modes (); /* get ONLY the mode word and term strucs */
tty_driver_not_setup = 0;
}
ioctl (SHIN, TIOCSETN, &new_term); /* set the terminal in CBREAK */
ioctl (SHIN, TIOCSETC, &new_tchars); /* with these special chars */
ioctl (SHIN, TIOCSLTC, &new_ltchars); /* and these local specials */
/* printf("in: %d out: %d\n", new_term.sg_ispeed,
new_term.sg_ospeed); */
}
/*
get the special characters from the tty driver.
*/
static
get_tty_special () {
ioctl (SHIN, TIOCGETP, &old_term);
ioctl (SHIN, TIOCGETC, &old_tchars);
ioctl (SHIN, TIOCGLTC, &old_ltchars);
ioctl (SHIN, TIOCGETP, &new_term);
ioctl (SHIN, TIOCGETP, &none_term);
ioctl (SHIN, TIOCGETC, &new_tchars);
ioctl (SHIN, TIOCGETC, &none_tchars);
ioctl (SHIN, TIOCGLTC, &new_ltchars);
ioctl (SHIN, TIOCGLTC, &none_ltchars);
ioctl (SHIN, TIOCLGET, &old_modwd); /* get local mode word */
/* so that we know old setup */
/* test prints */
/* printf("in: %d out: %d\n", old_term.sg_ispeed,
old_term.sg_ospeed); */
/* the old setup for when inputl exits */
old_term.sg_flags &= ~(RAW | CBREAK); /* unset */
old_term.sg_flags |= (ECHO | CRMOD); /* set */
DoBindToKey (DELETE_CHAR_BACKWARD, old_term.sg_erase);
DoBindToKey (KILL_TO_BEGINNING, old_term.sg_kill);
DoBindToKey (TTY_SIGINTR, old_tchars.t_intrc);
DoBindToKey (TTY_SIGQUIT, old_tchars.t_quitc);
DoBindToKey (TTY_START_OUTPUT, old_tchars.t_startc);
DoBindToKey (TTY_STOP_OUTPUT, old_tchars.t_stopc);
DoBindToKey (SEND_EOF, old_tchars.t_eofc);
old_tchars.t_brkc = -1; /* none */
DoBindToKey (TTY_SIGTSUSP, old_ltchars.t_suspc);
DoBindToKey (TTY_DSUSP, old_ltchars.t_dsuspc);
DoBindToKey (REDISPLAY, old_ltchars.t_rprntc);
DoBindToKey (TTY_FLUSH_OUTPUT, old_ltchars.t_flushc);
DoBindToKey (DELETE_WORD_BACKWARD, old_ltchars.t_werasc);
DoBindToKey (QUOTE_NEXT, old_ltchars.t_lnextc);
/* now for the current setup (CBREAK with some de-assigned special chars */
new_term.sg_flags &= ~(ECHO | XTABS); /* unset */
new_term.sg_flags |= (CBREAK | CRMOD); /* set */
/* the new chars should get worked out in the
old chars bind-to-keys */
/* now the none structures for literal nexting of characters */
none_term.sg_flags &= ~(ECHO | CRMOD); /* unset */
none_term.sg_flags |= (CBREAK); /* set */
none_tchars.t_intrc = -1;
none_tchars.t_quitc = -1;
none_tchars.t_startc = -1;
none_tchars.t_stopc = -1;
none_tchars.t_eofc = -1;
none_tchars.t_brkc = -1;
none_ltchars.t_suspc = -1;
none_ltchars.t_dsuspc = -1;
none_ltchars.t_rprntc = -1;
none_ltchars.t_flushc = -1;
none_ltchars.t_werasc = -1;
none_ltchars.t_lnextc = -1;
reset_term (); /* export the new bound values */
}
/*
get only the modes from the tty driver.
*/
static
get_tty_modes () {
ioctl (SHIN, TIOCGETP, &new_term); /* get new now, old later */
ioctl (SHIN, TIOCGETP, &none_term);
ioctl (SHIN, TIOCLGET, &old_modwd); /* get local mode word */
/* so that we know old setup */
/* now for the current setup (CBREAK with some de-assigned special chars */
new_term.sg_flags &= ~(ECHO | XTABS); /* unset */
new_term.sg_flags |= (CBREAK | CRMOD); /* set */
new_term.sg_erase = old_term.sg_erase; /* do this so that the */
new_term.sg_kill = old_term.sg_kill; /* erase and kill chars */
/* don't get changed to */
ioctl (SHIN, TIOCGETP, &old_term); /* something else. */
old_term.sg_erase = new_term.sg_erase;
old_term.sg_kill = new_term.sg_kill;
/* the old setup for when inputl exits */
old_term.sg_flags &= ~(RAW | CBREAK); /* unset */
old_term.sg_flags |= (ECHO | CRMOD); /* set */
/* now the none structures for literal nexting of characters */
none_term.sg_flags &= ~(ECHO | CRMOD); /* unset */
none_term.sg_flags |= (CBREAK); /* set */
reset_term (); /* export the new bound values */
}
/*
Reset the terminal to normal mode.
*/
static
reset_term() {
ioctl (SHIN, TIOCSETN, &old_term); /* set the terminal in CBREAK */
ioctl (SHIN, TIOCSETC, &old_tchars); /* with these special chars */
ioctl (SHIN, TIOCSLTC, &old_ltchars); /* and these local specials */
}
/* unset all special chars */
static
nospecial() {
ioctl (SHIN, TIOCSETN, &none_term); /* set the terminal in CBREAK */
ioctl (SHIN, TIOCSETC, &none_tchars); /* with these special chars */
ioctl (SHIN, TIOCSLTC, &none_ltchars); /* and these local specials */
}
/* ******************************************************* */
#ifdef TEST
main()
{
char buffer[1024];
char retnval;
while (1) {
if ((retnval = inputl("inputl:", buffer, 72)) == '\033') {
strcat(buffer, "foo");
ilpushback(buffer);
continue;
}
else
printf ("Return value = %o,\nI saw :%s\n", retnval, buffer);
if (buffer[0] == 'Q') exit(0);
}
}
#endif
/* ********************************************************* */
static int
outputchar(c)
char c;
{
(void) write (SHOUT, &c, 1);
}
static
beep()
{
outputchar(BELL);
}
static
Delete()
{
register int i;
if (cursor < endptr) {
for (i = cursor; i < endptr; i++) {
input_line[i] = input_line[i+1];
}
endptr--;
DelChar();
}
else beep();
}
static
DelPrev()
{
register int i;
if (cursor != 0) {
DelPrevChar();
--cursor;
if (cursor <0 ) cursor = 0;
for (i = cursor; i < endptr; i++) {
input_line[i] = input_line[i+1];
}
endptr--;
if (endptr <0 ) endptr = 0;
}
else beep();
}
static
Redisplay()
{
register int i;
ClearLine();
(void) write (SHOUT, prompt, prompt_length);
for (i = 1; i <= endptr; i++) {
PrintChar(input_line[i -1], i);
}
MoveCursor(endptr, cursor);
}
static
Insert(c)
char c;
{
register int i;
if (cursor >= endptr){ /* put it at the end of the line */
endptr++;
if (endptr > 1023) endptr = 1023;
input_line[cursor++] = c;
}
else { /* its in the middle of the line, shift line
first, then put in char */
endptr++;
if (endptr > 1023) endptr = 1023;
for (i = endptr; i >= cursor; i--) {
input_line[i+1] = input_line[i];
}
input_line[cursor++] = c;
}
InsChar(c);
}
static int
IsInWord (c)
char c;
{
register char *cp;
register int is_word_char = 0;
for (cp = WORD_CHARS; *cp; cp++)
if (*cp == c)
is_word_char = 1;
return (is_word_char);
}
static int
Count(to_where) /* count the number of spaces that many */
int to_where; /* characters take up on the screen */
{
register int i;
register int cntr = 0;
for (i = 0; i < to_where; i++) {
if (input_line[i] == '\t') {
cntr += prompt_length;
cntr = (((cntr/8)+1)*8);
cntr -= prompt_length;
}
else if ((input_line[i] < ' ') || (input_line[i] == '\0177')) {
cntr += 2;
}
else cntr++;
}
return (cntr);
}
static
PrintChar(c, pos)
char c;
int pos; /* where the character is */
{
register int count;
register int i;
c &= 0177;
if (c == '\177') {
outputchar('^');
c = '?';
}
else if (c == '\t') {
count = Count(pos) - Count(pos -1);
for (i = 0; i < count; i++) {
outputchar(' ');
}
return;
}
else if (c < ' ') {
outputchar('^');
c |= 0100;
}
outputchar(c);
}
/* **************************************************************** */
ilpushback(string)
char string[];
{
register int i;
int string_length;
int matched;
string_length = strlen(string);
if (string_length > 1023) string_length = 1023;
matching_length = 0;
matched = 1;
for (i = 0; i <= string_length; i++) {
if ((input_line[i] == string[i]) && (matched)) {
matching_length++;
}
else {
matched = FALSE;
input_line[i] = string[i];
}
}
endptr = string_length;
if (endptr > 1023) endptr = 1023;
cursor = endptr;
pushed_input = TRUE;
/* do_redisplay = TRUE; */
}
ilredisplay()
{
do_redisplay = TRUE;
}
/* this next pair is done this way so that I don't get an infinate recursion
bug with ilsetup. it is important that ilsetup is called first, so that
the keys actually get bound. */
ilbindtokey (func, key)
int func;
char key;
{
if (has_been_setup == FALSE) {
ilsetup();
}
DoBindToKey (func, key);
}
/* force a reset_term */
ilreset_tty()
{
reset_term();
}
static
DoBindToKey (func, key)
int func;
char key;
{
if (key == -1) { /* trap unsetings */
return (-1);
}
if ((func < 0) || (func > 200)) {
return(-1);
}
keybindings[key] = func;
switch (func) {
case TTY_DSUSP:
old_ltchars.t_dsuspc = key;
new_ltchars.t_dsuspc = key;
break;
case TTY_FLUSH_OUTPUT:
old_ltchars.t_flushc = key; /* ^O */
new_ltchars.t_flushc = key; /* ^O */
break;
case TTY_SIGINTR:
old_tchars.t_intrc = key; /* ^C */
new_tchars.t_intrc = key; /* ^C */
break;
case TTY_SIGQUIT:
old_tchars.t_quitc = key; /* ^\ */
new_tchars.t_quitc = key; /* ^\ */
break;
case TTY_SIGTSUSP:
old_ltchars.t_suspc = key; /* ^Z */
new_ltchars.t_suspc = key; /* ^Z */
break;
case TTY_START_OUTPUT:
old_tchars.t_startc = key; /* ^Q */
new_tchars.t_startc = key; /* ^Q */
break;
case TTY_STOP_OUTPUT:
old_tchars.t_stopc = key; /* ^S */
new_tchars.t_stopc = key; /* ^S */
break;
case REDISPLAY:
old_ltchars.t_rprntc = key; /* ^R */
new_ltchars.t_rprntc = -1; /* ^R */
break;
case SEND_EOF:
old_tchars.t_eofc = key; /* ^_ */
new_tchars.t_eofc = -1; /* ^_ */
break;
case QUOTE_NEXT:
old_ltchars.t_lnextc = key; /* ^^ */
new_ltchars.t_lnextc = -1; /* ^^ */
break;
case DELETE_WORD_BACKWARD:
old_ltchars.t_werasc = key; /* ^W */
new_ltchars.t_werasc = -1; /* ^W */
break;
case DELETE_CHAR_BACKWARD:
old_term.sg_erase = key;
new_term.sg_erase = -1;
break;
case KILL_TO_BEGINNING:
old_term.sg_kill = key;
new_term.sg_kill = -1;
break;
default:
return;
}
}
int
ilgetbinding(key)
char key;
{
return (keybindings[key]);
}
static int saved_ldisc; /* line discipline */
static struct sgttyb saved_term; /* old terminal modes + ERASE, KILL */
static struct tchars saved_tchars; /* INT, QUIT, XON, XOFF, EOF, BRK */
static struct ltchars saved_ltchars;
/* SUSP, DSTOP, RPRNT, FLUSH, WERASE, LNEXT */
static long saved_modwd;
static int tty_has_been_saved = 0;
/*
* Save and restore all of the terminal states
*/
ilsavetty () {
ioctl (SHIN, TIOCGETD, &saved_ldisc);
ioctl (SHIN, TIOCGETP, &saved_term);
ioctl (SHIN, TIOCGETC, &saved_tchars);
ioctl (SHIN, TIOCGLTC, &saved_ltchars);
ioctl (SHIN, TIOCLGET, &saved_modwd);
tty_has_been_saved = 1;
}
ilrestoretty () {
if (tty_has_been_saved == 0) return;
ioctl (SHIN, TIOCSETD, &saved_ldisc);
ioctl (SHIN, TIOCSETN, &saved_term);
ioctl (SHIN, TIOCSETC, &saved_tchars);
ioctl (SHIN, TIOCSLTC, &saved_ltchars);
ioctl (SHIN, TIOCLSET, &saved_modwd);
}
!Funky!Stuff!
echo x - inputl.h
cat > inputl.h << '!Funky!Stuff!'
#ifdef MAKE_INPUTL
#define TRUE 1
#define FALSE 0
#define NULL 0
#define BELL '\007'
/* this next is for all characters that should be considered a word to the
shell */
#define WORD_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890*?_-."
#include <sgtty.h>
#endif
#define AUTO_INSERT 0
#define BACKWARD_CHAR 1
#define BACKWARD_WORD 2
#define BEGINNING_OF_LINE 3
#define CLEAR_SCREEN 4
#define DELETE_CHAR_BACKWARD 5
#define DELETE_CHAR_FORWARD 6
#define DELETE_WORD_BACKWARD 7
#define DELETE_WORD_FORWARD 8
#define END_OF_LINE 9
#define SEND_EOF 10
#define FORWARD_CHAR 11
#define FORWARD_WORD 12
#define KILL_TO_BEGINNING 13
#define KILL_TO_END 14
#define NL_SEND_LINE 15
#define QUOTE_NEXT 16
#define REDISPLAY 17
#define SEND_LINE 18
#define START_OVER 19
#define TRANSPOSE_CHARS 20
#define YANK_KILLBUFFER 21
#define YANK_LAST_INPUT 22
#define NOP 23
#define ERR 24
#define TTY_DSUSP 101
#define TTY_FLUSH_OUTPUT 102
#define TTY_SIGINTR 103
#define TTY_SIGQUIT 104
#define TTY_SIGTSUSP 105
#define TTY_START_OUTPUT 106
#define TTY_STOP_OUTPUT 107
!Funky!Stuff!
More information about the Comp.sources.unix
mailing list