*** empty log message ***
[bpt/emacs.git] / src / term.c
index dc75820..317318e 100644 (file)
@@ -1,5 +1,5 @@
 /* Terminal control module for terminals described by TERMCAP
-   Copyright (C) 1985, 86, 87, 93, 94, 95, 98, 2000, 2001
+   Copyright (C) 1985, 86, 87, 93, 94, 95, 98, 2000, 2001, 2002
    Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -56,7 +56,7 @@ extern int tgetnum P_ ((char *id));
 #ifdef HAVE_X_WINDOWS
 #include "xterm.h"
 #endif
-#ifdef macintosh
+#ifdef MAC_OS
 #include "macterm.h"
 #endif
 
@@ -66,17 +66,17 @@ static void tty_show_cursor P_ ((void));
 static void tty_hide_cursor P_ ((void));
 
 #define OUTPUT(a) \
-     tputs (a, (int) (FRAME_HEIGHT (XFRAME (selected_frame)) - curY), cmputc)
+     tputs (a, (int) (FRAME_LINES (XFRAME (selected_frame)) - curY), cmputc)
 #define OUTPUT1(a) tputs (a, 1, cmputc)
 #define OUTPUTL(a, lines) tputs (a, lines, cmputc)
 
 #define OUTPUT_IF(a)                                                   \
      do {                                                              \
        if (a)                                                          \
-         tputs (a, (int) (FRAME_HEIGHT (XFRAME (selected_frame))       \
+         tputs (a, (int) (FRAME_LINES (XFRAME (selected_frame))        \
                          - curY), cmputc);                             \
      } while (0)
-     
+
 #define OUTPUT1_IF(a) do { if (a) tputs (a, 1, cmputc); } while (0)
 
 /* Function to use to ring the bell.  */
@@ -131,7 +131,7 @@ void (*insert_glyphs_hook) P_ ((struct glyph *, int));
 void (*write_glyphs_hook) P_ ((struct glyph *, int));
 void (*delete_glyphs_hook) P_ ((int));
 
-int (*read_socket_hook) P_ ((int, struct input_event *, int, int));
+int (*read_socket_hook) P_ ((int, int, struct input_event *));
 
 void (*frame_up_to_date_hook) P_ ((struct frame *));
 
@@ -203,7 +203,7 @@ void (*set_vertical_scroll_bar_hook)
 
 /* Arrange for all scroll bars on FRAME to be removed at the next call
    to `*judge_scroll_bars_hook'.  A scroll bar may be spared if
-   `*redeem_scroll_bar_hook' is applied to its window before the judgment. 
+   `*redeem_scroll_bar_hook' is applied to its window before the judgment.
 
    This should be applied to each frame each time its window tree is
    redisplayed, even if it is not displaying scroll bars at the moment;
@@ -222,7 +222,7 @@ void (*condemn_scroll_bars_hook) P_ ((FRAME_PTR frame));
 void (*redeem_scroll_bar_hook) P_ ((struct window *window));
 
 /* Remove all scroll bars on FRAME that haven't been saved since the
-   last call to `*condemn_scroll_bars_hook'.  
+   last call to `*condemn_scroll_bars_hook'.
 
    This should be applied to each frame after each time its window
    tree is redisplayed, even if it is not displaying scroll bars at the
@@ -235,11 +235,6 @@ void (*redeem_scroll_bar_hook) P_ ((struct window *window));
 
 void (*judge_scroll_bars_hook) P_ ((FRAME_PTR FRAME));
 
-/* Hook to call in estimate_mode_line_height, if any.  */
-
-int (* estimate_mode_line_height_hook) P_ ((struct frame *f, enum face_id));
-
-
 /* Strings, numbers and flags taken from the termcap entry.  */
 
 char *TS_ins_line;             /* "al" */
@@ -322,10 +317,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.  */
 
@@ -361,13 +352,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 */
@@ -379,13 +363,13 @@ static int se_is_so;      /* 1 if same string both enters and leaves
 
 /* The largest frame width in any call to calculate_costs.  */
 
-int max_frame_width;
+int max_frame_cols;
 
 /* The largest frame height in any call to calculate_costs.  */
 
-int max_frame_height;
+int max_frame_lines;
 
-int costs_set = 0;             /* Nonzero if costs have been calculated. */
+static int costs_set;    /* Nonzero if costs have been calculated. */
 
 int insert_mode;                       /* Nonzero when in insert mode.  */
 int standout_mode;                     /* Nonzero when in standout mode.  */
