(check_frame_size): Fix minimum height calculation.
[bpt/emacs.git] / src / term.c
index ae82907..6326d4b 100644 (file)
@@ -1,6 +1,6 @@
-/* terminal control module for terminals described by TERMCAP
-   Copyright (C) 1985, 86, 87, 93, 94, 95, 98
-     Free Software Foundation, Inc.
+/* Terminal control module for terminals described by TERMCAP
+   Copyright (C) 1985, 86, 87, 93, 94, 95, 98, 2000, 2001
+   Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -19,42 +19,52 @@ along with GNU Emacs; see the file COPYING.  If not, write to
 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
-/* New redisplay, TTY faces by Gerd Moellmann <gerd@acm.org>.  */
-
+/* New redisplay, TTY faces by Gerd Moellmann <gerd@gnu.org>.  */
 
 #include <config.h>
 #include <stdio.h>
 #include <ctype.h>
 #include <string.h>
+
 #include "termchar.h"
 #include "termopts.h"
 #include "lisp.h"
 #include "charset.h"
 #include "coding.h"
+#include "keyboard.h"
 #include "frame.h"
 #include "disptab.h"
 #include "termhooks.h"
-#include "keyboard.h"
 #include "dispextern.h"
 #include "window.h"
+#include "keymap.h"
 
-#ifdef HAVE_TERMCAP_H
+/* For now, don't try to include termcap.h.  On some systems,
+   configure finds a non-standard termcap.h that the main build
+   won't find.  */
+
+#if defined HAVE_TERMCAP_H && 0
 #include <termcap.h>
+#else
+extern void tputs P_ ((const char *, int, int (*)(int)));
+extern int tgetent P_ ((char *, const char *));
+extern int tgetflag P_ ((char *id));
+extern int tgetnum P_ ((char *id));
 #endif
 
 #include "cm.h"
 #ifdef HAVE_X_WINDOWS
 #include "xterm.h"
 #endif
+#ifdef macintosh
+#include "macterm.h"
+#endif
 
 static void turn_on_face P_ ((struct frame *, int face_id));
 static void turn_off_face P_ ((struct frame *, int face_id));
 static void tty_show_cursor P_ ((void));
 static void tty_hide_cursor P_ ((void));
 
-#define max(a, b) ((a) > (b) ? (a) : (b))
-#define min(a, b) ((a) < (b) ? (a) : (b))
-
 #define OUTPUT(a) \
      tputs (a, (int) (FRAME_HEIGHT (XFRAME (selected_frame)) - curY), cmputc)
 #define OUTPUT1(a) tputs (a, 1, cmputc)
@@ -108,9 +118,6 @@ void (*clear_end_of_line_hook) P_ ((int));
 
 void (*ins_del_lines_hook) P_ ((int, int));
 
-void (*change_line_highlight_hook) P_ ((int, int, int, int));
-void (*reassert_line_highlight_hook) P_ ((int, int));
-
 void (*delete_glyphs_hook) P_ ((int));
 
 void (*ring_bell_hook) P_ ((void));
@@ -146,6 +153,7 @@ void (*frame_up_to_date_hook) P_ ((struct frame *));
 
    This should clear mouse_moved until the next motion
    event arrives.  */
