]> code.delx.au - gnu-emacs/blobdiff - src/term.c
Merged in changes from CVS trunk.
[gnu-emacs] / src / term.c
index 785f2a3bb33535e86f47a33ea310af12f5ced435..899829ebadb29b6b7890f915eb5e9854fb8ff5e3 100644 (file)
@@ -29,7 +29,12 @@ Boston, MA 02111-1307, USA.  */
 #include <sys/file.h>
 
 #include <unistd.h>             /* For isatty. */
-#include <sys/ioctl.h>          /* For TIOCNOTTY. */
+
+#if HAVE_TERMIOS_H
+#include <termios.h>           /* For TIOCNOTTY. */
+#endif
+
+#include <signal.h>
 
 #include "lisp.h"
 #include "termchar.h"
@@ -43,6 +48,8 @@ Boston, MA 02111-1307, USA.  */
 #include "dispextern.h"
 #include "window.h"
 #include "keymap.h"
+#include "syssignal.h"
+#include "systty.h"
 
 /* For now, don't try to include termcap.h.  On some systems,
    configure finds a non-standard termcap.h that the main build
@@ -78,6 +85,8 @@ static void turn_off_face P_ ((struct frame *, int face_id));
 static void tty_show_cursor P_ ((struct tty_display_info *));
 static void tty_hide_cursor P_ ((struct tty_display_info *));
 
+static struct display *get_tty_display (Lisp_Object display);
+
 void delete_initial_display P_ ((struct display *));
 void create_tty_output P_ ((struct frame *));
 void delete_tty_output P_ ((struct frame *));
@@ -102,13 +111,14 @@ void delete_tty_output P_ ((struct frame *));
 
 #define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), 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;
 
-/* Functions to call after deleting a tty. */
-Lisp_Object Vdelete_tty_after_functions;
-
 /* Functions to call after suspending a tty. */
 Lisp_Object Vsuspend_tty_functions;
 
@@ -130,9 +140,6 @@ struct tty_display_info *tty_list;
    else. */
 int no_redraw_on_reenter;
 
-Lisp_Object Qframe_tty_name, Qframe_tty_type;
-
-
 
 /* Meaning of bits in no_color_video.  Each bit set means that the
    corresponding attribute cannot be combined with colors.  */
@@ -160,15 +167,13 @@ int max_frame_cols;
 
 int max_frame_lines;
 
-/* Frame currently being redisplayed; 0 if not currently redisplaying.
-   (Direct output does not count).  */
-
-FRAME_PTR updating_frame;
-
 /* Non-zero if we have dropped our controlling tty and therefore
    should not open a frame on stdout. */
 static int no_controlling_tty;
 
+/* The first unallocated display id. */
+static int next_display_id;
+
 /* Provided for lisp packages.  */
 
 static int system_uses_terminfo;
@@ -190,10 +195,8 @@ extern char *tgetstr ();
 #endif /* WINDOWSNT */
 
 void
-ring_bell ()
+ring_bell (struct frame *f)
 {
-  struct frame *f = XFRAME (selected_frame);
-
   if (!NILP (Vring_bell_function))
     {
       Lisp_Object function;
@@ -214,20 +217,23 @@ ring_bell ()
       Vring_bell_function = function;
     }
   else if (FRAME_DISPLAY (f)->ring_bell_hook)
-    (*FRAME_DISPLAY (f)->ring_bell_hook) ();
+    (*FRAME_DISPLAY (f)->ring_bell_hook) (f);
 }
 
 /* Ring the bell on a tty. */
 
 void
-tty_ring_bell ()
+tty_ring_bell (struct frame *f)
 {
-  struct frame *f = XFRAME (selected_frame);
   struct tty_display_info *tty = FRAME_TTY (f);
 
-  OUTPUT (tty, (tty->TS_visible_bell && visible_bell
-                ? tty->TS_visible_bell
-                : tty->TS_bell));
+  if (tty->output)
+    {
+      OUTPUT (tty, (tty->TS_visible_bell && visible_bell
+                    ? tty->TS_visible_bell
+                    : tty->TS_bell));
+      fflush (tty->output);
+    }
 }
 
 /* Set up termcap modes for Emacs. */
@@ -268,21 +274,17 @@ tty_reset_terminal_modes (struct display *display)
 }
 
 void
-update_begin (f)
-     struct frame *f;
+update_begin (struct frame *f)
 {
-  updating_frame = f;
   if (FRAME_DISPLAY (f)->update_begin_hook)
     (*FRAME_DISPLAY (f)->update_begin_hook) (f);
 }
 
 void
-update_end (f)
-     struct frame *f;
+update_end (struct frame *f)
 {
   if (FRAME_DISPLAY (f)->update_end_hook)
     (*FRAME_DISPLAY (f)->update_end_hook) (f);
-  updating_frame = NULL;
 }
 
 /* Flag the end of a display update on a termcap display. */
@@ -304,36 +306,28 @@ tty_update_end (struct frame *f)
    that is bounded by calls to update_begin and update_end.  */
 
 void
-set_terminal_window (size)
-     int size;
+set_terminal_window (struct frame *f, int size)
 {
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-
   if (FRAME_DISPLAY (f)->set_terminal_window_hook)
-    (*FRAME_DISPLAY (f)->set_terminal_window_hook) (size);
+    (*FRAME_DISPLAY (f)->set_terminal_window_hook) (f, size);
 }
 
 /* The implementation of set_terminal_window for termcap frames. */
 
 void
-tty_set_terminal_window (int size)
+tty_set_terminal_window (struct frame *f, int size)
 {
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-
   struct tty_display_info *tty = FRAME_TTY (f);
 
   tty->specified_window = size ? size : FRAME_LINES (f);
   if (FRAME_SCROLL_REGION_OK (f))
-    set_scroll_region (0, tty->specified_window);
+    set_scroll_region (f, 0, tty->specified_window);
 }
 
 void
