]> code.delx.au - gnu-emacs/blobdiff - src/term.c
(Version, mh-version): Update for release 8.0.
[gnu-emacs] / src / term.c
index 3add820421e14c3f2142e72dda91eda3bad8dd22..603305c8f1736e80ac9c54dcd4615f7f30921814 100644 (file)
@@ -1,6 +1,6 @@
 /* Terminal control module for terminals described by TERMCAP
-   Copyright (C) 1985, 86, 87, 93, 94, 95, 98, 2000, 2001, 2002
-   Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1998, 2000, 2001,
+                 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -16,8 +16,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 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.  */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 /* New redisplay, TTY faces by Gerd Moellmann <gerd@gnu.org>.  */
 
@@ -66,23 +66,31 @@ 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)
 
+/* Display space properties */
+
+extern Lisp_Object Qspace, QCalign_to, QCwidth;
+
 /* Function to use to ring the bell.  */
 
 Lisp_Object Vring_bell_function;
 
+/* If true, use "vs", otherwise use "ve" to make the cursor visible.  */
+
+static int visible_cursor;
+
 /* Terminal characteristics that higher levels want to look at.
    These are all extern'd in termchar.h */
 
@@ -131,7 +139,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 +211,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 +230,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 +243,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" */
@@ -368,11 +371,11 @@ 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;
 
 static int costs_set;    /* Nonzero if costs have been calculated. */
 
@@ -383,7 +386,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;
@@ -431,7 +434,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;
 
@@ -450,8 +453,18 @@ set_terminal_modes ()
 {
   if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
     {
-      OUTPUT_IF (TS_termcap_modes);
-      OUTPUT_IF (TS_cursor_visible);
+      if (TS_termcap_modes)
+       OUTPUT (TS_termcap_modes);
+      else
+       {
+         /* Output enough newlines to scroll all the old screen contents
+            off the screen, so it won't be overwritten and lost.  */
+         int i;
+         for (i = 0; i < FRAME_LINES (XFRAME (selected_frame)); i++)
+           putchar ('\n');
+       }
+
+      OUTPUT_IF (visible_cursor ? TS_cursor_visible : TS_cursor_normal);
       OUTPUT_IF (TS_keypad_mode);
       losecursor ();
     }
@@ -499,7 +512,7 @@ update_end (f)
     }
   else
     update_end_hook (f);
-  
+
   updating_frame = NULL;
 }
 
@@ -509,7 +522,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);
     }
@@ -523,17 +536,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 ();
@@ -606,7 +619,8 @@ tty_show_cursor ()
     {
       tty_cursor_hidden = 0;
       OUTPUT_IF (TS_cursor_normal);
-      OUTPUT_IF (TS_cursor_visible);
+      if (visible_cursor)
+       OUTPUT_IF (TS_cursor_visible);
     }
 }
 
@@ -644,7 +658,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);
@@ -706,10 +720,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)));
        }
     }
 }
@@ -720,7 +734,7 @@ void
 clear_frame ()
 {
   struct frame *sf = XFRAME (selected_frame);
-  
+
   if (clear_frame_hook
       && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : sf)))
     {
@@ -778,8 +792,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++)
@@ -792,39 +806,43 @@ clear_end_of_line (first_unused_hpos)
     }
 }
 \f
-/* Encode SRC_LEN glyphs starting at SRC to terminal output codes and
-   store them at DST.  Do not write more than DST_LEN bytes.  That may
-   require stopping before all SRC_LEN input glyphs have been
-   converted.
+/* Buffer to store the source and result of code conversion for terminal.  */
+static unsigned char *encode_terminal_buf;
+/* Allocated size of the above buffer.  */
+static int encode_terminal_bufsize;
 
-   We store the number of glyphs actually converted in *CONSUMED.  The
-   return value is the number of bytes store in DST.  */
+/* Encode SRC_LEN glyphs starting at SRC to terminal output codes.
+   Set CODING->produced to the byte-length of the resulting byte
+   sequence, and return a pointer to that byte sequence.  */
 
-int
-encode_terminal_code (src, dst, src_len, dst_len, consumed)
+unsigned char *
+encode_terminal_code (src, src_len, coding)
      struct glyph *src;
      int src_len;