+
 void (*mouse_position_hook) P_ ((FRAME_PTR *f, int insist,
                                 Lisp_Object *bar_window,
                                 enum scroll_bar_part *part,
@@ -158,6 +166,7 @@ void (*mouse_position_hook) P_ ((FRAME_PTR *f, int insist,
    frame; under X, this means it lies about where the focus is.
    This hook tells the window system code to re-decide where to put
    the highlight.  */
+
 void (*frame_rehighlight_hook) P_ ((FRAME_PTR f));
 
 /* If we're displaying frames using a window system that can stack
@@ -170,6 +179,7 @@ void (*frame_rehighlight_hook) P_ ((FRAME_PTR f));
    If RAISE is non-zero, F is brought to the front, before all other
    windows.  If RAISE is zero, F is sent to the back, behind all other
    windows.  */
+
 void (*frame_raise_lower_hook) P_ ((FRAME_PTR f, int raise));
 
 /* Set the vertical scroll bar for WINDOW to have its upper left corner
@@ -203,10 +213,12 @@ void (*set_vertical_scroll_bar_hook)
    If non-zero, this hook should be safe to apply to any frame,
    whether or not it can support scroll bars, and whether or not it is
    currently displaying them.  */
+
 void (*condemn_scroll_bars_hook) P_ ((FRAME_PTR frame));
 
 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
    Note that it's okay to redeem a scroll bar that is not condemned.  */
+
 void (*redeem_scroll_bar_hook) P_ ((struct window *window));
 
 /* Remove all scroll bars on FRAME that haven't been saved since the
@@ -220,6 +232,7 @@ void (*redeem_scroll_bar_hook) P_ ((struct window *window));
    If non-zero, this hook should be safe to apply to any frame,
    whether or not it can support scroll bars, and whether or not it is
    currently displaying them.  */
+
 void (*judge_scroll_bars_hook) P_ ((FRAME_PTR FRAME));
 
 /* Hook to call in estimate_mode_line_height, if any.  */
@@ -268,6 +281,27 @@ char *TS_cursor_invisible; /* "vi" */
 char *TS_set_window;           /* "wi" (4 params, start and end of window,
                                   each as vpos and hpos) */
 
+/* Value of the "NC" (no_color_video) capability, or 0 if not
+   present.  */
+
+static int TN_no_color_video;
+
+/* Meaning of bits in no_color_video.  Each bit set means that the
+   corresponding attribute cannot be combined with colors.  */
+
+enum no_color_bit
+{
+  NC_STANDOUT   = 1 << 0,
+  NC_UNDERLINE  = 1 << 1,
+  NC_REVERSE    = 1 << 2,
+  NC_BLINK      = 1 << 3,
+  NC_DIM        = 1 << 4,
+  NC_BOLD       = 1 << 5,
+  NC_INVIS      = 1 << 6,
+  NC_PROTECT    = 1 << 7,
+  NC_ALT_CHARSET = 1 << 8
+};
+
 /* "md" -- turn on bold (extra bright mode).  */
 
 char *TS_enter_bold_mode;
@@ -288,10 +322,6 @@ char *TS_enter_reverse_mode;
 
 char *TS_exit_underline_mode, *TS_enter_underline_mode;
 
-/* "ug" -- number of blanks left by underline.  */
-
-int TN_magic_cookie_glitch_ul;
-
 /* "as"/"ae" -- start/end alternate character set.  Not really
    supported, yet.  */
 
@@ -327,13 +357,6 @@ int TF_underscore; /* termcap ul flag: _ underlines if over-struck on
 int TF_teleray;                /* termcap xt flag: many weird consequences.
                           For t1061. */
 
-int TF_xs;             /* Nonzero for "xs".  If set together with
-                          TN_standout_width == 0, it means don't bother
-                          to write any end-standout cookies.  */
-
-int TN_standout_width; /* termcap sg number: width occupied by standout
-                          markers */
-
 static int RPov;       /* # chars to start a TS_repeat */
 
 static int delete_in_insert_mode;      /* delete mode == insert mode */
@@ -351,18 +374,7 @@ int max_frame_width;
 
 int max_frame_height;
 
-/* Number of chars of space used for standout marker at beginning of line,
-   or'd with 0100.  Zero if no standout marker at all.
-   The length of these vectors is max_frame_height.
-
-   Used IFF TN_standout_width >= 0. */
-
-static char *chars_wasted;
-static char *copybuf;
-
-/* nonzero means supposed to write text in standout mode.  */
-
-int standout_requested;
+int costs_set = 0;             /* Nonzero if costs have been calculated. */
 
 int insert_mode;                       /* Nonzero when in insert mode.  */
 int standout_mode;                     /* Nonzero when in standout mode.  */
@@ -385,13 +397,16 @@ FRAME_PTR updating_frame;
 
 static int system_uses_terminfo;
 
+/* Flag used in tty_show/hide_cursor.  */
+
+static int tty_cursor_hidden;
+
 char *tparam ();
 
 extern char *tgetstr ();
 \f
 
 #ifdef WINDOWSNT
-
 /* We aren't X windows, but we aren't termcap either.  This makes me
    uncertain as to what value to use for frame.output_method.  For
    this file, we'll define FRAME_TERMCAP_P to be zero so that our
@@ -405,7 +420,7 @@ extern char *tgetstr ();
 void
 ring_bell ()
 {
-  if (! NILP (Vring_bell_function))
+  if (!NILP (Vring_bell_function))
     {
       Lisp_Object function;
 
@@ -416,105 +431,90 @@ ring_bell ()
         We don't specbind it, because that would carefully
         restore the bad value if there's an error
         and make the loop of errors happen anyway.  */
+      
       function = Vring_bell_function;
       Vring_bell_function = Qnil;
 
       call0 (function);
 
       Vring_bell_function = function;
-      return;
-    }
-
-  if (! FRAME_TERMCAP_P (XFRAME (selected_frame)))
-    {
-      (*ring_bell_hook) ();
-      return;
     }
-  OUTPUT (TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell);
+  else if (!FRAME_TERMCAP_P (XFRAME (selected_frame)))
+    (*ring_bell_hook) ();
+  else
+    OUTPUT (TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell);
 }
 
 void
 set_terminal_modes ()
 {
-  if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
+  if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
     {
-      (*set_terminal_modes_hook) ();
-      return;
+      OUTPUT_IF (TS_termcap_modes);
+      OUTPUT_IF (TS_cursor_visible);
+      OUTPUT_IF (TS_keypad_mode);
+      losecursor ();
     }
-  OUTPUT_IF (TS_termcap_modes);
-  OUTPUT_IF (TS_cursor_visible);
-  OUTPUT_IF (TS_keypad_mode);
-  losecursor ();
+  else
+    (*set_terminal_modes_hook) ();
 }
 
 void
 reset_terminal_modes ()
 {
-  if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
+  if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
     {
-      if (reset_terminal_modes_hook)
-       (*reset_terminal_modes_hook) ();
-      return;
-    }
-  if (TN_standout_width < 0)
-    turn_off_highlight ();
-  turn_off_insert ();
-  OUTPUT_IF (TS_end_keypad_mode);
-  OUTPUT_IF (TS_cursor_normal);
-  OUTPUT_IF (TS_end_termcap_modes);
-  OUTPUT_IF (TS_orig_pair);
-  /* Output raw CR so kernel can track the cursor hpos.  */
-  /* But on magic-cookie terminals this can erase an end-standout marker and
-     cause the rest of the frame to be in standout, so move down first.  */
-  if (TN_standout_width >= 0)
-    cmputc ('\n');
-  cmputc ('\r');
+      turn_off_highlight ();
+      turn_off_insert ();
+      OUTPUT_IF (TS_end_keypad_mode);
+      OUTPUT_IF (TS_cursor_normal);
+      OUTPUT_IF (TS_end_termcap_modes);
+      OUTPUT_IF (TS_orig_pair);
+      /* Output raw CR so kernel can track the cursor hpos.  */
+      cmputc ('\r');
+    }
+  else if (reset_terminal_modes_hook)
+    (*reset_terminal_modes_hook) ();
 }
 
 void
 update_begin (f)
-     FRAME_PTR f;
+     struct frame *f;
 {
   updating_frame = f;
-  if (! FRAME_TERMCAP_P (updating_frame))
-    (*update_begin_hook) (f);
-  else
-    tty_hide_cursor ();
+  if (!FRAME_TERMCAP_P (f))
+    update_begin_hook (f);
 }
 
 void
 update_end (f)
-     FRAME_PTR f;
+     struct frame *f;
 {
-  if (! FRAME_TERMCAP_P (updating_frame))
+  if (FRAME_TERMCAP_P (f))
     {
-      (*update_end_hook) (f);
-      updating_frame = 0;
-      return;
+      if (!XWINDOW (selected_window)->cursor_off_p)
+       tty_show_cursor ();
+      turn_off_insert ();
+      background_highlight ();
     }
-
-  if (!XWINDOW (selected_window)->cursor_off_p)
-    tty_show_cursor ();
+  else
+    update_end_hook (f);
   
-  turn_off_insert ();
-  background_highlight ();
-  standout_requested = 0;
-  updating_frame = 0;
+  updating_frame = NULL;
 }
 
 void
 set_terminal_window (size)
      int size;
 {
-  if (FRAME_TERMCAP_P (updating_frame))
+  if (FRAME_TERMCAP_P (updating_frame))
     {
-      (*set_terminal_window_hook) (size);
-      return;
+      specified_window = size ? size : FRAME_HEIGHT (updating_frame);
+      if (scroll_region_ok)
+       set_scroll_region (0, specified_window);
     }
-  specified_window = size ? size : FRAME_HEIGHT (XFRAME (selected_frame));
-  if (!scroll_region_ok)
-    return;
-  set_scroll_region (0, specified_window);
+  else
+    set_terminal_window_hook (size);
 }
 
 void
@@ -525,26 +525,22 @@ set_scroll_region (start, stop)
   struct frame *sf = XFRAME (selected_frame);
   
   if (TS_set_scroll_region)
-    {
-      buf = tparam (TS_set_scroll_region, 0, 0, start, stop - 1);
-    }
+    buf = tparam (TS_set_scroll_region, 0, 0, start, stop - 1);
   else if (TS_set_scroll_region_1)
-    {
-      buf = tparam (TS_set_scroll_region_1, 0, 0,
-                   FRAME_HEIGHT (sf), start,
-                   FRAME_HEIGHT (sf) - stop,
-                   FRAME_HEIGHT (sf));
-    }
+    buf = tparam (TS_set_scroll_region_1, 0, 0,
+                 FRAME_HEIGHT (sf), start,
+                 FRAME_HEIGHT (sf) - stop,
+                 FRAME_HEIGHT (sf));
   else
-    {
-      buf = tparam (TS_set_window, 0, 0, start, 0, stop, FRAME_WIDTH (sf));
-    }
+    buf = tparam (TS_set_window, 0, 0, start, 0, stop, FRAME_WIDTH (sf));
+  
   OUTPUT (buf);
   xfree (buf);
   losecursor ();
 }
