This patch applies to UnixFrotz232R2Std10.tar.gz as found in the IF archive
and modifies the terminal I/O routines.  Notable changes in functionality:
* The terminal erase character, as set with stty, now functions
 as backspace.  On many terminals this character is DEL.
* Background colours should now work properly.
* timeout() from curses is now used for timed input instead of a busy loop.
* ^L and ^R now redraw the screen.  They are not passed as input to the
 Z-machine.
* ISO-Latin-1 characters are now valid input unless in plain
 ASCII mode.  This makes the meta bit unusable for hotkeys.  On
 terminals with 8-bit character sets alt usually sends ESC
 anyway.
* History search has been added.  Type the beginning of a past
 command and hit the up or down arrow key.
In addition there are lots of cosmetic changes.

I have only tested this with Ncurses -- other curses implementations
might cause problems I know nothing of.  But I have completed Beyond
Zork and Border Zone with the patched Frotz (you need to use page
up/down to scroll the upper window in Beyond Zork).

       Timo Korvola    <[email protected]> <URL:http://www.iki.fi/tkorvola>

--- frotz-2.32/ux_init.c.orig   Sat Oct  4 04:12:10 1997
+++ frotz-2.32/ux_init.c        Thu Apr 22 23:02:48 1999
@@ -320,7 +320,6 @@
       else
         h_default_background = BLUE_COLOUR;
       os_set_colour(h_default_foreground, h_default_background);
-       bkgdset(current_color);
       erase();
       /*os_erase_area(1, 1, h_screen_rows, h_screen_cols);*/
    }
--- frotz-2.32/ux_input.c.orig  Fri Oct 17 23:11:33 1997
+++ frotz-2.32/ux_input.c       Fri Apr 30 10:56:06 1999
@@ -10,6 +10,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <limits.h>

#include <sys/time.h>

@@ -24,10 +25,22 @@

static struct timeval global_timeout;

+/* Some special characters. */
+#define CHR_CTRL_L 12
+#define CHR_CTRL_R 18
+#define CHR_DEL 127
+#define MOD_META 0x80
+
+/* These are useful for circular buffers.
+ */
+#define RING_DEC( ptr, beg, end) (ptr > (beg) ? --ptr : (ptr = (end)))
+#define RING_INC( ptr, beg, end) (ptr < (end) ? ++ptr : (ptr = (beg)))
+
#define MAX_HISTORY 20
static char *history_buffer[MAX_HISTORY];
-static short history_pointer = 0; /* Pointer to next available slot */
-static short history_frame = 0; /* Pointer to what the user's looking at */
+static char **history_next = history_buffer; /* Next available slot. */
+static char **history_view = history_buffer; /* What the user is looking at. */
+#define history_end (history_buffer + MAX_HISTORY - 1)

extern bool is_terminator (zchar);
extern void read_string (int, zchar *);
@@ -56,107 +69,147 @@
    }
}

+/* This returns the number of milliseconds until the input timeout
+ * elapses or zero if it has already elapsed.  -1 is returned if no
+ * timeout is in effect, otherwise the return value is non-negative.
+ */
+static int timeout_to_ms()
+{
+    struct timeval now, diff;
+
+    if (global_timeout.tv_sec == 0) return -1;
+    gettimeofday( &now, NULL);
+    diff.tv_usec = global_timeout.tv_usec - now.tv_usec;
+    if (diff.tv_usec < 0) {
+       /* Carry */
+       now.tv_sec++;
+       diff.tv_usec += 1000000;
+    }
+    diff.tv_sec = global_timeout.tv_sec - now.tv_sec;
+    if (diff.tv_sec < 0) return 0;
+    if (diff.tv_sec >= INT_MAX / 1000 - 1) /* Paranoia... */
+       return INT_MAX - 1000;
+    return diff.tv_sec * 1000 + diff.tv_usec / 1000;
+}
+
/*
 * unix_read_char
 *
- * This uses the curses getch() routine to get the next character typed,
- * and returns it unless the global timeout is reached.  It returns values
- * which the standard considers to be legal input, and also returns editing
- * and frotz hot keys.  If called with a non-zero flag, it will also return
- * line-editing keys like INSERT, etc,
+ * This uses the curses getch() routine to get the next character
+ * typed, and returns it.  It returns values which the standard
+ * considers to be legal input, and also returns editing and frotz hot
+ * keys.  If called with extkeys set it will also return line-editing
+ * keys like INSERT etc.
 *
+ * If unix_set_global_timeout has been used to set a global timeout
+ * this routine may also return ZC_TIME_OUT if input times out.
 */