-set_scroll_region (start, stop)
-     int start, stop;
+set_scroll_region (struct frame *f, int start, int stop)
 {
   char *buf;
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-
   struct tty_display_info *tty = FRAME_TTY (f);
 
   if (tty->TS_set_scroll_region)
@@ -452,20 +446,15 @@ highlight_if_desired (struct tty_display_info *tty)
    frame-relative coordinates.  */
 
 void
-cursor_to (vpos, hpos)
-     int vpos, hpos;
+cursor_to (struct frame *f, int vpos, int hpos)
 {
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-
   if (FRAME_DISPLAY (f)->cursor_to_hook)
-    (*FRAME_DISPLAY (f)->cursor_to_hook) (vpos, hpos);
+    (*FRAME_DISPLAY (f)->cursor_to_hook) (f, vpos, hpos);
 }
 
 void
-tty_cursor_to (int vpos, int hpos)
+tty_cursor_to (struct frame *f, int vpos, int hpos)
 {
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-  
   struct tty_display_info *tty = FRAME_TTY (f);
 
   /* Detect the case where we are called from reset_sys_modes
@@ -486,20 +475,15 @@ tty_cursor_to (int vpos, int hpos)
 /* Similar but don't take any account of the wasted characters.  */
 
 void
-raw_cursor_to (row, col)
-     int row, col;
+raw_cursor_to (struct frame *f, int row, int col)
 {
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-
   if (FRAME_DISPLAY (f)->raw_cursor_to_hook)
-    (*FRAME_DISPLAY (f)->raw_cursor_to_hook) (row, col);  
+    (*FRAME_DISPLAY (f)->raw_cursor_to_hook) (f, row, col);  
 }
 
 void
-tty_raw_cursor_to (int row, int col)
+tty_raw_cursor_to (struct frame *f, int row, int col)
 {
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-
   struct tty_display_info *tty = FRAME_TTY (f);
 
   if (curY (tty) == row
@@ -516,21 +500,18 @@ tty_raw_cursor_to (int row, int col)
 
 /* Clear from cursor to end of frame. */
 void
-clear_to_end ()
+clear_to_end (struct frame *f)
 {
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-
   if (FRAME_DISPLAY (f)->clear_to_end_hook)
-    (*FRAME_DISPLAY (f)->clear_to_end_hook) ();
+    (*FRAME_DISPLAY (f)->clear_to_end_hook) (f);
 }
 
 /* Clear from cursor to end of frame on a termcap device. */
 
 void
-tty_clear_to_end (void)
+tty_clear_to_end (struct frame *f)
 {
   register int i;
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
   struct tty_display_info *tty = FRAME_TTY (f);
 
   if (tty->TS_clr_to_bottom)
@@ -542,8 +523,8 @@ tty_clear_to_end (void)
     {
       for (i = curY (tty); i < FRAME_LINES (f); i++)
        {
-         cursor_to (i, 0);
-         clear_end_of_line (FRAME_COLS (f));
+         cursor_to (f, i, 0);
+         clear_end_of_line (f, FRAME_COLS (f));
        }
     }
 }
@@ -551,21 +532,17 @@ tty_clear_to_end (void)
 /* Clear entire frame */
 
 void
-clear_frame ()
+clear_frame (struct frame *f)
 {
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-
   if (FRAME_DISPLAY (f)->clear_frame_hook)
-    (*FRAME_DISPLAY (f)->clear_frame_hook) ();
+    (*FRAME_DISPLAY (f)->clear_frame_hook) (f);
 }
 
 /* Clear an entire termcap frame. */
 
 void
-tty_clear_frame ()
+tty_clear_frame (struct frame *f)
 {
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-
   struct tty_display_info *tty = FRAME_TTY (f);
 
   if (tty->TS_clr_frame)
@@ -576,8 +553,8 @@ tty_clear_frame ()
     }
   else
     {
-      cursor_to (0, 0);
-      clear_to_end ();
+      cursor_to (f, 0, 0);
+      clear_to_end (f);
     }
 }
 
@@ -587,13 +564,10 @@ tty_clear_frame ()
    Note that the cursor may be moved, on terminals lacking a `ce' string.  */
 
 void
-clear_end_of_line (first_unused_hpos)
-     int first_unused_hpos;
+clear_end_of_line (struct frame *f, int first_unused_hpos)
 {
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-
   if (FRAME_DISPLAY (f)->clear_end_of_line_hook)
-    (*FRAME_DISPLAY (f)->clear_end_of_line_hook) (first_unused_hpos);
+    (*FRAME_DISPLAY (f)->clear_end_of_line_hook) (f, first_unused_hpos);
 }
 
 /* An implementation of clear_end_of_line for termcap frames.
@@ -601,10 +575,9 @@ clear_end_of_line (first_unused_hpos)
    Note that the cursor may be moved, on terminals lacking a `ce' string.  */
 
 void
-tty_clear_end_of_line (int first_unused_hpos)
+tty_clear_end_of_line (struct frame *f, int first_unused_hpos)
 {
   register int i;
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
   struct tty_display_info *tty = FRAME_TTY (f);
 
   /* Detect the case where we are called from reset_sys_modes
@@ -648,11 +621,12 @@ tty_clear_end_of_line (int first_unused_hpos)
    return value is the number of bytes store in DST.  */
 
 int
-encode_terminal_code (src, dst, src_len, dst_len, consumed)
-     struct glyph *src;
-     int src_len;
-     unsigned char *dst;
-     int dst_len, *consumed;
+encode_terminal_code (struct coding_system *coding,
+                      struct glyph *src,
+                      unsigned char *dst,
+                      int src_len,
+                      int dst_len,
+                      int *consumed)
 {
   struct glyph *src_start = src, *src_end = src + src_len;
   unsigned char *dst_start = dst, *dst_end = dst + dst_len;
@@ -663,13 +637,12 @@ encode_terminal_code (src, dst, src_len, dst_len, consumed)
   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
+  /* If the specified 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
+     because it always returns 1 if the member src_multibyte is 1.  */
+  coding = (coding->common_flags & CODING_REQUIRE_ENCODING_MASK
+           ? coding
            : &safe_terminal_coding);
 
   while (src < src_end)
@@ -752,27 +725,21 @@ encode_terminal_code (src, dst, src_len, dst_len, consumed)
    Advance the nominal cursor over the text.  */
 
 void
-write_glyphs (string, len)
-     register struct glyph *string;
-     register int len;
+write_glyphs (struct frame *f, struct glyph *string, int len)
 {
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-
   if (FRAME_DISPLAY (f)->write_glyphs_hook)
-    (*FRAME_DISPLAY (f)->write_glyphs_hook) (string, len);
+    (*FRAME_DISPLAY (f)->write_glyphs_hook) (f, string, len);
 }
 
 /* An implementation of write_glyphs for termcap frames. */
 
 void
-tty_write_glyphs (struct glyph *string, int len)
+tty_write_glyphs (struct frame *f, struct glyph *string, int len)
 {
   int produced, consumed;
   unsigned char conversion_buffer[1024];
   int conversion_buffer_size = sizeof conversion_buffer;
 
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-
   struct tty_display_info *tty = FRAME_TTY (f);
 
   turn_off_insert (tty);
@@ -792,7 +759,7 @@ tty_write_glyphs (struct glyph *string, int len)
 
   /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
      the tail.  */
-  terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
+  FRAME_TERMINAL_CODING (f)->mode &= ~CODING_MODE_LAST_BLOCK;
 
   while (len > 0)
     {
@@ -813,7 +780,8 @@ tty_write_glyphs (struct glyph *string, int len)
          /* 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,
+         produced = encode_terminal_code (FRAME_TERMINAL_CODING (f),
+                                           string, conversion_buffer,
                                           n, conversion_buffer_size,
                                           &consumed);
          if (produced > 0)
@@ -837,19 +805,21 @@ tty_write_glyphs (struct glyph *string, int len)
     }
 
   /* We may have to output some codes to terminate the writing.  */
-  if (CODING_REQUIRE_FLUSHING (&terminal_coding))
+  if (CODING_REQUIRE_FLUSHING (FRAME_TERMINAL_CODING (f)))
     {
-      terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
-      encode_coding (&terminal_coding, "", conversion_buffer,
-                    0, conversion_buffer_size);
-      if (terminal_coding.produced > 0)
+      FRAME_TERMINAL_CODING (f)->mode |= CODING_MODE_LAST_BLOCK;
+      encode_coding (FRAME_TERMINAL_CODING (f), "",
+                     conversion_buffer, 0, conversion_buffer_size);
+      if (FRAME_TERMINAL_CODING (f)->produced > 0)
        {
-         fwrite (conversion_buffer, 1, terminal_coding.produced,
+         fwrite (conversion_buffer, 1,
+                  FRAME_TERMINAL_CODING (f)->produced,
                   tty->output);
          if (ferror (tty->output))
            clearerr (tty->output);
          if (tty->termscript)
-           fwrite (conversion_buffer, 1, terminal_coding.produced,
+           fwrite (conversion_buffer, 1,
+                    FRAME_TERMINAL_CODING (f)->produced,
                    tty->termscript);
        }
     }
@@ -862,27 +832,22 @@ tty_write_glyphs (struct glyph *string, int len)
    If start is zero, insert blanks instead of a string at start */
 
 void
-insert_glyphs (start, len)
-     register struct glyph *start;
-     register int len;
+insert_glyphs (struct frame *f, struct glyph *start, int len)
 {
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-
   if (len <= 0)
     return;
 
   if (FRAME_DISPLAY (f)->insert_glyphs_hook)
-    (*FRAME_DISPLAY (f)->insert_glyphs_hook) (start, len);
+    (*FRAME_DISPLAY (f)->insert_glyphs_hook) (f, start, len);
 }
 
 /* An implementation of insert_glyphs for termcap frames. */
 
 void
-tty_insert_glyphs (struct glyph *start, int len)
+tty_insert_glyphs (struct frame *f, struct glyph *start, int len)
 {
   char *buf;
   struct glyph *glyph = NULL;
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
 
   struct tty_display_info *tty = FRAME_TTY (f);
 
@@ -892,14 +857,14 @@ tty_insert_glyphs (struct glyph *start, int len)
       OUTPUT1 (tty, buf);
       xfree (buf);
       if (start)
-       write_glyphs (start, len);
+       write_glyphs (f, start, len);
       return;
     }
 
   turn_on_insert (tty);
   cmplus (tty, len);
   /* The bit CODING_MODE_LAST_BLOCK should be set to 1 only at the tail.  */
-  terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
+  FRAME_TERMINAL_CODING (f)->mode &= ~CODING_MODE_LAST_BLOCK;
   while (len-- > 0)
     {
       int produced, consumed;
@@ -928,11 +893,12 @@ tty_insert_glyphs (struct glyph *start, int len)
 
          if (len <= 0)
            /* This is the last glyph.  */
-           terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
+           FRAME_TERMINAL_CODING (f)->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,
+         produced = encode_terminal_code (FRAME_TERMINAL_CODING (f),
+                                           glyph, conversion_buffer, 1,
                                           conversion_buffer_size, &consumed);
        }
 
@@ -961,23 +927,19 @@ tty_insert_glyphs (struct glyph *start, int len)
 /* Delete N glyphs at the nominal cursor position. */
 
 void
-delete_glyphs (n)
-     register int n;
+delete_glyphs (struct frame *f, int n)
 {
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-
   if (FRAME_DISPLAY (f)->delete_glyphs_hook)
-    (*FRAME_DISPLAY (f)->delete_glyphs_hook) (n);
+    (*FRAME_DISPLAY (f)->delete_glyphs_hook) (f, n);
 }
 
 /* An implementation of delete_glyphs for termcap frames. */
 
 void
-tty_delete_glyphs (int n)
+tty_delete_glyphs (struct frame *f, int n)
 {
   char *buf;
   register int i;
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
 
   struct tty_display_info *tty = FRAME_TTY (f);
 
@@ -1007,22 +969,17 @@ tty_delete_glyphs (int n)
 /* Insert N lines at vpos VPOS.  If N is negative, delete -N lines.  */
 
 void
-ins_del_lines (vpos, n)
-     int vpos, n;
+ins_del_lines (struct frame *f, int vpos, int n)
 {
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-  
   if (FRAME_DISPLAY (f)->ins_del_lines_hook)
-    (*FRAME_DISPLAY (f)->ins_del_lines_hook) (vpos, n);
+    (*FRAME_DISPLAY (f)->ins_del_lines_hook) (f, vpos, n);
 }
 
 /* An implementation of ins_del_lines for termcap frames. */
 
 void
-tty_ins_del_lines (int vpos, int n)
+tty_ins_del_lines (struct frame *f, int vpos, int n)
 {
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-
   struct tty_display_info *tty = FRAME_TTY (f);
   char *multi = n > 0 ? tty->TS_ins_multi_lines : tty->TS_del_multi_lines;
   char *single = n > 0 ? tty->TS_ins_line : tty->TS_del_line;
@@ -1047,7 +1004,7 @@ tty_ins_del_lines (int vpos, int n)
   
   if (multi)
     {
-      raw_cursor_to (vpos, 0);
+      raw_cursor_to (f, vpos, 0);
       background_highlight (tty);
       buf = tparam (multi, 0, 0, i);
       OUTPUT (tty, buf);
@@ -1055,7 +1012,7 @@ tty_ins_del_lines (int vpos, int n)
     }
   else if (single)
     {
-      raw_cursor_to (vpos, 0);
+      raw_cursor_to (f, vpos, 0);
       background_highlight (tty);
       while (--i >= 0)
         OUTPUT (tty, single);
@@ -1064,23 +1021,23 @@ tty_ins_del_lines (int vpos, int n)
     }
   else
     {
-      set_scroll_region (vpos, tty->specified_window);
+      set_scroll_region (f, vpos, tty->specified_window);
       if (n < 0)
-        raw_cursor_to (tty->specified_window - 1, 0);
+        raw_cursor_to (f, tty->specified_window - 1, 0);
       else
-        raw_cursor_to (vpos, 0);
+        raw_cursor_to (f, vpos, 0);
       background_highlight (tty);
       while (--i >= 0)
         OUTPUTL (tty, scroll, tty->specified_window - vpos);
-      set_scroll_region (0, tty->specified_window);
+      set_scroll_region (f, 0, tty->specified_window);
     }
   
   if (!FRAME_SCROLL_REGION_OK (f)
       && FRAME_MEMORY_BELOW_FRAME (f)
       && n < 0)
     {
-      cursor_to (FRAME_LINES (f) + n, 0);
-      clear_to_end ();
+      cursor_to (f, FRAME_LINES (f) + n, 0);
+      clear_to_end (f);
     }
 }
 \f
@@ -1088,8 +1045,7 @@ tty_ins_del_lines (int vpos, int n)
    not counting any line-dependent padding.  */
 
 int
-string_cost (str)
-     char *str;
+string_cost (char *str)
 {
   cost = 0;
   if (str)
@@ -1101,8 +1057,7 @@ string_cost (str)
    counting any line-dependent padding at one line.  */
 
 static int
-string_cost_one_line (str)
-     char *str;
+string_cost_one_line (char *str)
 {
   cost = 0;
   if (str)
@@ -1114,8 +1069,7 @@ string_cost_one_line (str)
    in tenths of characters.  */
 
 int
-per_line_cost (str)
-     register char *str;
+per_line_cost (char *str)
 {
   cost = 0;
   if (str)
@@ -1138,8 +1092,7 @@ int *char_ins_del_vector;
 
 /* ARGSUSED */
 static void
-calculate_ins_del_char_costs (f)
-     FRAME_PTR f;
+calculate_ins_del_char_costs (struct frame *f)
 {
   struct tty_display_info *tty = FRAME_TTY (f);
   int ins_startup_cost, del_startup_cost;
@@ -1200,8 +1153,7 @@ calculate_ins_del_char_costs (f)
 }
 
 void
-calculate_costs (frame)
-     FRAME_PTR frame;
+calculate_costs (struct frame *frame)
 {
   FRAME_COST_BAUD_RATE (frame) = baud_rate;
 
@@ -1493,6 +1445,7 @@ term_get_fkeys_1 ()
  ***********************************************************************/
 
 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
@@ -1556,9 +1509,14 @@ 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.  */
@@ -1632,6 +1590,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)
@@ -1641,6 +1600,81 @@ 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;
+      int c = it->c;
+
+      if (!STRINGP (object))
+       object = it->w->buffer;
+      it->object = object;
+      it->c = ' ';
+      it->pixel_width = it->len = 1;
+      while (n--)
+       append_glyph (it);
+      it->object = o_object;
+      it->c = c;
+    }
+  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
@@ -1893,58 +1927,11 @@ tty_capable_p (tty, caps, fg, bg)
   return 1;
 }
 
-/* Return the tty display object specified by DISPLAY.  DISPLAY may be
-   a frame, a string, or nil for the display device of the current
-   frame. */
-
-static struct display *
-get_tty_display (Lisp_Object display)
-{
-  struct display *d;
-
-  if (NILP (display))
-    display = selected_frame;
-
-  if (! FRAMEP (display) && ! STRINGP (display))
-    return 0;
-
-  /* The initial frame does not support colors. */
-  if (FRAMEP (display) && FRAME_INITIAL_P (XFRAME (display)))
-    return 0;
-
-  if (FRAMEP (display))
-    {
-      if (! FRAME_TERMCAP_P (XFRAME (display)))
-#if 0   /* XXX We need a predicate as the first argument; find one. */
-        wrong_type_argument ("Not a termcap frame", display);
-#else /* Until we fix the wrong_type_argument call above, simply throw
-         a dumb error. */
-      error ("DISPLAY is not a termcap frame");
-#endif  
-  
-      d = FRAME_DISPLAY (XFRAME (display));
-    }
-  else if (STRINGP (display))
-    {
-      char *name = (char *) alloca (SBYTES (display) + 1);
-      strncpy (name, SDATA (display), SBYTES (display));
-      name[SBYTES (display)] = 0;
-
-      d = get_named_tty_display (name);
-
-      if (!d)
-        error ("There is no tty display on %s", name);
-    }
-
-  return d;
-}
-
-
 /* Return non-zero if the terminal is capable to display colors.  */
 
 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
        0, 1, 0,
-       doc: /* Return non-nil if TTY can display colors on DISPLAY.  */)
+       doc: /* Return non-nil if the tty device that DISPLAY uses can display colors. */)
      (display)
      Lisp_Object display;
 {
@@ -1958,13 +1945,13 @@ DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
 /* Return the number of supported colors.  */
 DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
        Stty_display_color_cells, 0, 1, 0,
-       doc: /* Return the number of colors supported by TTY on DISPLAY.  */)
+       doc: /* Return the number of colors supported by the tty device that DISPLAY uses.  */)
      (display)
      Lisp_Object display;
 {
   struct display *d = get_tty_display (display);
   if (!d)
-    return Qnil;
+    return make_number (0);
   else
     return make_number (d->display_info.tty->TN_max_colors);
 }
@@ -2108,8 +2095,65 @@ set_tty_color_mode (f, val)
 
 \f
 
-/* Return the termcap display with the given name.  If NAME is null,
-   return the display corresponding to our controlling terminal.
+/* Return the display object specified by DISPLAY.  DISPLAY may be a
+   display id, a frame, or nil for the display device of the current
+   frame. */
+
+struct display *
+get_display (Lisp_Object display)
+{
+  if (NILP (display))
+    display = selected_frame;
+
+  if (! INTEGERP (display) && ! FRAMEP (display))
+    return NULL;
+
+  if (INTEGERP (display))
+    {
+      struct display *d;
+
+      for (d = display_list; d; d = d->next_display)
+        {
+          if (d->id == XINT (display))
+            return d;
+        }
+      return NULL;
+    }
+  else if (FRAMEP (display))
+    {
+      return FRAME_DISPLAY (XFRAME (display));
+    }
+  return NULL;
+}
+
+/* Return the tty display object specified by DISPLAY. */
+
+static struct display *
+get_tty_display (Lisp_Object display)
+{
+  struct display *d = get_display (display);
+  
+  if (d && d->type == output_initial)
+    d = NULL;
+
+  if (d && d->type != output_termcap)
+    {
+#if 0   /* XXX We need a predicate as the first argument; find one. */
+      wrong_type_argument ("Not a termcap display", display);
+#else /* Until we fix the wrong_type_argument call above, simply throw
+         a dumb error. */
+      error ("DISPLAY is not a termcap display");
+#endif
+    }
+
+  return d;
+}
+
+/* Return the active termcap display that uses the tty device with the
+   given name.  If NAME is NULL, return the display corresponding to
+   our controlling terminal.
+
+   This function ignores suspended displays.
 
    Returns NULL if the named terminal device is not opened.  */
  
@@ -2123,7 +2167,8 @@ get_named_tty_display (name)
     if (d->type == output_termcap
         && ((d->display_info.tty->name == 0 && name == 0)
             || (name && d->display_info.tty->name
-                && !strcmp (d->display_info.tty->name, name))))
+                && !strcmp (d->display_info.tty->name, name)))
+        && DISPLAY_ACTIVE_P (d))
       return d;
   };
 
@@ -2132,56 +2177,58 @@ get_named_tty_display (name)
 
 \f
 
-DEFUN ("frame-tty-name", Fframe_tty_name, Sframe_tty_name, 0, 1, 0,
-       doc: /* Return the name of the TTY device that FRAME is displayed on. */)
-  (frame)
-     Lisp_Object frame;
-{
-  struct frame *f;
+DEFUN ("display-name", Fdisplay_name, Sdisplay_name, 0, 1, 0,
+       doc: /* Return the name of the device that DISPLAY uses.
+It is not guaranteed that the returned value is unique among opened displays.
 
-  if (NILP (frame))
-    {
-      f = XFRAME (selected_frame);
-    }
-  else
-    {
-      CHECK_LIVE_FRAME (frame);
-      f = XFRAME (frame);
-    }
+DISPLAY can be a display, a frame, or nil (meaning the selected
+frame's display). */)
+  (display)
+     Lisp_Object display;
+{
+  struct display *d = get_display (display);
 
-  if (f->output_method != output_termcap)
-    wrong_type_argument (Qframe_tty_name, frame);
+  if (!d)
+    wrong_type_argument (Qdisplay_live_p, display);
 
-  if (FRAME_TTY (f)->name)
-    return build_string (FRAME_TTY (f)->name);
+  if (d->name)
+    return build_string (d->name);
   else
     return Qnil;
 }
 
-DEFUN ("frame-tty-type", Fframe_tty_type, Sframe_tty_type, 0, 1, 0,
-       doc: /* Return the type of the TTY device that FRAME is displayed on. */)
-  (frame)
-     Lisp_Object frame;
+DEFUN ("display-tty-type", Fdisplay_tty_type, Sdisplay_tty_type, 0, 1, 0,
+       doc: /* Return the type of the TTY device that DISPLAY uses. */)
+  (display)
+     Lisp_Object display;
 {
-  struct frame *f;
+  struct display *d = get_display (display);
 
-  if (NILP (frame))
-    {
-      f = XFRAME (selected_frame);
-    }
+  if (!d)
+    wrong_type_argument (Qdisplay_live_p, display);
+  if (d->type != output_termcap)
+    error ("Display %d is not a termcap display", d->id);
+           
+  if (d->display_info.tty->type)
+    return build_string (d->display_info.tty->type);
   else
-    {
-      CHECK_LIVE_FRAME (frame);
-      f = XFRAME (frame);
-    }
+    return Qnil;
+}
 
-  if (f->output_method != output_termcap)
-    wrong_type_argument (Qframe_tty_type, frame);
+DEFUN ("display-controlling-tty-p", Fdisplay_controlling_tty_p, Sdisplay_controlling_tty_p, 0, 1, 0,
+       doc: /* Return non-nil if DISPLAY is on the controlling tty of the Emacs process. */)
+  (display)
+     Lisp_Object display;
+{
+  struct display *d = get_display (display);
 
-  if (FRAME_TTY (f)->type)
-    return build_string (FRAME_TTY (f)->type);
-  else
+  if (!d)
+    wrong_type_argument (Qdisplay_live_p, display);
+
+  if (d->type != output_termcap || d->display_info.tty->name)
     return Qnil;
+  else
+    return Qt;
 }
 
 \f
@@ -2200,7 +2247,8 @@ init_initial_display (void)
 
   initial_display = create_display ();
   initial_display->type = output_initial;
-  
+  initial_display->name = xstrdup ("initial_display");
+
   initial_display->delete_display_hook = &delete_initial_display;
   /* All other hooks are NULL. */
   
@@ -2220,6 +2268,36 @@ delete_initial_display (struct display *display)
   initial_display = NULL;
 }
 
+/* Drop the controlling terminal if fd is the same device. */
+void
+dissociate_if_controlling_tty (int fd)
+{
+  int pgid;
+  EMACS_GET_TTY_PGRP (fd, &pgid); /* If tcgetpgrp succeeds, fd is the ctty. */
+  if (pgid != -1)
+    {
+#if defined (USG) && !defined (BSD_PGRPS)
+      setpgrp ();
+      no_controlling_tty = 1;
+#else
+#ifdef TIOCNOTTY                /* Try BSD ioctls. */
+      sigblock (sigmask (SIGTTOU));
+      fd = emacs_open ("/dev/tty", O_RDWR, 0);
+      if (fd != -1 && ioctl (fd, TIOCNOTTY, 0) != -1)
+        {
+          no_controlling_tty = 1;
+        }
+      if (fd != -1)
+        emacs_close (fd);
+      sigunblock (sigmask (SIGTTOU));
+#else
+      /* Unknown system. */
+      croak ();
+#endif  /* ! TIOCNOTTY */
+#endif  /* ! USG */
+    }
+}
+
 /* Create a termcap display on the tty device with the given name and
    type.
 
@@ -2249,14 +2327,15 @@ term_init (char *name, char *terminal_type, int must_succeed)
     maybe_fatal (must_succeed, 0, 0,
                  "Unknown terminal type",
                  "Unknown terminal type");
-  
+
+  /* If we already have an active display on the given device, use that.
+     If all displays are suspended, create a new one instead.  */
+  /* XXX Perhaps this should be made explicit by having term_init
+     always create a new display and separating display and frame
+     creation on Lisp level.  */
   display = get_named_tty_display (name);
   if (display)
-    {
-      if (! display->display_info.tty->input)
-        error ("%s already has a suspended frame on it, can't open it twice", name);
-      return display;
-    }
+    return display;
 
   display = create_display ();
   tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info));
@@ -2320,21 +2399,13 @@ term_init (char *name, char *terminal_type, int must_succeed)
          if we don't have one at the moment.  */
       fd = emacs_open (name, O_RDWR | O_IGNORE_CTTY | O_NOCTTY, 0);
 #else
-      /* Alas, O_IGNORE_CTTY is a GNU extension that is only defined
-         on Hurd.  On other systems, we need to dissociate ourselves
-         from the controlling tty when we want to open a frame on the
-         same terminal.  The function setsid should be used for this,
-         but it didn't work for me. */
+      /* Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
+         defined on Hurd.  On other systems, we need to dissociate
+         ourselves from the controlling tty when we want to open a
+         frame on the same terminal.  */
 
       fd = emacs_open (name, O_RDWR | O_NOCTTY, 0);
-      
-#ifdef TIOCNOTTY
-      /* Drop our controlling tty if it is the same device. */
-      if (ioctl (fd, TIOCNOTTY, 0) != -1)
-        {
-          no_controlling_tty = 1;
-        }
-#endif
+
 #endif /* O_IGNORE_CTTY */
 
       if (fd < 0)
@@ -2348,8 +2419,11 @@ term_init (char *name, char *terminal_type, int must_succeed)
           error ("Not a tty device: %s", name);
         }
 
+      dissociate_if_controlling_tty (fd);
+      
       file = fdopen (fd, "w+");
       tty->name = xstrdup (name);
+      display->name = xstrdup (name);
       tty->input = file;
       tty->output = file;
     }