@@ -394,7 +378,7 @@ int standout_mode;                  /* Nonzero when in standout mode.  */
    This is the number of lines, from the top of frame downwards,
    which can participate in insert-line/delete-line operations.
 
-   Effectively it excludes the bottom frame_height - specified_window_size
+   Effectively it excludes the bottom frame_lines - specified_window_size
    lines from those operations.  */
 
 int specified_window;
@@ -442,7 +426,7 @@ 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;
 
@@ -475,19 +459,13 @@ reset_terminal_modes ()
 {
   if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
     {
-      if (TN_standout_width < 0)
-       turn_off_highlight ();
+      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');
     }
   else if (reset_terminal_modes_hook)
@@ -516,7 +494,7 @@ update_end (f)
     }
   else
     update_end_hook (f);
-  
+
   updating_frame = NULL;
 }
 
@@ -526,7 +504,7 @@ set_terminal_window (size)
 {
   if (FRAME_TERMCAP_P (updating_frame))
     {
-      specified_window = size ? size : FRAME_HEIGHT (updating_frame);
+      specified_window = size ? size : FRAME_LINES (updating_frame);
       if (scroll_region_ok)
        set_scroll_region (0, specified_window);
     }
@@ -540,17 +518,17 @@ set_scroll_region (start, stop)
 {
   char *buf;
   struct frame *sf = XFRAME (selected_frame);
-  
+
   if (TS_set_scroll_region)
     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));
+                 FRAME_LINES (sf), start,
+                 FRAME_LINES (sf) - stop,
+                 FRAME_LINES (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_COLS (sf));
+
   OUTPUT (buf);
   xfree (buf);
   losecursor ();
@@ -573,33 +551,22 @@ 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;
 }
 
 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
@@ -646,8 +613,6 @@ tty_show_cursor ()
 void
 background_highlight ()
 {
-  if (TN_standout_width >= 0)
-    return;
   if (inverse_video)
     turn_on_highlight ();
   else
@@ -659,8 +624,6 @@ background_highlight ()
 static void
 highlight_if_desired ()
 {
-  if (TN_standout_width >= 0)
-    return;
   if (inverse_video)
     turn_on_highlight ();
   else
@@ -676,7 +639,7 @@ cursor_to (vpos, hpos)
      int vpos, hpos;
 {
   struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
-  
+
   if (! FRAME_TERMCAP_P (f) && cursor_to_hook)
     {
       (*cursor_to_hook) (vpos, hpos);
@@ -738,10 +701,10 @@ clear_to_end ()
     }
   else
     {
-      for (i = curY; i < FRAME_HEIGHT (XFRAME (selected_frame)); i++)
+      for (i = curY; i < FRAME_LINES (XFRAME (selected_frame)); i++)
        {
          cursor_to (i, 0);
-         clear_end_of_line (FRAME_WIDTH (XFRAME (selected_frame)));
+         clear_end_of_line (FRAME_COLS (XFRAME (selected_frame)));
        }
     }
 }
@@ -752,7 +715,7 @@ void
 clear_frame ()
 {
   struct frame *sf = XFRAME (selected_frame);
-  
+
   if (clear_frame_hook
       && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : sf)))
     {
@@ -810,8 +773,8 @@ clear_end_of_line (first_unused_hpos)
       turn_off_insert ();
 
       /* Do not write in last row last col with Auto-wrap on. */
-      if (AutoWrap && curY == FRAME_HEIGHT (sf) - 1
-         && first_unused_hpos == FRAME_WIDTH (sf))
+      if (AutoWrap && curY == FRAME_LINES (sf) - 1
+         && first_unused_hpos == FRAME_COLS (sf))
        first_unused_hpos--;
 
       for (i = curX; i < first_unused_hpos; i++)
@@ -842,7 +805,8 @@ 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 char workbuf[MAX_MULTIBYTE_LENGTH], *buf;
+  unsigned char workbuf[MAX_MULTIBYTE_LENGTH];
+  const unsigned char *buf;
   int len;
   register int tlen = GLYPH_TABLE_LENGTH;
   register Lisp_Object *tbase = GLYPH_TABLE_BASE;
@@ -903,7 +867,7 @@ encode_terminal_code (src, dst, src_len, dst_len, consumed)
                  coding->src_multibyte = STRING_MULTIBYTE (tbase[g]);
                }
            }