-
-static int unix_read_char(int flag)
+static int unix_read_char(int extkeys)
{
    int c;
-    struct timeval ctime;

    while(1) {
-      /* Timed keyboard input.  Crude but functional. */
-      if (global_timeout.tv_sec) {
-         nodelay(stdscr, TRUE);
-         do {
-              c = getch();
-              if (c == ERR) {
-                  gettimeofday(&ctime, NULL);
-                  if ((ctime.tv_sec >= global_timeout.tv_sec) &&
-                      (ctime.tv_usec >= global_timeout.tv_usec)) {
-                      nodelay(stdscr, FALSE);
-                      return 0;
-                  }
-              }
-          } while (c == ERR);
-          nodelay(stdscr, FALSE);
-      }
-      /* The easy way. */
-      else c = getch();
-
-      /* Catch 98% of all input right here... */
-      if ( ((c >= 32) && (c <= 126)) || (c == 13) || (c == 8))
-        return c;
-
-      /* ...and the other 2% makes up 98% of the code. :( */
-      switch(c) {
-        /* Lucian P. Smith reports KEY_ENTER on Irix 5.3.  10 has never
-           been reported, but I'm leaving it in just in case. */
-        case 10: case KEY_ENTER: return 13;
-        /* I've seen KEY_BACKSPACE returned on some terminals. */
-        case KEY_BACKSPACE: return 8;
-        /* On seven-bit connections, "Alt-Foo" is returned as an escape
-           followed by the ASCII value of the letter.  We have to decide
-           here whether to return a single escape or a frotz hot key. */
-        case 27: nodelay(stdscr, TRUE); c = getch(); nodelay(stdscr, FALSE);
-                 if (c == ERR) return 27;
-                 switch(c) {
-                   case 112: return ZC_HKEY_PLAYBACK; /* Alt-P */
-                   case 114: return ZC_HKEY_RECORD; /* Alt-R */
-                   case 115: return ZC_HKEY_SEED; /* Alt-S */
-                   case 117: return ZC_HKEY_UNDO; /* Alt-U */
-                   case 110: return ZC_HKEY_RESTART; /* Alt-N */
-                   case 120: return ZC_HKEY_QUIT; /* Alt-X */
-                  case 100: return ZC_HKEY_DEBUG; /* Alt-D */
-                  case 104: return ZC_HKEY_HELP; /* Alt-H */
-                   default: return 27;
-                 }
-                 break;
+       timeout( timeout_to_ms());
+       c = getch();
+
+       /* Catch 98% of all input right here... */
+       if ((c >= ZC_ASCII_MIN && c <= ZC_ASCII_MAX)
+           || (!unix_plain_ascii
+               && c >= ZC_LATIN1_MIN && c <= ZC_LATIN1_MAX))
+           return c;
+
+       /* ...and the other 2% makes up 98% of the code. :( */
+
+       /* On many terminals the backspace key returns DEL. */
+       if (c == erasechar()) return ZC_BACKSPACE;;
+       switch(c) {
+       /* Normally ERR means timeout.  I suppose we might also get
+          ERR if a signal hits getch. */
+       case ERR:
+           if (timeout_to_ms() == 0)
+               return ZC_TIME_OUT;
+           else
+               continue;
+       /* Screen decluttering. */
+       case CHR_CTRL_L: case CHR_CTRL_R:
+           clearok( curscr, 1); refresh(); clearok( curscr, 0);
+           continue;
+       /* Lucian P. Smith reports KEY_ENTER on Irix 5.3.  LF has never
+          been reported, but I'm leaving it in just in case. */
+       case '\n': case '\r': case KEY_ENTER: return ZC_RETURN;
+       /* I've seen KEY_BACKSPACE returned on some terminals. */
+       case KEY_BACKSPACE: case '\b': return ZC_BACKSPACE;
+       /* On terminals with 8-bit character sets or 7-bit connections
+          "Alt-Foo" may be returned as an escape followed by the ASCII
+          value of the letter.  We have to decide here whether to
+          return a single escape or a frotz hot key. */
+       case ZC_ESCAPE:
+           nodelay(stdscr, TRUE); c = getch(); nodelay(stdscr, FALSE);
+           switch(c) {
+           case ERR: return ZC_ESCAPE;
+           case 'p': return ZC_HKEY_PLAYBACK;
+           case 'r': return ZC_HKEY_RECORD;
+           case 's': return ZC_HKEY_SEED;
+           case 'u': return ZC_HKEY_UNDO;
+           case 'n': return ZC_HKEY_RESTART;
+           case 'x': return ZC_HKEY_QUIT;
+           case 'd': return ZC_HKEY_DEBUG;
+           case 'h': return ZC_HKEY_HELP;
+           default: continue;  /* Ignore unknown combinations. */
+           }
       /* The standard function key block. */
-        case KEY_UP: return 129;
-        case KEY_DOWN: return 130;
-        case KEY_LEFT: return 131;
-        case KEY_RIGHT: return 132;
-        case KEY_F(1): return 133; case KEY_F(2): return 134;
-        case KEY_F(3): return 135; case KEY_F(4): return 136;
-        case KEY_F(5): return 137; case KEY_F(6): return 138;
-        case KEY_F(7): return 139; case KEY_F(8): return 140;
-        case KEY_F(9): return 141; case KEY_F(10): return 142;
-        case KEY_F(11): return 143; case KEY_F(12): return 144;
-        /* Curses can't differentiate keypad numbers from cursor keys. Damn. */
-        /* This will catch the alt-keys on 8-bit clean input streams... */
-        case 240: return ZC_HKEY_PLAYBACK; /* Alt-P */
-        case 242: return ZC_HKEY_RECORD; /* Alt-R */
-        case 243: return ZC_HKEY_SEED; /* Alt-S */
-        case 245: return ZC_HKEY_UNDO; /* Alt-U */
-        case 238: return ZC_HKEY_RESTART; /* Alt-N */
-        case 248: return ZC_HKEY_QUIT; /* Alt-X */
-        case 228: return ZC_HKEY_DEBUG; /* Alt-D */
-        case 232: return ZC_HKEY_HELP; /* Alt-H */
+       case KEY_UP: return ZC_ARROW_UP;
+       case KEY_DOWN: return ZC_ARROW_DOWN;
+       case KEY_LEFT: return ZC_ARROW_LEFT;
+       case KEY_RIGHT: return ZC_ARROW_RIGHT;
+       case KEY_F(1): return ZC_FKEY_MIN;
+       case KEY_F(2): return ZC_FKEY_MIN + 1;
+       case KEY_F(3): return ZC_FKEY_MIN + 2;
+       case KEY_F(4): return ZC_FKEY_MIN + 3;
+       case KEY_F(5): return ZC_FKEY_MIN + 4;
+       case KEY_F(6): return ZC_FKEY_MIN + 5;
+       case KEY_F(7): return ZC_FKEY_MIN + 6;
+       case KEY_F(8): return ZC_FKEY_MIN + 7;
+       case KEY_F(9): return ZC_FKEY_MIN + 8;
+       case KEY_F(10): return ZC_FKEY_MIN + 9;
+       case KEY_F(11): return ZC_FKEY_MIN + 10;
+       case KEY_F(12): return ZC_FKEY_MIN + 11;
+       /* Curses can't differentiate keypad numbers from cursor keys,
+          which is annoying, as cursor and keypad keys have
+          nothing to do with each other on, say, a vt200.
+          So we can only read 1, 3, 5, 7 and 9 from the keypad.  This
+          would be so silly that we choose not to provide keypad keys at all.
+       */
+        /* Catch the meta key on those plain old ASCII terminals where
+          it sets the high bit.  This only works in
+          unix_plain_ascii mode: otherwise these character codes
+          would have been interpreted according to ISO-Latin-1
+          earlier. */
+       case MOD_META | 'p': return ZC_HKEY_PLAYBACK;
+       case MOD_META | 'r': return ZC_HKEY_RECORD;
+       case MOD_META | 's': return ZC_HKEY_SEED;
+       case MOD_META | 'u': return ZC_HKEY_UNDO;
+       case MOD_META | 'n': return ZC_HKEY_RESTART;
+       case MOD_META | 'x': return ZC_HKEY_QUIT;
+       case MOD_META | 'd': return ZC_HKEY_DEBUG;
+       case MOD_META | 'h': return ZC_HKEY_HELP;
#ifdef EMACS_EDITING
-        case 21: return 27; /* Ctrl-U, erase line */
-        case 2: return 131; /* Ctrl-B, left arrow  */
-        case 6: return 132; /* Ctrl-F, right arrow */
-        case 16: return 129; /* Ctrl-P, up arrow */
-        case 14: return 130; /* Ctrl-N, down arrow */
-        case 1: c = KEY_HOME; break; /* Ctrl-A */
-        case 4: c = 127; break; /* Ctrl-D */
-        case 5: c = KEY_END; break; /* Ctrl-E */
+       case 21: return ZC_ESCAPE; /* Ctrl-U, erase line */
+       case 2: return ZC_ARROW_LEFT; /* Ctrl-B */
+       case 6: return ZC_ARROW_RIGHT; /* Ctrl-F */
+       case 16: return ZC_ARROW_UP; /* Ctrl-P */
+       case 14: return ZC_ARROW_DOWN; /* Ctrl-N */
+       case 1: c = KEY_HOME; break; /* Ctrl-A */
+       case 4: c = CHR_DEL; break; /* Ctrl-D */
+       case 5: c = KEY_END; break; /* Ctrl-E */
#endif
       default: break; /* Who knows? */
-      }
+       }

-      /* Finally, if we're in full line mode (os_read_line), we might return
-         codes which aren't legal Z-machine keys but are used by the editor. */
-      if (flag) return c;
+       /* Finally, if we're in full line mode (os_read_line), we
+          might return codes which aren't legal Z-machine keys but
+          are used by the editor. */
+       if (extkeys) return c;
    }
}

