/* TTY input line editing * Copyright 1991 Phil Karn, KA9Q * split screen by G. J. van der Grinten, PA0GRI */ #include #ifdef __TURBOC__ #include #endif #include #include "global.h" #include "mbuf.h" #include "session.h" #include "tty.h" #include "socket.h" extern FILE *Rawterm; #define OFF 0 #define ON 1 static int Lastsize = 1; static char Lastline[LINESIZE+1] = "\n"; #define CTLU 21 /* delete current line in total */ #define CTLR 18 /* reprint current line */ #define CTLZ 26 /* EOF char in dos */ #define CTLW 23 /* erase last word including preceding space */ #define CTLB 02 /* use as F3 in dos but no editing */ #define DEL 0x7f /* Accept characters from the incoming tty buffer and process them * (if in cooked mode) or just pass them directly (if in raw mode). * * Echoing (if enabled) is direct to the raw terminal. This requires * recording (if enabled) of locally typed info to be done by the session * itself so that edited output instead of raw input is recorded. * Control-W added by g1emm again.... for word delete. * Control-B/Function key 3 added by g1emm for line repeat. */ struct mbuf * ttydriv(sp,c) struct session *sp; char c; { struct mbuf *bp; char *cp,*rp; int cnt; switch(sp->ttystate.edit){ case OFF: bp = ambufw(1); *bp->data = c; bp->cnt = 1; if(sp->ttystate.echo){ if(sp->split){ sp->tsavex = wherex(); sp->tsavey = wherey(); window(1,24,80,25); gotoxy(sp->bsavex,sp->bsavey); highvideo(); putch(c); normvideo(); cputs("_\b"); sp->bsavex = wherex(); sp->bsavey = wherey(); window(1,1,80,23); gotoxy(sp->tsavex,sp->tsavey); } else { putc(c,Rawterm); } } return bp; case ON: if(sp->ttystate.line == NULLBUF) sp->ttystate.line = ambufw(LINESIZE); bp = sp->ttystate.line; cp = bp->data + bp->cnt; /* Perform cooked-mode line editing */ switch(c & 0x7f){ case '\r': /* CR and LF both terminate the line */ case '\n': if(sp->ttystate.crnl) *cp = '\n'; else *cp = c; if(sp->ttystate.echo){ if(sp->split){ highvideo(); rp = bp->data; while(rp < cp) { putch(*rp++); } normvideo(); clreol(); cputs(Eol); clreol(); sp->tsavex = wherex(); sp->tsavey = wherey(); window(1,24,80,25); clrscr(); cputs("_\b"); sp->bsavex = wherex(); sp->bsavey = wherey(); window(1,1,80,23); gotoxy(sp->tsavex,sp->tsavey); } else { fputs(Eol,Rawterm); } } bp->cnt += 1; sp->ttystate.line = NULLBUF; Lastsize = bp->cnt; memcpy(Lastline, bp->data, Lastsize); return bp; case DEL: case '\b': /* Character delete */ if(bp->cnt != 0){ bp->cnt--; if(sp->ttystate.echo){ if(sp->split){ sp->tsavex = wherex(); sp->tsavey = wherey(); window(1,24,80,25); gotoxy(sp->bsavex,sp->bsavey); cputs(" \b\b_\b"); sp->bsavex = wherex(); sp->bsavey = wherey(); window(1,1,80,23); gotoxy(sp->tsavex,sp->tsavey); } else { fputs("\b \b",Rawterm); } } } break; case CTLR: /* print line buffer */ if(sp->ttystate.echo){ if(sp->split) { sp->tsavex = wherex(); sp->tsavey = wherey(); window(1,24,80,25); gotoxy(sp->bsavex,sp->bsavey); clrscr(); rp = bp->data; while (rp < cp) putch(*rp++) ; cputs("_\b"); sp->bsavex = wherex(); sp->bsavey = wherey(); window(1,1,80,23); gotoxy(sp->tsavex,sp->tsavey); } else { fprintf(Rawterm,"^R%s",Eol) ; rp = bp->data; while (rp < cp) putc(*rp++,Rawterm) ; } } break ; case CTLU: /* Line kill */ if(sp->split) { sp->tsavex = wherex(); sp->tsavey = wherey(); window(1,24,80,25); gotoxy(sp->bsavex,sp->bsavey); cputs(" \b"); while(bp->cnt != 0){ cputs("\b \b"); bp->cnt--; } cputs("_\b"); sp->bsavex = wherex(); sp->bsavey = wherey(); window(1,1,80,23); gotoxy(sp->tsavex,sp->tsavey); } else { while(bp->cnt != 0){ bp->cnt--; if(sp->ttystate.echo) fputs("\b \b",Rawterm); } } break; case CTLB: /* Use last line to finish current */ cnt = bp->cnt; /* save count so far */ while(bp->cnt != 0){ bp->cnt--; if(sp->ttystate.echo) fputs("\b \b", Rawterm); } bp->cnt = cnt; if(bp->cnt < (Lastsize-1)){ memcpy(bp->data+bp->cnt, &Lastline[bp->cnt], (Lastsize-1) - bp->cnt); bp->cnt = Lastsize-1; } *(bp->data + bp->cnt) = '\0'; /* make it a string */ if(sp->ttystate.echo) fputs(bp->data, Rawterm); /* repaint line */ break ; case CTLW: /* erase word */ cnt = 0 ; /* we haven't seen a printable char yet */ while(bp->cnt != 0){ *(bp->data + bp->cnt--) = '\n'; if(sp->ttystate.echo) fputs("\b \b", Rawterm); if (isspace((int)*(bp->data + bp->cnt))) { if (cnt) break ; } else { cnt = 1 ; } } break ; default: /* Ordinary character */ *cp = c; bp->cnt++; /* ^Z apparently hangs the terminal emulators under * DoubleDos and Desqview. I REALLY HATE having to patch * around other people's bugs like this!!! */ if(sp->ttystate.echo && #ifndef AMIGA c != CTLZ && #endif bp->cnt < LINESIZE-1){ if(sp->split) { sp->tsavex = wherex(); sp->tsavey = wherey(); window(1,24,80,25); gotoxy(sp->bsavex,sp->bsavey); putch(c); cputs("_\b"); sp->bsavex = wherex(); sp->bsavey = wherey(); window(1,1,80,23); gotoxy(sp->tsavex,sp->tsavey); } else { putc(c,Rawterm); } } else if(bp->cnt >= LINESIZE-1){ putc('\007',Rawterm); /* Beep */ bp->cnt--; } break; } break; } return NULLBUF; }