-         
+
          result = encode_coding (coding, buf, dst, len, dst_end - dst);
          len -= coding->consumed;
          dst += coding->produced;
@@ -926,7 +890,7 @@ encode_terminal_code (src, dst, src_len, dst_len, consumed)
        }
       src++;
     }
-  
+
   *consumed = src - src_start;
   return (dst - dst_start);
 }
@@ -957,24 +921,24 @@ write_glyphs (string, len)
      since that would scroll the whole frame on some terminals.  */
 
   if (AutoWrap
-      && curY + 1 == FRAME_HEIGHT (sf)
-      && (curX + len) == FRAME_WIDTH (sf))
+      && curY + 1 == FRAME_LINES (sf)
+      && (curX + len) == FRAME_COLS (sf))
     len --;
   if (len <= 0)
     return;
 
   cmplus (len);
-  
+
   /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
      the tail.  */
   terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
-  
+
   while (len > 0)
     {
       /* Identify a run of glyphs with the same face.  */
       int face_id = string->face_id;
       int n;
-      
+
       for (n = 1; n < len; ++n)
        if (string[n].face_id != face_id)
          break;
@@ -1008,7 +972,7 @@ write_glyphs (string, len)
       turn_off_face (f, face_id);
       turn_off_highlight ();
     }
-  
+
   /* We may have to output some codes to terminate the writing.  */
   if (CODING_REQUIRE_FLUSHING (&terminal_coding))
     {
@@ -1025,12 +989,12 @@ write_glyphs (string, len)
                    termscript);
        }
     }
-  
+
   cmcheckmagic ();
 }
 
 /* If start is zero, insert blanks instead of a string at start */
+
 void
 insert_glyphs (start, len)
      register struct glyph *start;
@@ -1118,7 +1082,7 @@ insert_glyphs (start, len)
          turn_off_highlight ();
        }
     }
-  
+
   cmcheckmagic ();
 }
 
@@ -1179,7 +1143,7 @@ ins_del_lines (vpos, n)
     }
 
   sf = XFRAME (selected_frame);
-  
+
   /* If the lines below the insertion are being pushed
      into the end of the window, this is the same as clearing;
      and we know the lines are already clear, since the matching
@@ -1189,7 +1153,7 @@ ins_del_lines (vpos, n)
      as there will be a matching inslines later that will flush them. */
   if (scroll_region_ok && vpos + i >= specified_window)
     return;
-  if (!memory_below_frame && vpos + i >= FRAME_HEIGHT (sf))
+  if (!memory_below_frame && vpos + i >= FRAME_LINES (sf))
     return;
 
   if (multi)
@@ -1222,16 +1186,9 @@ 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 (!scroll_region_ok && memory_below_frame && n < 0)
     {
-      cursor_to (FRAME_HEIGHT (sf) + n, 0);
+      cursor_to (FRAME_LINES (sf) + n, 0);
       clear_to_end ();
     }
 }
@@ -1281,11 +1238,11 @@ per_line_cost (str)
 #ifndef old
 /* char_ins_del_cost[n] is cost of inserting N characters.
    char_ins_del_cost[-n] is cost of deleting N characters.
-   The length of this vector is based on max_frame_width.  */
+   The length of this vector is based on max_frame_cols.  */
 
 int *char_ins_del_vector;
 
-#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WIDTH ((f))])
+#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
 #endif
 
 /* ARGSUSED */
@@ -1338,7 +1295,7 @@ calculate_ins_del_char_costs (frame)
 
   /* Delete costs are at negative offsets */
   p = &char_ins_del_cost (frame)[0];
-  for (i = FRAME_WIDTH (frame); --i >= 0;)
+  for (i = FRAME_COLS (frame); --i >= 0;)
     *--p = (del_startup_cost += del_cost_per_char);
 
   /* Doing nothing is free */
@@ -1346,7 +1303,7 @@ calculate_ins_del_char_costs (frame)
   *p++ = 0;
 
   /* Insert costs are at positive offsets */
-  for (i = FRAME_WIDTH (frame); --i >= 0;)
+  for (i = FRAME_COLS (frame); --i >= 0;)
     *p++ = (ins_startup_cost += ins_cost_per_char);
 }
 
@@ -1368,8 +1325,8 @@ calculate_costs (frame)
      char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
      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));
+  max_frame_lines = max (max_frame_lines, FRAME_LINES (frame));
+  max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
 
   costs_set = 1;
 
