karn (06/10/82)
/* The number of requests for my terminal paging program has been * sufficient to warrant posting it on net.sources. * This version is set up for the Heathkit H-19; * three constants can be changed to configure it for other * terminals. * Note that no attempt is made to keep track of cursor movement by * means other than printing characters, carriage return or line feed * characters; hence, this program will get very confused if you try * to run emacs, vi, etc., through it. * * Use BDS-C to compile, and clink with the cio terminal I/O * package. Note that I make reference to the terminal and modem port * definitions in bdscio.h. */ /* * Modem buffering program. A large chunk of memory is used as a circular * buffer for incoming modem data, which is sent out to the terminal * a crt page at a time. High/low water marks are used to flow control * the host when the buffer is filled. * * The program is NOT interrupt driven. Frequent polls are made on * both the keyboard and modem ports to avoid losing characters. * March 1982, Phil Karn */ #include <a:bdscio.h> /* Terminal dependent parameters */ #define ROWS 24 #define COLS 80 #define ERASE "\033E" #define BSIZE 32767 #define HIWATER 32000 #define LOWATER 31000 #define CTLS 19 #define CTLQ 17 char buffer[BSIZE]; char *in,*out; int count; int stopped; main() { register char c; int row,col; /* Cursor position */ stopped = count = col = row = 0; in = out = buffer; TTYMode(0); /* Really raw mode */ puts(ERASE); /* Erase screen */ loop: scanmod(); scankbd(); c = getb(); switch(c & 0x7f){ case '\n': row++; break; case '\r': col = 0; break; default: /* Normal character; check for end of line wraparound */ col++; if(col == COLS){ col = 0; row++; } break; } /* Screen full. Wait for any character before proceeding */ while(row == ROWS){ while(!kbhit()) scanmod(); getchar(); col = row = 0; puts(ERASE); } /* Don't waste the top line of the screen with the newline */ if(c != '\n' || row != 0 ) putchar(c); goto loop; } scanmod() { /* Scan modem input for activity */ if(inp(MSTAT) & MIMASK){ *in++ = inp(MDATA); count++; if(in == &buffer[BSIZE]) in = buffer; if(!stopped && count > HIWATER){ stopped = 1; putmod(CTLS); } } } scankbd() { /* Do same for keyboard */ if(kbhit()) putmod(getchar()); } /* Fetch char from modem input buffer */ char getb() { char c; while(count == 0){ scanmod(); scankbd(); } c = *out++; count--; if(stopped && count < LOWATER){ stopped = 0; putmod(CTLQ); } if(out == &buffer[BSIZE]) out = buffer; return(c); } /* Send character to modem */ putmod(c) char c; { while((inp(MSTAT) & MOMASK) == 0) scanmod(); outp(MDATA,c); }