]> code.delx.au - gnu-emacs/blobdiff - src/term.c
(xic_create_fontsetname): If ADSTYLE field is not a wild
[gnu-emacs] / src / term.c
index 9fe490786eabc7f993f81ba3ddae1bb87fab2e09..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 *));
 
@@ -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;
@@ -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 ();
     }
@@ -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);
     }
@@ -528,11 +541,11 @@ set_scroll_region (start, stop)
     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);
@@ -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);
     }
 }
 
@@ -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)));
        }
     }
 }
@@ -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,17 +948,22 @@ 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)
     {
@@ -952,49 +979,26 @@ 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 ();
 }
 
@@ -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);
@@ -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,7 +1466,26 @@ 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;
@@ -1599,14 +1629,21 @@ 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)
@@ -1626,7 +1663,7 @@ append_glyph (it)
     {
       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);
@@ -1663,15 +1700,23 @@ produce_glyphs (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;
@@ -1701,13 +1746,11 @@ produce_glyphs (it)
        {
          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
     {
@@ -1739,6 +1798,7 @@ produce_glyphs (it)
        append_glyph (it);
     }
 
+ done:
   /* Advance current_x by the pixel width as a convenience for
      the caller.  */
   if (it->area == TEXT_AREA)
@@ -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,6 +1893,7 @@ produce_special_glyphs (it, what)
      enum display_element_type what;
 {
   struct it temp_it;
+  GLYPH glyph;
 
   temp_it = *it;
   temp_it.dp = NULL;
@@ -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 ();
-}
 
+  temp_it.c = FAST_GLYPH_CHAR (glyph);
+  temp_it.face_id = FAST_GLYPH_FACE (glyph);
+  temp_it.len = CHAR_BYTES (temp_it.c);
 
-/* 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;
+  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,18 +2037,20 @@ turn_on_face (f, face_id)
 
   if (TN_max_colors > 0)
     {
-      char *p;
+      char *ts, *p;
 
-      if (fg >= 0 && TS_set_foreground)
+      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);
        }
@@ -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);
@@ -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");
+    SET_FRAME_COLS (sf, FRAME_COLS (sf));
+  if (FRAME_LINES (sf) <= 0)
+    FRAME_LINES (sf) = tgetnum ("li");
 
-  if (FRAME_HEIGHT (sf) < 3 || FRAME_WIDTH (sf) < 3)
+  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");
@@ -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) */