-     unsigned char *dst;
-     int dst_len, *consumed;
+     struct coding_system *coding;
 {
-  struct glyph *src_start = src, *src_end = src + src_len;
-  unsigned char *dst_start = dst, *dst_end = dst + dst_len;
+  struct glyph *src_end = src + src_len;
   register GLYPH g;
-  unsigned char workbuf[MAX_MULTIBYTE_LENGTH];
-  const unsigned char *buf;
-  int len;
+  unsigned char *buf;
+  int nchars, nbytes, required;
   register int tlen = GLYPH_TABLE_LENGTH;
   register Lisp_Object *tbase = GLYPH_TABLE_BASE;
-  int result;
-  struct coding_system *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);
+  /* Allocate sufficient size of buffer to store all characters in
+     multibyte-form.  But, it may be enlarged on demand if
+     Vglyph_table contains a string.  */
+  required = MAX_MULTIBYTE_LENGTH * src_len;
+  if (encode_terminal_bufsize < required)
+    {
+      if (encode_terminal_bufsize == 0)
+       encode_terminal_buf = xmalloc (required);
+      else
+       encode_terminal_buf = xrealloc (encode_terminal_buf, required);
+      encode_terminal_bufsize = required;
+    }
 
+  buf = encode_terminal_buf;
+  nchars = 0;
   while (src < src_end)
     {
       /* We must skip glyphs to be padded for a wide character.  */
@@ -835,18 +853,11 @@ encode_terminal_code (src, dst, src_len, dst_len, consumed)
          if (g < 0 || g >= tlen)
            {
              /* This glyph doesn't has an entry in Vglyph_table.  */
-             if (! CHAR_VALID_P (src->u.ch, 0))
-               {
-                 len = 1;
-                 buf = " ";
-                 coding->src_multibyte = 0;
-               }
+             if (CHAR_VALID_P (src->u.ch, 0))
+               buf += CHAR_STRING (src->u.ch, buf);
              else
-               {
-                 len = CHAR_STRING (src->u.ch, workbuf);
-                 buf = workbuf;
-                 coding->src_multibyte = 1;
-               }
+               *buf++ = SPACEGLYPH;
+             nchars++;
            }
          else
            {
@@ -856,61 +867,72 @@ encode_terminal_code (src, dst, src_len, dst_len, consumed)
 
              if (GLYPH_SIMPLE_P (tbase, tlen, g))
                {
-                 /* We set the multi-byte form of a character in G
-                    (that should be an ASCII character) at
-                    WORKBUF.  */
-                 workbuf[0] = FAST_GLYPH_CHAR (g);
-                 len = 1;
-                 buf = workbuf;
-                 coding->src_multibyte = 0;
+                 int c = FAST_GLYPH_CHAR (g);
+
+                 if (CHAR_VALID_P (c, 0))
+                   buf += CHAR_STRING (c, buf);
+                 else
+                   *buf++ = SPACEGLYPH;
+                 nchars++;
                }
              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]);
+                 Lisp_Object string;
+
+                 string = tbase[g];
+                 if (! STRING_MULTIBYTE (string))
+                   string = string_to_multibyte (string);
+                 nbytes = buf - encode_terminal_buf;
+                 if (encode_terminal_bufsize < nbytes + SBYTES (string))
+                   {
+                     encode_terminal_bufsize = nbytes + SBYTES (string);
+                     encode_terminal_buf = xrealloc (encode_terminal_buf,
+                                                     encode_terminal_bufsize);
+                     buf = encode_terminal_buf + nbytes;
+                   }
+                 bcopy (SDATA (string), buf, SBYTES (string));
+                 buf += SBYTES (string);
+                 nchars += SCHARS (string);
                }
            }