@@ -164,65 +217,67 @@
/*
 * unix_add_to_history
 *
- * Add the given string to the next available history buffer slot.  Commandeer
- * that slot if necessary using realloc.
+ * Add the given string to the next available history buffer slot.
 *
 */

static void unix_add_to_history(zchar *str)
{

-    if (history_buffer[history_pointer] == NULL)
-      history_buffer[history_pointer] = (char *) malloc(strlen(str) + 1);
-    else
-      history_buffer[history_pointer] =
-        (char *) realloc(history_buffer[history_pointer], strlen(str) + 1);
-    strcpy(history_buffer[history_pointer], str);
-    history_pointer = ((history_pointer + 1) % MAX_HISTORY);
-    history_frame = history_pointer; /* Reset user frame after each line */
+    if (*history_next != NULL)
+       free( *history_next);
+    *history_next = (char *)malloc(strlen(str) + 1);
+    strcpy( *history_next, str);
+    RING_INC( history_next, history_buffer, history_end);
+    history_view = history_next; /* Reset user frame after each line */
}

/*
 * unix_history_back
 *
 * Copy last available string to str, if possible.  Return 1 if successful.
- *
+ * Only lines of at most maxlen characters will be considered.  In addition
+ * the first searchlen characters of the history entry must match those of str.
 */