@@ -2362,6 +2436,7 @@ term_init (char *name, char *terminal_type, int must_succeed)
           error ("There is no controlling terminal any more");
         }
       tty->name = 0;
+      display->name = xstrdup (ttyname (0));
       tty->input = stdin;
       tty->output = stdout;
     }
@@ -2405,7 +2480,13 @@ term_init (char *name, char *terminal_type, int must_succeed)
   Wcm_clear (tty);
 
   buffer = (char *) xmalloc (buffer_size);
+  
+  /* On some systems, tgetent tries to access the controlling
+     terminal. */
+  sigblock (sigmask (SIGTTOU));
   status = tgetent (buffer, terminal_type);
+  sigunblock (sigmask (SIGTTOU));
+  
   if (status < 0)
     {
 #ifdef TERMINFO
@@ -2841,37 +2922,6 @@ fatal (str, arg1, arg2)
 
 \f
 
-DEFUN ("delete-tty", Fdelete_tty, Sdelete_tty, 0, 1, 0,
-       doc: /* Delete all frames on the terminal named TTY, and close the device.
-If omitted, TTY defaults to the controlling terminal.
-
-This function runs `delete-tty-after-functions' after closing the
-tty.  The functions are run with one arg, the frame to be deleted.  */)
-  (tty)
-     Lisp_Object tty;
-{
-  struct display *d;
-  char *name = 0;
-
-  CHECK_STRING (tty);
-
-  if (SBYTES (tty) > 0)
-    {
-      name = (char *) alloca (SBYTES (tty) + 1);
-      strncpy (name, SDATA (tty), SBYTES (tty));
-      name[SBYTES (tty)] = 0;
-    }
-
-  d = get_named_tty_display (name);
-
-  if (! d)
-    error ("No such terminal device: %s", name);
-
-  delete_tty (d);
-
-  return Qnil;
-}
-
 static int deleting_tty = 0;
 
 
@@ -2972,21 +3022,6 @@ delete_tty (struct display *display)
   bzero (tty, sizeof (struct tty_display_info));
   xfree (tty);
   deleting_tty = 0;
-
-  /* Run `delete-tty-after-functions'.  */
-  if (!NILP (Vrun_hooks))
-    {
-      Lisp_Object args[2];
-      args[0] = intern ("delete-tty-after-functions");
-      if (tty_name)
-        {
-          args[1] = build_string (tty_name);
-          xfree (tty_name);
-        }
-      else
-        args[1] = Qnil;
-      Frun_hook_with_args (2, args);
-    }
 }
 
 \f