-         
-         result = encode_coding (coding, buf, dst, len, dst_end - dst);
-         len -= coding->consumed;
-         dst += coding->produced;
-         if (result == CODING_FINISH_INSUFFICIENT_DST
-             || (result == CODING_FINISH_INSUFFICIENT_SRC
-                 && len > dst_end - dst))
-           /* The remaining output buffer is too short.  We must
-              break the loop here without increasing SRC so that the
-              next call of this function starts from the same glyph.  */
-           break;
-
-         if (len > 0)
-           {
-             /* This is the case that a code of the range 0200..0237
-                exists in buf.  We must just write out such a code.  */
-             buf += coding->consumed;
-             while (len--)
-               *dst++ = *buf++;
-           }
        }
       src++;
     }
-  
-  *consumed = src - src_start;
-  return (dst - dst_start);
-}
 
+  nbytes = buf - encode_terminal_buf;
+  coding->src_multibyte = 1;
+  coding->dst_multibyte = 0;
+  if (SYMBOLP (coding->pre_write_conversion)
+      && ! NILP (Ffboundp (coding->pre_write_conversion)))
+    {
+      run_pre_write_conversin_on_c_str (&encode_terminal_buf,
+                                       &encode_terminal_bufsize,
+                                       nchars, nbytes, coding);
+      nchars = coding->produced_char;
+      nbytes = coding->produced;
+    }
+  required = nbytes + encoding_buffer_size (coding, nbytes);
+  if (encode_terminal_bufsize < required)
+    {
+      encode_terminal_bufsize = required;
+      encode_terminal_buf = xrealloc (encode_terminal_buf, required);
+    }
+
+  encode_coding (coding, encode_terminal_buf, encode_terminal_buf + nbytes,
+                nbytes, encode_terminal_bufsize - nbytes);
+  return encode_terminal_buf + nbytes;
+}
 
 void
 write_glyphs (string, len)
      register struct glyph *string;
      register int 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;
+  unsigned char *conversion_buffer;
+  struct coding_system *coding;
 
   if (write_glyphs_hook
       && ! FRAME_TERMCAP_P (f))
@@ -926,24 +948,29 @@ 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);
-  
+
+  /* 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);
   /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
      the tail.  */
-  terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
-  
+  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;
@@ -952,54 +979,31 @@ write_glyphs (string, len)
       highlight_if_desired ();
       turn_on_face (f, face_id);
 
-      while (n > 0)
+      if (n == len)
+       /* This is the last run.  */
+       coding->mode |= CODING_MODE_LAST_BLOCK;
+      conversion_buffer = encode_terminal_code (string, n, coding);
+      if (coding->produced > 0)
        {
-         /* 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);
-         if (produced > 0)
-           {
-             fwrite (conversion_buffer, 1, produced, stdout);
-             if (ferror (stdout))
-               clearerr (stdout);
-             if (termscript)
-               fwrite (conversion_buffer, 1, produced, termscript);
-           }
-         len -= consumed;
-         n -= consumed;
-         string += consumed;
+         fwrite (conversion_buffer, 1, coding->produced, stdout);
+         if (ferror (stdout))
+           clearerr (stdout);
+         if (termscript)
+           fwrite (conversion_buffer, 1, coding->produced, termscript);
        }
+      len -= n;
+      string += n;
 
       /* Turn appearance modes off.  */
       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))
-    {
-      terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
-      encode_coding (&terminal_coding, "", conversion_buffer,
-                    0, conversion_buffer_size);
-      if (terminal_coding.produced > 0)
-       {
-         fwrite (conversion_buffer, 1, terminal_coding.produced, stdout);
-         if (ferror (stdout))
-           clearerr (stdout);
-         if (termscript)
-           fwrite (conversion_buffer, 1, terminal_coding.produced,
-                   termscript);
-       }
-    }
-  
+
   cmcheckmagic ();
 }
 
 /* If start is zero, insert blanks instead of a string at start */
+
 void
 insert_glyphs (start, len)
      register struct glyph *start;
@@ -1008,6 +1012,9 @@ insert_glyphs (start, len)
   char *buf;
   struct glyph *glyph = NULL;
   struct frame *f, *sf;
+  unsigned char *conversion_buffer;
+  unsigned char space[1];
+  struct coding_system *coding;
 
   if (len <= 0)
     return;
@@ -1033,19 +1040,26 @@ insert_glyphs (start, len)
 
   turn_on_insert ();
   cmplus (len);