@@ -1377,14 +1334,14 @@ calculate_costs (frame)
     char_ins_del_vector
       = (int *) xrealloc (char_ins_del_vector,
                          (sizeof (int)
-                          + 2 * max_frame_width * sizeof (int)));
+                          + 2 * max_frame_cols * sizeof (int)));
   else
     char_ins_del_vector
       = (int *) xmalloc (sizeof (int)
-                        + 2 * max_frame_width * sizeof (int));
+                        + 2 * max_frame_cols * sizeof (int));
 
   bzero (char_ins_del_vector, (sizeof (int)
-                              + 2 * max_frame_width * sizeof (int)));
+                              + 2 * max_frame_cols * sizeof (int)));
 
   if (f && (!TS_ins_line && !TS_del_line))
     do_line_insertion_deletion_costs (frame,
@@ -1403,7 +1360,7 @@ calculate_costs (frame)
   if (TS_repeat && per_line_cost (TS_repeat) * baud_rate < 9000)
     RPov = string_cost (TS_repeat);
   else
-    RPov = FRAME_WIDTH (frame) * 2;
+    RPov = FRAME_COLS (frame) * 2;
 
   cmcostinit ();               /* set up cursor motion costs */
 }
@@ -1421,86 +1378,86 @@ 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;
 static Lisp_Object term_get_fkeys_1 ();
 
 /* Find the escape codes sent by the function keys for Vfunction_key_map.
-   This function scans the termcap function key sequence entries, and 
+   This function scans the termcap function key sequence entries, and
    adds entries to Vfunction_key_map for each function key it finds.  */
 
 void
@@ -1552,12 +1509,15 @@ term_get_fkeys_1 ()
 
     if (k_semi)
       {
+       if (k0)
+         /* Define f0 first, so that f10 takes precedence in case the
+            key sequences happens to be the same.  */
+         Fdefine_key (Vfunction_key_map, build_string (k0),
+                      Fmake_vector (make_number (1), intern ("f0")));
        Fdefine_key (Vfunction_key_map, build_string (k_semi),
                     Fmake_vector (make_number (1), intern ("f10")));
-       k0_name = "f0";
       }
-
-    if (k0)
+    else if (k0)
       Fdefine_key (Vfunction_key_map, build_string (k0),
                   Fmake_vector (make_number (1), intern (k0_name)));
   }
@@ -1602,7 +1562,7 @@ term_get_fkeys_1 ()
                         Fmake_vector (make_number (1), \
                                       intern (sym)));  \
        }
-         
+
       /* if there's no key_next keycap, map key_npage to `next' keysym */
       CONDITIONAL_REASSIGN ("%5", "kN", "next");
       /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
@@ -1642,7 +1602,7 @@ static void append_glyph P_ ((struct it *));
    for which to produce glyphs; IT->face_id contains the character's
    face.  Padding glyphs are appended if IT->c has a IT->pixel_width >
    1.  */
-   
+
 static void
 append_glyph (it)
      struct it *it;
@@ -1655,8 +1615,8 @@ append_glyph (it)
           + it->glyph_row->used[it->area]);
   end = it->glyph_row->glyphs[1 + it->area];
 
-  for (i = 0; 
-       i < it->pixel_width && glyph < end; 
+  for (i = 0;
+       i < it->pixel_width && glyph < end;
        ++i)
     {
       glyph->type = CHAR_GLYPH;
@@ -1666,20 +1626,32 @@ append_glyph (it)
       glyph->padding_p = i > 0;
       glyph->charpos = CHARPOS (it->position);
       glyph->object = it->object;
-      
+
       ++it->glyph_row->used[it->area];
       ++glyph;
     }
 }
 
 
-/* Produce glyphs for the display element described by IT.  The
-   function fills output fields of IT with pixel information like the
-   pixel width and height of a character, and maybe produces glyphs at
+/* Produce glyphs for the display element described by IT.  *IT
+   specifies what we want to produce a glyph for (character, image, ...),
+   and where in the glyph matrix we currently are (glyph row and hpos).
+   produce_glyphs fills in output fields of *IT with information such as the
+   pixel width and height of a character, and maybe output actual glyphs at
    the same time if IT->glyph_row is non-null.  See the explanation of
-   struct display_iterator in dispextern.h for an overview.  */
+   struct display_iterator in dispextern.h for an overview.
+
+   produce_glyphs also stores the result of glyph width, ascent
+   etc. computations in *IT.
+
+   IT->glyph_row may be null, in which case produce_glyphs does not
+   actually fill in the glyphs.  This is used in the move_* functions
+   in xdisp.c for text width and height computations.
 