@@ -3046,19 +3081,29 @@ mark_ttys ()
 struct display *
 create_display (void)
 {
-  struct display *dev = (struct display *) xmalloc (sizeof (struct display));
+  struct display *display = (struct display *) xmalloc (sizeof (struct display));
   
-  bzero (dev, sizeof (struct display));
-  dev->next_display = display_list;
-  display_list = dev;
+  bzero (display, sizeof (struct display));
+  display->next_display = display_list;
+  display_list = display;
+
+  display->id = next_display_id++;
 
-  return dev;
+  display->keyboard_coding =
+    (struct coding_system *) xmalloc (sizeof (struct coding_system));
+  display->terminal_coding =
+    (struct coding_system *) xmalloc (sizeof (struct coding_system));
+  
+  setup_coding_system (Qnil, display->keyboard_coding);
+  setup_coding_system (Qnil, display->terminal_coding);
+  
+  return display;
 }
 
 /* Remove a display from the display list and free its memory. */
 
 void
-delete_display (struct display *dev)
+delete_display (struct display *display)
 {
   struct display **dp;
   Lisp_Object tail, frame;
@@ -3068,36 +3113,129 @@ delete_display (struct display *dev)
   FOR_EACH_FRAME (tail, frame)
     {
       struct frame *f = XFRAME (frame);
-      if (FRAME_LIVE_P (f) && f->display == dev)
+      if (FRAME_LIVE_P (f) && f->display == display)
         {
           Fdelete_frame (frame, Qt);
         }
     }
 
-  for (dp = &display_list; *dp != dev; dp = &(*dp)->next_display)
+  for (dp = &display_list; *dp != display; dp = &(*dp)->next_display)
     if (! *dp)
       abort ();
-  *dp = dev->next_display;
+  *dp = display->next_display;
+
+  if (display->keyboard_coding)
+    xfree (display->keyboard_coding);
+  if (display->terminal_coding)
+    xfree (display->terminal_coding);
+  if (display->name)
+    xfree (display->name);
+  
+  bzero (display, sizeof (struct display));
+  xfree (display);
+}
+
+DEFUN ("delete-display", Fdelete_display, Sdelete_display, 0, 2, 0,
+       doc: /* Delete DISPLAY by deleting all frames on it and closing the device.
+DISPLAY may be a display id, a frame, or nil for the display
+device of the current frame.
+
+Normally, you may not delete a display if all other displays are suspended,
+but if the second argument FORCE is non-nil, you may do so. */)
+  (display, force)
+     Lisp_Object display, force;
+{
+  struct display *d, *p;
+
+  d = get_display (display);
+
+  if (!d)
+    return Qnil;
+
+  p = display_list;
+  while (p && (p == d || !DISPLAY_ACTIVE_P (p)))
+    p = p->next_display;
+  
+  if (NILP (force) && !p)
+    error ("Attempt to delete the sole active display");
+
+  if (d->delete_display_hook)
+    (*d->delete_display_hook) (d);
+  else
+    delete_display (d);
+
+  return Qnil;
+}
+
+DEFUN ("display-live-p", Fdisplay_live_p, Sdisplay_live_p, 1, 1, 0,
+       doc: /* Return non-nil if OBJECT is a display which has not been deleted.
+Value is nil if OBJECT is not a live display.
+If object is a live display, the return value indicates what sort of
+output device it uses.  See the documentation of `framep' for possible
+return values.
+
+Displays are represented by their integer identifiers. */)
+  (object)
+     Lisp_Object object;
+{
+  struct display *d;
+  
+  if (!INTEGERP (object))
+    return Qnil;
+
+  d = get_display (object);
+
+  if (!d)
+    return Qnil;
+
+  switch (d->type)
+    {
+    case output_initial: /* The initial frame is like a termcap frame. */
+    case output_termcap:
+      return Qt;
+    case output_x_window:
+      return Qx;
+    case output_w32:
+      return Qw32;
+    case output_msdos_raw:
+      return Qpc;
+    case output_mac:
+      return Qmac;
+    default:
+      abort ();
+    }
+}
+
+DEFUN ("display-list", Fdisplay_list, Sdisplay_list, 0, 0, 0,
+       doc: /* Return a list of all displays.
+Displays are represented by their integer identifiers. */)
+  ()
+{
+  Lisp_Object displays = Qnil;
+  struct display *d;
+
+  for (d = display_list; d; d = d->next_display)
+    displays = Fcons (make_number (d->id), displays);
 
-  bzero (dev, sizeof (struct display));
-  xfree (dev);
+  return displays;
 }
 