+
 \f
-void
+static void
 turn_on_insert ()
 {
   if (!insert_mode)
@@ -560,33 +556,31 @@ turn_off_insert ()
   insert_mode = 0;
 }
 \f
-/* Handle highlighting when TN_standout_width (termcap sg) is not specified.
-   In these terminals, output is affected by the value of standout
-   mode when the output is written.
-
-   These functions are called on all terminals, but do nothing
-   on terminals whose standout mode does not work that way.  */
+/* Handle highlighting.  */
 
 void
 turn_off_highlight ()
 {
-  if (TN_standout_width < 0)
-    {
-      if (standout_mode)
-       OUTPUT_IF (TS_end_standout_mode);
-      standout_mode = 0;
-    }
+  if (standout_mode)
+    OUTPUT_IF (TS_end_standout_mode);
+  standout_mode = 0;
 }
 
-void
+static void
 turn_on_highlight ()
 {
-  if (TN_standout_width < 0)
-    {
-      if (!standout_mode)
-       OUTPUT_IF (TS_standout_mode);
-      standout_mode = 1;
-    }
+  if (!standout_mode)
+    OUTPUT_IF (TS_standout_mode);
+  standout_mode = 1;
+}
+
+static void
+toggle_highlight ()
+{
+  if (standout_mode)
+    turn_off_highlight ();
+  else
+    turn_on_highlight ();
 }
 
 
@@ -595,7 +589,11 @@ turn_on_highlight ()
 static void
 tty_hide_cursor ()
 {
-  OUTPUT_IF (TS_cursor_invisible);
+  if (tty_cursor_hidden == 0)
+    {
+      tty_cursor_hidden = 1;
+      OUTPUT_IF (TS_cursor_invisible);
+    }
 }
 
 
@@ -604,8 +602,12 @@ tty_hide_cursor ()
 static void
 tty_show_cursor ()
 {
-  OUTPUT_IF (TS_cursor_normal);
-  OUTPUT_IF (TS_cursor_visible);
+  if (tty_cursor_hidden)
+    {
+      tty_cursor_hidden = 0;
+      OUTPUT_IF (TS_cursor_normal);
+      OUTPUT_IF (TS_cursor_visible);
+    }
 }
 
 
@@ -616,8 +618,6 @@ tty_show_cursor ()
 void
 background_highlight ()
 {
-  if (TN_standout_width >= 0)
-    return;
   if (inverse_video)
     turn_on_highlight ();
   else
@@ -629,98 +629,10 @@ background_highlight ()
 static void
 highlight_if_desired ()
 {
-  if (TN_standout_width >= 0)
-    return;
-  if (!inverse_video == !standout_requested)
-    turn_off_highlight ();
-  else
+  if (inverse_video)
     turn_on_highlight ();
-}
-\f
-/* Handle standout mode for terminals in which TN_standout_width >= 0.
-   On these terminals, standout is controlled by markers that
-   live inside the terminal's memory.  TN_standout_width is the width
-   that the marker occupies in memory.  Standout runs from the marker
-   to the end of the line on some terminals, or to the next
-   turn-off-standout marker (TS_end_standout_mode) string
-   on other terminals.  */
-
-/* Write a standout marker or end-standout marker at the front of the line
-   at vertical position vpos.  */
-
-void
-write_standout_marker (flag, vpos)
-     int flag, vpos;
-{
-  if (flag || (TS_end_standout_mode && !TF_teleray && !se_is_so
-              && !(TF_xs && TN_standout_width == 0)))
-    {
-      cmgoto (vpos, 0);
-      cmplus (TN_standout_width);
-      OUTPUT (flag ? TS_standout_mode : TS_end_standout_mode);
-      chars_wasted[curY] = TN_standout_width | 0100;
-    }
-}
-\f
-/* External interface to control of standout mode.
-   Call this when about to modify line at position VPOS
-   and not change whether it is highlighted.  */
-
-void
-reassert_line_highlight (highlight, vpos)
-     int highlight;
-     int vpos;
-{
-  struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
-  if (! FRAME_TERMCAP_P (f))
-    {
-      (*reassert_line_highlight_hook) (highlight, vpos);
-      return;
-    }
-  if (TN_standout_width < 0)
-    /* Handle terminals where standout takes affect at output time */
-    standout_requested = highlight;
-  else if (chars_wasted && chars_wasted[vpos] == 0)
-    /* For terminals with standout markers, write one on this line
-       if there isn't one already.  */
-    write_standout_marker (highlight, vpos);
-}
-
-/* Call this when about to modify line at position VPOS
-   and change whether it is highlighted.  */
-
-void
-change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
-     int new_highlight, vpos, y, first_unused_hpos;
-{
-  standout_requested = new_highlight;
-  if (! FRAME_TERMCAP_P (updating_frame))
-    {
-      (*change_line_highlight_hook) (new_highlight, vpos, y, first_unused_hpos);
-      return;
-    }
-
-  cursor_to (vpos, 0);
-
-  if (TN_standout_width < 0)
-    background_highlight ();
-  /* If line starts with a marker, delete the marker */
-  else if (TS_clr_line && chars_wasted[curY])
-    {
-      turn_off_insert ();
-      /* On Teleray, make sure to erase the SO marker.  */
-      if (TF_teleray)
-       {
-         cmgoto (curY - 1, FRAME_WIDTH (XFRAME (selected_frame)) - 4);
-         OUTPUT ("\033S");
-         curY++;               /* ESC S moves to next line where the TS_standout_mode was */
-         curX = 0;
-       }
-      else
-       cmgoto (curY, 0);       /* reposition to kill standout marker */
-    }
-  clear_end_of_line_raw (first_unused_hpos);
-  reassert_line_highlight (new_highlight, curY);
+  else
+    turn_off_highlight ();
 }
 \f
 
@@ -741,10 +653,9 @@ cursor_to (vpos, hpos)
 
   /* Detect the case where we are called from reset_sys_modes
      and the costs have never been calculated.  Do nothing.  */
-  if (chars_wasted == 0)
+  if (! costs_set)
     return;
 
-  hpos += chars_wasted[vpos] & 077;
   if (curY == vpos && curX == hpos)
     return;
   if (!TF_standout_motion)
@@ -792,15 +703,13 @@ clear_to_end ()
     {
       background_highlight ();
       OUTPUT (TS_clr_to_bottom);
-      bzero (chars_wasted + curY,
-            FRAME_HEIGHT (XFRAME (selected_frame)) - curY);
     }
   else
     {
       for (i = curY; i < FRAME_HEIGHT (XFRAME (selected_frame)); i++)
        {
          cursor_to (i, 0);
-         clear_end_of_line_raw (FRAME_WIDTH (XFRAME (selected_frame)));
+         clear_end_of_line (FRAME_WIDTH (XFRAME (selected_frame)));
        }
     }
 }