-  /* The bit CODING_MODE_LAST_BLOCK should be set to 1 only at the tail.  */
-  terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
+
+  if (! start)
+    space[0] = SPACEGLYPH;
+
+  /* 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);
+  /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
+     the tail.  */
+  coding->mode &= ~CODING_MODE_LAST_BLOCK;
+
   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)
        {
-         conversion_buffer[0] = SPACEGLYPH;
-         produced = 1;
+         conversion_buffer = space;
+         coding->produced = 1;
        }
       else
        {
@@ -1063,21 +1077,18 @@ insert_glyphs (start, len)
 
          if (len <= 0)
            /* This is the last glyph.  */
-           terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
+           coding->mode |= CODING_MODE_LAST_BLOCK;
 
-         /* 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);
+         conversion_buffer = encode_terminal_code (glyph, 1, coding);
        }
 
-      if (produced > 0)
+      if (coding->produced > 0)
        {
-         fwrite (conversion_buffer, 1, produced, stdout);
+         fwrite (conversion_buffer, 1, coding->produced, stdout);
          if (ferror (stdout))
            clearerr (stdout);
          if (termscript)
-           fwrite (conversion_buffer, 1, produced, termscript);
+           fwrite (conversion_buffer, 1, coding->produced, termscript);
        }
 
       OUTPUT1_IF (TS_pad_inserted_char);
@@ -1087,7 +1098,7 @@ insert_glyphs (start, len)
          turn_off_highlight ();
        }
     }
-  
+
   cmcheckmagic ();
 }
 
@@ -1148,7 +1159,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
@@ -1158,7 +1169,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)
@@ -1193,7 +1204,7 @@ ins_del_lines (vpos, n)
 
   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 ();
     }
 }
@@ -1243,11 +1254,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 */
@@ -1300,7 +1311,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 */
@@ -1308,7 +1319,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);
 }
 
@@ -1330,8 +1341,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;
 
@@ -1339,14 +1350,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,
@@ -1365,7 +1376,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 */
 }
@@ -1455,14 +1466,33 @@ static struct fkey_table keys[] =
   {"k6", "f6"},
   {"k7", "f7"},
   {"k8", "f8"},
-  {"k9", "f9"}
+  {"k9", "f9"},
+
+  {"&0", "S-cancel"},    /*shifted cancel key*/
+  {"&9", "S-begin"},     /*shifted begin key*/
+  {"*0", "S-find"},      /*shifted find key*/
+  {"*1", "S-execute"},   /*shifted execute? actually shifted command key*/
+  {"*4", "S-delete"},    /*shifted delete-character key*/
+  {"*7", "S-end"},       /*shifted end key*/
+  {"*8", "S-clearline"}, /*shifted clear-to end-of-line key*/
+  {"#1", "S-help"},      /*shifted help key*/
+  {"#2", "S-home"},      /*shifted home key*/
+  {"#3", "S-insert"},    /*shifted insert-character key*/
+  {"#4", "S-left"},      /*shifted left-arrow key*/
+  {"%d", "S-menu"},      /*shifted menu? actually shifted options key*/
+  {"%c", "S-next"},      /*shifted next key*/
+  {"%e", "S-prior"},     /*shifted previous key*/
+  {"%f", "S-print"},     /*shifted print key*/
+  {"%g", "S-redo"},      /*shifted redo key*/
+  {"%i", "S-right"},     /*shifted right-arrow key*/
+  {"!3", "S-undo"}       /*shifted undo key*/
   };
 
 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
@@ -1567,7 +1597,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 */
@@ -1599,15 +1629,22 @@ term_get_fkeys_1 ()
                       Character Display Information
  ***********************************************************************/
 
+/* Avoid name clash with functions defined in xterm.c */
+#ifdef static
+#define append_glyph append_glyph_term
+#define produce_stretch_glyph produce_stretch_glyph_term
+#endif
+
 static void append_glyph P_ ((struct it *));
