/* Copyright (C) Magna Carta Software, Inc. 1990. All Rights Reserved C COMMUNICATIONS TOOLKIT RXFORMAT.C -- formatted character receive routines. */ #define CCT_DEVELOPMENT #include #include #include #define xlat_rx(x) p->a_rx_xlat[(short) (x)] /* C_FLUSH_RX_ -- Flush a character stored due to EOL processing. Return Value: c -- the stored character; EOF -- no character waiting; */ static short NEAR_ c_flush_rx_(COMM_PORT *p) { short c; if (p->rx_f_lastchar) { p->rx_f_lastchar = FALSE; c = p->rx_lastchar; if (p->echo & RX) { /* IF LOCAL ECHO IS ON, DISPLAY THE CHARACTER */ if (isrxecholocal(p)) (*p->con_out)(p, c); /* IF PRINTER ECHO IS ON, PRINT THE CHARACTER */ if (isrxechoprn(p)) (*p->p_out)(p, c); /* IF THE RECEIVE BUFFER/FILE IS ON, BUFFER/WRITE THE CHARACTER */ if (isrxechobuf(p)) (*p->b_out)(p, c); } return (c); } return (EOF); } /* C_GETC -- Get a character from the serial port. NOTE: f_rx is a flag indicating that we pretend no character has been received; Returns: c -- the formatted value of the character; EOF -- no character received after wait; -2 -- char. received but not returned; USER_CANCELLED -- user cancelled from keyboard; */ short c_getc(COMM_PORT *p) { short f_rx, c; /* SEE IF THERE IS A CHARACTER WAITING FROM EOL FORMATTING */ if (p->rx_f_lastchar) return(c_flush_rx_(p)); /* ASSERTING FLOW CONTROL -- TURN ON IF BELOW LOW WATER MARK */ if (p->inhold & TX) { if ((p->rxbufhead > p->rxbuftail && (WORD) (p->rxbufhead - p->rxbuftail) < p->lowwater) || (p->rxbufhead < p->rxbuftail && (WORD) (p->rxbuftail - p->rxbufhead) > p->highwater)) { if (p->flowctl & TXONXOFF) { /* XON/XOFF PROCESSING */ c_putc_(p, p->xonchar); p->inhold &= ~TXONXOFF; #if XDEBUG puts("\nXON sent..."); #endif } if (p->flowctl & TRTS_CTS) { /* RTS/CTS FLOW CONTROL */ set_rts(p, HIGH); p->inhold &= ~TRTS_CTS; #if XDEBUG puts("\nRTS set high..."); #endif } if (p->flowctl & TDTR_DSR) { /* DTR/DSR FLOW CONTROL */ set_dtr(p, HIGH); p->inhold &= ~TDTR_DSR; #if XDEBUG puts("\nDTR is high..."); #endif } } } #if 0 /* ASSERT FLOW CONTROL -- TURN OFF IF ABOVE HIGH WATER MARK */ if (p->flowhigh) { if ((p->rxbufhead > p->rxbuftail && (WORD) (p->rxbufhead - p->rxbuftail) > p->highwater) || (p->rxbufhead < p->rxbuftail && (WORD) (p->rxbuftail - p->rxbufhead) < p->lowwater)) { if (p->flowctl & TXONXOFF) { /* XON/XOFF PROCESSING */ c_putc_(p, p->xoffchar); p->inhold |= TXONXOFF; #if XDEBUG puts("\nXOFF SENT..."); #endif } if (p->flowctl & TRTS_CTS) { /* RTS/CTS FLOW CONTROL */ set_rts(p, LOW); p->inhold |= TRTS_CTS; #if XDEBUG puts("\nRTS SET LOW..."); #endif } if (p->flowctl & TDTR_DSR) { /* DTR/DSR FLOW CONTROL */ set_dtr(p, LOW); p->inhold |= TDTR_DSR; #if XDEBUG puts("\nDTR is low -- waiting..."); #endif } } } #endif /* DETERMINE WHETHER ANY FORMATTING IS NECESSARY */ if (!p->rx_xlat) return(c_inchar(p)); /* SHOULD WE WAIT FOR A CHARACTER? */ c = (p->rx_ibdelay) ? c_waitc(p, EOF, p->rx_ibdelay) : c_inchar(p); if (c < 0) return (c); f_rx = TRUE; #if 0 /* OUR RECEIVER FLOW CONTROL */ if (p->flowhigh) { if (p->inhold & RX) { /* ACCEPT FLOW CONTROL -- TEST FOR RECEIVED XON AND TURN FLOW ON */ if ((p->flowctl & RXONXOFF) && (c == (short) p->xonchar || p->xonchar == XON_ALL)) p->inhold &= ~RXONXOFF; } else { /* ACCEPT FLOW CONTROL -- TEST FOR RECEIVED XOFF AND TURN FLOW OFF */ if ((p->flowctl & RXONXOFF) && c == (short) p->xoffchar) p->inhold |= RXONXOFF; } } #endif /* SHOULD WE ECHO THE RECEIVED BYTE BACK TO THE SENDER? */ if (isrxechoremote(p)) c_putc_(p, c); /* PERFORM ANY NECESSARY SINGLE CHARACTER TRANSLATION */ if (p->decodec != NULL) c = (*p->decodec)(p, c); /* CHECK IF ONLY ASCII CHARACTERS ALLOWED */ if (p->rx_ascii_only) if (c & 0X80) f_rx = FALSE; /* PERFORM ANY NECESSARY CASE CONVERSION */ if (p->rx_case_convert == UPPER) c = toupper(c); else if (p->rx_case_convert == LOWER) c = tolower(c); /* END-OF-LINE TRANSLATION */ switch (p->rx_eol) { case LF2CR: /* lf->cr */ if (c == LF) c = CR; break; case CR2LF: /* cr->lf */ if (c == CR) c = LF; break; case EOL2SP: /* cr and lf converted to spaces */ if (c == CR) f_rx = FALSE; /* crlf = one space */ if (c == LF && p->rx_lastchar == CR) c = SP; break; case STRIPEOL: /* cr and lf not transmitted */ if (c == CR || c == LF) f_rx = FALSE; break; case LF2CRLF: /* lf -> crlf */ if (c == LF) { p->rx_f_lastchar = TRUE; p->rx_lastchar = LF; c = CR; } break; case CR2CRLF: /* cr->crlf */ if (c == CR) { p->rx_f_lastchar = TRUE; p->rx_lastchar = LF; } break; case CRLF2LF: /* crlf->lf */ if (c != LF) { /* RETURN A STORED CR */ if (p->rx_lastchar == CR) { p->rx_lastchar = c; p->rx_f_lastchar = TRUE; c = CR; } /* RECEIVED A CR */ else if (c == CR) f_rx = FALSE; } break; case CRLF2CR: /* crlf -> cr */ if (c == LF && p->rx_lastchar == CR) f_rx = FALSE; break; default: break; } /* STORE LAST CHARACTER RECEIVED */ if (!p->rx_f_lastchar) p->rx_lastchar = c; if ((p->echo & RX) && f_rx) { /* IF LOCAL ECHO IS ON, DISPLAY THE CHARACTER */ if (isrxecholocal(p)) (*p->con_out)(p, c); /* IF PRINTER ECHO IS ON, PRINT THE CHARACTER */ if (isrxechoprn(p)) (*p->p_out)(p, c); /* IF THE RECEIVE BUFFER/FILE IS ON, BUFFER/WRITE THE CHARACTER */ if (isrxechobuf(p)) (*p->b_out)(p, c); } return (f_rx ? c : -2); } /* C_GETS -- Get a sequence of "len" characters from the designated serial port. If 'term' is not EOF, stop if 'term' is received. Store incoming characters in 'str'. 'str' should be at least len+1 characters long. Use input transformation. Return value: The number of characters received (possibly 0); USER_CANCELLED if abort key pressed. */ short c_gets(COMM_PORT *p, char *str, WORD len, short term) { short ch, save_ibdelay; short ret = 0; WORD i = 0; if (!p->rx_lbdelay && p->rx_ibdelay) p->rx_lbdelay = p->rx_ibdelay; save_ibdelay = p->rx_ibdelay; p->rx_ibdelay = p->rx_lbdelay; ch = c_getc(p); if (ch < 0 && ch != -2) ret = ch; if (ch >= 0) { *str++ = (char) ch; --len; /* adjust length to get below */ ++i; if (ch == term) ret = EOF; } p->rx_ibdelay = save_ibdelay; for (; !ret && i < len; i++) { if ((ch = c_getc(p)) >= 0) *str++ = (char) ch; else if (ch == -2) --i; else ret = ch; if (ch != EOF && ch == term) break; } *str = '\0'; return ((ret == USER_CANCELLED) ? ret : (short) i); } /* GET_RX_XLAT -- Query the setting of each of the input translation variables used in c_getcf(). */ short get_rx_xlat(COMM_PORT *p, short item) { return ((*p->get_rx_xlat)(p, item)); } /* SET_RX_XLAT -- Specify the type of input translation used by c_getcf() and c_getsf(). */ short set_rx_xlat(COMM_PORT *p, short item, short value) { return ((*p->set_rx_xlat)(p, item, value)); } /* ISRXXLAT -- Determine is RX data translation of any kind is in use. */ short isrxxlat(COMM_PORT *p) { if (!p->echo && !p->rx_eol && !p->rx_case_convert && !p->rx_ascii_only && !p->rx_lbdelay && !p->rx_ibdelay && !p->rx_tbdelay && !(p->flowctl & RX)) return (FALSE); else return (TRUE); }