Files
sicspsi/tecs/term.c
cvs 064ec37e9a - Rearranged directory structure for forking out ANSTO
- Refactored site specific stuff into a site module
- PSI specific stuff is now in the PSI directory.
- The old version has been tagged with pre-ansto
2003-06-20 10:18:47 +00:00

239 lines
5.1 KiB
C

#include <unistd.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include "myc_mem.h"
#include "sys_select.h"
#define ESC_TMO 1000
#define REF_TMO 100
#define HISTORY_LINES 256
#define L_ARROW '\200'
#define R_ARROW '\201'
#define U_ARROW '\202'
#define D_ARROW '\203'
#define EVT_CHAR '\0'
#define DEL_CHAR '\b'
#define RET_CHAR '\n'
static char esc_key='\0';
static fd_set regMask;
static int lastFd=-1;
void term_reg_socket(int fd) {
FD_SET(fd, &regMask);
}
void term_unr_socket(int fd) {
FD_CLR(fd, &regMask);
}
int term_raw_key(char *key, int msecTmo) {
fd_set mask;
mask=regMask;
return(sys_select_or_key(&mask, msecTmo, key));
}
int term_wait_fd(int fd, int msecTmo) {
fd_set mask;
struct timeval tmo;
FD_ZERO(&mask);
FD_SET(fd, &mask);
tmo.tv_sec=msecTmo / 1000;
tmo.tv_usec=(msecTmo % 1000) * 1000+1;
return(select(FD_SETSIZE, &mask, NULL, NULL, &tmo));
}
int term_get_key(char *key, int msecTmo) {
int iret;
char k;
if (esc_key==0) {
iret=term_raw_key(&k, msecTmo);
} else {
k=esc_key;
}
while (k==27) { /* esc */
iret=term_raw_key(&k, ESC_TMO);
switch (k) {
case 'O': k='\217'; break; /* ss3 */
case '[': k='\233'; break; /* csi */
default: break;
}
}
if (iret!=STDIN_FILENO) {
esc_key=k;
*key='\0';
return(iret);
}
switch (k) {
case '\233': /* csi */
iret=term_raw_key(&k, ESC_TMO);
while (k>='0' && k <='9') {
iret=term_raw_key(&k, ESC_TMO);
}
if (iret!=STDIN_FILENO) {
esc_key=k;
*key='\0';
return(iret);
}
switch (k) { /* L,R,U,D arrows */
case 'D': k=L_ARROW; break;
case 'C': k=R_ARROW; break;
case 'A': k=U_ARROW; break;
case 'B': k=D_ARROW; break;
default: k='?';
}
break;
case '\217': /* ss3 */
iret=term_raw_key(&k, ESC_TMO);
if (iret!=STDIN_FILENO) {
esc_key=k;
*key='\0';
return(iret);
}
if (k=='M') { /* enter */
k=RET_CHAR;
} else if (k >= 'l' && k <= 'y') {
k=k-64;
} else {
k='?';
}
break;
case '\177': /* del */
case '\b': /* bs */
k=DEL_CHAR;
break;
case '\r': /* cr */
case '\n': /* lf */
k=RET_CHAR;
break;
case EVT_CHAR: /* time out*/
break;
default:
if (k<' ' || k>'\176') k='?';
}
*key=k;
esc_key='\0';
return (STDIN_FILENO);
}
static char *history[HISTORY_LINES]={NULL};
/* history array: it's a cyclic buffer, when it is full, the oldest values
are overwritten.
*/
static int hist_pos=0; /* position when scrolling through the history */
static int hist_end=0; /* end of history. Always history[hist_end]==NULL */
int term_get_line(char *buf, int size, int *pos, char *prompt, fd_set *mask) {
char key, *lin;
int i,j,l,iret,buflen;
char tmp[512];
buf[size-1]='\0'; /* make sure buf is null terminated */
l=strlen(buf);
if (*pos>l) {
*pos=l;
} else if (*pos<0) {
*pos=0;
}
iret=term_get_key(&key, 0);
while (1) {
if (iret==-1 || key == RET_CHAR || key==EVT_CHAR) { /* refresh after a short timeout */
assert(l*2+20+strlen(prompt)<sizeof(tmp));
tmp[0]='\r';
tmp[1]='\0';
strcat(tmp, prompt);
strcat(tmp, buf);
strcat(tmp,"\033[K");
j=strlen(tmp);
for (i=l; i>*pos; i--) {
tmp[j]='\b'; j++;
}
tmp[j]='\0';
fputs(tmp, stdout);
if (iret==-1) {
iret=term_get_key(&key, -1); /* no timeout */
}
}
switch (key) {
case EVT_CHAR:
fputs("\r\033[K", stdout);
return(iret);
/* interrupted EXIT */
case RET_CHAR:
/* fputs("\r\033[K", stdout); */
i=hist_end-1; if (i<0) i=HISTORY_LINES-1;
if ((history[i]==NULL || 0!=strcmp(history[i], buf)) && buf[0]!='\0') { /* do not save equal and empty lines */
buflen=strlen(buf)+1;
lin=MALLOC(buflen);
strncpy(lin, buf, buflen);
history[hist_end]=lin;
hist_end++; if (hist_end>=HISTORY_LINES) hist_end=0;
if (history[hist_end]!=NULL) {
FREE(history[hist_end]); /* clear line at end of history */
}
history[hist_end]==NULL;
}
hist_pos=hist_end;
return(STDIN_FILENO);
/* normal EXIT */
case DEL_CHAR:
if (*pos>0) {
for (i=*pos; buf[i]!='\0'; i++) {
buf[i-1] = buf [i];
}
buf[i-1]='\0';
(*pos)--;
l--;
}
break;
case L_ARROW:
if (*pos>0) (*pos)--;
break;
case R_ARROW:
if (buf[*pos]!='\0') (*pos)++;
break;
case U_ARROW:
case D_ARROW:
if (key==U_ARROW) {
i=hist_pos-1; if (i<0) i=HISTORY_LINES-1;
} else {
i=hist_pos+1; if (i>=HISTORY_LINES) i=0;
}
if (history[i]!=NULL) {
strncpy(buf, history[i], size-1);
buf[size-1]='\0';
hist_pos=i;
l=strlen(buf);
*pos=l;
}
break;
default:
if (l<size-1) {
for (i=l; i>*pos; i--) {
buf[i]=buf[i-1];
}
(*pos)++; l++;
buf[i]=key;
buf[l]='\0';
}
break;
}
iret=term_get_key(&key, REF_TMO);
}
}