@@ -822,7 +731,6 @@ clear_frame ()
     {
       background_highlight ();
       OUTPUT (TS_clr_frame);
-      bzero (chars_wasted, FRAME_HEIGHT (sf));
       cmat (0, 0);
     }
   else
@@ -832,32 +740,13 @@ clear_frame ()
     }
 }
 
-/* Clear to end of line, but do not clear any standout marker.
-   Assumes that the cursor is positioned at a character of real text,
-   which implies it cannot be before a standout marker
-   unless the marker has zero width.
-
-   Note that the cursor may be moved.  */
-
-void
-clear_end_of_line (first_unused_hpos)
-     int first_unused_hpos;
-{
-  if (FRAME_TERMCAP_P (XFRAME (selected_frame))
-      && chars_wasted != 0
-      && TN_standout_width == 0 && curX == 0 && chars_wasted[curY] != 0)
-    write_glyphs (&space_glyph, 1);
-  clear_end_of_line_raw (first_unused_hpos);
-}
-
 /* Clear from cursor to end of line.
    Assume that the line is already clear starting at column first_unused_hpos.
-   If the cursor is at a standout marker, erase the marker.
 
    Note that the cursor may be moved, on terminals lacking a `ce' string.  */
 
 void
-clear_end_of_line_raw (first_unused_hpos)
+clear_end_of_line (first_unused_hpos)
      int first_unused_hpos;
 {
   register int i;
@@ -873,15 +762,11 @@ clear_end_of_line_raw (first_unused_hpos)
 
   /* Detect the case where we are called from reset_sys_modes
      and the costs have never been calculated.  Do nothing.  */
-  if (chars_wasted == 0)
+  if (! costs_set)
     return;
 
-  first_unused_hpos += chars_wasted[curY] & 077;
   if (curX >= first_unused_hpos)
     return;
-  /* Notice if we are erasing a magic cookie */
-  if (curX == 0)
-    chars_wasted[curY] = 0;
   background_highlight ();
   if (TS_clr_line)
     {
@@ -925,7 +810,6 @@ encode_terminal_code (src, dst, src_len, dst_len, consumed)
   struct glyph *src_start = src, *src_end = src + src_len;
   unsigned char *dst_start = dst, *dst_end = dst + dst_len;
   register GLYPH g;
-  unsigned int c;
   unsigned char workbuf[MAX_MULTIBYTE_LENGTH], *buf;
   int len;
   register int tlen = GLYPH_TABLE_LENGTH;
@@ -933,7 +817,10 @@ encode_terminal_code (src, dst, src_len, dst_len, consumed)
   int result;
   struct coding_system *coding;
 
-  coding = (CODING_REQUIRE_ENCODING (&terminal_coding)
+  /* If terminal_coding does any conversion, use it, otherwise use
+     safe_terminal_coding.  We can't use CODING_REQUIRE_ENCODING here
+     because it always return 1 if the member src_multibyte is 1.  */
+  coding = (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK
            ? &terminal_coding
            : &safe_terminal_coding);
 
@@ -951,11 +838,13 @@ encode_terminal_code (src, dst, src_len, dst_len, consumed)
                {
                  len = 1;
                  buf = " ";
+                 coding->src_multibyte = 0;
                }
              else
                {
                  len = CHAR_STRING (src->u.ch, workbuf);
                  buf = workbuf;
+                 coding->src_multibyte = 1;
                }
            }
          else
@@ -972,12 +861,14 @@ encode_terminal_code (src, dst, src_len, dst_len, consumed)
                  workbuf[0] = FAST_GLYPH_CHAR (g);
                  len = 1;
                  buf = workbuf;
+                 coding->src_multibyte = 0;
                }
              else
                {
                  /* We have a string in Vglyph_table.  */
                  len = GLYPH_LENGTH (tbase, g);
                  buf = GLYPH_STRING (tbase, g);
+                 coding->src_multibyte = STRING_MULTIBYTE (tbase[g]);
                }
            }
          
@@ -1017,6 +908,8 @@ write_glyphs (string, len)
   int produced, consumed;
   struct frame *sf = XFRAME (selected_frame);
   struct frame *f = updating_frame ? updating_frame : sf;
+  unsigned char conversion_buffer[1024];
+  int conversion_buffer_size = sizeof conversion_buffer;
 
   if (write_glyphs_hook
       && ! FRAME_TERMCAP_P (f))
@@ -1025,15 +918,15 @@ write_glyphs (string, len)
       return;
     }
 
-  highlight_if_desired ();
   turn_off_insert ();
+  tty_hide_cursor ();
 
   /* Don't dare write in last column of bottom line, if Auto-Wrap,
      since that would scroll the whole frame on some terminals.  */
 
   if (AutoWrap
       && curY + 1 == FRAME_HEIGHT (sf)
-      && (curX + len - (chars_wasted[curY] & 077) == FRAME_WIDTH (sf)))
+      && (curX + len) == FRAME_WIDTH (sf))
     len --;
   if (len <= 0)
     return;
@@ -1055,13 +948,14 @@ write_glyphs (string, len)
          break;
 
       /* Turn appearance modes of the face of the run on.  */
+      highlight_if_desired ();
       turn_on_face (f, face_id);
 
       while (n > 0)
        {
-         /* We use a shared conversion buffer of the current size
-            (1024 bytes at least).  Usually it is sufficient, but if
-            not, we just repeat the loop.  */
+         /* We use a fixed size (1024 bytes) of conversion buffer.
+            Usually it is sufficient, but if not, we just repeat the
+            loop.  */
          produced = encode_terminal_code (string, conversion_buffer,
                                           n, conversion_buffer_size,
                                           &consumed);
@@ -1080,6 +974,7 @@ write_glyphs (string, len)
 
       /* Turn appearance modes off.  */
       turn_off_face (f, face_id);
+      turn_off_highlight ();
     }
   
   /* We may have to output some codes to terminate the writing.  */