+static void produce_stretch_glyph P_ ((struct it *));
 
 
 /* Append glyphs to IT's glyph_row.  Called from produce_glyphs for
-   terminal frames if IT->glyph_row != NULL.  IT->c is the character
-   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.  */
-   
+   terminal frames if IT->glyph_row != NULL.  IT->char_to_display is
+   the character 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;
@@ -1620,18 +1657,18 @@ 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;
       glyph->pixel_width = 1;
-      glyph->u.ch = it->c;
+      glyph->u.ch = it->char_to_display;
       glyph->face_id = it->face_id;
       glyph->padding_p = i > 0;
       glyph->charpos = CHARPOS (it->position);
       glyph->object = it->object;
-      
+
       ++it->glyph_row->used[it->area];
       ++glyph;
     }
@@ -1656,22 +1693,30 @@ append_glyph (it)
    Callers usually don't call produce_glyphs directly;
    instead they use the macro PRODUCE_GLYPHS.  */
 
-void 
+void
 produce_glyphs (it)
      struct it *it;
 {
   /* If a hook is installed, let it do the work.  */
   xassert (it->what == IT_CHARACTER
           || it->what == IT_COMPOSITION
-          || it->what == IT_IMAGE
           || it->what == IT_STRETCH);
-  
+
+  if (it->what == IT_STRETCH)
+    {
+      produce_stretch_glyph (it);
+      goto done;
+    }
+
   /* Nothing but characters are supported on terminal frames.  For a
      composition sequence, it->c is the first character of the
      sequence.  */
   xassert (it->what == IT_CHARACTER
           || it->what == IT_COMPOSITION);
 
+  /* Maybe translate single-byte characters to multibyte.  */
+  it->char_to_display = it->c;
+
   if (it->c >= 040 && it->c < 0177)
     {
       it->pixel_width = it->nglyphs = 1;
@@ -1684,8 +1729,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;
@@ -1696,18 +1741,16 @@ 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->char_to_display = ' ';
          it->pixel_width = it->len = 1;
-         
+
          while (n--)
            append_glyph (it);
-         
-         it->c = '\t';
        }
 
       it->pixel_width = nspaces;
@@ -1715,14 +1758,30 @@ produce_glyphs (it)
     }
   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);
+      if (unibyte_display_via_language_environment
+         && (it->c >= 0240
+             || !NILP (Vnonascii_translation_table)))
+       {
+         int charset;
+
+         it->char_to_display = unibyte_char_to_multibyte (it->c);
+         charset = CHAR_CHARSET (it->char_to_display);
+         it->pixel_width = CHARSET_WIDTH (charset);
+         it->nglyphs = it->pixel_width;
+         if (it->glyph_row)
+           append_glyph (it);
+       }
+      else
+       {
+         /* 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
     {
@@ -1734,12 +1793,13 @@ 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 
+ done:
+  /* Advance current_x by the pixel width as a convenience for
      the caller.  */
   if (it->area == TEXT_AREA)
     it->current_x += it->pixel_width;
@@ -1748,6 +1808,79 @@ produce_glyphs (it)
 }
 
 
