]> code.delx.au - gnu-emacs/blobdiff - src/term.c
(syms_of_term): Initialize default_orig_pair, default_set_foreground,
[gnu-emacs] / src / term.c
index 5c25c7419dce216dd0a27f604d5fb2ffff71d8dc..56ea06565996062c1ff1d49bb18ae21883a7ca8e 100644 (file)
@@ -1,12 +1,13 @@
 /* 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, 2007, 2008
+                 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 GNU Emacs is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -16,8 +17,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>.  */
 
@@ -38,6 +39,7 @@ Boston, MA 02111-1307, USA.  */
 #include "dispextern.h"
 #include "window.h"
 #include "keymap.h"
+#include "blockinput.h"
 
 /* For now, don't try to include termcap.h.  On some systems,
    configure finds a non-standard termcap.h that the main build
@@ -79,10 +81,18 @@ static void tty_hide_cursor P_ ((void));
 
 #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 +141,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 *));
 
@@ -182,6 +192,11 @@ void (*frame_rehighlight_hook) P_ ((FRAME_PTR f));
 
 void (*frame_raise_lower_hook) P_ ((FRAME_PTR f, int raise));
 
+/* If the value of the frame parameter changed, whis hook is called.
+   For example, if going from fullscreen to not fullscreen this hook
+   may do something OS dependent, like extended window manager hints on X11.  */
+void (*fullscreen_hook) P_ ((struct frame *f));
+
 /* Set the vertical scroll bar for WINDOW to have its upper left corner
    at (TOP, LEFT), and be LENGTH rows high.  Set its handle to
    indicate that we are displaying PORTION characters out of a total
@@ -445,8 +460,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 ();
     }
@@ -601,7 +626,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);
     }
 }
 
@@ -787,39 +813,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.  */
@@ -830,18 +860,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
            {
@@ -851,61 +874,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))
@@ -929,9 +963,14 @@ write_glyphs (string, len)
 
   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)
     {
@@ -947,49 +986,28 @@ 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;
+         BLOCK_INPUT;
+         fwrite (conversion_buffer, 1, coding->produced, stdout);
+         if (ferror (stdout))
+           clearerr (stdout);
+         if (termscript)
+           fwrite (conversion_buffer, 1, coding->produced, termscript);
+         UNBLOCK_INPUT;
        }
+      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 ();
 }
 
@@ -1003,6 +1021,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;
@@ -1028,19 +1049,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
        {
@@ -1058,21 +1086,20 @@ 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);
+         BLOCK_INPUT;
+         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);
+         UNBLOCK_INPUT;
        }
 
       OUTPUT1_IF (TS_pad_inserted_char);
@@ -1450,7 +1477,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;
@@ -1594,14 +1640,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)
@@ -1621,7 +1674,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);
@@ -1658,15 +1711,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;
@@ -1696,13 +1757,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;
@@ -1710,14 +1769,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,6 +1809,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)
@@ -1743,6 +1819,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
@@ -1755,6 +1904,7 @@ produce_special_glyphs (it, what)
      enum display_element_type what;
 {
   struct it temp_it;
+  GLYPH glyph;
 
   temp_it = *it;
   temp_it.dp = NULL;
@@ -1770,15 +1920,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)
     {
@@ -1787,18 +1933,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);
+
+  produce_glyphs (&temp_it);
+  it->pixel_width = temp_it.pixel_width;
+  it->nglyphs = temp_it.pixel_width;
 }
 
 
@@ -1817,7 +1967,8 @@ produce_special_glyphs (it, what)
       ? (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)
@@ -1897,18 +2048,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);
        }
@@ -2017,15 +2170,22 @@ DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
 
 #ifndef WINDOWSNT
 
+/* Declare here rather than in the function, as in the rest of Emacs,
+   to work around an HPUX compiler bug (?). See
+   http://lists.gnu.org/archive/html/emacs-devel/2007-08/msg00410.html  */
+static int default_max_colors;
+static int default_max_pairs;
+static int default_no_color_video;
+static char *default_orig_pair;
+static char *default_set_foreground;
+static char *default_set_background;
+
 /* 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)
     {
@@ -2171,6 +2331,8 @@ term_init (terminal_type)
   int status;
   struct frame *sf = XFRAME (selected_frame);
 
+  encode_terminal_bufsize = 0;
+
 #ifdef WINDOWSNT
   initialize_w32_display ();
 
@@ -2581,6 +2743,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 ()
 {
@@ -2598,8 +2770,21 @@ 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);
+
+  fullscreen_hook = NULL;
+  default_orig_pair = NULL;
+  default_set_foreground = NULL;
+  default_set_background = NULL;
 }
 
 /* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193