+ termLiteralNextChar,
+ termQuitChar;
+
+\f
+/*
+ * MSDOS doesn't have anyway of deciding whether a full-edited line
+ * is ready to be read in, so we need to do character-by-character
+ * reads, and then do the editing in the program (in the case where
+ * we are supporting line-by-line mode).
+ *
+ * The following routines, which are internal to the MSDOS-specific
+ * code, accomplish this miracle.
+ */
+
+#define Hex(c) HEX[(c)&0xff]
+
+static survivorSetup = 0; /* Do we have ^C hooks in? */
+
+static int
+ lineend = 0, /* There is a line terminator */
+ ctrlCCount = 0;
+
+static char linein[200], /* Where input line is assembled */
+ *nextin = linein, /* Next input character */
+ *nextout = linein; /* Next character to be consumed */
+
+#define consumechar() \
+ if ((++nextout) >= nextin) { \
+ nextout = nextin = linein; \
+ lineend = 0; \
+ }
+
+#define characteratatime() (!MODE_LINE(globalmode)) /* one by one */
+
+
+/*
+ * killone()
+ *
+ * Erase the last character on the line.
+ */
+
+static void
+killone()
+{
+ if (lineend) {
+ return; /* ??? XXX */
+ }
+ if (nextin == linein) {
+ return; /* Nothing to do */
+ }
+ nextin--;
+ if (!(isspace(*nextin) || isprint(*nextin))) {
+ putchar('\b');
+ putchar(' ');
+ putchar('\b');
+ }
+ putchar('\b');
+ putchar(' ');
+ putchar('\b');
+}
+
+
+/*
+ * setlineend()
+ *
+ * Decide if it's time to send the current line up to the user
+ * process.
+ */
+
+static void
+setlineend()
+{
+ if (nextin == nextout) {
+ return;
+ }
+ if (characteratatime()) {
+ lineend = 1;
+ } else if (nextin >= (linein+sizeof linein)) {
+ lineend = 1;
+ } else {
+ int c = *(nextin-1);
+ if ((c == termIntChar)
+ || (c == termQuitChar)
+ || (c == termEofChar)) {
+ lineend = 1;
+ } else if (c == termFlushChar) {
+ lineend = 1;
+ } else if ((c == '\n') || (c == '\r')) {
+ lineend = 1;
+ }
+ }
+ /* Otherwise, leave it alone (reset by 'consumechar') */
+}
+
+/*
+ * OK, what we do here is:
+ *
+ * o If we are echoing, then
+ * o Look for character erase, line kill characters
+ * o Echo the character (using '^' if a control character)
+ * o Put the character in the input buffer
+ * o Set 'lineend' as necessary
+ */
+
+static void
+DoNextChar(c)
+int c; /* Character to process */
+{
+ static char literalnextcharacter = 0;
+
+ if (nextin >= (linein+sizeof linein)) {
+ putchar('\7'); /* Ring bell */
+ setlineend();
+ return;
+ }
+ if (MODE_LOCAL_CHARS(globalmode)) {
+ /* Look for some special character */
+ if (!literalnextcharacter) {
+ if (c == termEraseChar) {
+ killone();
+ setlineend();
+ return;
+ } else if (c == termKillChar) {
+ while (nextin != linein) {
+ killone();
+ }
+ setlineend();
+ return;
+ } else if (c == termLiteralNextChar) {
+ literalnextcharacter = 1;
+ return;
+ }
+ }
+
+ if (MODE_LOCAL_ECHO(globalmode)) {
+ if ((literalnextcharacter == 0) && ((c == '\r') || (c == '\n'))) {
+ putchar('\r');
+ putchar('\n');
+ c = '\n';
+ } else if (!isprint(c) && !isspace(c)) {
+ putchar('^');
+ putchar(c^0x40);
+ } else {
+ putchar(c);
+ }
+ }
+ literalnextcharacter = 0;
+ }
+ *nextin++ = c;
+ setlineend();
+}
+
+static int
+inputExists()
+{
+ int input;
+ static state = 0;
+
+ while (ctrlCCount) {
+ DoNextChar(0x03);
+ ctrlCCount--;
+ }
+ if (lineend) {
+ return 1;
+ }
+ if (!kbhit()) {
+ return lineend;
+ }
+ input = getch(); /* MSC - get console character */
+#if 0 /* For BIOS variety of calls */
+ if ((input&0xff) == 0) {
+ if ((input&0xff00) == 0x0300) { /* Null */
+ DoNextChar(0);
+ } else {
+ DoNextChar(0x01);
+ if (input&0x8000) {
+ DoNextChar(0x01);
+ DoNextChar((input>>8)&0x7f);
+ } else {
+ DoNextChar((input>>8)&0xff);
+ }
+ }
+ } else {
+ DoNextChar(input&0xff);
+ }
+#endif /* 0 */
+ if ((input&0xff) == 0) {
+ DoNextChar(0x01); /* ^A */
+ } else {
+ DoNextChar(input&0xff);
+ }
+ return lineend;
+}
+
+
+void
+CtrlCInterrupt()
+{
+ if (!MODE_COMMAND_LINE(globalmode)) {
+ ctrlCCount++; /* XXX */
+ signal(SIGINT, CtrlCInterrupt);
+ } else {
+ closeallsockets();
+ exit();
+ }
+}
+\f
+/*
+ * The MSDOS routines, called from elsewhere.
+ */
+
+
+static int
+TerminalAutoFlush() /* MSDOS */
+{
+ return 1;
+}
+
+static int
+TerminalCanRead()
+{
+ return inputExists();
+}