home *** CD-ROM | disk | FTP | other *** search
- /*
- * The input routines.
- */
-
- #include <stdio.h>
- #include "config.h"
- #include "misc.h"
- #include "param.h"
- #include "status.h"
- #include "vcs.h"
-
- static int add_lf;
- static void vs_scroll();
- static FILE *logfp = (FILE *) NULL;
- static FILE *lprfp = (FILE *) NULL;
-
- /*
- * Read the serial port and write the characters to the screen. Watch
- * for changes in status structure to toggle the fancy options.
- * Writes the characters received to a virtual screen buffer.
- */
-
- void
- tty_input()
- {
- extern int fd;
- register int in_cnt, out_cnt;
- char c, *bufp, in_buf[INPUT_BUF], out_buf[INPUT_BUF*2];
- void vs_putchar();
-
- /* here we go... */
- if ((in_cnt = read(fd, in_buf, INPUT_BUF)) <= 0)
- return;
-
- /*
- * If we're doing a script, send a duplicate down the pipe
- */
- if (status->dup_fd != -1)
- write(status->dup_fd, in_buf, in_cnt);
-
- /* "peel" the buffer one at a time */
- out_cnt = 0;
- bufp = in_buf;
- add_lf = !strcmp(param->cr_in, "CR/LF");
- while (--in_cnt >= 0) {
- c = *bufp++ & 0xff;
- /* send to logfile? */
- if (status->log_status) {
- if (c == '\r' && add_lf)
- putc('\n', logfp);
- /* no carriage returns in logfile */
- if (c != '\r')
- putc(c, logfp);
- }
- /* send to printer too? */
- if (status->print_status)
- putc(c, lprfp);
-
- /* put a char in virtual screen */
- vs_putchar(c);
-
- /* build the output buffer */
- out_buf[out_cnt++] = c;
- if (c == '\r' && add_lf)
- out_buf[out_cnt++] = '\n';
-
- /* output in smaller chunks */
- if (out_cnt >= OUTPUT_BUF) {
- write(1, out_buf, out_cnt);
- out_cnt = 0;
- }
- }
- if (out_cnt)
- write(1, out_buf, out_cnt);
-
- return;
- }
-
- /*
- * Put a character in the virtual screen. This routine saves incoming
- * characters in a two dimensional buffer designed to mimic the real
- * screen.
- */
-
- void
- vs_putchar(c)
- char c;
- {
- register int i;
- extern int vcs_param[NUM_VCS][5], vcs_opt[NUM_VCS][10];
- char *memset();
- int tab_stop;
-
- switch (vcs_filter(c)) {
- case MAYBE: /* wait and see... */
- break;
- case 256+HOME: /* home virtual screen "cursor" */
- status->row = 0;
- status->col = 0;
- break;
- case 256+CLR_EOL: /* clear to end of line */
- memset(&status->vs[status->row][status->col], ' ', status->max_col - status->col);
- status->col = status->max_col -1;
- break;
- case 256+CLR_EOS: /* clear to end of screen */
- memset(&status->vs[status->row][status->col], ' ', status->max_col - status->col);
- for (i=status->row+1; i<status->max_row; i++)
- memset(status->vs[i], ' ', status->max_col);
- status->row = status->max_row -1;
- status->col = status->max_col -1;
- break;
- case 256+CLEAR: /* clear all and home "cursor" */
- for (i=0; i<status->max_row; i++)
- memset(status->vs[i], ' ', status->max_col);
- status->row = 0;
- status->col = 0;
- break;
- case 256+MV_UP: /* move "cursor" up */
- status->row--;
- if (status->row < 0)
- status->row = 0;
- break;
- case 256+MV_DOWN: /* move "cursor" down */
- status->row++;
- if (status->row >= status->max_row)
- status->row = status->max_row -1;
- break;
- case 256+MV_RIGHT: /* move "cursor" right */
- status->col++;
- if (status->col >= status->max_col)
- status->col = status->max_col -1;
- break;
- case 256+MV_LEFT: /* move "cursor" left */
- case BS: /* non destructive back space */
- status->col--;
- if (status->col < 0)
- status->col = 0;
- break;
- case 256+MV_DIRECT: /* direct cursor movement */
- status->row = vcs_param[MV_DIRECT][0];
- status->col = vcs_param[MV_DIRECT][1];
-
- /* if "add one" and "decimal" */
- if (vcs_opt[MV_DIRECT][0] && vcs_opt[MV_DIRECT][1]) {
- status->row--;
- status->col--;
- }
- /* if "character" */
- if (vcs_opt[MV_DIRECT][2]) {
- /* if "add offset" */
- if (vcs_opt[MV_DIRECT][3]) {
- status->row -= vcs_opt[MV_DIRECT][5];
- status->col -= vcs_opt[MV_DIRECT][5];
- }
- /* if "subtract offset" */
- if (vcs_opt[MV_DIRECT][4]) {
- status->row += vcs_opt[MV_DIRECT][5];
- status->col += vcs_opt[MV_DIRECT][5];
- }
- status->row--;
- status->col--;
- }
- /* sanity check... */
- if (status->row < 0)
- status->row = 0;
- if (status->col < 0)
- status->col = 0;
- if (status->row >= status->max_row)
- status->row = status->max_row -1;
- if (status->col >= status->max_col)
- status->col = status->max_col -1;
- break;
- case 0:
- case 7: /* skip NULL and "bell" character */
- break;
- case '\t': /* tab character */
- tab_stop = status->col + 8 - (status->col % 8);
- /* if wrap around */
- if (tab_stop >= status->max_col) {
- /* spaces up to eol */
- memset(&status->vs[status->row][status->col], ' ', status->max_col - status->col);
- status->row++;
- if (status->row >= status->max_row)
- vs_scroll();
-
- /* the remainder of the tab */
- status->col = tab_stop - status->max_col;
- }
- else {
- memset(&status->vs[status->row][status->col], ' ', tab_stop - status->col);
- status->col = tab_stop;
- }
- break;
- case '\r': /* carriage return */
- status->col = 0;
- if (!add_lf)
- break;
- /* FALLTHRU */
- case '\n': /* line feed */
- status->row++;
- if (status->row >= status->max_row)
- vs_scroll();
- break;
- default: /* a normal character */
- status->vs[status->row][status->col] = c;
- status->col++;
- /* wrap around */
- if (status->col >= status->max_col) {
- status->col = 0;
- status->row++;
- if (status->row >= status->max_row)
- vs_scroll();
- }
- break;
- }
- return;
- }
-
- /*
- * Do a software scroll on the virtual screen. Does not alter the
- * "col" variable.
- */
-
- static void
- vs_scroll()
- {
- char *memset();
- /* move 'em up 1 line */
- #ifdef MEMMOVE
- MEMMOVE(status->vs[0], status->vs[1], (status->max_row -1) * MAX_COL);
- #else /* MEMMOVE */
- register int i;
- char *strcpy();
-
- for (i=0; i<status->max_row-1; i++)
- strcpy(status->vs[i], status->vs[i+1]);
- #endif /* MEMMOVE */
- /* clear the bottom line */
- memset(status->vs[status->max_row-1], ' ', status->max_col);
-
- status->row = status->max_row -1;
- return;
- }
-
- /*
- * A short-cut for charcters that are "echoed" in the half duplex
- * mode. Since the TTY driver is putting the characters on the
- * screen (rather than being sent back by the modem), they need
- * to be faked as modem input.
- */
-
- void
- half_duplex(c)
- char c;
- {
- /* send to logfile? */
- if (status->log_status) {
- if (c == '\r' && add_lf)
- putc('\n', logfp);
- /* no carriage returns in logfile */
- if (c != '\r')
- putc(c, logfp);
- }
- /* send to printer too? */
- if (status->print_status)
- putc(c, lprfp);
-
- /* put a char in virtual screen */
- vs_putchar(c);
- return;
- }
-
- /*
- * Toggle the printer log
- */
-
- void
- lpr_toggle()
- {
- FILE *n_popen();
-
- status->print_status = status->print_status ? 0 : 1;
-
- if (status->print_status && lprfp == NULL) {
- if (!(lprfp = n_popen(LPR, "w")))
- status->print_status = 0;
- }
-
- if (!status->print_status && lprfp != NULL) {
- putc('\f', lprfp);
- n_pclose(lprfp);
- lprfp = (FILE *) NULL;
- }
- return;
- }
-
- /*
- * Toggle the data log
- */
-
- void
- log_toggle()
- {
- FILE *uid_fopen();
-
- status->log_status = status->log_status ? 0 : 1;
-
- if (status->log_status && logfp == NULL) {
- if (!(logfp = uid_fopen(status->log_path, "a")))
- status->log_status = 0;
- }
-
- if (!status->log_status && logfp != NULL) {
- fclose(logfp);
- logfp = (FILE *) NULL;
- }
- return;
- }
-