-void 
+   Callers usually don't call produce_glyphs directly;
+   instead they use the macro PRODUCE_GLYPHS.  */
+
+void
 produce_glyphs (it)
      struct it *it;
 {
@@ -1688,7 +1660,7 @@ produce_glyphs (it)
           || it->what == IT_COMPOSITION
           || it->what == IT_IMAGE
           || it->what == IT_STRETCH);
-  
+
   /* Nothing but characters are supported on terminal frames.  For a
      composition sequence, it->c is the first character of the
      sequence.  */
@@ -1707,8 +1679,8 @@ produce_glyphs (it)
     {
       int absolute_x = (it->current_x
                        + it->continuation_lines_width);
-      int next_tab_x 
-       = (((1 + absolute_x + it->tab_width - 1) 
+      int next_tab_x
+       = (((1 + absolute_x + it->tab_width - 1)
            / it->tab_width)
           * it->tab_width);
       int nspaces;
@@ -1719,17 +1691,17 @@ produce_glyphs (it)
         continued line.  So, we will get the right number of spaces
         here.  */
       nspaces = next_tab_x - absolute_x;
-      
+
       if (it->glyph_row)
        {
          int n = nspaces;
-         
+
          it->c = ' ';
          it->pixel_width = it->len = 1;
-         
+
          while (n--)
            append_glyph (it);
-         
+
          it->c = '\t';
        }
 
@@ -1757,12 +1729,12 @@ produce_glyphs (it)
 
       it->pixel_width = CHARSET_WIDTH (charset);
       it->nglyphs = it->pixel_width;
-      
+
       if (it->glyph_row)
        append_glyph (it);
     }
 
-  /* Advance current_x by the pixel width as a convenience for 
+  /* Advance current_x by the pixel width as a convenience for
      the caller.  */
   if (it->area == TEXT_AREA)
     it->current_x += it->pixel_width;
@@ -1783,7 +1755,7 @@ produce_special_glyphs (it, what)
      enum display_element_type what;
 {
   struct it temp_it;
-  
+
   temp_it = *it;
   temp_it.dp = NULL;
   temp_it.what = IT_CHARACTER;
@@ -1803,7 +1775,7 @@ produce_special_glyphs (it, what)
        }
       else
        temp_it.c = '\\';
-      
+
       produce_glyphs (&temp_it);
       it->pixel_width = temp_it.pixel_width;
       it->nglyphs = temp_it.pixel_width;
@@ -1820,7 +1792,7 @@ produce_special_glyphs (it, what)
        }
       else
        temp_it.c = '$';
-      
+
       produce_glyphs (&temp_it);
       it->pixel_width = temp_it.pixel_width;
       it->nglyphs = temp_it.pixel_width;
@@ -1830,21 +1802,6 @@ produce_special_glyphs (it, what)
 }
 
 
-/* Return an estimation of the pixel height of mode or top lines on
-   frame F.  FACE_ID specifies what line's height to estimate.  */
-
-int
-estimate_mode_line_height (f, face_id)
-     struct frame *f;
-     enum face_id face_id;
-{
-  if (estimate_mode_line_height_hook)
-    return estimate_mode_line_height_hook (f, face_id);
-  else
-    return 1;
-}
-
-
 \f
 /***********************************************************************
                                Faces
@@ -1935,16 +1892,13 @@ turn_on_face (f, face_id)
       && 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
-      && MAY_USE_WITH_COLORS_P (NC_UNDERLINE))
+  if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (NC_UNDERLINE))
     OUTPUT1_IF (TS_enter_underline_mode);
 
   if (TN_max_colors > 0)
     {
       char *p;
-      
+
       if (fg >= 0 && TS_set_foreground)
        {
          p = tparam (TS_set_foreground, NULL, 0, (int) fg);
@@ -1960,7 +1914,7 @@ turn_on_face (f, face_id)
        }
     }
 }
-  
+
 
 /* Turn off appearances of face FACE_ID on tty frame F.  */
 
@@ -2000,9 +1954,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);
     }
 
@@ -2014,20 +1966,193 @@ turn_off_face (f, face_id)
              && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
     OUTPUT1_IF (TS_orig_pair);
 }