@@ -1110,7 +1005,7 @@ insert_glyphs (start, len)
      register int len;
 {
   char *buf;
-  struct glyph *glyph;
+  struct glyph *glyph = NULL;
   struct frame *f, *sf;
 
   if (len <= 0)
@@ -1124,7 +1019,6 @@ insert_glyphs (start, len)
 
   sf = XFRAME (selected_frame);
   f = updating_frame ? updating_frame : sf;
-  highlight_if_desired ();
 
   if (TS_ins_multi_chars)
     {
@@ -1143,6 +1037,8 @@ insert_glyphs (start, len)
   while (len-- > 0)
     {
       int produced, consumed;
+      unsigned char conversion_buffer[1024];
+      int conversion_buffer_size = sizeof conversion_buffer;
 
       OUTPUT1_IF (TS_ins_char);
       if (!start)
@@ -1152,6 +1048,7 @@ insert_glyphs (start, len)
        }
       else
        {
+         highlight_if_desired ();
          turn_on_face (f, start->face_id);
          glyph = start;
          ++start;
@@ -1167,8 +1064,8 @@ insert_glyphs (start, len)
            /* This is the last glyph.  */
            terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
 
-         /* We use shared conversion buffer of the current size (1024
-            bytes at least).  It is surely sufficient for just one glyph.  */
+         /* The size of conversion buffer (1024 bytes) is surely
+            sufficient for just one glyph.  */
          produced = encode_terminal_code (glyph, conversion_buffer, 1,
                                           conversion_buffer_size, &consumed);
        }
@@ -1184,7 +1081,10 @@ insert_glyphs (start, len)
 
       OUTPUT1_IF (TS_pad_inserted_char);
       if (start)
-       turn_off_face (f, glyph->face_id);
+       {
+         turn_off_face (f, glyph->face_id);
+         turn_off_highlight ();
+       }
     }
   
   cmcheckmagic ();
@@ -1290,27 +1190,6 @@ ins_del_lines (vpos, n)
       set_scroll_region (0, specified_window);
     }
 