-
-static int unix_history_back(zchar *str)
+static int unix_history_back(zchar *str, int searchlen, int maxlen)
{
+    char **prev = history_view;

-    history_frame--; if (history_frame==-1) history_frame = (MAX_HISTORY - 1);
-    if ((history_frame == history_pointer) ||
-        (history_buffer[history_frame] == NULL)) {
-        beep(); history_frame = (history_frame + 1) % MAX_HISTORY;
-        return 0;
-    }
-    strcpy(str, history_buffer[history_frame]);
+    do {
+       RING_DEC( history_view, history_buffer, history_end);
+       if ((history_view == history_next)
+           || (*history_view == NULL)) {
+           beep();
+           history_view = prev;
+           return 0;
+       }
+    } while (strlen( *history_view) > maxlen
+            || (searchlen != 0 && strncmp( str, *history_view, searchlen)));
+    strcpy(str + searchlen, *history_view + searchlen);
    return 1;
-
}

/*
 * unix_history_forward
 *
 * Opposite of unix_history_back, and works in the same way.
- *
 */
-
-static int unix_history_forward(zchar *str)
+static int unix_history_forward(zchar *str, int searchlen, int maxlen)
{
+    char **prev = history_view;

-    history_frame = (history_frame + 1) % MAX_HISTORY;
-    if ((history_frame == history_pointer) ||
-        (history_buffer[history_frame] == NULL)) {
-        beep(); history_frame--; if (history_frame == -1) history_frame =
-                                                            (MAX_HISTORY - 1);
-        return 0;
-    }
-    strcpy(str, history_buffer[history_frame]);
+    do {
+       RING_INC( history_view, history_buffer, history_end);
+       if ((history_view == history_next)
+           || (*history_view == NULL)) {
+           beep();
+           history_view = prev;
+           return 0;
+       }
+    } while (strlen( *history_view) > maxlen
+            || (searchlen != 0 && strncmp( str, *history_view, searchlen)));
+    strcpy(str + searchlen, *history_view + searchlen);
    return 1;
-
}