-  
-    
+
+
+/* Return non-zero if the terminal on frame F supports all of the
+   capabilities in CAPS simultaneously, with foreground and background
+   colors FG and BG.  */
+
+int
+tty_capable_p (f, caps, fg, bg)
+     struct frame *f;
+     unsigned caps;
+     unsigned long fg, bg;
+{
+#define TTY_CAPABLE_P_TRY(cap, TS, NC_bit)                             \
+  if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(NC_bit)))     \
+    return 0;
+
+  TTY_CAPABLE_P_TRY (TTY_CAP_INVERSE,  TS_standout_mode,        NC_REVERSE);
+  TTY_CAPABLE_P_TRY (TTY_CAP_UNDERLINE, TS_enter_underline_mode, NC_UNDERLINE);
+  TTY_CAPABLE_P_TRY (TTY_CAP_BOLD,     TS_enter_bold_mode,      NC_BOLD);
+  TTY_CAPABLE_P_TRY (TTY_CAP_DIM,      TS_enter_dim_mode,       NC_DIM);
+  TTY_CAPABLE_P_TRY (TTY_CAP_BLINK,    TS_enter_blink_mode,     NC_BLINK);
+  TTY_CAPABLE_P_TRY (TTY_CAP_ALT_CHARSET, TS_enter_alt_charset_mode, NC_ALT_CHARSET);
+
+  /* We can do it!  */
+  return 1;
+}
+
+
 /* Return non-zero if the terminal is capable to display colors.  */
 
 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
        0, 1, 0,
-       doc: /* Return non-nil if TTY can display colors on FRAME.  */)
-     (frame)
-     Lisp_Object frame;
+       doc: /* Return non-nil if TTY can display colors on DISPLAY.  */)
+     (display)
+     Lisp_Object display;
 {
   return TN_max_colors > 0 ? Qt : Qnil;
 }
 
+/* Return the number of supported colors.  */
+DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
+       Stty_display_color_cells, 0, 1, 0,
+       doc: /* Return the number of colors supported by TTY on DISPLAY.  */)
+     (display)
+     Lisp_Object display;
+{
+  return make_number (TN_max_colors);
+}
+
+#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;
+{
+  /* Canonicalize all negative values of MODE.  */
+  if (mode < -1)
+    mode = -1;
+
+  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 (INTEGERP (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);
+
+      if (CONSP (color_mode_spec))
+       color_mode = XCDR (color_mode_spec);
+      else
+       color_mode = Qnil;
+    }
+
+  current_mode_spec = assq_no_quit (Qtty_color_mode, f->param_alist);
+
+  if (CONSP (current_mode_spec))
+    current_mode = XCDR (current_mode_spec);
+  else
+    current_mode = Qnil;
+  if (INTEGERP (color_mode))
+    mode = XINT (color_mode);
+  else
+    mode = 0;  /* meaning default */
+  if (INTEGERP (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
 /***********************************************************************
@@ -2040,7 +2165,8 @@ term_init (terminal_type)
 {
   char *area;
   char **address = &area;
-  char buffer[2044];
+  char *buffer = NULL;
+  int buffer_size = 4096;
   register char *p;
   int status;
   struct frame *sf = XFRAME (selected_frame);
@@ -2052,12 +2178,9 @@ term_init (terminal_type)
 
   area = (char *) xmalloc (2044);
 
-  if (area == 0)
-    abort ();
-
-  FrameRows = FRAME_HEIGHT (sf);
-  FrameCols = FRAME_WIDTH (sf);
-  specified_window = FRAME_HEIGHT (sf);
+  FrameRows = FRAME_LINES (sf);
+  FrameCols = FRAME_COLS (sf);
+  specified_window = FRAME_LINES (sf);
 
   delete_in_insert_mode = 1;
 
@@ -2083,6 +2206,7 @@ term_init (terminal_type)
 
   Wcm_clear ();
 
+  buffer = (char *) xmalloc (buffer_size);
   status = tgetent (buffer, terminal_type);
   if (status < 0)
     {
@@ -2110,13 +2234,13 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
             terminal_type);
 #endif
     }
-#ifdef TERMINFO
-  area = (char *) xmalloc (2044);
-#else
-  area = (char *) xmalloc (strlen (buffer));
-#endif /* not TERMINFO */
-  if (area == 0)
+
+#ifndef TERMINFO
+  if (strlen (buffer) >= buffer_size)
     abort ();
+  buffer_size = strlen (buffer);
+#endif
+  area = (char *) xmalloc (buffer_size);
 
   TS_ins_line = tgetstr ("al", address);
   TS_ins_multi_lines = tgetstr ("AL", address);
@@ -2177,10 +2301,9 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
   TS_cursor_visible = tgetstr ("vs", address);
   TS_cursor_invisible = tgetstr ("vi", address);
   TS_set_window = tgetstr ("wi", address);
-  
+
   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);
@@ -2188,7 +2311,7 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
   TS_enter_alt_charset_mode = tgetstr ("as", address);
   TS_exit_alt_charset_mode = tgetstr ("ae", address);
   TS_exit_attribute_mode = tgetstr ("me", address);
-  
+
   MultiUp = tgetstr ("UP", address);
   MultiDown = tgetstr ("DO", address);
   MultiLeft = tgetstr ("LE", address);
@@ -2208,15 +2331,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.  */
@@ -2228,7 +2353,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);
@@ -2237,24 +2361,23 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
   {
     int height, width;
     get_frame_size (&width, &height);
-    FRAME_WIDTH (sf) = width;
-    FRAME_HEIGHT (sf) = height;
+    FRAME_COLS (sf) = width;
+    FRAME_LINES (sf) = height;
   }
 
-  if (FRAME_WIDTH (sf) <= 0)
-    SET_FRAME_WIDTH (sf, tgetnum ("co"));
+  if (FRAME_COLS (sf) <= 0)
+    SET_FRAME_COLS (sf, tgetnum ("co"));
   else
     /* Keep width and external_width consistent */
-    SET_FRAME_WIDTH (sf, FRAME_WIDTH (sf));
-  if (FRAME_HEIGHT (sf) <= 0)
-    FRAME_HEIGHT (sf) = tgetnum ("li");
-  
-  if (FRAME_HEIGHT (sf) < 3 || FRAME_WIDTH (sf) < 3)
+    SET_FRAME_COLS (sf, FRAME_COLS (sf));
+  if (FRAME_LINES (sf) <= 0)
+    FRAME_LINES (sf) = tgetnum ("li");
+
+  if (FRAME_LINES (sf) < 3 || FRAME_COLS (sf) < 3)
     fatal ("Screen size %dx%d is too small",
-          FRAME_HEIGHT (sf), FRAME_WIDTH (sf));
+          FRAME_LINES (sf), FRAME_COLS (sf));
 
   min_padding_speed = tgetnum ("pb");