-  if (TN_standout_width >= 0)
-    {
-      register int lower_limit
-       = (scroll_region_ok
-          ? specified_window
-          : FRAME_HEIGHT (sf));
-
-      if (n < 0)
-       {
-         bcopy (&chars_wasted[vpos - n], &chars_wasted[vpos],
-                lower_limit - vpos + n);
-         bzero (&chars_wasted[lower_limit + n], - n);
-       }
-      else
-       {
-         bcopy (&chars_wasted[vpos], &copybuf[vpos], lower_limit - vpos - n);
-         bcopy (&copybuf[vpos], &chars_wasted[vpos + n],
-                lower_limit - vpos - n);
-         bzero (&chars_wasted[vpos], n);
-       }
-    }
   if (!scroll_region_ok && memory_below_frame && n < 0)
     {
       cursor_to (FRAME_HEIGHT (sf) + n, 0);
@@ -1448,23 +1327,12 @@ calculate_costs (frame)
      once for the terminal frame of X-windows emacs, but not used afterwards.
 
      char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
-     X turns off char_ins_del_ok.
-
-     chars_wasted and copybuf are only used here in term.c in cases where
-     the term hook isn't called. */
+     X turns off char_ins_del_ok. */
 
   max_frame_height = max (max_frame_height, FRAME_HEIGHT (frame));
   max_frame_width = max (max_frame_width, FRAME_WIDTH (frame));
 
-  if (chars_wasted != 0)
-    chars_wasted = (char *) xrealloc (chars_wasted, max_frame_height);
-  else
-    chars_wasted = (char *) xmalloc (max_frame_height);
-
-  if (copybuf != 0)
-    copybuf = (char *) xrealloc (copybuf, max_frame_height);
-  else
-    copybuf = (char *) xmalloc (max_frame_height);
+  costs_set = 1;
 
   if (char_ins_del_vector != 0)
     char_ins_del_vector
@@ -1476,8 +1344,6 @@ calculate_costs (frame)
       = (int *) xmalloc (sizeof (int)
                         + 2 * max_frame_width * sizeof (int));
 
-  bzero (chars_wasted, max_frame_height);
-  bzero (copybuf, max_frame_height);
   bzero (char_ins_del_vector, (sizeof (int)
                               + 2 * max_frame_width * sizeof (int)));
 
@@ -1516,79 +1382,79 @@ struct fkey_table {
 
 static struct fkey_table keys[] =
 {
-  "kh", "home",                /* termcap */
-  "kl", "left",                /* termcap */
-  "ku", "up",          /* termcap */
-  "kr", "right",       /* termcap */
-  "kd", "down",                /* termcap */
-  "%8", "prior",       /* terminfo */
-  "%5", "next",                /* terminfo */
-  "@7",        "end",          /* terminfo */
-  "@1", "begin",       /* terminfo */
-  "*6", "select",      /* terminfo */
-  "%9", "print",       /* terminfo */
-  "@4", "execute",     /* terminfo --- actually the `command' key */
+  {"kh", "home"},      /* termcap */
+  {"kl", "left"},      /* termcap */
+  {"ku", "up"},                /* termcap */
+  {"kr", "right"},     /* termcap */
+  {"kd", "down"},      /* termcap */
+  {"%8", "prior"},     /* terminfo */
+  {"%5", "next"},      /* terminfo */
+  {"@7", "end"},       /* terminfo */
+  {"@1", "begin"},     /* terminfo */
+  {"*6", "select"},    /* terminfo */
+  {"%9", "print"},     /* terminfo */
+  {"@4", "execute"},   /* terminfo --- actually the `command' key */
   /*
    * "insert" --- see below
    */
-  "&8",        "undo",         /* terminfo */
-  "%0",        "redo",         /* terminfo */
-  "%7",        "menu",         /* terminfo --- actually the `options' key */
-  "@0",        "find",         /* terminfo */
-  "@2",        "cancel",       /* terminfo */
-  "%1", "help",                /* terminfo */
+  {"&8", "undo"},      /* terminfo */
+  {"%0", "redo"},      /* terminfo */
+  {"%7", "menu"},      /* terminfo --- actually the `options' key */
+  {"@0", "find"},      /* terminfo */
+  {"@2", "cancel"},    /* terminfo */
+  {"%1", "help"},      /* terminfo */
   /*
    * "break" goes here, but can't be reliably intercepted with termcap
    */
-  "&4", "reset",       /* terminfo --- actually `restart' */
+  {"&4", "reset"},     /* terminfo --- actually `restart' */
   /*
    * "system" and "user" --- no termcaps
    */
-  "kE", "clearline",   /* terminfo */
-  "kA", "insertline",  /* terminfo */
-  "kL", "deleteline",  /* terminfo */
-  "kI", "insertchar",  /* terminfo */
-  "kD", "deletechar",  /* terminfo */
-  "kB", "backtab",     /* terminfo */
+  {"kE", "clearline"}, /* terminfo */
+  {"kA", "insertline"},        /* terminfo */
+  {"kL", "deleteline"},        /* terminfo */
+  {"kI", "insertchar"},        /* terminfo */
+  {"kD", "deletechar"},        /* terminfo */
+  {"kB", "backtab"},   /* terminfo */
   /*
    * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
    */
-  "@8", "kp-enter",    /* terminfo */
+  {"@8", "kp-enter"},  /* terminfo */
   /*
    * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
    * "kp-multiply", "kp-add", "kp-separator",
    * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
    * --- no termcaps for any of these.
    */
-  "K4", "kp-1",                /* terminfo */
+  {"K4", "kp-1"},      /* terminfo */
   /*
    * "kp-2" --- no termcap
    */
-  "K5", "kp-3",                /* terminfo */
+  {"K5", "kp-3"},      /* terminfo */
   /*
    * "kp-4" --- no termcap
    */
-  "K2", "kp-5",                /* terminfo */
+  {"K2", "kp-5"},      /* terminfo */
   /*
    * "kp-6" --- no termcap
    */
-  "K1", "kp-7",                /* terminfo */
+  {"K1", "kp-7"},      /* terminfo */
   /*
    * "kp-8" --- no termcap
    */
-  "K3", "kp-9",                /* terminfo */
+  {"K3", "kp-9"},      /* terminfo */
   /*
    * "kp-equal" --- no termcap
    */
-  "k1",        "f1",
-  "k2",        "f2",
-  "k3",        "f3",
-  "k4",        "f4",
-  "k5",        "f5",
-  "k6",        "f6",
-  "k7",        "f7",
-  "k8",        "f8",
-  "k9",        "f9",
+  {"k1", "f1"},
+  {"k2", "f2"},
+  {"k3", "f3"},
+  {"k4", "f4"},
+  {"k5", "f5"},
+  {"k6", "f6"},
+  {"k7", "f7"},
+  {"k8", "f8"},
+  {"k9", "f9"}
   };
 
 static char **term_get_fkeys_arg;
@@ -1800,7 +1666,7 @@ produce_glyphs (it)
     it->pixel_width = it->nglyphs = 0;
   else if (it->c == '\t')
     {
-      int absolute_x = (it->current_x - it->prompt_width
+      int absolute_x = (it->current_x
                        + it->continuation_lines_width);
       int next_tab_x 
        = (((1 + absolute_x + it->tab_width - 1) 
@@ -1831,6 +1697,17 @@ produce_glyphs (it)
       it->pixel_width = nspaces;
       it->nglyphs = nspaces;
     }
+  else if (SINGLE_BYTE_CHAR_P (it->c))
+    {
+      /* Coming here means that it->c is from display table, thus we
+        must send the code as is to the terminal.  Although there's
+        no way to know how many columns it occupies on a screen, it
+        is a good assumption that a single byte code has 1-column
+        width.  */
+      it->pixel_width = it->nglyphs = 1;
+      if (it->glyph_row)
+       append_glyph (it);
+    }
   else
     {
       /* A multi-byte character.  The display width is fixed for all
@@ -1872,7 +1749,7 @@ produce_special_glyphs (it, what)
   temp_it.dp = NULL;
   temp_it.what = IT_CHARACTER;
   temp_it.len = 1;
-  temp_it.object = 0;
+  temp_it.object = make_number (0);
   bzero (&temp_it.current, sizeof temp_it.current);
 
   if (what == IT_CONTINUATION)
@@ -1883,7 +1760,7 @@ produce_special_glyphs (it, what)
          && GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (it->dp))))
        {
          temp_it.c = FAST_GLYPH_CHAR (XINT (DISP_CONTINUE_GLYPH (it->dp)));
-         temp_it.len = CHAR_LEN (temp_it.c);
+         temp_it.len = CHAR_BYTES (temp_it.c);
        }
       else
        temp_it.c = '\\';
@@ -1900,7 +1777,7 @@ produce_special_glyphs (it, what)
          && GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (it->dp))))
        {
          temp_it.c = FAST_GLYPH_CHAR (XINT (DISP_TRUNC_GLYPH (it->dp)));
-         temp_it.len = CHAR_LEN (temp_it.c);
+         temp_it.len = CHAR_BYTES (temp_it.c);
        }
       else
        temp_it.c = '$';
@@ -1934,6 +1811,15 @@ estimate_mode_line_height (f, face_id)
                                Faces
  ***********************************************************************/
 
+/* Value is non-zero if attribute ATTR may be used.  ATTR should be
+   one of the enumerators from enum no_color_bit, or a bit set built
+   from them.  Some display attributes may not be used together with
+   color; the termcap capability `NC' specifies which ones.  */
+
+#define MAY_USE_WITH_COLORS_P(ATTR)            \
+     (TN_max_colors > 0                                \
+      ? (TN_no_color_video & (ATTR)) == 0      \
+      : 1)
 
 /* Turn appearances of face FACE_ID on tty frame F on.  */
 
@@ -1943,51 +1829,90 @@ turn_on_face (f, face_id)
      int face_id;
 {
   struct face *face = FACE_FROM_ID (f, face_id);
+  long fg = face->foreground;
+  long bg = face->background;
 
-  xassert (face != NULL);
+  /* Do this first because TS_end_standout_mode may be the same
+     as TS_exit_attribute_mode, which turns all appearances off. */
+  if (MAY_USE_WITH_COLORS_P (NC_REVERSE))
+    {
+      if (TN_max_colors > 0)
+       {
+         if (fg >= 0 && bg >= 0)
+           {
+             /* If the terminal supports colors, we can set them
+                below without using reverse video.  The face's fg
+                and bg colors are set as they should appear on
+                the screen, i.e. they take the inverse-video'ness
+                of the face already into account.  */
+           }
+         else if (inverse_video)
+           {
+             if (fg == FACE_TTY_DEFAULT_FG_COLOR
+                 || bg == FACE_TTY_DEFAULT_BG_COLOR)
+               toggle_highlight ();
+           }
+         else
+           {
+             if (fg == FACE_TTY_DEFAULT_BG_COLOR
+                 || bg == FACE_TTY_DEFAULT_FG_COLOR)
+               toggle_highlight ();
+           }
+       }
+      else
+       {
+         /* If we can't display colors, use reverse video
+            if the face specifies that.  */
+         if (inverse_video)
+           {
+             if (fg == FACE_TTY_DEFAULT_FG_COLOR
+                 || bg == FACE_TTY_DEFAULT_BG_COLOR)
+               toggle_highlight ();
+           }
+         else
+           {
+             if (fg == FACE_TTY_DEFAULT_BG_COLOR
+                 || bg == FACE_TTY_DEFAULT_FG_COLOR)
+               toggle_highlight ();
+           }
+       }
+    }
 
   if (face->tty_bold_p)
-    OUTPUT1_IF (TS_enter_bold_mode);
+    {
+      if (MAY_USE_WITH_COLORS_P (NC_BOLD))
+       OUTPUT1_IF (TS_enter_bold_mode);
+    }
   else if (face->tty_dim_p)
-    OUTPUT1_IF (TS_enter_dim_mode);
+    if (MAY_USE_WITH_COLORS_P (NC_DIM))
+      OUTPUT1_IF (TS_enter_dim_mode);
 
   /* Alternate charset and blinking not yet used.  */
-  if (face->tty_alt_charset_p)
+  if (face->tty_alt_charset_p
+      && MAY_USE_WITH_COLORS_P (NC_ALT_CHARSET))
     OUTPUT1_IF (TS_enter_alt_charset_mode);
 
-  if (face->tty_blinking_p)
+  if (face->tty_blinking_p
+      && MAY_USE_WITH_COLORS_P (NC_BLINK))
     OUTPUT1_IF (TS_enter_blink_mode);
 
-  if (face->tty_underline_p
-      /* Don't underline if that's difficult.  */
-      && TN_magic_cookie_glitch_ul <= 0)
+  if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (NC_UNDERLINE))
     OUTPUT1_IF (TS_enter_underline_mode);
 
-  if (face->tty_reverse_p
-      || face->foreground == FACE_TTY_DEFAULT_BG_COLOR
-      || face->background == FACE_TTY_DEFAULT_FG_COLOR)
-    OUTPUT1_IF (TS_enter_reverse_mode);
-
   if (TN_max_colors > 0)
     {
       char *p;
       
-      if (face->foreground != FACE_TTY_DEFAULT_COLOR
-         && face->foreground != FACE_TTY_DEFAULT_FG_COLOR
-         && face->foreground != FACE_TTY_DEFAULT_BG_COLOR
-         && TS_set_foreground)
+      if (fg >= 0 && TS_set_foreground)
        {
-         p = tparam (TS_set_foreground, NULL, 0, (int) face->foreground);
+         p = tparam (TS_set_foreground, NULL, 0, (int) fg);
          OUTPUT (p);
          xfree (p);
        }
 
-      if (face->background != FACE_TTY_DEFAULT_COLOR
-         && face->background != FACE_TTY_DEFAULT_BG_COLOR
-         && face->background != FACE_TTY_DEFAULT_FG_COLOR
-         && TS_set_background)
+      if (bg >= 0 && TS_set_background)
        {
-         p = tparam (TS_set_background, NULL, 0, (int) face->background);
+         p = tparam (TS_set_background, NULL, 0, (int) bg);
          OUTPUT (p);
          xfree (p);
        }
@@ -2017,7 +1942,11 @@ turn_off_face (f, face_id)
          || face->tty_alt_charset_p
          || face->tty_blinking_p
          || face->tty_underline_p)
-       OUTPUT1_IF (TS_exit_attribute_mode);
+       {
+         OUTPUT1_IF (TS_exit_attribute_mode);
+         if (strcmp (TS_exit_attribute_mode, TS_end_standout_mode) == 0)
+           standout_mode = 0;
+       }
 
       if (face->tty_alt_charset_p)
        OUTPUT_IF (TS_exit_alt_charset_mode);
@@ -2029,9 +1958,7 @@ turn_off_face (f, face_id)
       if (face->tty_alt_charset_p)
        OUTPUT_IF (TS_exit_alt_charset_mode);
 
-      if (face->tty_underline_p
-         /* We don't underline if that's difficult.  */
-         && TN_magic_cookie_glitch_ul <= 0)
+      if (face->tty_underline_p)
        OUTPUT_IF (TS_exit_underline_mode);
     }
 
@@ -2049,14 +1976,145 @@ turn_off_face (f, face_id)
 
 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
        0, 1, 0,
-  "Return non-nil if TTY can display colors on FRAME.")
+       doc: /* Return non-nil if TTY can display colors on FRAME.  */)
      (frame)
      Lisp_Object frame;
 {
   return TN_max_colors > 0 ? Qt : Qnil;
 }
 
+#ifndef WINDOWSNT
+
+/* Save or restore the default color-related capabilities of this
+   terminal.  */
+static void
+tty_default_color_capabilities (save)
+     int save;
+{
+  static char
+    *default_orig_pair, *default_set_foreground, *default_set_background;
+  static int default_max_colors, default_max_pairs, default_no_color_video;
+
+  if (save)
+    {
+      if (default_orig_pair)
+       xfree (default_orig_pair);
+      default_orig_pair = TS_orig_pair ? xstrdup (TS_orig_pair) : NULL;
+
+      if (default_set_foreground)
+       xfree (default_set_foreground);
+      default_set_foreground = TS_set_foreground ? xstrdup (TS_set_foreground)
+                              : NULL;
+
+      if (default_set_background)
+       xfree (default_set_background);
+      default_set_background = TS_set_background ? xstrdup (TS_set_background)
+                              : NULL;
+
+      default_max_colors = TN_max_colors;
+      default_max_pairs = TN_max_pairs;
+      default_no_color_video = TN_no_color_video;
+    }
+  else
+    {
+      TS_orig_pair = default_orig_pair;
+      TS_set_foreground = default_set_foreground;
+      TS_set_background = default_set_background;
+      TN_max_colors = default_max_colors;
+      TN_max_pairs = default_max_pairs;
+      TN_no_color_video = default_no_color_video;
+    }
+}
+
+/* Setup one of the standard tty color schemes according to MODE.
+   MODE's value is generally the number of colors which we want to
+   support; zero means set up for the default capabilities, the ones
+   we saw at term_init time; -1 means turn off color support.  */
+void
+tty_setup_colors (mode)
+     int mode;
+{
+  switch (mode)
+    {
+      case -1:  /* no colors at all */
+       TN_max_colors = 0;
+       TN_max_pairs = 0;
+       TN_no_color_video = 0;
+       TS_set_foreground = TS_set_background = TS_orig_pair = NULL;
+       break;
+      case 0:   /* default colors, if any */
+      default:
+       tty_default_color_capabilities (0);
+       break;
+      case 8:  /* 8 standard ANSI colors */
+       TS_orig_pair = "\033[0m";
+#ifdef TERMINFO
+       TS_set_foreground = "\033[3%p1%dm";
+       TS_set_background = "\033[4%p1%dm";
+#else
+       TS_set_foreground = "\033[3%dm";
+       TS_set_background = "\033[4%dm";
+#endif
+       TN_max_colors = 8;
+       TN_max_pairs = 64;
+       TN_no_color_video = 0;
+       break;
+    }
+}
+
+void
+set_tty_color_mode (f, val)
+     struct frame *f;
+     Lisp_Object val;
+{
+  Lisp_Object color_mode_spec, current_mode_spec;
+  Lisp_Object color_mode, current_mode;
+  int mode, old_mode;
+  extern Lisp_Object Qtty_color_mode;
+  Lisp_Object tty_color_mode_alist;
+
+  tty_color_mode_alist = Fintern_soft (build_string ("tty-color-mode-alist"),
+                                      Qnil);
 
+  if (NATNUMP (val))
+    color_mode = val;
+  else
+    {
+      if (NILP (tty_color_mode_alist))
+       color_mode_spec = Qnil;
+      else
+       color_mode_spec = Fassq (val, XSYMBOL (tty_color_mode_alist)->value);
+      current_mode_spec = assq_no_quit (Qtty_color_mode, f->param_alist);
+
+      if (CONSP (color_mode_spec))
+       color_mode = XCDR (color_mode_spec);
+      else
+       color_mode = Qnil;
+    }
+  if (CONSP (current_mode_spec))
+    current_mode = XCDR (current_mode_spec);
+  else
+    current_mode = Qnil;
+  if (NATNUMP (color_mode))
+    mode = XINT (color_mode);
+  else
+    mode = 0;  /* meaning default */
+  if (NATNUMP (current_mode))
+    old_mode = XINT (current_mode);
+  else
+    old_mode = 0;
+
+  if (mode != old_mode)
+    {
+      tty_setup_colors (mode);
+      /*  This recomputes all the faces given the new color
+         definitions.  */
+      call0 (intern ("tty-set-up-initial-frame-faces"));
+      redraw_frame (f);
+    }
+}
+
+#endif /* !WINDOWSNT */
 
 \f
 /***********************************************************************
@@ -2154,7 +2212,7 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
   TS_clr_to_bottom = tgetstr ("cd", address);
   TS_clr_line = tgetstr ("ce", address);
   TS_clr_frame = tgetstr ("cl", address);
-  ColPosition = tgetstr ("ch", address);
+  ColPosition = NULL; /* tgetstr ("ch", address); */
   AbsPosition = tgetstr ("cm", address);
   CR = tgetstr ("cr", address);
   TS_set_scroll_region = tgetstr ("cs", address);
@@ -2209,7 +2267,6 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
   
   TS_enter_underline_mode = tgetstr ("us", address);
   TS_exit_underline_mode = tgetstr ("ue", address);
-  TN_magic_cookie_glitch_ul = tgetnum ("ug");
   TS_enter_bold_mode = tgetstr ("md", address);
   TS_enter_dim_mode = tgetstr ("mh", address);
   TS_enter_blink_mode = tgetstr ("mb", address);
@@ -2237,10 +2294,17 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
          TS_set_foreground = tgetstr ("Sf", address);
          TS_set_background = tgetstr ("Sb", address);
        }
+      
       TN_max_colors = tgetnum ("Co");
       TN_max_pairs = tgetnum ("pa");
+      
+      TN_no_color_video = tgetnum ("NC");
+      if (TN_no_color_video == -1)
+       TN_no_color_video = 0;
     }
 
+  tty_default_color_capabilities (1);
+
   MagicWrap = tgetflag ("xn");
   /* Since we make MagicWrap terminals look like AutoWrap, we need to have
      the former flag imply the latter.  */
@@ -2252,7 +2316,6 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
   TF_insmode_motion = tgetflag ("mi");
   TF_standout_motion = tgetflag ("ms");
   TF_underscore = tgetflag ("ul");
-  TF_xs = tgetflag ("xs");
   TF_teleray = tgetflag ("xt");
 
   term_get_fkeys (address);
@@ -2278,7 +2341,6 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
           FRAME_HEIGHT (sf), FRAME_WIDTH (sf));
 
   min_padding_speed = tgetnum ("pb");