+/* Produce a stretch glyph for iterator IT.  IT->object is the value
+   of the glyph property displayed.  The value must be a list
+   `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
+   being recognized:
+
+   1. `:width WIDTH' specifies that the space should be WIDTH *
+   canonical char width wide.  WIDTH may be an integer or floating
+   point number.
+
+   2. `:align-to HPOS' specifies that the space should be wide enough
+   to reach HPOS, a value in canonical character units.  */
+
+static void
+produce_stretch_glyph (it)
+     struct it *it;
+{
+  /* (space :width WIDTH ...)  */
+  Lisp_Object prop, plist;
+  int width = 0, align_to = -1;
+  int zero_width_ok_p = 0;
+  double tem;
+
+  /* List should start with `space'.  */
+  xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
+  plist = XCDR (it->object);
+
+  /* Compute the width of the stretch.  */
+  if ((prop = Fplist_get (plist, QCwidth), !NILP (prop))
+      && calc_pixel_width_or_height (&tem, it, prop, 0, 1, 0))
+    {
+      /* Absolute width `:width WIDTH' specified and valid.  */
+      zero_width_ok_p = 1;
+      width = (int)(tem + 0.5);
+    }
+  else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
+          && calc_pixel_width_or_height (&tem, it, prop, 0, 1, &align_to))
+    {
+      if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
+       align_to = (align_to < 0
+                   ? 0
+                   : align_to - window_box_left_offset (it->w, TEXT_AREA));
+      else if (align_to < 0)
+       align_to = window_box_left_offset (it->w, TEXT_AREA);
+      width = max (0, (int)(tem + 0.5) + align_to - it->current_x);
+      zero_width_ok_p = 1;
+    }
+  else
+    /* Nothing specified -> width defaults to canonical char width.  */
+    width = FRAME_COLUMN_WIDTH (it->f);
+
+  if (width <= 0 && (width < 0 || !zero_width_ok_p))
+    width = 1;
+
+  if (width > 0 && it->glyph_row)
+    {
+      Lisp_Object o_object = it->object;
+      Lisp_Object object = it->stack[it->sp - 1].string;
+      int n = width;
+
+      if (!STRINGP (object))
+       object = it->w->buffer;
+      it->object = object;
+      it->char_to_display = ' ';
+      it->pixel_width = it->len = 1;
+      while (n--)
+       append_glyph (it);
+      it->object = o_object;
+    }
+  it->pixel_width = width;
+  it->nglyphs = width;
+}
+
+
 /* Get information about special display element WHAT in an
    environment described by IT.  WHAT is one of IT_TRUNCATION or
    IT_CONTINUATION.  Maybe produce glyphs for WHAT if IT has a
@@ -1760,7 +1893,8 @@ produce_special_glyphs (it, what)
      enum display_element_type what;
 {
   struct it temp_it;
-  
+  GLYPH glyph;
+
   temp_it = *it;
   temp_it.dp = NULL;
   temp_it.what = IT_CHARACTER;
@@ -1775,15 +1909,11 @@ produce_special_glyphs (it, what)
          && INTEGERP (DISP_CONTINUE_GLYPH (it->dp))
          && 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_BYTES (temp_it.c);
+         glyph = XINT (DISP_CONTINUE_GLYPH (it->dp));
+         glyph = spec_glyph_lookup_face (XWINDOW (it->window), glyph);
        }
       else
-       temp_it.c = '\\';
-      
-      produce_glyphs (&temp_it);
-      it->pixel_width = temp_it.pixel_width;
-      it->nglyphs = temp_it.pixel_width;
+       glyph = '\\';
     }
   else if (what == IT_TRUNCATION)
     {
@@ -1792,33 +1922,22 @@ produce_special_glyphs (it, what)
          && INTEGERP (DISP_TRUNC_GLYPH (it->dp))
          && 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_BYTES (temp_it.c);
+         glyph = XINT (DISP_TRUNC_GLYPH (it->dp));
+         glyph = spec_glyph_lookup_face (XWINDOW (it->window), glyph);
        }
       else
-       temp_it.c = '$';
-      
-      produce_glyphs (&temp_it);
-      it->pixel_width = temp_it.pixel_width;
-      it->nglyphs = temp_it.pixel_width;
+       glyph = '$';
     }
   else
     abort ();
-}
-
 
-/* Return an estimation of the pixel height of mode or top lines on
-   frame F.  FACE_ID specifies what line's height to estimate.  */
+  temp_it.c = FAST_GLYPH_CHAR (glyph);
+  temp_it.face_id = FAST_GLYPH_FACE (glyph);
+  temp_it.len = CHAR_BYTES (temp_it.c);
 
-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;
+  produce_glyphs (&temp_it);
+  it->pixel_width = temp_it.pixel_width;
+  it->nglyphs = temp_it.pixel_width;
 }
 
 
@@ -1837,7 +1956,8 @@ estimate_mode_line_height (f, face_id)
       ? (TN_no_color_video & (ATTR)) == 0      \
       : 1)
 
-/* Turn appearances of face FACE_ID on tty frame F on.  */
+/* Turn appearances of face FACE_ID on tty frame F on.
+   FACE_ID is a realized face ID number, in the face cache.  */
 
 static void
 turn_on_face (f, face_id)