+            
 \f
 
 DEFUN ("suspend-tty", Fsuspend_tty, Ssuspend_tty, 0, 1, 0,
        doc: /* Suspend the terminal device TTY.
-The terminal is restored to its default state, and Emacs closes all
+The terminal is restored to its default state, and Emacs ceases all
 access to the terminal device.  Frames that use the device are not
 deleted, but input is not read from them and if they change, their
 display is not updated.
 
-TTY may a string (a device name), a frame, or nil for the display
-device of the currently selected frame.
+TTY may be a display id, a frame, or nil for the display device of the
+currently selected frame.
 
 This function runs `suspend-tty-functions' after suspending the
-device.  The functions are run with one arg, the name of the terminal
-device.
+device.  The functions are run with one arg, the id of the suspended
+display device.
 
 `suspend-tty' does nothing if it is called on an already suspended
 device.
@@ -3136,12 +3274,7 @@ it. */)
         {
           Lisp_Object args[2];
           args[0] = intern ("suspend-tty-functions");
-          if (d->display_info.tty->name)
-            {
-              args[1] = build_string (d->display_info.tty->name);
-            }
-          else
-            args[1] = Qnil;
+          args[1] = make_number (d->id);
           Frun_hook_with_args (2, args);
         }
     }
@@ -3152,17 +3285,21 @@ it. */)
 
 DEFUN ("resume-tty", Fresume_tty, Sresume_tty, 0, 1, 0,
        doc: /* Resume the previously suspended terminal device TTY.
-The terminal is opened and reinitialized.  Frames that used the
-suspended device are revived.
+The terminal is opened and reinitialized.  Frames that are on the
+suspended display are revived.
+
+It is an error to resume a display while another display is active on
+the same device.
 
 This function runs `resume-tty-functions' after resuming the device.
-The functions are run with one arg, the name of the terminal device.
+The functions are run with one arg, the id of the resumed display
+device.
 
 `resume-tty' does nothing if it is called on a device that is not
 suspended.
 
-TTY may a string (a device name), a frame, or nil for the display
-device of the currently selected frame. */)
+TTY may be a display id, a frame, or nil for the display device of the
+currently selected frame. */)
   (tty)
      Lisp_Object tty;
 {
@@ -3174,16 +3311,15 @@ device of the currently selected frame. */)
 
   if (!d->display_info.tty->input)
     {
+      if (get_named_tty_display (d->display_info.tty->name))
+        error ("Cannot resume display while another display is active on the same device");
+
       fd = emacs_open (d->display_info.tty->name, O_RDWR | O_NOCTTY, 0);
-  
-#ifdef TIOCNOTTY
-      /* Drop our controlling tty if it is the same device. */
-      if (ioctl (fd, TIOCNOTTY, 0) != -1)
-        {
-          no_controlling_tty = 1;
-        }
-#endif
 
+      /* XXX What if open fails? */
+
+      dissociate_if_controlling_tty (fd);
+      
       d->display_info.tty->output = fdopen (fd, "w+");
       d->display_info.tty->input = d->display_info.tty->output;
     
@@ -3199,12 +3335,7 @@ device of the currently selected frame. */)
         {
           Lisp_Object args[2];
           args[0] = intern ("resume-tty-functions");
-          if (d->display_info.tty->name)
-            {
-              args[1] = build_string (d->display_info.tty->name);
-            }
-          else
-            args[1] = Qnil;
+          args[1] = make_number (d->id);
           Frun_hook_with_args (2, args);
         }
     }