-  TN_standout_width = tgetnum ("sg");
   TabWidth = tgetnum ("tw");
 
 #ifdef VMS
@@ -2307,11 +2369,24 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
     Wcm.cm_tab = "\t";
 */
 
+  /* We don't support standout modes that use `magic cookies', so
+     turn off any that do.  */
+  if (TS_standout_mode && tgetnum ("sg") >= 0)
+    {
+      TS_standout_mode = 0;
+      TS_end_standout_mode = 0;
+    }
+  if (TS_enter_underline_mode && tgetnum ("ug") >= 0)
+    {
+      TS_enter_underline_mode = 0;
+      TS_exit_underline_mode = 0;
+    }
+
+  /* If there's no standout mode, try to use underlining instead.  */
   if (TS_standout_mode == 0)
     {
-      TN_standout_width = tgetnum ("ug");
-      TS_end_standout_mode = tgetstr ("ue", address);
-      TS_standout_mode = tgetstr ("us", address);
+      TS_standout_mode = TS_enter_underline_mode;
+      TS_end_standout_mode = TS_exit_underline_mode;
     }
 
   /* If no `se' string, try using a `me' string instead.
@@ -2328,10 +2403,8 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
   if (TF_teleray)
     {
       Wcm.cm_tab = 0;
-      /* Teleray: most programs want a space in front of TS_standout_mode,
-          but Emacs can do without it (and give one extra column).  */
-      TS_standout_mode = "\033RD";
-      TN_standout_width = 1;
+      /* We can't support standout mode, because it uses magic cookies.  */
+      TS_standout_mode = 0;
       /* But that means we cannot rely on ^M to go to column zero! */
       CR = 0;
       /* LF can't be trusted either -- can alter hpos */
