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	<tkorvola@iki.fi> <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;
     }