@@ -3230,13 +3361,6 @@ This variable can be used by terminal emulator packages.  */);
 The function should accept no arguments.  */);
   Vring_bell_function = Qnil;
 
-  DEFVAR_LISP ("delete-tty-after-functions", &Vdelete_tty_after_functions,
-    doc: /* Functions to be run after deleting a tty.
-The functions are run with one argument, the name of the tty to be deleted.
-See `delete-tty'.  */);
-  Vdelete_tty_after_functions = Qnil;
-
-
   DEFVAR_LISP ("suspend-tty-functions", &Vsuspend_tty_functions,
     doc: /* Functions to be run after suspending a tty.
 The functions are run with one argument, the name of the tty to be suspended.
@@ -3250,17 +3374,14 @@ The functions are run with one argument, the name of the tty that was revived.
 See `resume-tty'.  */);
   Vresume_tty_functions = Qnil;
 
-  Qframe_tty_name = intern ("frame-tty-name");
-  staticpro (&Qframe_tty_name);
-
-  Qframe_tty_type = intern ("frame-tty-type");
-  staticpro (&Qframe_tty_type);
-
   defsubr (&Stty_display_color_p);
   defsubr (&Stty_display_color_cells);
-  defsubr (&Sframe_tty_name);
-  defsubr (&Sframe_tty_type);
-  defsubr (&Sdelete_tty);
+  defsubr (&Sdisplay_name);
+  defsubr (&Sdisplay_tty_type);
+  defsubr (&Sdisplay_controlling_tty_p);
+  defsubr (&Sdelete_display);
+  defsubr (&Sdisplay_live_p);
+  defsubr (&Sdisplay_list);
   defsubr (&Ssuspend_tty);
   defsubr (&Sresume_tty);