@@ -2431,10 +2504,6 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
              && TS_end_standout_mode
              && !strcmp (TS_standout_mode, TS_end_standout_mode));
 
-  /* Remove width of standout marker from usable width of line */
-  if (TN_standout_width > 0)
-    SET_FRAME_WIDTH (sf, FRAME_WIDTH (sf) - TN_standout_width);
-
   UseTabs = tabs_safe_p () && TabWidth == 8;
 
   scroll_region_ok
@@ -2477,8 +2546,8 @@ void
 syms_of_term ()
 {
   DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
-    "Non-nil means the system uses terminfo rather than termcap.\n\
-This variable can be used by terminal emulator packages.");
+    doc: /* Non-nil means the system uses terminfo rather than termcap.
+This variable can be used by terminal emulator packages.  */);
 #ifdef TERMINFO
   system_uses_terminfo = 1;
 #else
@@ -2486,8 +2555,8 @@ This variable can be used by terminal emulator packages.");
 #endif
 
   DEFVAR_LISP ("ring-bell-function", &Vring_bell_function,
-    "Non-nil means call this function to ring the bell.\n\
-The function should accept no arguments.");
+    doc: /* Non-nil means call this function to ring the bell.
+The function should accept no arguments.  */);
   Vring_bell_function = Qnil;
 
   defsubr (&Stty_display_color_p);