#include "io.h"

#define OBUFSIZE  (4096)
#define IBUFSIZE  (256)

extern int dumb_term ;

char outbuf[OBUFSIZE] ;
int obufsize = 0 ;

char inbuf[IBUFSIZE] ;
int ibufsize = 0 ;
int icurrchar = 0 ;

static int i_mode = INPUT_ACTIVE ;

void
hit_alarm_clock(stat)
int stat ;
{
    if(i_mode == INPUT_IDLE) {
        fprintf(stderr,"INPUT WENT IDLE, Booting...\n") ;
        kill(getpid(),SIGHUP) ;
    }
    i_mode = INPUT_IDLE ;
    alarm(SNOOZE) ;
}

init_alarm()
{
    signal(SIGALRM,hit_alarm_clock) ;
    alarm(SNOOZE) ;
}

oflush()
{
    if(obufsize)
      write(1,outbuf,obufsize) ;
    obufsize = 0 ;
}

output(s,len)
char *s ;
{
    /* Invalid if len >= OBUFSIZE */

    if(obufsize+len > OBUFSIZE) {  /* doin a oflush */
        write(1,outbuf,obufsize) ;
        obufsize = 0 ;
    }
    bcopy(s,outbuf+obufsize,len) ;
    obufsize+=len ;
}

ochar(c)
{
    if(obufsize > OBUFSIZE-1) {  /* doin a oflush */
        write(1,outbuf,obufsize) ;
        obufsize = 0 ;
    }
    outbuf[obufsize++] = c ;
}

int i_newfd  = 0 ;
struct timeval i_to, *i_top = NULL ;
int (*flushf)() = NULL ;

add_io(fd,timeout)
int fd ;
int timeout ;
{
    i_newfd = fd ;
    if(timeout) {
        i_to.tv_sec = timeout ;
        i_to.tv_usec = 0 ;
        i_top = &i_to ;
    } else i_top = NULL ;
}

add_flush(flushfunc)
int (*flushfunc)() ;
{
    flushf = flushfunc ;
}

num_in_buf()
{
    return icurrchar - ibufsize ;
}

int
igetch()
{
  igetagain:
    if(ibufsize == icurrchar) {
        fd_set readfds ;
        struct timeval to ;
        int sr ;

        to.tv_sec = 0 ;
        to.tv_usec = 0 ;
        FD_ZERO(&readfds) ;
        FD_SET(0,&readfds) ;
        if(i_newfd)
          FD_SET(i_newfd,&readfds) ;
        if((sr = select(getdtablesize(),&readfds, NULL, NULL, &to)) <= 0) {
            if(flushf)
              (*flushf)() ;
            if(dumb_term) {
              oflush() ; }
            else {
               refresh() ; }
            FD_ZERO(&readfds) ;
            FD_SET(0,&readfds) ;
            if(i_newfd)
              FD_SET(i_newfd,&readfds) ;
            while((sr = select(getdtablesize(),&readfds, 
                               NULL, NULL, i_top)) <0) {
                if(errno == EINTR)
                  continue ;
                else {
                    perror("select") ;
                    fprintf(stderr,"abnormal select conditions\n") ;
                    return -1 ;
                }
            }
            if(sr == 0)
              return I_TIMEOUT ;
        }
        if(i_newfd && FD_ISSET(i_newfd,&readfds))
          return I_OTHERDATA ;
        while((ibufsize = read(0,inbuf,IBUFSIZE)) <= 0) {
            if(ibufsize == 0)
              generic_abort() ;
            if(ibufsize < 0 && errno != EINTR)
              generic_abort() ;
        }
        icurrchar = 0 ;
    }
    i_mode = INPUT_ACTIVE ;
    inbuf[icurrchar] &= 0x7f ;
    switch(inbuf[icurrchar]) {
      case 0x0c:
        redoscr() ;
        icurrchar++ ;
        goto igetagain ;
      default:
        break ;
    }
    return inbuf[icurrchar++] ;
}

getdata(line,col,prompt,buf,len,echo,complete)
int line,col ;
char *prompt, *buf ;
int len, echo ;
int (*complete)() ;
{
    int ch ;
    int clen = 0 ;
    int x,y ;
    extern unsigned char scr_cols ;

    if(prompt) {
        move(line,col) ;
        prints("%s",prompt) ;
    }
    if(dumb_term) {
        while((ch = igetch()) != '\r') {
            if(ch == '\n')
              break ;
            if(ch == '\177' || ch == 0x08) {
                if(clen == 0) {
                    bell() ;
                    continue ;
                }
                clen-- ;
                if(echo) {
                    ochar(0x08) ;
                    ochar(' ') ;
                    ochar(0x08) ;
                }
                continue ;
            }
            if(!isprint(ch)) {
                if(echo)
                  bell() ;
                continue ;
            }
            if(clen >= len-1) {
                if(echo)
                  bell() ;
                continue ;
            }
            buf[clen++] = ch ;
            if(echo)
              ochar(ch) ;
        }
        buf[clen] = '\0' ;
        prints("\n") ;
        oflush() ;
        return clen ;
    }
    clrtoeol() ;
    getyx(&y,&x) ;
    while((ch = igetch()) != '\r') {
        if(ch == '\n')
          break ;
        if(ch == '\177' || ch == 0x08) {
            if(clen == 0) {
                bell() ;
                continue ;
            }
            clen-- ;
            if(echo) {
                move(y,x+clen) ;
                prints(" ") ;
                move(y,x+clen) ;
            }
            continue ;
        }
        if(!isprint(ch)) {
            bell() ;
            continue ;
        }
        if(x+clen >= scr_cols || clen >= len-1) {
            bell() ;
            continue ;
        }
        buf[clen++] = ch ;
        if(echo)
          prints("%c",ch) ;
    }
    buf[clen] = '\0' ;
    if(echo)
      prints("\n") ;
    refresh() ;
    return clen ;
}