/*
@@ -253,7 +308,7 @@
 *     ZC_HKEY_HELP (Alt-H)
 *
 * If the timeout argument is not zero, the input gets interrupted
- * after timeout/10 seconds (and the return value is 0).
+ * after timeout/10 seconds (and the return value is ZC_TIME_OUT).
 *
 * The complete input line including the cursor must fit in "width"
 * screen units.
@@ -273,145 +328,161 @@

zchar os_read_line (int max, zchar *buf, int timeout, int width, int continued)
{
-    int ch, scrpos, pos, y, x;
-    char insert_flag = 1;  /* Insert mode is now default */
-
-    scrpos = pos = strlen((char *) buf);
-
-    if (!continued)
-      history_frame = history_pointer;  /* Reset user's history view */
-
-    unix_set_global_timeout(timeout);
+    int ch, y, x, len = strlen( (char *)buf);
+    /* These are static to allow input continuation to work smoothly. */
+    static int scrpos = 0, searchpos = -1, insert_flag = 1;

    getyx(stdscr, y, x);
+    if (width < max) max = width;
+    /* Better be careful here or it might segv.  I wonder if we should just
+       ignore 'continued' and check for len > 0 instead?  Might work better
+       with Beyond Zork. */
+    if (continued && scrpos <= len && searchpos <= len) {
+       x += scrpos - len;
+       move( y, x);
+    } else {
+       scrpos = len;
+       history_view = history_next; /* Reset user's history view. */
+       searchpos = -1;         /* -1 means initialize from len. */
+       insert_flag = 1;        /* Insert mode is now default. */
+    }

