#include <sys/file.h>
#include "lisp.h"
-#include "systty.h" /* For emacs_tty in termchar.h */
#include "termchar.h"
#include "termopts.h"
#include "charset.h"
static void tty_show_cursor P_ ((struct tty_display_info *));
static void tty_hide_cursor P_ ((struct tty_display_info *));
-void delete_tty P_ ((struct tty_display_info *));
-static void delete_tty_1 P_ ((struct tty_display_info *));
-
+void delete_initial_display P_ ((struct display *));
+void delete_tty P_ ((struct display *));
+void create_tty_output P_ ((struct frame *));
+void delete_tty_output P_ ((struct frame *));
#define OUTPUT(tty, a) \
emacs_tputs ((tty), a, \
/* Functions to call after a tty was deleted. */
Lisp_Object Vdelete_tty_after_functions;
-/* Terminal characteristics that higher levels want to look at. */
+/* Chain of all displays currently in use. */
+struct display *display_list;
+
+/* The initial display device, created by initial_term_init. */
+struct display *initial_display;
+/* Chain of all tty device parameters. */
struct tty_display_info *tty_list;
/* Nonzero means no need to redraw the entire frame on resuming a
Lisp_Object Qframe_tty_name, Qframe_tty_type;
-/* Hook functions that you can set to snap out the functions in this file.
- These are all extern'd in termhooks.h */
-
-void (*cursor_to_hook) P_ ((int, int));
-void (*raw_cursor_to_hook) P_ ((int, int));
-void (*clear_to_end_hook) P_ ((void));
-void (*clear_frame_hook) P_ ((void));
-void (*clear_end_of_line_hook) P_ ((int));
-
-void (*ins_del_lines_hook) P_ ((int, int));
-
-void (*delete_glyphs_hook) P_ ((int));
-
-void (*ring_bell_hook) P_ ((void));
-
-void (*reset_terminal_modes_hook) P_ ((void));
-void (*set_terminal_modes_hook) P_ ((void));
-void (*update_begin_hook) P_ ((struct frame *));
-void (*update_end_hook) P_ ((struct frame *));
-void (*set_terminal_window_hook) P_ ((int));
-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_ ((struct input_event *, int, int));
-
-void (*frame_up_to_date_hook) P_ ((struct frame *));
-
-/* Return the current position of the mouse.
-
- Set *f to the frame the mouse is in, or zero if the mouse is in no
- Emacs frame. If it is set to zero, all the other arguments are
- garbage.
-
- If the motion started in a scroll bar, set *bar_window to the
- scroll bar's window, *part to the part the mouse is currently over,
- *x to the position of the mouse along the scroll bar, and *y to the
- overall length of the scroll bar.
-
- Otherwise, set *bar_window to Qnil, and *x and *y to the column and
- row of the character cell the mouse is over.
-
- Set *time to the time the mouse was at the returned position.
-
- This should clear mouse_moved until the next motion
- event arrives. */
-
-void (*mouse_position_hook) P_ ((FRAME_PTR *f, int insist,
- Lisp_Object *bar_window,
- enum scroll_bar_part *part,
- Lisp_Object *x,
- Lisp_Object *y,
- unsigned long *time));
-
-/* When reading from a minibuffer in a different frame, Emacs wants
- to shift the highlight from the selected frame to the mini-buffer's
- frame; under X, this means it lies about where the focus is.
- This hook tells the window system code to re-decide where to put
- the highlight. */
-
-void (*frame_rehighlight_hook) P_ ((FRAME_PTR f));
-
-/* If we're displaying frames using a window system that can stack
- frames on top of each other, this hook allows you to bring a frame
- to the front, or bury it behind all the other windows. If this
- hook is zero, that means the device we're displaying on doesn't
- support overlapping frames, so there's no need to raise or lower
- anything.
-
- If RAISE is non-zero, F is brought to the front, before all other
- windows. If RAISE is zero, F is sent to the back, behind all other
- windows. */
-
-void (*frame_raise_lower_hook) P_ ((FRAME_PTR f, int raise));
-
-/* 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
- of WHOLE characters, starting at POSITION. If WINDOW doesn't yet
- have a scroll bar, create one for it. */
-
-void (*set_vertical_scroll_bar_hook)
- P_ ((struct window *window,
- int portion, int whole, int position));
-
-
-/* The following three hooks are used when we're doing a thorough
- redisplay of the frame. We don't explicitly know which scroll bars
- are going to be deleted, because keeping track of when windows go
- away is a real pain - can you say set-window-configuration?
- Instead, we just assert at the beginning of redisplay that *all*
- scroll bars are to be removed, and then save scroll bars from the
- fiery pit when we actually redisplay their window. */
-
-/* Arrange for all scroll bars on FRAME to be removed at the next call
- to `*judge_scroll_bars_hook'. A scroll bar may be spared if
- `*redeem_scroll_bar_hook' is applied to its window before the judgment.
-
- This should be applied to each frame each time its window tree is
- redisplayed, even if it is not displaying scroll bars at the moment;
- if the HAS_SCROLL_BARS flag has just been turned off, only calling
- this and the judge_scroll_bars_hook will get rid of them.
-
- If non-zero, this hook should be safe to apply to any frame,
- whether or not it can support scroll bars, and whether or not it is
- currently displaying them. */
-
-void (*condemn_scroll_bars_hook) P_ ((FRAME_PTR frame));
-
-/* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
- Note that it's okay to redeem a scroll bar that is not condemned. */
-
-void (*redeem_scroll_bar_hook) P_ ((struct window *window));
-
-/* Remove all scroll bars on FRAME that haven't been saved since the
- last call to `*condemn_scroll_bars_hook'.
-
- This should be applied to each frame after each time its window
- tree is redisplayed, even if it is not displaying scroll bars at the
- moment; if the HAS_SCROLL_BARS flag has just been turned off, only
- calling this and condemn_scroll_bars_hook will get rid of them.
-
- If non-zero, this hook should be safe to apply to any frame,
- whether or not it can support scroll bars, and whether or not it is
- currently displaying them. */
-
-void (*judge_scroll_bars_hook) P_ ((FRAME_PTR FRAME));
/* Meaning of bits in no_color_video. Each bit set means that the
int max_frame_lines;
-/* A template for tty display methods, with common values
- preinitialized. */
-static struct display_method tty_display_method_template;
-
/* Frame currently being redisplayed; 0 if not currently redisplaying.
(Direct output does not count). */
void
ring_bell ()
{
- struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
+ struct frame *f = XFRAME (selected_frame);
if (!NILP (Vring_bell_function))
{
Vring_bell_function = function;
}
- else if (!FRAME_TERMCAP_P (f))
- (*ring_bell_hook) ();
- else {
- struct tty_display_info *tty = FRAME_TTY (f);
- OUTPUT (tty, tty->TS_visible_bell && visible_bell ? tty->TS_visible_bell : tty->TS_bell);
- }
+ else if (FRAME_DISPLAY (f)->ring_bell_hook)
+ (*FRAME_DISPLAY (f)->ring_bell_hook) ();
}
-void tty_set_terminal_modes (struct tty_display_info *tty)
+/* Ring the bell on a tty. */
+
+void
+tty_ring_bell ()
+{
+ 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));
+}
+
+/* Set up termcap modes for Emacs. */
+
+void
+tty_set_terminal_modes (struct display *display)
{
+ 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);
}
-void
-set_terminal_modes ()
-{
- struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
- if (FRAME_TERMCAP_P (f))
- tty_set_terminal_modes (FRAME_TTY (f));
- else
- (*set_terminal_modes_hook) ();
-}
+/* Reset termcap modes before exiting Emacs. */
-void tty_reset_terminal_modes (struct tty_display_info *tty)
+void
+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);
cmputc ('\r');
}
-void
-reset_terminal_modes ()
-{
- struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
- if (FRAME_TERMCAP_P (f))
- tty_reset_terminal_modes (FRAME_TTY (f));
- else if (reset_terminal_modes_hook)
- (*reset_terminal_modes_hook) ();
-}
-
void
update_begin (f)
struct frame *f;
{
updating_frame = f;
- if (!FRAME_TERMCAP_P (f))
- update_begin_hook (f);
+ if (FRAME_DISPLAY (f)->update_begin_hook)
+ (*FRAME_DISPLAY (f)->update_begin_hook) (f);
}
void
update_end (f)
struct frame *f;
{
- if (FRAME_TERMCAP_P (f))
- {
- struct tty_display_info *tty = FRAME_TTY (f);
- if (!XWINDOW (selected_window)->cursor_off_p)
- tty_show_cursor (tty);
- turn_off_insert (tty);
- background_highlight (tty);
- }
- else
- update_end_hook (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. */
+
+void
+tty_update_end (struct frame *f)
+{
+ struct tty_display_info *tty = FRAME_TTY (f);
+
+ if (!XWINDOW (selected_window)->cursor_off_p)
+ tty_show_cursor (tty);
+ turn_off_insert (tty);
+ background_highlight (tty);
+}
+
+/* Specify how many text lines, from the top of the window,
+ should be affected by insert-lines and delete-lines operations.
+ This, and those operations, are used only within an update
+ that is bounded by calls to update_begin and update_end. */
+
void
set_terminal_window (size)
int size;
{
- struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
- if (FRAME_TERMCAP_P (f))
- {
- 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);
- }
- else
- set_terminal_window_hook (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);
+}
+
+/* The implementation of set_terminal_window for termcap frames. */
+
+void
+tty_set_terminal_window (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);
}
void
int start, stop;
{
char *buf;
- struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
+ struct frame *f = (updating_frame
+ ? updating_frame
+ : XFRAME (selected_frame));
+
struct tty_display_info *tty = FRAME_TTY (f);
if (tty->TS_set_scroll_region)
cursor_to (vpos, hpos)
int vpos, hpos;
{
- struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
- struct tty_display_info *tty;
+ struct frame *f = (updating_frame
+ ? updating_frame
+ : XFRAME (selected_frame));
- if (! FRAME_TERMCAP_P (f) && cursor_to_hook)
- {
- (*cursor_to_hook) (vpos, hpos);
- return;
- }
+ if (FRAME_DISPLAY (f)->cursor_to_hook)
+ (*FRAME_DISPLAY (f)->cursor_to_hook) (vpos, hpos);
+}
- tty = FRAME_TTY (f);
+void
+tty_cursor_to (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
and the costs have never been calculated. Do nothing. */
raw_cursor_to (row, col)
int row, col;
{
- struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
- struct tty_display_info *tty;
- if (! FRAME_TERMCAP_P (f))
- {
- (*raw_cursor_to_hook) (row, col);
- return;
- }
- tty = FRAME_TTY (f);
+ 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);
+}
+
+void
+tty_raw_cursor_to (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
&& curX (tty) == col)
return;
\f
/* Erase operations */
-/* clear from cursor to end of frame */
+/* Clear from cursor to end of frame. */
void
clear_to_end ()
{
- register int i;
+ struct frame *f = (updating_frame
+ ? updating_frame
+ : XFRAME (selected_frame));
- struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
- struct tty_display_info *tty;
+ if (FRAME_DISPLAY (f)->clear_to_end_hook)
+ (*FRAME_DISPLAY (f)->clear_to_end_hook) ();
+}
+
+/* Clear from cursor to end of frame on a termcap device. */
+
+void
+tty_clear_to_end (void)
+{
+ register int i;
+ struct frame *f = (updating_frame
+ ? updating_frame
+ : XFRAME (selected_frame));
+ struct tty_display_info *tty = FRAME_TTY (f);
- if (clear_to_end_hook && ! FRAME_TERMCAP_P (f))
- {
- (*clear_to_end_hook) ();
- return;
- }
- tty = FRAME_TTY (f);
if (tty->TS_clr_to_bottom)
{
background_highlight (tty);
clear_frame ()
{
struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
- struct tty_display_info *tty;
- if (clear_frame_hook && ! FRAME_TERMCAP_P (f))
- {
- (*clear_frame_hook) ();
- return;
- }
- tty = FRAME_TTY (f);
+ if (FRAME_DISPLAY (f)->clear_frame_hook)
+ (*FRAME_DISPLAY (f)->clear_frame_hook) ();
+}
+
+/* Clear an entire termcap frame. */
+
+void
+tty_clear_frame ()
+{
+ struct frame *f = (updating_frame
+ ? updating_frame
+ : XFRAME (selected_frame));
+
+ struct tty_display_info *tty = FRAME_TTY (f);
+
if (tty->TS_clr_frame)
{
background_highlight (tty);
clear_end_of_line (first_unused_hpos)
int first_unused_hpos;
{
- struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
- struct tty_display_info *tty;
+ struct frame *f = (updating_frame
+ ? updating_frame
+ : XFRAME (selected_frame));
- if (clear_end_of_line_hook && ! FRAME_TERMCAP_P (f))
- {
- (*clear_end_of_line_hook) (first_unused_hpos);
- return;
- }
-
- tty_clear_end_of_line (FRAME_TTY (f), first_unused_hpos);
+ if (FRAME_DISPLAY (f)->clear_end_of_line_hook)
+ (*FRAME_DISPLAY (f)->clear_end_of_line_hook) (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 (struct tty_display_info *tty, int first_unused_hpos)
+tty_clear_end_of_line (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
and the costs have never been calculated. Do nothing. */
if (! tty->costs_set)
}
+/* Output LEN glyphs starting at STRING at the nominal cursor position.
+ Advance the nominal cursor over the text. */
+
void
write_glyphs (string, len)
register struct glyph *string;
register 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);
+}
+
+/* An implementation of write_glyphs for termcap frames. */
+
+void
+tty_write_glyphs (struct glyph *string, int len)
{
int produced, consumed;
- struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
- struct tty_display_info *tty;
unsigned char conversion_buffer[1024];
int conversion_buffer_size = sizeof conversion_buffer;
- if (write_glyphs_hook && ! FRAME_TERMCAP_P (f))
- {
- (*write_glyphs_hook) (string, len);
- return;
- }
+ struct frame *f = (updating_frame
+ ? updating_frame
+ : XFRAME (selected_frame));
- tty = FRAME_TTY (f);
+ struct tty_display_info *tty = FRAME_TTY (f);
turn_off_insert (tty);
tty_hide_cursor (tty);
cmcheckmagic (tty);
}
-/* If start is zero, insert blanks instead of a string at start */
+/* Insert LEN glyphs from START at the nominal cursor position.
+
+ If start is zero, insert blanks instead of a string at start */
void
insert_glyphs (start, len)
register struct glyph *start;
register int len;
{
- char *buf;
- struct glyph *glyph = NULL;
- struct frame *f;
- struct tty_display_info *tty;
+ struct frame *f = (updating_frame
+ ? updating_frame
+ : XFRAME (selected_frame));
if (len <= 0)
return;
- f = (updating_frame ? updating_frame : XFRAME (selected_frame));
+ if (FRAME_DISPLAY (f)->insert_glyphs_hook)
+ (*FRAME_DISPLAY (f)->insert_glyphs_hook) (start, len);
+}
- if (insert_glyphs_hook && ! FRAME_TERMCAP_P (f))
- {
- (*insert_glyphs_hook) (start, len);
- return;
- }
+/* An implementation of insert_glyphs for termcap frames. */
- tty = FRAME_TTY (f);
+void
+tty_insert_glyphs (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);
if (tty->TS_ins_multi_chars)
{
cmcheckmagic (tty);
}
+/* Delete N glyphs at the nominal cursor position. */
+
void
delete_glyphs (n)
register 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);
+}
+
+/* An implementation of delete_glyphs for termcap frames. */
+
+void
+tty_delete_glyphs (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);
-
- if (delete_glyphs_hook && ! FRAME_TERMCAP_P (f))
- {
- (*delete_glyphs_hook) (n);
- return;
- }
+ struct frame *f = (updating_frame
+ ? updating_frame
+ : XFRAME (selected_frame));
+ struct tty_display_info *tty = FRAME_TTY (f);
if (tty->delete_in_insert_mode)
{
ins_del_lines (vpos, n)
int vpos, n;
{
- struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
- if (ins_del_lines_hook && ! FRAME_TERMCAP_P (f))
+ 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);
+}
+
+/* An implementation of ins_del_lines for termcap frames. */
+
+void
+tty_ins_del_lines (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;
+ char *scroll = n > 0 ? tty->TS_rev_scroll : tty->TS_fwd_scroll;
+
+ register int i = n > 0 ? n : -n;
+ register char *buf;
+
+ /* If the lines below the insertion are being pushed
+ into the end of the window, this is the same as clearing;
+ and we know the lines are already clear, since the matching
+ deletion has already been done. So can ignore this. */
+ /* If the lines below the deletion are blank lines coming
+ out of the end of the window, don't bother,
+ as there will be a matching inslines later that will flush them. */
+ if (FRAME_SCROLL_REGION_OK (f)
+ && vpos + i >= tty->specified_window)
+ return;
+ if (!FRAME_MEMORY_BELOW_FRAME (f)
+ && vpos + i >= FRAME_LINES (f))
+ return;
+
+ if (multi)
{
- (*ins_del_lines_hook) (vpos, n);
- return;
+ raw_cursor_to (vpos, 0);
+ background_highlight (tty);
+ buf = tparam (multi, 0, 0, i);
+ OUTPUT (tty, buf);
+ xfree (buf);
+ }
+ else if (single)
+ {
+ raw_cursor_to (vpos, 0);
+ background_highlight (tty);
+ while (--i >= 0)
+ OUTPUT (tty, single);
+ if (tty->TF_teleray)
+ curX (tty) = 0;
}
else
{
- 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;
- char *scroll = n > 0 ? tty->TS_rev_scroll : tty->TS_fwd_scroll;
-
- register int i = n > 0 ? n : -n;
- register char *buf;
-
- /* If the lines below the insertion are being pushed
- into the end of the window, this is the same as clearing;
- and we know the lines are already clear, since the matching
- deletion has already been done. So can ignore this. */
- /* If the lines below the deletion are blank lines coming
- out of the end of the window, don't bother,
- as there will be a matching inslines later that will flush them. */
- if (FRAME_SCROLL_REGION_OK (f)
- && vpos + i >= tty->specified_window)
- return;
- if (!FRAME_MEMORY_BELOW_FRAME (f)
- && vpos + i >= FRAME_LINES (f))
- return;
-
- if (multi)
- {
- raw_cursor_to (vpos, 0);
- background_highlight (tty);
- buf = tparam (multi, 0, 0, i);
- OUTPUT (tty, buf);
- xfree (buf);
- }
- else if (single)
- {
- raw_cursor_to (vpos, 0);
- background_highlight (tty);
- while (--i >= 0)
- OUTPUT (tty, single);
- if (tty->TF_teleray)
- curX (tty) = 0;
- }
+ set_scroll_region (vpos, tty->specified_window);
+ if (n < 0)
+ raw_cursor_to (tty->specified_window - 1, 0);
else
- {
- set_scroll_region (vpos, tty->specified_window);
- if (n < 0)
- raw_cursor_to (tty->specified_window - 1, 0);
- else
- raw_cursor_to (vpos, 0);
- background_highlight (tty);
- while (--i >= 0)
- OUTPUTL (tty, scroll, tty->specified_window - vpos);
- set_scroll_region (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 ();
- }
+ raw_cursor_to (vpos, 0);
+ background_highlight (tty);
+ while (--i >= 0)
+ OUTPUTL (tty, scroll, tty->specified_window - vpos);
+ set_scroll_region (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 ();
}
}
\f
return 1;
}
+/* Return the tty display object specified by DISPLAY.
+ DISPLAY may be a frame or a string. */
+
+static struct display *
+get_tty_display (Lisp_Object display)
+{
+ struct display *d;
+
+ 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. */
(display)
Lisp_Object display;
{
- struct tty_display_info *tty = FRAME_TTY (SELECTED_FRAME ());
- return tty->TN_max_colors > 0 ? Qt : Qnil;
+ struct display *d = get_tty_display (display);
+ if (!d)
+ return Qnil;
+ else
+ return d->display_info.tty->TN_max_colors > 0 ? Qt : Qnil;
}
/* Return the number of supported colors. */
(display)
Lisp_Object display;
{
- struct tty_display_info *tty = FRAME_TTY (SELECTED_FRAME ());
- return make_number (tty->TN_max_colors);
+ struct display *d = get_tty_display (display);
+ if (!d)
+ return Qnil;
+ else
+ return make_number (d->display_info.tty->TN_max_colors);
}
#ifndef WINDOWSNT
\f
-struct tty_display_info *
-get_named_tty (name)
+/* Return the termcap display with the given name. If NAME is null,
+ return the display corresponding to our controlling terminal.
+
+ Returns NULL if the named terminal device is not opened. */
+
+struct display *
+get_named_tty_display (name)
char *name;
{
- struct tty_display_info *tty = tty_list;
-
- while (tty) {
- if ((tty->name == 0 && name == 0)
- || (name && tty->name && !strcmp (tty->name, name)))
- return tty;
- tty = tty->next;
+ struct display *d;
+
+ for (d = display_list; d; d = d->next_display) {
+ 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))))
+ return d;
};
return 0;
Initialization
***********************************************************************/
-struct tty_display_info *
-term_dummy_init (void)
+/* Create the bootstrap display device for the initial frame.
+ Returns a display of type output_initial. */
+
+struct display *
+init_initial_display (void)
{
- if (initialized || tty_list)
- error ("tty already initialized");
+ struct tty_display_info *tty;
+
+ if (initialized || display_list || tty_list)
+ abort ();
- tty_list = xmalloc (sizeof (struct tty_display_info));
- bzero (tty_list, sizeof (struct tty_display_info));
- tty_list->name = 0;
- tty_list->input = stdin;
- tty_list->output = stdout;
- tty_list->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
- tty_list->display_method = (struct display_method *) xmalloc (sizeof (struct display_method));
- tty_list->kboard = initial_kboard;
- return tty_list;
+ initial_display = create_display ();
+ initial_display->type = output_initial;
+
+ initial_display->delete_display_hook = &delete_initial_display;
+ /* All other hooks are NULL. */
+
+ return initial_display;
}
+/* Deletes the bootstrap display device.
+ Called through delete_display_hook. */
-struct tty_display_info *
-term_init (Lisp_Object frame, char *name, char *terminal_type)
+void
+delete_initial_display (struct display *display)
+{
+ if (display != initial_display)
+ abort ();
+
+ delete_display (display);
+ initial_display = NULL;
+}
+
+/* Create a termcap display on the tty device with the given name and
+ type.
+
+ If NAME is NULL, then use the controlling tty, i.e., stdin/stdout.
+ Otherwise NAME should be a path to the tty device file,
+ e.g. "/dev/pts/7".
+
+ TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
+
+ If MUST_SUCCEED is true, then all errors are fatal. */
+
+struct display *
+term_init (char *name, char *terminal_type, int must_succeed)
{
char *area;
char **address = &area;
int buffer_size = 4096;
register char *p;
int status;
- struct frame *f = XFRAME (frame);
struct tty_display_info *tty;
+ struct display *display;
- tty = get_named_tty (name);
- if (tty)
- {
- /* Return the previously initialized terminal, except if it is
- the dummy terminal created for the initial frame. */
- if (tty->type)
- return tty;
+ static void maybe_fatal();
- /* Free up temporary structures. */
- if (tty->Wcm)
- xfree (tty->Wcm);
- if (tty->display_method)
- xfree (tty->display_method);
- if (tty->kboard != initial_kboard)
- abort ();
- tty->kboard = 0;
- }
- else
- {
- tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info));
- bzero (tty, sizeof (struct tty_display_info));
- tty->next = tty_list;
- tty_list = tty;
- }
+ if (!terminal_type)
+ maybe_fatal (must_succeed, 0, 0,
+ "Unknown terminal type",
+ "Unknown terminal type");
+
+ display = get_named_tty_display (name);
+ if (display)
+ return display; /* We have already opened a display there. */
+
+ display = create_display ();
+ tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info));
+ bzero (tty, sizeof (struct tty_display_info));
+ tty->next = tty_list;
+ tty_list = tty;
+
+ display->type = output_termcap;
+ display->display_info.tty = tty;
+ tty->display = display;
tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
Wcm_clear (tty);
- /* Each termcap frame has its own display method. */
- tty->display_method = (struct display_method *) xmalloc (sizeof (struct display_method));
- bzero (tty->display_method, sizeof (struct display_method));
+ display->rif = 0; /* ttys don't support window-based redisplay. */
- /* Initialize the common members in the new display method with our
- predefined template. */
- *tty->display_method = tty_display_method_template;
- f->display_method = tty->display_method;
+ display->cursor_to_hook = &tty_cursor_to;
+ display->raw_cursor_to_hook = &tty_raw_cursor_to;
- /* Make sure the frame is live; if an error happens, it must be
- deleted. */
- f->output_method = output_termcap;
- if (! f->output_data.tty)
- abort ();
- f->output_data.tty->display_info = tty;
+ display->clear_to_end_hook = &tty_clear_to_end;
+ display->clear_frame_hook = &tty_clear_frame;
+ display->clear_end_of_line_hook = &tty_clear_end_of_line;
+
+ display->ins_del_lines_hook = &tty_ins_del_lines;
+
+ display->insert_glyphs_hook = &tty_insert_glyphs;
+ display->write_glyphs_hook = &tty_write_glyphs;
+ display->delete_glyphs_hook = &tty_delete_glyphs;
+
+ display->ring_bell_hook = &tty_ring_bell;
+
+ display->reset_terminal_modes_hook = &tty_reset_terminal_modes;
+ display->set_terminal_modes_hook = &tty_set_terminal_modes;
+ display->update_begin_hook = 0; /* Not needed. */
+ display->update_end_hook = &tty_update_end;
+ display->set_terminal_window_hook = &tty_set_terminal_window;
+
+ display->mouse_position_hook = 0; /* Not needed. */
+ display->frame_rehighlight_hook = 0; /* Not needed. */
+ display->frame_raise_lower_hook = 0; /* Not needed. */
+
+ display->set_vertical_scroll_bar_hook = 0; /* Not needed. */
+ display->condemn_scroll_bars_hook = 0; /* Not needed. */
+ display->redeem_scroll_bar_hook = 0; /* Not needed. */
+ display->judge_scroll_bars_hook = 0; /* Not needed. */
+
+ display->read_socket_hook = &tty_read_avail_input; /* keyboard.c */
+ display->frame_up_to_date_hook = 0; /* Not needed. */
+
+ display->delete_frame_hook = &delete_tty_output;
+ display->delete_display_hook = &delete_tty;
+
if (name)
{
int fd;
fd = emacs_open (name, O_RDWR, 0);
if (fd < 0)
{
- delete_tty (tty);
+ delete_tty (display);
error ("Could not open file: %s", name);
}
file = fdopen (fd, "w+");
area = (char *) xmalloc (2044);
- FrameRows (tty) = FRAME_LINES (f);
- FrameCols (tty) = FRAME_COLS (f);
- tty->specified_window = FRAME_LINES (f);
+ FrameRows (tty) = FRAME_LINES (f); /* XXX */
+ FrameCols (tty) = FRAME_COLS (f); /* XXX */
+ tty->specified_window = FRAME_LINES (f); /* XXX */
- tty->display_method->delete_in_insert_mode = 1;
+ tty->display->delete_in_insert_mode = 1;
UseTabs (tty) = 0;
- FRAME_SCROLL_REGION_OK (f) = 0;
+ display->scroll_region_ok = 0;
/* Seems to insert lines when it's not supposed to, messing
up the display. In doing a trace, it didn't seem to be
called much, so I don't think we're losing anything by
turning it off. */
- FRAME_LINE_INS_DEL_OK (f) = 0;
- FRAME_CHAR_INS_DEL_OK (f) = 1;
+ display->line_ins_del_ok = 0;
+ display->char_ins_del_ok = 1;
baud_rate = 19200;
- FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
- FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
+ FRAME_CAN_HAVE_SCROLL_BARS (f) = 0; /* XXX */
+ FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none; /* XXX */
TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
- return tty;
+ return display;
#else /* not WINDOWSNT */
Wcm_clear (tty);
if (status < 0)
{
#ifdef TERMINFO
- if (name)
- {
- xfree (buffer);
- delete_tty (tty);
- error ("Cannot open terminfo database file");
- }
- else
- fatal ("Cannot open terminfo database file");
+ maybe_fatal (must_succeed, buffer, display,
+ "Cannot open terminfo database file",
+ "Cannot open terminfo database file");
#else
- if (name)
- {
- xfree (buffer);
- delete_tty (tty);
- error ("Cannot open termcap database file");
- }
- else
- fatal ("Cannot open termcap database file");
+ maybe_fatal (must_succeed, buffer, display,
+ "Cannot open termcap database file",
+ "Cannot open termcap database file");
#endif
}
if (status == 0)
{
#ifdef TERMINFO
- if (name)
- {
- xfree (buffer);
- delete_tty (tty);
- error ("Terminal type %s is not defined", terminal_type);
- }
- else
- fatal ("Terminal type %s is not defined.\n\
+ maybe_fatal (must_succeed, buffer, display,
+ "Terminal type %s is not defined",
+ "Terminal type %s is not defined.\n\
If that is not the actual type of terminal you have,\n\
use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
`setenv TERM ...') to specify the correct type. It may be necessary\n\
to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
- terminal_type);
+ terminal_type);
#else
- if (name)
- {
- xfree (buffer);
- delete_tty (tty);
- error ("Terminal type %s is not defined", terminal_type);
- }
- else
- fatal ("Terminal type %s is not defined.\n\
+ maybe_fatal (must_succeed, buffer, display,
+ "Terminal type %s is not defined",
+ "Terminal type %s is not defined.\n\
If that is not the actual type of terminal you have,\n\
use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
`setenv TERM ...') to specify the correct type. It may be necessary\n\
to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
- terminal_type);
+ terminal_type);
#endif
}
/* Since we make MagicWrap terminals look like AutoWrap, we need to have
the former flag imply the latter. */
AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
- FRAME_MEMORY_BELOW_FRAME (f) = tgetflag ("db");
+ display->memory_below_frame = tgetflag ("db");
tty->TF_hazeltine = tgetflag ("hz");
- FRAME_MUST_WRITE_SPACES (f) = tgetflag ("in");
+ display->must_write_spaces = tgetflag ("in");
tty->meta_key = tgetflag ("km") || tgetflag ("MT");
tty->TF_insmode_motion = tgetflag ("mi");
tty->TF_standout_motion = tgetflag ("ms");
FrameRows (tty) = tgetnum ("li");
if (FrameRows (tty) < 3 || FrameCols (tty) < 3)
- {
- if (initialized)
- {
- delete_tty (tty);
- error ("Screen size %dx%d is too small",
+ maybe_fatal (must_succeed, NULL, display,
+ "Screen size %dx%d is too small"
+ "Screen size %dx%d is too small",
FrameCols (tty), FrameRows (tty));
- }
- else
- {
- fatal ("Screen size %dx%d is too small",
- FrameCols (tty), FrameRows (tty));
- }
- }
#if 0 /* This is not used anywhere. */
- tty->display_method->min_padding_speed = tgetnum ("pb");
+ tty->display->min_padding_speed = tgetnum ("pb");
#endif
TabWidth (tty) = tgetnum ("tw");
if (!strcmp (terminal_type, "supdup"))
{
- FRAME_MEMORY_BELOW_FRAME (f) = 1;
+ display->memory_below_frame = 1;
tty->Wcm->cm_losewrap = 1;
}
if (!strncmp (terminal_type, "c10", 3)
tty->TS_set_window = "\033v%C %C %C %C ";
}
/* Termcap entry often fails to have :in: flag */
- FRAME_MUST_WRITE_SPACES (f) = 1;
+ display->must_write_spaces = 1;
/* :ti string typically fails to have \E^G! in it */
/* This limits scope of insert-char to one line. */
strcpy (area, tty->TS_termcap_modes);
tty->specified_window = FrameRows (tty);
if (Wcm_init (tty) == -1) /* can't do cursor motion */
- if (name)
- {
- delete_tty (tty);
- error ("Terminal type \"%s\" is not powerful enough to run Emacs",
- terminal_type);
- }
- else {
+ {
+ maybe_fatal (must_succeed, NULL, display,
+ "Terminal type \"%s\" is not powerful enough to run Emacs",
#ifdef VMS
- fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
+ "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
It lacks the ability to position the cursor.\n\
If that is not the actual type of terminal you have, use either the\n\
DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
- terminal_type);
#else /* not VMS */
# ifdef TERMINFO
- fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
+ "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
It lacks the ability to position the cursor.\n\
If that is not the actual type of terminal you have,\n\
use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
`setenv TERM ...') to specify the correct type. It may be necessary\n\
to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
- terminal_type);
# else /* TERMCAP */
- fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
+ "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
It lacks the ability to position the cursor.\n\
If that is not the actual type of terminal you have,\n\
use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
`setenv TERM ...') to specify the correct type. It may be necessary\n\
to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
- terminal_type);
# endif /* TERMINFO */
#endif /*VMS */
+ terminal_type);
}
if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
- {
- if (name)
- {
- delete_tty (tty);
- error ("The frame size has not been specified");
- }
- else
- fatal ("The frame size has not been specified");
- }
+ maybe_fatal (must_succeed, NULL, display,
+ "Could not determine the frame size",
+ "Could not determine the frame size");
tty->delete_in_insert_mode
= tty->TS_delete_mode && tty->TS_insert_mode
UseTabs (tty) = tabs_safe_p (fileno (TTY_INPUT (tty))) && TabWidth (tty) == 8;
- FRAME_SCROLL_REGION_OK (f)
+ display->scroll_region_ok
= (tty->Wcm->cm_abs
&& (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
- FRAME_LINE_INS_DEL_OK (f)
+ display->line_ins_del_ok
= (((tty->TS_ins_line || tty->TS_ins_multi_lines)
&& (tty->TS_del_line || tty->TS_del_multi_lines))
- || (FRAME_SCROLL_REGION_OK (f)
+ || (display->scroll_region_ok
&& tty->TS_fwd_scroll && tty->TS_rev_scroll));
- FRAME_CHAR_INS_DEL_OK (f)
+ display->char_ins_del_ok
= ((tty->TS_ins_char || tty->TS_insert_mode
|| tty->TS_pad_inserted_char || tty->TS_ins_multi_chars)
&& (tty->TS_del_char || tty->TS_del_multi_chars));
- FRAME_FAST_CLEAR_END_OF_LINE (f) = tty->TS_clr_line != 0;
+ display->fast_clear_end_of_line = tty->TS_clr_line != 0;
init_baud_rate (fileno (TTY_INPUT (tty)));
- if (read_socket_hook) /* Baudrate is somewhat
- meaningless in this case */
- baud_rate = 9600;
-
- FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
- FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
#ifdef AIXHFT
/* The HFT system on AIX doesn't optimize for scrolling, so it's
really ugly at times. */
- FRAME_LINE_INS_DEL_OK (f) = 0;
- FRAME_CHAR_INS_DEL_OK (f) = 0;
+ display->line_ins_del_ok = 0;
+ display->char_ins_del_ok = 0;
#endif
#ifdef MULTI_KBOARD
/* Don't do this. I think termcap may still need the buffer. */
/* xfree (buffer); */
- /* Set the top frame to the first frame on this display. */
- tty->top_frame = frame;
-
/* Init system terminal modes (RAW or CBREAK, etc.). */
init_sys_modes (tty);
- return tty;
+ return display;
#endif /* not WINDOWSNT */
}
+/* Auxiliary error-handling function for term_init.
+ Free BUFFER and delete DISPLAY, then call error or fatal
+ with str1 or str2, respectively, according to MUST_SUCCEED. */
+
+static void
+maybe_fatal (must_succeed, buffer, display, str1, str2, arg1, arg2)
+ int must_succeed;
+ char *buffer;
+ struct display *display;
+ char *str1, *str2, *arg1, *arg2;
+{
+ if (buffer)
+ xfree (buffer);
+
+ if (display)
+ delete_tty (display);
+
+ if (must_succeed)
+ fatal (str2, arg1, arg2);
+ else
+ error (str1, arg1, arg2);
+
+ abort ();
+}
+
/* VARARGS 1 */
void
fatal (str, arg1, arg2)
(tty)
Lisp_Object tty;
{
- struct tty_display_info *t;
+ struct display *d;
char *name = 0;
CHECK_STRING (tty);
name[SBYTES (tty)] = 0;
}
- t = get_named_tty (name);
+ d = get_named_tty_display (name);
- if (! t)
- error ("No such tty device: %s", name);
+ if (! d)
+ error ("No such terminal device: %s", name);
- delete_tty (t);
+ delete_tty (d);
}
static int deleting_tty = 0;
+
+/* Delete the given terminal device, closing all frames on it. */
+
void
-delete_tty (struct tty_display_info *tty)
+delete_tty (struct display *display)
{
+ struct tty_display_info *tty;
Lisp_Object tail, frame;
char *tty_name;
if (deleting_tty)
/* We get a recursive call when we delete the last frame on this
- tty. */
+ display. */
return;
deleting_tty = 1;
+ if (display->type != output_termcap)
+ abort ();
+
+ tty = display->display_info.tty;
+
if (tty == tty_list)
tty_list = tty->next;
else
if (FRAME_TERMCAP_P (f) && FRAME_LIVE_P (f) && FRAME_TTY (f) == tty)
{
Fdelete_frame (frame, Qt);
- f->output_data.tty = 0;
}
}
+ /* reset_sys_modes needs a valid display, so this call needs to be
+ before delete_display. */
reset_sys_modes (tty);
+ delete_display (display);
+
tty_name = tty->name;
if (tty->type)
xfree (tty->type);
if (tty->Wcm)
xfree (tty->Wcm);
- if (tty->display_method)
- xfree (tty->display_method);
-
#ifdef MULTI_KBOARD
if (tty->kboard && --tty->kboard->reference_count > 0)
abort ();
}
}
+\f
+
+/* Initialize the tty-dependent part of frame F. The frame must
+ already have its display initialized. */
+
+void
+create_tty_output (struct frame *f)
+{
+ struct tty_output *t;
+
+ if (! FRAME_TERMCAP_P (f))
+ abort ();
+
+ t = xmalloc (sizeof (struct tty_output));
+ bzero (t, sizeof (struct tty_output));
+
+ t->display_info = FRAME_DISPLAY (f)->display_info.tty;
+
+ f->output_data.tty = t;
+}
+
+/* Delete the tty-dependent part of frame F. */
+
+void
+delete_tty_output (struct frame *f)
+{
+ if (! FRAME_TERMCAP_P (f))
+ abort ();
+
+ xfree (f->output_data.tty);
+}
+
\f
/* Mark the pointers in the tty_display_info objects.
Called by the Fgarbage_collector. */
+
void
mark_ttys ()
{
}
}
+\f
+
+/* Create a new display object and add it to the display list. */
+
+struct display *
+create_display (void)
+{
+ struct display *dev = (struct display *) xmalloc (sizeof (struct display));
+
+ bzero (dev, sizeof (struct display));
+ dev->next_display = display_list;
+ display_list = dev;
+
+ return dev;
+}
+
+/* Remove a display from the display list and free its memory. */
+
+void
+delete_display (struct display *dev)
+{
+ struct display **dp;
+ Lisp_Object tail, frame;
+
+ /* Check for and close live frames that are still on this
+ display. */
+ FOR_EACH_FRAME (tail, frame)
+ {
+ struct frame *f = XFRAME (frame);
+ if (FRAME_LIVE_P (f) && f->display == dev)
+ {
+ Fdelete_frame (frame, Qt);
+ }
+ }
+
+ for (dp = &display_list; *dp != dev; dp = &(*dp)->next_display)
+ if (! *dp)
+ abort ();
+ *dp = dev->next_display;
+
+ bzero (dev, sizeof (struct display));
+ xfree (dev);
+}
+
\f
void
Fprovide (intern ("multi-tty"), Qnil);
- /* Initialize the display method template. */
-
- /* Termcap-based displays don't support window-based redisplay. */
- tty_display_method_template.rif = 0;
-
}