-  TN_standout_width = tgetnum ("sg");
   TabWidth = tgetnum ("tw");
 
 #ifdef VMS
@@ -2276,18 +2399,31 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
 
   if (TabWidth < 0)
     TabWidth = 8;
-  
+
 /* Turned off since /etc/termcap seems to have :ta= for most terminals
    and newer termcap doc does not seem to say there is a default.
   if (!Wcm.cm_tab)
     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.
@@ -2304,10 +2440,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 */
@@ -2364,9 +2498,9 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
        }
     }
 
-  FrameRows = FRAME_HEIGHT (sf);
-  FrameCols = FRAME_WIDTH (sf);
-  specified_window = FRAME_HEIGHT (sf);
+  FrameRows = FRAME_LINES (sf);
+  FrameCols = FRAME_COLS (sf);
+  specified_window = FRAME_LINES (sf);
 
   if (Wcm_init () == -1)       /* can't do cursor motion */
 #ifdef VMS
@@ -2395,8 +2529,8 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
           terminal_type);
 # endif /* TERMINFO */
 #endif /*VMS */
-  if (FRAME_HEIGHT (sf) <= 0
-      || FRAME_WIDTH (sf) <= 0)
+  if (FRAME_LINES (sf) <= 0
+      || FRAME_COLS (sf) <= 0)
     fatal ("The frame size has not been specified");
 
   delete_in_insert_mode
@@ -2407,10 +2541,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
@@ -2435,6 +2565,8 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
   FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0;
   FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none;
 #endif /* WINDOWSNT */
+
+  xfree (buffer);
 }
 
 /* VARARGS 1 */
@@ -2467,5 +2599,8 @@ The function should accept no arguments.  */);
   Vring_bell_function = Qnil;
 
   defsubr (&Stty_display_color_p);
+  defsubr (&Stty_display_color_cells);
 }
 
+/* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193
+   (do not change this comment) */