-    do {
-        refresh(); /* Shouldn't be necessary, but is, to print spaces */
-
-        ch = unix_read_char(1);
-
-       /* Backspace */
-        if ((ch == 8) && (scrpos)) {
-            mvdelch(y, --x);
-            pos--; scrpos--;
-            if (scrpos != pos)
-              memmove(&(buf[scrpos]), &(buf[scrpos+1]), pos-scrpos);
-        }
-
-       /* Delete */
-       if (((ch == 127) || (ch == KEY_DC)) && (scrpos < pos)) {
-           delch(); pos--;
-           memmove(&(buf[scrpos]), &(buf[scrpos+1]), pos-scrpos);
-       }
-
-        /* Left key */
-        if ((ch == 131) && (scrpos)) {
-            scrpos--;
-            move(y, --x);
-        }
-        /* Right key */
-        if ((ch == 132) && (scrpos < pos)) {
-            scrpos++;
-            move(y, ++x);
-        }
-
-        /* Home */
-        if (ch == KEY_HOME) {
-            x -= scrpos; scrpos = 0;
+    unix_set_global_timeout(timeout);
+    for (;;) {
+        switch (ch = unix_read_char(1)) {
+       case ZC_BACKSPACE:
+           if (scrpos > 0) {
+               mvdelch(y, --x);
+               len--; scrpos--; searchpos = -1;
+               if (scrpos != len)
+                   memmove(&(buf[scrpos]), &(buf[scrpos+1]), len-scrpos);
+           }
+           break;
+       case CHR_DEL:
+       case KEY_DC:            /* Delete Character */
+           if (scrpos < len) {
+               delch();
+               len--; searchpos = -1;
+               memmove(&(buf[scrpos]), &(buf[scrpos+1]), len-scrpos);
+           }
+           continue;           /* Don't feed is_terminator bad zchars. */
+       case ZC_ARROW_LEFT:
+           if (scrpos > 0) {
+               scrpos--;
+               move(y, --x);
+           }
+           continue;
+        case ZC_ARROW_RIGHT:
+           if (scrpos < len) {
+               scrpos++;
+               move(y, ++x);
+           }
+           continue;
+       case KEY_HOME:
+            x -= scrpos;
+           scrpos = 0;
            move(y, x);
-        }
-        /* End */
-        if (ch == KEY_END) {
-            x += (pos - scrpos); scrpos = pos;
+           continue;
+        case KEY_END:
+            x += (len - scrpos); scrpos = len;
            move(y,x);
-        }
-
-        /* Insert */
-        if (ch == KEY_IC)
-          insert_flag = (insert_flag ? 0 : 1);
-
-        /* Up and down keys */
-        if (ch == 129) {
-            if (unix_history_back(buf)) {
-              x -= scrpos;
-              move(y, x);
-              while (scrpos) {addch(' '); scrpos--;}
-              move(y, x);
-              addstr(buf);
-              scrpos = pos = strlen(buf);
-              x += scrpos;
+           continue;
+       case KEY_IC:            /* Insert Character */
+           insert_flag = !insert_flag;
+           continue;
+       case ZC_ARROW_UP:
+           if (searchpos < 0)
+               searchpos = len;
+            if (unix_history_back(buf, searchpos, max)) {
+               x -= scrpos;
+               move(y, x);
+               clrtoeol();
+               addstr(buf);
+               x += scrpos = len = strlen(buf);
            }
-        }
-        if (ch == 130) {
-            if (unix_history_forward(buf)) {
-              x -= scrpos;
-              move(y, x);
-              while(scrpos) {addch(' '); scrpos--;}
-              move(y, x);
-              addstr(buf);
-              scrpos = pos = strlen(buf);
-              x += scrpos;
+           continue;
+        case ZC_ARROW_DOWN:
+           if (searchpos < 0)
+               searchpos = len;
+            if (unix_history_forward(buf, searchpos, max)) {
+               x -= scrpos;
+               move(y, x);
+               clrtoeol();
+               addstr(buf);
+               x += scrpos = len = strlen(buf);
            }
-        }
-
-       /* Page up/down (passthrough as up/down arrows for beyond zork) */
-        if (ch == KEY_PPAGE) ch = 129;
-        if (ch == KEY_NPAGE) ch = 130;
-
-        /* Escape */
-        if (ch == 27) {
-           /* Move cursor to end of buffer first */
-            x += (pos - scrpos); scrpos = pos; move(y,x);
+           continue;
+       /* Passthrough as up/down arrows for Beyond Zork. */
+       case KEY_PPAGE: ch = ZC_ARROW_UP; break;
+       case KEY_NPAGE: ch = ZC_ARROW_DOWN; break;
+       case ZC_ESCAPE:
            x -= scrpos;
            move(y, x);
-            while (scrpos) {addch(' '); scrpos--;}
-            move(y, x); pos = 0;
-        }
-
-       /* Tab */
-       if ((ch == 9) && (scrpos == pos)) {
-           int status;
-           zchar extension[10];
-
-           status = completion(buf, extension);
-           if (status != 2) {
-             addstr(extension);
-             strcpy(&buf[pos], extension);
-             pos += strlen(extension); scrpos += strlen(extension);
+           clrtoeol();
+           scrpos = len = 0;
+           searchpos = -1;
+           history_view = history_next;
+           break;
+       case '\t':
+           /* This really should be fixed to work also in the middle of a
+              sentence. */
+           if (scrpos == len) {
+               int status;
+               zchar extension[10];
+
+               buf[len] = '\0';
+               status = completion( buf, extension);
+               if (status != 2) {
+                   strncpy( &buf[len], extension, max - len);
+                   len += strlen( extension);
+                   if (len > max) {len = max; status = 1;}
+                   addnstr( extension, len - scrpos);
+                   x += len - scrpos;
+                   scrpos = len;
+                   searchpos = -1;
+               }
+               if (status) beep();
+           }
+           continue;           /* TAB is invalid as an input character. */
+       default:
+           /* ASCII or ISO-Latin-1 */
+           if ((ch >= ZC_ASCII_MIN && ch <= ZC_ASCII_MAX)
+               || (!unix_plain_ascii
+                   && ch >= ZC_LATIN1_MIN && ch <= ZC_LATIN1_MAX)) {
+               if (len == scrpos)
+                   /* Append to end of buffer */
+                   if (len < max) {
+                       buf[len++] = (char) ch;
+                       addch(ch);
+                       scrpos++; x++;
+                   } else
+                       beep();
+               else
+                   /* Insert/overwrite in middle of buffer */
+                   if (insert_flag) {
+                       memmove(&buf[scrpos+1], &buf[scrpos], len-scrpos);
+                       buf[scrpos++] = (char) ch;
+                       insch(ch);
+                       len++; x++; move(y, x);
+                   } else {
+                       buf[scrpos++] = (char) ch;
+                       addch(ch);
+                       x++;
+                   }
+               searchpos = -1;
           }
-           if (status) beep();
-       }
-
-        /* ASCII printable */
-        if ((ch >= 32) && (ch <= 126)) {
-            if (pos == scrpos) {
-                /* Append to end of buffer */
-                if ((pos < max) && (pos < width)) {
-                    buf[pos++] = (char) ch;
-                    addch(ch);
-                    scrpos++; x++;
-                } else beep();
-            }
-            else {
-                /* Insert/overwrite in middle of buffer */
-                if (insert_flag) {
-                    memmove(&buf[scrpos+1], &buf[scrpos], pos-scrpos);
-                    buf[scrpos++] = (char) ch;
-                    insch(ch);
-                    pos++; x++; move(y, x);
-                } else {
-                    buf[scrpos++] = (char) ch;
-                    addch(ch);
-                    x++;
-                }
-            }
        }
-    } while (!is_terminator(ch));
-
-    buf[pos] = '\0';
-    if (ch == 13) unix_add_to_history(buf);
-    return ch;
-
+       if (is_terminator(ch)) {
+           buf[len] = '\0';
+           if (ch == ZC_RETURN)
+               unix_add_to_history(buf);
+           /* Games don't know about line editing and might get
+              confused if the cursor is not at the end of the input
+              line. */
+           move( y, x + len - scrpos);
+           return ch;
+       }
+    }
}/* os_read_line */

/*
@@ -487,3 +558,9 @@
    return 1;

} /* os_read_file_name */
+
+/*
+ * Local Variables:
+ * c-basic-offset: 4
+ * End:
+ */
--- frotz-2.32/ux_text.c.orig   Sat Oct  4 04:12:10 1997
+++ frotz-2.32/ux_text.c        Sat Apr 24 12:45:17 1999
@@ -111,26 +111,21 @@
 *
 */

-#ifdef COLOR_SUPPORT
-static int colorspace[10][10];
-static int count = 0;
-#endif
-
void os_set_colour (int new_foreground, int new_background)
{
#ifdef COLOR_SUPPORT
-    int saved_style;
+    static int colorspace[10][10];
+    static int n_colors = 0;

-    saved_style = current_text_style;
    if (new_foreground == 1) new_foreground = h_default_foreground;
    if (new_background == 1) new_background = h_default_background;
    if (!colorspace[new_foreground][new_background]) {
-      init_pair(++count, unix_convert(new_foreground), unix_convert(new_background));
-      colorspace[new_foreground][new_background] = count;
+      init_pair(++n_colors, unix_convert(new_foreground),
+               unix_convert(new_background));
+      colorspace[new_foreground][new_background] = n_colors;
    }
    current_color = COLOR_PAIR(colorspace[new_foreground][new_background]);
-    os_set_text_style(saved_style);
-
+    bkgdset( current_color | ' ');
#endif
}/* os_set_colour */

@@ -154,12 +149,7 @@
    if (new_style & REVERSE_STYLE) temp |= A_REVERSE;
    if (new_style & BOLDFACE_STYLE) temp |= A_BOLD;
    if (new_style & EMPHASIS_STYLE) temp |= A_UNDERLINE;
-#ifdef COLOR_SUPPORT
-    attrset(temp | current_color);
-#else
    attrset(temp);
-#endif
-
}/* os_set_text_style */

/*
@@ -211,7 +201,7 @@
         addch(c);
       return;
    }
-    if (c >= 32 && c <= 126) {
+    if (c >= ZC_ASCII_MIN && c <= ZC_ASCII_MAX) {
        addch(c);
       return;
    }