#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"
#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
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 *));
#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 a tty was deleted. */
-Lisp_Object Vdelete_tty_after_functions;
+/* Functions to call after suspending a tty. */
+Lisp_Object Vsuspend_tty_functions;
+
+/* Functions to call after resuming a tty. */
+Lisp_Object Vresume_tty_functions;
/* Chain of all displays currently in use. */
struct display *display_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. */
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;
#endif /* WINDOWSNT */
void
-ring_bell ()
+ring_bell (struct frame *f)
{
- struct frame *f = XFRAME (selected_frame);
-
if (!NILP (Vring_bell_function))
{
Lisp_Object function;
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. */
{
struct tty_display_info *tty = display->display_info.tty;
- OUTPUT_IF (tty, tty->TS_termcap_modes);
- OUTPUT_IF (tty, tty->TS_cursor_visible);
- OUTPUT_IF (tty, tty->TS_keypad_mode);
- losecursor (tty);
+ if (tty->output)
+ {
+ OUTPUT_IF (tty, tty->TS_termcap_modes);
+ OUTPUT_IF (tty, tty->TS_cursor_visible);
+ OUTPUT_IF (tty, tty->TS_keypad_mode);
+ losecursor (tty);
+ }
}
/* Reset termcap modes before exiting Emacs. */
tty_reset_terminal_modes (struct display *display)
{
struct tty_display_info *tty = display->display_info.tty;
-
- turn_off_highlight (tty);
- turn_off_insert (tty);
- OUTPUT_IF (tty, tty->TS_end_keypad_mode);
- OUTPUT_IF (tty, tty->TS_cursor_normal);
- OUTPUT_IF (tty, tty->TS_end_termcap_modes);
- OUTPUT_IF (tty, tty->TS_orig_pair);
- /* Output raw CR so kernel can track the cursor hpos. */
- current_tty = tty;
- cmputc ('\r');
+
+ if (tty->output)
+ {
+ turn_off_highlight (tty);
+ turn_off_insert (tty);
+ OUTPUT_IF (tty, tty->TS_end_keypad_mode);
+ OUTPUT_IF (tty, tty->TS_cursor_normal);
+ OUTPUT_IF (tty, tty->TS_end_termcap_modes);
+ OUTPUT_IF (tty, tty->TS_orig_pair);
+ /* Output raw CR so kernel can track the cursor hpos. */
+ current_tty = tty;
+ cmputc ('\r');
+ }
}
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. */
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)
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
/* 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
/* 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)
{
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));
}
}
}
/* 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)
}
else
{
- cursor_to (0, 0);
- clear_to_end ();
+ cursor_to (f, 0, 0);
+ clear_to_end (f);
}
}
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.
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
for (i = curX (tty); i < first_unused_hpos; i++)
{
- if (TTY_TERMSCRIPT (tty))
- fputc (' ', TTY_TERMSCRIPT (tty));
- fputc (' ', TTY_OUTPUT (tty));
+ if (tty->termscript)
+ fputc (' ', tty->termscript);
+ fputc (' ', tty->output);
}
cmplus (tty, first_unused_hpos - curX (tty));
}
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;
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)
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);
/* 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)
{
/* 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)
{
fwrite (conversion_buffer, 1, produced,
- TTY_OUTPUT (tty));
- if (ferror (TTY_OUTPUT (tty)))
- clearerr (TTY_OUTPUT (tty));
- if (TTY_TERMSCRIPT (tty))
+ tty->output);
+ if (ferror (tty->output))
+ clearerr (tty->output);
+ if (tty->termscript)
fwrite (conversion_buffer, 1, produced,
- TTY_TERMSCRIPT (tty));
+ tty->termscript);
}
len -= consumed;
n -= consumed;
}
/* 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,
- TTY_OUTPUT (tty));
- if (ferror (TTY_OUTPUT (tty)))
- clearerr (TTY_OUTPUT (tty));
- if (TTY_TERMSCRIPT (tty))
- fwrite (conversion_buffer, 1, terminal_coding.produced,
- TTY_TERMSCRIPT (tty));
+ 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,
+ FRAME_TERMINAL_CODING (f)->produced,
+ tty->termscript);
}
}
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);
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;
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);
}
if (produced > 0)
{
fwrite (conversion_buffer, 1, produced,
- TTY_OUTPUT (tty));
- if (ferror (TTY_OUTPUT (tty)))
- clearerr (TTY_OUTPUT (tty));
- if (TTY_TERMSCRIPT (tty))
+ tty->output);
+ if (ferror (tty->output))
+ clearerr (tty->output);
+ if (tty->termscript)
fwrite (conversion_buffer, 1, produced,
- TTY_TERMSCRIPT (tty));
+ tty->termscript);
}
OUTPUT1_IF (tty, tty->TS_pad_inserted_char);
/* 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);
/* 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;
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);
}
else if (single)
{
- raw_cursor_to (vpos, 0);
+ raw_cursor_to (f, vpos, 0);
background_highlight (tty);
while (--i >= 0)
OUTPUT (tty, single);
}
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
not counting any line-dependent padding. */
int
-string_cost (str)
- char *str;
+string_cost (char *str)
{
cost = 0;
if (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)
in tenths of characters. */
int
-per_line_cost (str)
- register char *str;
+per_line_cost (char *str)
{
cost = 0;
if (str)
/* 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;
}
void
-calculate_costs (frame)
- FRAME_PTR frame;
+calculate_costs (struct frame *frame)
{
FRAME_COST_BAUD_RATE (frame) = baud_rate;
***********************************************************************/
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
/* 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. */
append_glyph (it);
}
+ done:
/* Advance current_x by the pixel width as a convenience for
the caller. */
if (it->area == TEXT_AREA)
}
+/* 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
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;
{
/* 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);
}
\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. */
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;
};
\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
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. */
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.
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)
- return display; /* We have already opened a display there. */
+ return display;
display = create_display ();
tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info));
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)
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;
}
error ("There is no controlling terminal any more");
}
tty->name = 0;
+ display->name = xstrdup (ttyname (0));
tty->input = stdin;
tty->output = stdout;
}
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
/* Get frame size from system, or else from termcap. */
{
int height, width;
- get_tty_size (fileno (TTY_INPUT (tty)), &width, &height);
+ get_tty_size (fileno (tty->input), &width, &height);
FrameCols (tty) = width;
FrameRows (tty) = height;
}
&& tty->TS_end_standout_mode
&& !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode));
- UseTabs (tty) = tabs_safe_p (fileno (TTY_INPUT (tty))) && TabWidth (tty) == 8;
+ UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8;
display->scroll_region_ok
= (tty->Wcm->cm_abs
display->fast_clear_end_of_line = tty->TS_clr_line != 0;
- init_baud_rate (fileno (TTY_INPUT (tty)));
+ init_baud_rate (fileno (tty->input));
#ifdef AIXHFT
/* The HFT system on AIX doesn't optimize for scrolling, so it's
\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;
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
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;
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 ();
+ }
+}
- bzero (dev, sizeof (struct display));
- xfree (dev);
+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);
+
+ 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 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 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 id of the suspended
+display device.
+
+`suspend-tty' does nothing if it is called on an already suspended
+device.
+
+A suspended terminal device may be resumed by calling `resume-tty' on
+it. */)
+ (tty)
+ Lisp_Object tty;
+{
+ struct display *d = get_tty_display (tty);
+ FILE *f;
+
+ if (!d)
+ error ("Unknown tty device");
+
+ f = d->display_info.tty->input;
+
+ if (f)
+ {
+ reset_sys_modes (d->display_info.tty);
+
+ delete_keyboard_wait_descriptor (fileno (f));
+
+ fclose (f);
+ if (f != d->display_info.tty->output)
+ fclose (d->display_info.tty->output);
+
+ d->display_info.tty->input = 0;
+ d->display_info.tty->output = 0;
+
+ if (FRAMEP (d->display_info.tty->top_frame))
+ FRAME_SET_VISIBLE (XFRAME (d->display_info.tty->top_frame), 0);
+
+ /* Run `suspend-tty-functions'. */
+ if (!NILP (Vrun_hooks))
+ {
+ Lisp_Object args[2];
+ args[0] = intern ("suspend-tty-functions");
+ args[1] = make_number (d->id);
+ Frun_hook_with_args (2, args);
+ }
+ }
+
+ return Qnil;
+}
+
+
+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 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 id of the resumed display
+device.
+
+`resume-tty' does nothing if it is called on a device that is not
+suspended.
+
+TTY may be a display id, a frame, or nil for the display device of the
+currently selected frame. */)
+ (tty)
+ Lisp_Object tty;
+{
+ struct display *d = get_tty_display (tty);
+ int fd;
+
+ if (!d)
+ error ("Unknown tty device");
+
+ 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);
+
+ /* 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;
+
+ add_keyboard_wait_descriptor (fd);
+
+ if (FRAMEP (d->display_info.tty->top_frame))
+ FRAME_SET_VISIBLE (XFRAME (d->display_info.tty->top_frame), 1);
+
+ init_sys_modes (d->display_info.tty);
+
+ /* Run `suspend-tty-functions'. */
+ if (!NILP (Vrun_hooks))
+ {
+ Lisp_Object args[2];
+ args[0] = intern ("resume-tty-functions");
+ args[1] = make_number (d->id);
+ Frun_hook_with_args (2, args);
+ }
+ }
+
+ return Qnil;
+}
\f
void
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.
+See `suspend-tty'. */);
+ Vsuspend_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);
+ DEFVAR_LISP ("resume-tty-functions", &Vresume_tty_functions,
+ doc: /* Functions to be run after resuming a tty.
+The functions are run with one argument, the name of the tty that was revived.
+See `resume-tty'. */);
+ Vresume_tty_functions = Qnil;
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);
Fprovide (intern ("multi-tty"), Qnil);