@@ -1917,24 +2037,26 @@ turn_on_face (f, face_id)
 
   if (TN_max_colors > 0)
     {
-      char *p;
-      
-      if (fg >= 0 && TS_set_foreground)
+      char *ts, *p;
+
+      ts = standout_mode ? TS_set_background : TS_set_foreground;
+      if (fg >= 0 && ts)
        {
-         p = tparam (TS_set_foreground, NULL, 0, (int) fg);
+         p = tparam (ts, NULL, 0, (int) fg);
          OUTPUT (p);
          xfree (p);
        }
 
-      if (bg >= 0 && TS_set_background)
+      ts = standout_mode ? TS_set_foreground : TS_set_background;
+      if (bg >= 0 && ts)
        {
-         p = tparam (TS_set_background, NULL, 0, (int) bg);
+         p = tparam (ts, NULL, 0, (int) bg);
          OUTPUT (p);
          xfree (p);
        }
     }
 }
-  
+
 
 /* Turn off appearances of face FACE_ID on tty frame F.  */
 
@@ -1986,8 +2108,8 @@ 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.  */
@@ -2086,6 +2208,10 @@ 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 */
@@ -2128,7 +2254,7 @@ set_tty_color_mode (f, val)
   tty_color_mode_alist = Fintern_soft (build_string ("tty-color-mode-alist"),
                                       Qnil);
 
-  if (NATNUMP (val))
+  if (INTEGERP (val))
     color_mode = val;
   else
     {
@@ -2136,22 +2262,24 @@ set_tty_color_mode (f, val)
        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;
     }
+
+  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 (NATNUMP (color_mode))
+  if (INTEGERP (color_mode))
     mode = XINT (color_mode);
   else
     mode = 0;  /* meaning default */
-  if (NATNUMP (current_mode))
+  if (INTEGERP (current_mode))
     old_mode = XINT (current_mode);
   else
     old_mode = 0;
@@ -2179,11 +2307,14 @@ 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);
 
+  encode_terminal_bufsize = 0;
+
 #ifdef WINDOWSNT
   initialize_w32_display ();
 
@@ -2191,12 +2322,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;
 
@@ -2222,6 +2350,7 @@ term_init (terminal_type)
 
   Wcm_clear ();
 
+  buffer = (char *) xmalloc (buffer_size);
   status = tgetent (buffer, terminal_type);
   if (status < 0)
     {
@@ -2249,13 +2378,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);
@@ -2316,7 +2445,7 @@ 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);
   TS_enter_bold_mode = tgetstr ("md", address);
@@ -2326,7 +2455,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);
@@ -2346,10 +2475,10 @@ 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;
@@ -2376,21 +2505,21 @@ 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");
   TabWidth = tgetnum ("tw");
@@ -2414,7 +2543,7 @@ 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)
@@ -2513,9 +2642,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
@@ -2544,8 +2673,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
@@ -2580,6 +2709,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 */
@@ -2594,6 +2725,16 @@ fatal (str, arg1, arg2)
   exit (1);
 }
 
+DEFUN ("tty-no-underline", Ftty_no_underline, Stty_no_underline, 0, 0, 0,
+       doc: /* Declare that this terminal does not handle underlining.
+This is used to override the terminfo data, for certain terminals that
+do not really do underlining, but say that they do.  */)
+  ()
+{
+  TS_enter_underline_mode = 0;
+  return Qnil;
+}
+
 void
 syms_of_term ()
 {
@@ -2611,7 +2752,17 @@ This variable can be used by terminal emulator packages.  */);
 The function should accept no arguments.  */);
   Vring_bell_function = Qnil;
 
+  DEFVAR_BOOL ("visible-cursor", &visible_cursor,
+              doc: /* Non-nil means to make the cursor very visible.
+This only has an effect when running in a text terminal.
+What means \"very visible\" is up to your terminal.  It may make the cursor
+bigger, or it may make it blink, or it may do nothing at all.  */);
+  visible_cursor = 1;
+
   defsubr (&Stty_display_color_p);
   defsubr (&Stty_display_color_cells);
+  defsubr (&Stty_no_underline);
 }
 
+/* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193
+   (do not change this comment) */