Mercurial > emacs
diff src/term.c @ 91041:bdb3fe0ba9fa
Merge from emacs--devo--0
Patches applied:
* emacs--devo--0 (patch 866-879)
- Merge multi-tty branch
- Update from CVS
- Merge from emacs--rel--22
Revision: emacs@sv.gnu.org/emacs--unicode--0--patch-257
author | Miles Bader <miles@gnu.org> |
---|---|
date | Thu, 11 Oct 2007 16:22:07 +0000 |
parents | aaccdab0ee26 fd282fb888de |
children | 35069180a991 |
line wrap: on
line diff
--- a/src/term.c Thu Oct 11 16:14:00 2007 +0000 +++ b/src/term.c Thu Oct 11 16:22:07 2007 +0000 @@ -25,10 +25,20 @@ #include <stdio.h> #include <ctype.h> #include <string.h> +#include <errno.h> +#include <sys/file.h> + #ifdef HAVE_UNISTD_H #include <unistd.h> #endif +#if HAVE_TERMIOS_H +#include <termios.h> /* For TIOCNOTTY. */ +#endif + +#include <signal.h> + +#include "lisp.h" #include "termchar.h" #include "termopts.h" #include "lisp.h" @@ -45,6 +55,8 @@ #include "window.h" #include "keymap.h" #include "blockinput.h" +#include "syssignal.h" +#include "systty.h" #include "intervals.h" /* For now, don't try to include termcap.h. On some systems, @@ -68,221 +80,75 @@ #include "macterm.h" #endif +#ifndef O_RDWR +#define O_RDWR 2 +#endif + +#ifndef O_NOCTTY +#define O_NOCTTY 0 +#endif + +/* The name of the default console device. */ +#ifdef WINDOWSNT +#define DEV_TTY "CONOUT$" +#else +#define DEV_TTY "/dev/tty" +#endif + +static void tty_set_scroll_region P_ ((struct frame *f, int start, int stop)); static void turn_on_face P_ ((struct frame *, int face_id)); static void turn_off_face P_ ((struct frame *, int face_id)); -static void tty_show_cursor P_ ((void)); -static void tty_hide_cursor P_ ((void)); - -#define OUTPUT(a) \ - tputs (a, (int) (FRAME_LINES (XFRAME (selected_frame)) - curY), cmputc) -#define OUTPUT1(a) tputs (a, 1, cmputc) -#define OUTPUTL(a, lines) tputs (a, lines, cmputc) - -#define OUTPUT_IF(a) \ - do { \ - if (a) \ - tputs (a, (int) (FRAME_LINES (XFRAME (selected_frame)) \ - - curY), cmputc); \ - } while (0) - -#define OUTPUT1_IF(a) do { if (a) tputs (a, 1, cmputc); } while (0) - -/* Display space properties */ - -extern Lisp_Object Qspace, QCalign_to, QCwidth; - -/* Function to use to ring the bell. */ - -Lisp_Object Vring_bell_function; +static void tty_show_cursor P_ ((struct tty_display_info *)); +static void tty_hide_cursor P_ ((struct tty_display_info *)); +static void tty_background_highlight P_ ((struct tty_display_info *tty)); +static void clear_tty_hooks P_ ((struct terminal *terminal)); +static void set_tty_hooks P_ ((struct terminal *terminal)); +static void dissociate_if_controlling_tty P_ ((int fd)); +static void delete_tty P_ ((struct terminal *)); + +#define OUTPUT(tty, a) \ + emacs_tputs ((tty), a, \ + (int) (FRAME_LINES (XFRAME (selected_frame)) \ + - curY (tty)), \ + cmputc) + +#define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc) +#define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc) + +#define OUTPUT_IF(tty, a) \ + do { \ + if (a) \ + emacs_tputs ((tty), a, \ + (int) (FRAME_LINES (XFRAME (selected_frame)) \ + - curY (tty) ), \ + cmputc); \ + } while (0) + +#define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0) /* If true, use "vs", otherwise use "ve" to make the cursor visible. */ static int visible_cursor; -/* Terminal characteristics that higher levels want to look at. - These are all extern'd in termchar.h */ - -int must_write_spaces; /* Nonzero means spaces in the text - must actually be output; can't just skip - over some columns to leave them blank. */ -int min_padding_speed; /* Speed below which no padding necessary */ - -int line_ins_del_ok; /* Terminal can insert and delete lines */ -int char_ins_del_ok; /* Terminal can insert and delete chars */ -int scroll_region_ok; /* Terminal supports setting the - scroll window */ -int scroll_region_cost; /* Cost of setting a scroll window, - measured in characters */ -int memory_below_frame; /* Terminal remembers lines - scrolled off bottom */ -int fast_clear_end_of_line; /* Terminal has a `ce' string */ - -/* Nonzero means no need to redraw the entire frame on resuming - a suspended Emacs. This is useful on terminals with multiple pages, - where one page is used for Emacs and another for all else. */ - +/* Display space properties */ + +extern Lisp_Object Qspace, QCalign_to, QCwidth; + +/* 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 tty device parameters. */ +struct tty_display_info *tty_list; + +/* Nonzero means no need to redraw the entire frame on resuming a + suspended Emacs. This is useful on terminals with multiple + pages, where one page is used for Emacs and another for all + else. */ int no_redraw_on_reenter; -/* 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_ ((int, int, struct input_event *)); - -void (*frame_up_to_date_hook) P_ ((struct frame *)); - -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)); - -/* If the value of the frame parameter changed, whis hook is called. - For example, if going from fullscreen to not fullscreen this hook - may do something OS dependent, like extended window manager hints on X11. */ -void (*fullscreen_hook) P_ ((struct frame *f)); - -/* Set the vertical scroll bar for WINDOW to have its upper left corner - at (TOP, LEFT), and be LENGTH rows high. Set its handle to - indicate that we are displaying PORTION characters out of a total - 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)); - -/* Strings, numbers and flags taken from the termcap entry. */ - -char *TS_ins_line; /* "al" */ -char *TS_ins_multi_lines; /* "AL" (one parameter, # lines to insert) */ -char *TS_bell; /* "bl" */ -char *TS_clr_to_bottom; /* "cd" */ -char *TS_clr_line; /* "ce", clear to end of line */ -char *TS_clr_frame; /* "cl" */ -char *TS_set_scroll_region; /* "cs" (2 params, first line and last line) */ -char *TS_set_scroll_region_1; /* "cS" (4 params: total lines, - lines above scroll region, lines below it, - total lines again) */ -char *TS_del_char; /* "dc" */ -char *TS_del_multi_chars; /* "DC" (one parameter, # chars to delete) */ -char *TS_del_line; /* "dl" */ -char *TS_del_multi_lines; /* "DL" (one parameter, # lines to delete) */ -char *TS_delete_mode; /* "dm", enter character-delete mode */ -char *TS_end_delete_mode; /* "ed", leave character-delete mode */ -char *TS_end_insert_mode; /* "ei", leave character-insert mode */ -char *TS_ins_char; /* "ic" */ -char *TS_ins_multi_chars; /* "IC" (one parameter, # chars to insert) */ -char *TS_insert_mode; /* "im", enter character-insert mode */ -char *TS_pad_inserted_char; /* "ip". Just padding, no commands. */ -char *TS_end_keypad_mode; /* "ke" */ -char *TS_keypad_mode; /* "ks" */ -char *TS_pad_char; /* "pc", char to use as padding */ -char *TS_repeat; /* "rp" (2 params, # times to repeat - and character to be repeated) */ -char *TS_end_standout_mode; /* "se" */ -char *TS_fwd_scroll; /* "sf" */ -char *TS_standout_mode; /* "so" */ -char *TS_rev_scroll; /* "sr" */ -char *TS_end_termcap_modes; /* "te" */ -char *TS_termcap_modes; /* "ti" */ -char *TS_visible_bell; /* "vb" */ -char *TS_cursor_normal; /* "ve" */ -char *TS_cursor_visible; /* "vs" */ -char *TS_cursor_invisible; /* "vi" */ -char *TS_set_window; /* "wi" (4 params, start and end of window, - each as vpos and hpos) */ - -/* Value of the "NC" (no_color_video) capability, or 0 if not - present. */ - -static int TN_no_color_video; - /* Meaning of bits in no_color_video. Each bit set means that the corresponding attribute cannot be combined with colors. */ @@ -299,68 +165,6 @@ NC_ALT_CHARSET = 1 << 8 }; -/* "md" -- turn on bold (extra bright mode). */ - -char *TS_enter_bold_mode; - -/* "mh" -- turn on half-bright mode. */ - -char *TS_enter_dim_mode; - -/* "mb" -- enter blinking mode. */ - -char *TS_enter_blink_mode; - -/* "mr" -- enter reverse video mode. */ - -char *TS_enter_reverse_mode; - -/* "us"/"ue" -- start/end underlining. */ - -char *TS_exit_underline_mode, *TS_enter_underline_mode; - -/* "as"/"ae" -- start/end alternate character set. Not really - supported, yet. */ - -char *TS_enter_alt_charset_mode, *TS_exit_alt_charset_mode; - -/* "me" -- switch appearances off. */ - -char *TS_exit_attribute_mode; - -/* "Co" -- number of colors. */ - -int TN_max_colors; - -/* "pa" -- max. number of color pairs on screen. Not handled yet. - Could be a problem if not equal to TN_max_colors * TN_max_colors. */ - -int TN_max_pairs; - -/* "op" -- SVr4 set default pair to its original value. */ - -char *TS_orig_pair; - -/* "AF"/"AB" or "Sf"/"Sb"-- set ANSI or SVr4 foreground/background color. - 1 param, the color index. */ - -char *TS_set_foreground, *TS_set_background; - -int TF_hazeltine; /* termcap hz flag. */ -int TF_insmode_motion; /* termcap mi flag: can move while in insert mode. */ -int TF_standout_motion; /* termcap mi flag: can move while in standout mode. */ -int TF_underscore; /* termcap ul flag: _ underlines if over-struck on - non-blank position. Must clear before writing _. */ -int TF_teleray; /* termcap xt flag: many weird consequences. - For t1061. */ - -static int RPov; /* # chars to start a TS_repeat */ - -static int delete_in_insert_mode; /* delete mode == insert mode */ - -static int se_is_so; /* 1 if same string both enters and leaves - standout mode */ - /* internal state */ /* The largest frame width in any call to calculate_costs. */ @@ -371,57 +175,27 @@ int max_frame_lines; -static int costs_set; /* Nonzero if costs have been calculated. */ - -int insert_mode; /* Nonzero when in insert mode. */ -int standout_mode; /* Nonzero when in standout mode. */ - -/* Size of window specified by higher levels. - This is the number of lines, from the top of frame downwards, - which can participate in insert-line/delete-line operations. - - Effectively it excludes the bottom frame_lines - specified_window_size - lines from those operations. */ - -int specified_window; - -/* 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; /* Provided for lisp packages. */ static int system_uses_terminfo; -/* Flag used in tty_show/hide_cursor. */ - -static int tty_cursor_hidden; - char *tparam (); extern char *tgetstr (); + + +#ifdef HAVE_GPM +#include <sys/fcntl.h> static void term_clear_mouse_face (); static void term_mouse_highlight (struct frame *f, int x, int y); - - -#ifdef WINDOWSNT -/* We aren't X windows, but we aren't termcap either. This makes me - uncertain as to what value to use for frame.output_method. For - this file, we'll define FRAME_TERMCAP_P to be zero so that our - output hooks get called instead of the termcap functions. Probably - the best long-term solution is to define an output_windows_nt... */ - -#undef FRAME_TERMCAP_P -#define FRAME_TERMCAP_P(_f_) 0 -#endif /* WINDOWSNT */ - -#ifdef HAVE_GPM -#include <sys/fcntl.h> - -/* Nonzero means mouse is enabled on Linux console. */ -int term_gpm = 0; + +/* The device for which we have enabled gpm support (or NULL). */ +struct tty_display_info *gpm_tty = NULL; /* These variables describe the range of text currently shown in its mouse-face, together with the window they apply to. As long as @@ -431,199 +205,180 @@ static int mouse_face_beg_row, mouse_face_beg_col; static int mouse_face_end_row, mouse_face_end_col; static int mouse_face_past_end; -static Lisp_Object Qmouse_face_window; +static Lisp_Object mouse_face_window; static int mouse_face_face_id; static int pos_x, pos_y; static int last_mouse_x, last_mouse_y; #endif /* HAVE_GPM */ -void -ring_bell () +/* Ring the bell on a tty. */ + +static void +tty_ring_bell (struct frame *f) { - if (!NILP (Vring_bell_function)) + struct tty_display_info *tty = FRAME_TTY (f); + + if (tty->output) { - Lisp_Object function; - - /* Temporarily set the global variable to nil - so that if we get an error, it stays nil - and we don't call it over and over. - - We don't specbind it, because that would carefully - restore the bad value if there's an error - and make the loop of errors happen anyway. */ - - function = Vring_bell_function; - Vring_bell_function = Qnil; - - call0 (function); - - Vring_bell_function = function; + OUTPUT (tty, (tty->TS_visible_bell && visible_bell + ? tty->TS_visible_bell + : tty->TS_bell)); + fflush (tty->output); } - else if (!FRAME_TERMCAP_P (XFRAME (selected_frame))) - (*ring_bell_hook) (); - else - OUTPUT (TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell); } +/* Set up termcap modes for Emacs. */ + void -set_terminal_modes () +tty_set_terminal_modes (struct terminal *terminal) { - if (FRAME_TERMCAP_P (XFRAME (selected_frame))) + struct tty_display_info *tty = terminal->display_info.tty; + + if (tty->output) { - if (TS_termcap_modes) - OUTPUT (TS_termcap_modes); + if (tty->TS_termcap_modes) + OUTPUT (tty, tty->TS_termcap_modes); else - { - /* Output enough newlines to scroll all the old screen contents - off the screen, so it won't be overwritten and lost. */ - int i; - for (i = 0; i < FRAME_LINES (XFRAME (selected_frame)); i++) - putchar ('\n'); - } - - OUTPUT_IF (visible_cursor ? TS_cursor_visible : TS_cursor_normal); - OUTPUT_IF (TS_keypad_mode); - losecursor (); + { + /* Output enough newlines to scroll all the old screen contents + off the screen, so it won't be overwritten and lost. */ + int i; + current_tty = tty; + for (i = 0; i < FRAME_LINES (XFRAME (selected_frame)); i++) + cmputc ('\n'); + } + + OUTPUT_IF (tty, tty->TS_termcap_modes); + OUTPUT_IF (tty, visible_cursor ? tty->TS_cursor_visible : tty->TS_cursor_normal); + OUTPUT_IF (tty, tty->TS_keypad_mode); + losecursor (tty); + fflush (tty->output); } - else - (*set_terminal_modes_hook) (); } +/* Reset termcap modes before exiting Emacs. */ + void -reset_terminal_modes () -{ - if (FRAME_TERMCAP_P (XFRAME (selected_frame))) - { - turn_off_highlight (); - turn_off_insert (); - OUTPUT_IF (TS_end_keypad_mode); - OUTPUT_IF (TS_cursor_normal); - OUTPUT_IF (TS_end_termcap_modes); - OUTPUT_IF (TS_orig_pair); - /* Output raw CR so kernel can track the cursor hpos. */ - cmputc ('\r'); - } - 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); -} - -void -update_end (f) - struct frame *f; +tty_reset_terminal_modes (struct terminal *terminal) { - if (FRAME_TERMCAP_P (f)) + struct tty_display_info *tty = terminal->display_info.tty; + + if (tty->output) { - if (!XWINDOW (selected_window)->cursor_off_p) - tty_show_cursor (); - turn_off_insert (); - background_highlight (); + tty_turn_off_highlight (tty); + 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'); + fflush (tty->output); } - else - update_end_hook (f); - - updating_frame = NULL; } -void -set_terminal_window (size) - int size; +/* Flag the end of a display update on a termcap terminal. */ + +static void +tty_update_end (struct frame *f) { - if (FRAME_TERMCAP_P (updating_frame)) - { - specified_window = size ? size : FRAME_LINES (updating_frame); - if (scroll_region_ok) - set_scroll_region (0, specified_window); - } - else - set_terminal_window_hook (size); + struct tty_display_info *tty = FRAME_TTY (f); + + if (!XWINDOW (selected_window)->cursor_off_p) + tty_show_cursor (tty); + tty_turn_off_insert (tty); + tty_background_highlight (tty); } -void -set_scroll_region (start, stop) - int start, stop; +/* The implementation of set_terminal_window for termcap frames. */ + +static void +tty_set_terminal_window (struct frame *f, int size) +{ + struct tty_display_info *tty = FRAME_TTY (f); + + tty->specified_window = size ? size : FRAME_LINES (f); + if (FRAME_SCROLL_REGION_OK (f)) + tty_set_scroll_region (f, 0, tty->specified_window); +} + +static void +tty_set_scroll_region (struct frame *f, int start, int stop) { char *buf; - struct frame *sf = XFRAME (selected_frame); - - if (TS_set_scroll_region) - buf = tparam (TS_set_scroll_region, 0, 0, start, stop - 1); - else if (TS_set_scroll_region_1) - buf = tparam (TS_set_scroll_region_1, 0, 0, - FRAME_LINES (sf), start, - FRAME_LINES (sf) - stop, - FRAME_LINES (sf)); + struct tty_display_info *tty = FRAME_TTY (f); + + if (tty->TS_set_scroll_region) + buf = tparam (tty->TS_set_scroll_region, 0, 0, start, stop - 1); + else if (tty->TS_set_scroll_region_1) + buf = tparam (tty->TS_set_scroll_region_1, 0, 0, + FRAME_LINES (f), start, + FRAME_LINES (f) - stop, + FRAME_LINES (f)); else - buf = tparam (TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (sf)); - - OUTPUT (buf); + buf = tparam (tty->TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (f)); + + OUTPUT (tty, buf); xfree (buf); - losecursor (); + losecursor (tty); } static void -turn_on_insert () +tty_turn_on_insert (struct tty_display_info *tty) { - if (!insert_mode) - OUTPUT (TS_insert_mode); - insert_mode = 1; + if (!tty->insert_mode) + OUTPUT (tty, tty->TS_insert_mode); + tty->insert_mode = 1; } void -turn_off_insert () +tty_turn_off_insert (struct tty_display_info *tty) { - if (insert_mode) - OUTPUT (TS_end_insert_mode); - insert_mode = 0; + if (tty->insert_mode) + OUTPUT (tty, tty->TS_end_insert_mode); + tty->insert_mode = 0; } /* Handle highlighting. */ void -turn_off_highlight () +tty_turn_off_highlight (struct tty_display_info *tty) { - if (standout_mode) - OUTPUT_IF (TS_end_standout_mode); - standout_mode = 0; + if (tty->standout_mode) + OUTPUT_IF (tty, tty->TS_end_standout_mode); + tty->standout_mode = 0; } static void -turn_on_highlight () +tty_turn_on_highlight (struct tty_display_info *tty) { - if (!standout_mode) - OUTPUT_IF (TS_standout_mode); - standout_mode = 1; + if (!tty->standout_mode) + OUTPUT_IF (tty, tty->TS_standout_mode); + tty->standout_mode = 1; } static void -toggle_highlight () +tty_toggle_highlight (struct tty_display_info *tty) { - if (standout_mode) - turn_off_highlight (); + if (tty->standout_mode) + tty_turn_off_highlight (tty); else - turn_on_highlight (); + tty_turn_on_highlight (tty); } /* Make cursor invisible. */ static void -tty_hide_cursor () +tty_hide_cursor (struct tty_display_info *tty) { - if (tty_cursor_hidden == 0) + if (tty->cursor_hidden == 0) { - tty_cursor_hidden = 1; - OUTPUT_IF (TS_cursor_invisible); + tty->cursor_hidden = 1; + OUTPUT_IF (tty, tty->TS_cursor_invisible); } } @@ -631,14 +386,14 @@ /* Ensure that cursor is visible. */ static void -tty_show_cursor () +tty_show_cursor (struct tty_display_info *tty) { - if (tty_cursor_hidden) + if (tty->cursor_hidden) { - tty_cursor_hidden = 0; - OUTPUT_IF (TS_cursor_normal); + tty->cursor_hidden = 0; + OUTPUT_IF (tty, tty->TS_cursor_normal); if (visible_cursor) - OUTPUT_IF (TS_cursor_visible); + OUTPUT_IF (tty, tty->TS_cursor_visible); } } @@ -647,180 +402,151 @@ empty space inside windows. What this is, depends on the user option inverse-video. */ -void -background_highlight () +static void +tty_background_highlight (struct tty_display_info *tty) { if (inverse_video) - turn_on_highlight (); + tty_turn_on_highlight (tty); else - turn_off_highlight (); + tty_turn_off_highlight (tty); } /* Set standout mode to the mode specified for the text to be output. */ static void -highlight_if_desired () +tty_highlight_if_desired (struct tty_display_info *tty) { if (inverse_video) - turn_on_highlight (); + tty_turn_on_highlight (tty); else - turn_off_highlight (); + tty_turn_off_highlight (tty); } /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are frame-relative coordinates. */ -void -cursor_to (vpos, hpos) - int vpos, hpos; +static void +tty_cursor_to (struct frame *f, int vpos, int hpos) { - struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame); - - if (! FRAME_TERMCAP_P (f) && cursor_to_hook) - { - (*cursor_to_hook) (vpos, hpos); - return; - } + 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 (! costs_set) + if (! tty->costs_set) return; - if (curY == vpos && curX == hpos) + if (curY (tty) == vpos + && curX (tty) == hpos) return; - if (!TF_standout_motion) - background_highlight (); - if (!TF_insmode_motion) - turn_off_insert (); - cmgoto (vpos, hpos); + if (!tty->TF_standout_motion) + tty_background_highlight (tty); + if (!tty->TF_insmode_motion) + tty_turn_off_insert (tty); + cmgoto (tty, vpos, hpos); } /* Similar but don't take any account of the wasted characters. */ -void -raw_cursor_to (row, col) - int row, col; +static void +tty_raw_cursor_to (struct frame *f, int row, int col) { - struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame); - if (! FRAME_TERMCAP_P (f)) - { - (*raw_cursor_to_hook) (row, col); - return; - } - if (curY == row && curX == col) + struct tty_display_info *tty = FRAME_TTY (f); + + if (curY (tty) == row + && curX (tty) == col) return; - if (!TF_standout_motion) - background_highlight (); - if (!TF_insmode_motion) - turn_off_insert (); - cmgoto (row, col); + if (!tty->TF_standout_motion) + tty_background_highlight (tty); + if (!tty->TF_insmode_motion) + tty_turn_off_insert (tty); + cmgoto (tty, row, col); } /* Erase operations */ -/* clear from cursor to end of frame */ -void -clear_to_end () +/* Clear from cursor to end of frame on a termcap device. */ + +static void +tty_clear_to_end (struct frame *f) { register int i; - - if (clear_to_end_hook && ! FRAME_TERMCAP_P (updating_frame)) + struct tty_display_info *tty = FRAME_TTY (f); + + if (tty->TS_clr_to_bottom) { - (*clear_to_end_hook) (); - return; - } - if (TS_clr_to_bottom) - { - background_highlight (); - OUTPUT (TS_clr_to_bottom); + tty_background_highlight (tty); + OUTPUT (tty, tty->TS_clr_to_bottom); } else { - for (i = curY; i < FRAME_LINES (XFRAME (selected_frame)); i++) + for (i = curY (tty); i < FRAME_LINES (f); i++) { - cursor_to (i, 0); - clear_end_of_line (FRAME_COLS (XFRAME (selected_frame))); + cursor_to (f, i, 0); + clear_end_of_line (f, FRAME_COLS (f)); } } } -/* Clear entire frame */ - -void -clear_frame () +/* Clear an entire termcap frame. */ + +static void +tty_clear_frame (struct frame *f) { - struct frame *sf = XFRAME (selected_frame); - - if (clear_frame_hook - && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : sf))) + struct tty_display_info *tty = FRAME_TTY (f); + + if (tty->TS_clr_frame) { - (*clear_frame_hook) (); - return; - } - if (TS_clr_frame) - { - background_highlight (); - OUTPUT (TS_clr_frame); - cmat (0, 0); + tty_background_highlight (tty); + OUTPUT (tty, tty->TS_clr_frame); + cmat (tty, 0, 0); } else { - cursor_to (0, 0); - clear_to_end (); + cursor_to (f, 0, 0); + clear_to_end (f); } } -/* Clear from cursor to end of line. - Assume that the line is already clear starting at column 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 -clear_end_of_line (first_unused_hpos) - int first_unused_hpos; +static void +tty_clear_end_of_line (struct frame *f, int first_unused_hpos) { register int i; - - if (clear_end_of_line_hook - && ! FRAME_TERMCAP_P ((updating_frame - ? updating_frame - : XFRAME (selected_frame)))) - { - (*clear_end_of_line_hook) (first_unused_hpos); - return; - } + 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 (! costs_set) + if (! tty->costs_set) return; - if (curX >= first_unused_hpos) + if (curX (tty) >= first_unused_hpos) return; - background_highlight (); - if (TS_clr_line) + tty_background_highlight (tty); + if (tty->TS_clr_line) { - OUTPUT1 (TS_clr_line); + OUTPUT1 (tty, tty->TS_clr_line); } else { /* have to do it the hard way */ - struct frame *sf = XFRAME (selected_frame); - turn_off_insert (); + tty_turn_off_insert (tty); /* Do not write in last row last col with Auto-wrap on. */ - if (AutoWrap && curY == FRAME_LINES (sf) - 1 - && first_unused_hpos == FRAME_COLS (sf)) + if (AutoWrap (tty) + && curY (tty) == FrameRows (tty) - 1 + && first_unused_hpos == FrameCols (tty)) first_unused_hpos--; - for (i = curX; i < first_unused_hpos; i++) + for (i = curX (tty); i < first_unused_hpos; i++) { - if (termscript) - fputc (' ', termscript); - putchar (' '); + if (tty->termscript) + fputc (' ', tty->termscript); + fputc (' ', tty->output); } - cmplus (first_unused_hpos - curX); + cmplus (tty, first_unused_hpos - curX (tty)); } } @@ -1005,44 +731,37 @@ } -void -write_glyphs (string, len) - register struct glyph *string; - register int len; + +/* An implementation of write_glyphs for termcap frames. */ + +static void +tty_write_glyphs (struct frame *f, struct glyph *string, int len) { - int produced, consumed; - struct frame *sf = XFRAME (selected_frame); - struct frame *f = updating_frame ? updating_frame : sf; unsigned char *conversion_buffer; struct coding_system *coding; - if (write_glyphs_hook - && ! FRAME_TERMCAP_P (f)) - { - (*write_glyphs_hook) (string, len); - return; - } - - turn_off_insert (); - tty_hide_cursor (); + struct tty_display_info *tty = FRAME_TTY (f); + + tty_turn_off_insert (tty); + tty_hide_cursor (tty); /* Don't dare write in last column of bottom line, if Auto-Wrap, since that would scroll the whole frame on some terminals. */ - if (AutoWrap - && curY + 1 == FRAME_LINES (sf) - && (curX + len) == FRAME_COLS (sf)) + if (AutoWrap (tty) + && curY (tty) + 1 == FRAME_LINES (f) + && (curX (tty) + len) == FRAME_COLS (f)) len --; if (len <= 0) return; - cmplus (len); + cmplus (tty, len); /* If terminal_coding does any conversion, use it, otherwise use safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here because it always return 1 if the member src_multibyte is 1. */ - coding = (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK - ? &terminal_coding : &safe_terminal_coding); + coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK + ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding); /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at the tail. */ coding->mode &= ~CODING_MODE_LAST_BLOCK; @@ -1058,7 +777,7 @@ break; /* Turn appearance modes of the face of the run on. */ - highlight_if_desired (); + tty_highlight_if_desired (tty); turn_on_face (f, face_id); if (n == len) @@ -1068,11 +787,11 @@ if (coding->produced > 0) { BLOCK_INPUT; - fwrite (conversion_buffer, 1, coding->produced, stdout); - if (ferror (stdout)) - clearerr (stdout); - if (termscript) - fwrite (conversion_buffer, 1, coding->produced, termscript); + fwrite (conversion_buffer, 1, coding->produced, tty->output); + if (ferror (tty->output)) + clearerr (tty->output); + if (tty->termscript) + fwrite (conversion_buffer, 1, coding->produced, tty->termscript); UNBLOCK_INPUT; } len -= n; @@ -1080,49 +799,51 @@ /* Turn appearance modes off. */ turn_off_face (f, face_id); - turn_off_highlight (); + tty_turn_off_highlight (tty); } - cmcheckmagic (); + cmcheckmagic (tty); } -void -write_glyphs_with_face (string, len, face_id) +#ifdef HAVE_GPM /* Only used by GPM code. */ + +static void +tty_write_glyphs_with_face (f, string, len, face_id) + register struct frame *f; register struct glyph *string; register int len, face_id; { - struct frame *sf = XFRAME (selected_frame); - struct frame *f = updating_frame ? updating_frame : sf; unsigned char *conversion_buffer; struct coding_system *coding; - turn_off_insert (); - tty_hide_cursor (); + struct tty_display_info *tty = FRAME_TTY (f); + + tty_turn_off_insert (tty); + tty_hide_cursor (tty); /* Don't dare write in last column of bottom line, if Auto-Wrap, since that would scroll the whole frame on some terminals. */ - if (AutoWrap - && curY + 1 == FRAME_LINES (sf) - && (curX + len) == FRAME_COLS (sf)) + if (AutoWrap (tty) + && curY (tty) + 1 == FRAME_LINES (f) + && (curX (tty) + len) == FRAME_COLS (f)) len --; if (len <= 0) return; - cmplus (len); + cmplus (tty, len); /* If terminal_coding does any conversion, use it, otherwise use safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here because it always return 1 if the member src_multibyte is 1. */ - coding = (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK - ? &terminal_coding : &safe_terminal_coding); + coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK + ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding); /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at the tail. */ coding->mode &= ~CODING_MODE_LAST_BLOCK; - /* Turn appearance modes of the face. */ - highlight_if_desired (); + tty_highlight_if_desired (tty); turn_on_face (f, face_id); coding->mode |= CODING_MODE_LAST_BLOCK; @@ -1130,59 +851,47 @@ if (coding->produced > 0) { BLOCK_INPUT; - fwrite (conversion_buffer, 1, coding->produced, stdout); - if (ferror (stdout)) - clearerr (stdout); - if (termscript) - fwrite (conversion_buffer, 1, coding->produced, termscript); + fwrite (conversion_buffer, 1, coding->produced, tty->output); + if (ferror (tty->output)) + clearerr (tty->output); + if (tty->termscript) + fwrite (conversion_buffer, 1, coding->produced, tty->termscript); UNBLOCK_INPUT; } /* Turn appearance modes off. */ turn_off_face (f, face_id); - turn_off_highlight (); - - cmcheckmagic (); + tty_turn_off_highlight (tty); + + cmcheckmagic (tty); } - -/* If start is zero, insert blanks instead of a string at start */ - -void -insert_glyphs (start, len) - register struct glyph *start; - register int len; +#endif + +/* An implementation of insert_glyphs for termcap frames. */ + +static void +tty_insert_glyphs (struct frame *f, struct glyph *start, int len) { char *buf; struct glyph *glyph = NULL; - struct frame *f, *sf; unsigned char *conversion_buffer; unsigned char space[1]; struct coding_system *coding; - if (len <= 0) - return; - - if (insert_glyphs_hook) + struct tty_display_info *tty = FRAME_TTY (f); + + if (tty->TS_ins_multi_chars) { - (*insert_glyphs_hook) (start, len); + buf = tparam (tty->TS_ins_multi_chars, 0, 0, len); + OUTPUT1 (tty, buf); + xfree (buf); + if (start) + write_glyphs (f, start, len); return; } - sf = XFRAME (selected_frame); - f = updating_frame ? updating_frame : sf; - - if (TS_ins_multi_chars) - { - buf = tparam (TS_ins_multi_chars, 0, 0, len); - OUTPUT1 (buf); - xfree (buf); - if (start) - write_glyphs (start, len); - return; - } - - turn_on_insert (); - cmplus (len); + tty_turn_on_insert (tty); + cmplus (tty, len); if (! start) space[0] = SPACEGLYPH; @@ -1190,15 +899,15 @@ /* If terminal_coding does any conversion, use it, otherwise use safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here because it always return 1 if the member src_multibyte is 1. */ - coding = (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK - ? &terminal_coding : &safe_terminal_coding); + coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK + ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding); /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at the tail. */ coding->mode &= ~CODING_MODE_LAST_BLOCK; while (len-- > 0) { - OUTPUT1_IF (TS_ins_char); + OUTPUT1_IF (tty, tty->TS_ins_char); if (!start) { conversion_buffer = space; @@ -1206,7 +915,7 @@ } else { - highlight_if_desired (); + tty_highlight_if_desired (tty); turn_on_face (f, start->face_id); glyph = start; ++start; @@ -1214,7 +923,7 @@ occupies more than one column. */ while (len && CHAR_GLYPH_PADDING_P (*start)) { - OUTPUT1_IF (TS_ins_char); + OUTPUT1_IF (tty, tty->TS_ins_char); start++, len--; } @@ -1222,89 +931,77 @@ /* This is the last glyph. */ coding->mode |= CODING_MODE_LAST_BLOCK; - conversion_buffer = encode_terminal_code (glyph, 1, coding); + conversion_buffer = encode_terminal_code (glyph, 1, coding); } if (coding->produced > 0) { BLOCK_INPUT; - fwrite (conversion_buffer, 1, coding->produced, stdout); - if (ferror (stdout)) - clearerr (stdout); - if (termscript) - fwrite (conversion_buffer, 1, coding->produced, termscript); + fwrite (conversion_buffer, 1, coding->produced, tty->output); + if (ferror (tty->output)) + clearerr (tty->output); + if (tty->termscript) + fwrite (conversion_buffer, 1, coding->produced, tty->termscript); UNBLOCK_INPUT; } - OUTPUT1_IF (TS_pad_inserted_char); + OUTPUT1_IF (tty, tty->TS_pad_inserted_char); if (start) { turn_off_face (f, glyph->face_id); - turn_off_highlight (); + tty_turn_off_highlight (tty); } } - cmcheckmagic (); + cmcheckmagic (tty); } -void -delete_glyphs (n) - register int n; +/* An implementation of delete_glyphs for termcap frames. */ + +static void +tty_delete_glyphs (struct frame *f, int n) { char *buf; register int i; - if (delete_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame)) + struct tty_display_info *tty = FRAME_TTY (f); + + if (tty->delete_in_insert_mode) { - (*delete_glyphs_hook) (n); - return; - } - - if (delete_in_insert_mode) - { - turn_on_insert (); + tty_turn_on_insert (tty); } else { - turn_off_insert (); - OUTPUT_IF (TS_delete_mode); + tty_turn_off_insert (tty); + OUTPUT_IF (tty, tty->TS_delete_mode); } - if (TS_del_multi_chars) + if (tty->TS_del_multi_chars) { - buf = tparam (TS_del_multi_chars, 0, 0, n); - OUTPUT1 (buf); + buf = tparam (tty->TS_del_multi_chars, 0, 0, n); + OUTPUT1 (tty, buf); xfree (buf); } else for (i = 0; i < n; i++) - OUTPUT1 (TS_del_char); - if (!delete_in_insert_mode) - OUTPUT_IF (TS_end_delete_mode); + OUTPUT1 (tty, tty->TS_del_char); + if (!tty->delete_in_insert_mode) + OUTPUT_IF (tty, tty->TS_end_delete_mode); } -/* Insert N lines at vpos VPOS. If N is negative, delete -N lines. */ - -void -ins_del_lines (vpos, n) - int vpos, n; +/* An implementation of ins_del_lines for termcap frames. */ + +static void +tty_ins_del_lines (struct frame *f, int vpos, int n) { - char *multi = n > 0 ? TS_ins_multi_lines : TS_del_multi_lines; - char *single = n > 0 ? TS_ins_line : TS_del_line; - char *scroll = n > 0 ? TS_rev_scroll : TS_fwd_scroll; - struct frame *sf; + 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 (ins_del_lines_hook && ! FRAME_TERMCAP_P (updating_frame)) - { - (*ins_del_lines_hook) (vpos, n); - return; - } - - sf = XFRAME (selected_frame); - /* 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 @@ -1312,45 +1009,49 @@ /* 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 (scroll_region_ok && vpos + i >= specified_window) + if (FRAME_SCROLL_REGION_OK (f) + && vpos + i >= tty->specified_window) return; - if (!memory_below_frame && vpos + i >= FRAME_LINES (sf)) + if (!FRAME_MEMORY_BELOW_FRAME (f) + && vpos + i >= FRAME_LINES (f)) return; - + if (multi) { - raw_cursor_to (vpos, 0); - background_highlight (); + raw_cursor_to (f, vpos, 0); + tty_background_highlight (tty); buf = tparam (multi, 0, 0, i); - OUTPUT (buf); + OUTPUT (tty, buf); xfree (buf); } else if (single) { - raw_cursor_to (vpos, 0); - background_highlight (); + raw_cursor_to (f, vpos, 0); + tty_background_highlight (tty); while (--i >= 0) - OUTPUT (single); - if (TF_teleray) - curX = 0; + OUTPUT (tty, single); + if (tty->TF_teleray) + curX (tty) = 0; } else { - set_scroll_region (vpos, specified_window); + tty_set_scroll_region (f, vpos, tty->specified_window); if (n < 0) - raw_cursor_to (specified_window - 1, 0); + raw_cursor_to (f, tty->specified_window - 1, 0); else - raw_cursor_to (vpos, 0); - background_highlight (); + raw_cursor_to (f, vpos, 0); + tty_background_highlight (tty); while (--i >= 0) - OUTPUTL (scroll, specified_window - vpos); - set_scroll_region (0, specified_window); + OUTPUTL (tty, scroll, tty->specified_window - vpos); + tty_set_scroll_region (f, 0, tty->specified_window); } - - if (!scroll_region_ok && memory_below_frame && n < 0) + + if (!FRAME_SCROLL_REGION_OK (f) + && FRAME_MEMORY_BELOW_FRAME (f) + && n < 0) { - cursor_to (FRAME_LINES (sf) + n, 0); - clear_to_end (); + cursor_to (f, FRAME_LINES (f) + n, 0); + clear_to_end (f); } } @@ -1358,8 +1059,7 @@ not counting any line-dependent padding. */ int -string_cost (str) - char *str; +string_cost (char *str) { cost = 0; if (str) @@ -1371,8 +1071,7 @@ 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) @@ -1384,8 +1083,7 @@ in tenths of characters. */ int -per_line_cost (str) - register char *str; +per_line_cost (char *str) { cost = 0; if (str) @@ -1408,26 +1106,26 @@ /* ARGSUSED */ static void -calculate_ins_del_char_costs (frame) - FRAME_PTR frame; +calculate_ins_del_char_costs (struct frame *f) { + struct tty_display_info *tty = FRAME_TTY (f); int ins_startup_cost, del_startup_cost; int ins_cost_per_char, del_cost_per_char; register int i; register int *p; - if (TS_ins_multi_chars) + if (tty->TS_ins_multi_chars) { ins_cost_per_char = 0; - ins_startup_cost = string_cost_one_line (TS_ins_multi_chars); + ins_startup_cost = string_cost_one_line (tty->TS_ins_multi_chars); } - else if (TS_ins_char || TS_pad_inserted_char - || (TS_insert_mode && TS_end_insert_mode)) + else if (tty->TS_ins_char || tty->TS_pad_inserted_char + || (tty->TS_insert_mode && tty->TS_end_insert_mode)) { - ins_startup_cost = (30 * (string_cost (TS_insert_mode) - + string_cost (TS_end_insert_mode))) / 100; - ins_cost_per_char = (string_cost_one_line (TS_ins_char) - + string_cost_one_line (TS_pad_inserted_char)); + ins_startup_cost = (30 * (string_cost (tty->TS_insert_mode) + + string_cost (tty->TS_end_insert_mode))) / 100; + ins_cost_per_char = (string_cost_one_line (tty->TS_ins_char) + + string_cost_one_line (tty->TS_pad_inserted_char)); } else { @@ -1435,18 +1133,18 @@ ins_cost_per_char = 0; } - if (TS_del_multi_chars) + if (tty->TS_del_multi_chars) { del_cost_per_char = 0; - del_startup_cost = string_cost_one_line (TS_del_multi_chars); + del_startup_cost = string_cost_one_line (tty->TS_del_multi_chars); } - else if (TS_del_char) + else if (tty->TS_del_char) { - del_startup_cost = (string_cost (TS_delete_mode) - + string_cost (TS_end_delete_mode)); - if (delete_in_insert_mode) + del_startup_cost = (string_cost (tty->TS_delete_mode) + + string_cost (tty->TS_end_delete_mode)); + if (tty->delete_in_insert_mode) del_startup_cost /= 2; - del_cost_per_char = string_cost_one_line (TS_del_char); + del_cost_per_char = string_cost_one_line (tty->TS_del_char); } else { @@ -1455,75 +1153,80 @@ } /* Delete costs are at negative offsets */ - p = &char_ins_del_cost (frame)[0]; - for (i = FRAME_COLS (frame); --i >= 0;) + p = &char_ins_del_cost (f)[0]; + for (i = FRAME_COLS (f); --i >= 0;) *--p = (del_startup_cost += del_cost_per_char); /* Doing nothing is free */ - p = &char_ins_del_cost (frame)[0]; + p = &char_ins_del_cost (f)[0]; *p++ = 0; /* Insert costs are at positive offsets */ - for (i = FRAME_COLS (frame); --i >= 0;) + for (i = FRAME_COLS (f); --i >= 0;) *p++ = (ins_startup_cost += ins_cost_per_char); } void -calculate_costs (frame) - FRAME_PTR frame; +calculate_costs (struct frame *frame) { - register char *f = (TS_set_scroll_region - ? TS_set_scroll_region - : TS_set_scroll_region_1); - FRAME_COST_BAUD_RATE (frame) = baud_rate; - scroll_region_cost = string_cost (f); - - /* These variables are only used for terminal stuff. They are allocated - once for the terminal frame of X-windows emacs, but not used afterwards. - - char_ins_del_vector (i.e., char_ins_del_cost) isn't used because - X turns off char_ins_del_ok. */ - - max_frame_lines = max (max_frame_lines, FRAME_LINES (frame)); - max_frame_cols = max (max_frame_cols, FRAME_COLS (frame)); - - costs_set = 1; - - if (char_ins_del_vector != 0) - char_ins_del_vector - = (int *) xrealloc (char_ins_del_vector, - (sizeof (int) - + 2 * max_frame_cols * sizeof (int))); - else - char_ins_del_vector - = (int *) xmalloc (sizeof (int) - + 2 * max_frame_cols * sizeof (int)); - - bzero (char_ins_del_vector, (sizeof (int) - + 2 * max_frame_cols * sizeof (int))); - - if (f && (!TS_ins_line && !TS_del_line)) - do_line_insertion_deletion_costs (frame, - TS_rev_scroll, TS_ins_multi_lines, - TS_fwd_scroll, TS_del_multi_lines, - f, f, 1); - else - do_line_insertion_deletion_costs (frame, - TS_ins_line, TS_ins_multi_lines, - TS_del_line, TS_del_multi_lines, - 0, 0, 1); - - calculate_ins_del_char_costs (frame); - - /* Don't use TS_repeat if its padding is worse than sending the chars */ - if (TS_repeat && per_line_cost (TS_repeat) * baud_rate < 9000) - RPov = string_cost (TS_repeat); - else - RPov = FRAME_COLS (frame) * 2; - - cmcostinit (); /* set up cursor motion costs */ + if (FRAME_TERMCAP_P (frame)) + { + struct tty_display_info *tty = FRAME_TTY (frame); + register char *f = (tty->TS_set_scroll_region + ? tty->TS_set_scroll_region + : tty->TS_set_scroll_region_1); + + FRAME_SCROLL_REGION_COST (frame) = string_cost (f); + + tty->costs_set = 1; + + /* These variables are only used for terminal stuff. They are + allocated once for the terminal frame of X-windows emacs, but not + used afterwards. + + char_ins_del_vector (i.e., char_ins_del_cost) isn't used because + X turns off char_ins_del_ok. */ + + max_frame_lines = max (max_frame_lines, FRAME_LINES (frame)); + max_frame_cols = max (max_frame_cols, FRAME_COLS (frame)); + + if (char_ins_del_vector != 0) + char_ins_del_vector + = (int *) xrealloc (char_ins_del_vector, + (sizeof (int) + + 2 * max_frame_cols * sizeof (int))); + else + char_ins_del_vector + = (int *) xmalloc (sizeof (int) + + 2 * max_frame_cols * sizeof (int)); + + bzero (char_ins_del_vector, (sizeof (int) + + 2 * max_frame_cols * sizeof (int))); + + + if (f && (!tty->TS_ins_line && !tty->TS_del_line)) + do_line_insertion_deletion_costs (frame, + tty->TS_rev_scroll, tty->TS_ins_multi_lines, + tty->TS_fwd_scroll, tty->TS_del_multi_lines, + f, f, 1); + else + do_line_insertion_deletion_costs (frame, + tty->TS_ins_line, tty->TS_ins_multi_lines, + tty->TS_del_line, tty->TS_del_multi_lines, + 0, 0, 1); + + calculate_ins_del_char_costs (frame); + + /* Don't use TS_repeat if its padding is worse than sending the chars */ + if (tty->TS_repeat && per_line_cost (tty->TS_repeat) * baud_rate < 9000) + tty->RPov = string_cost (tty->TS_repeat); + else + tty->RPov = FRAME_COLS (frame) * 2; + + cmcostinit (FRAME_TTY (frame)); /* set up cursor motion costs */ + } } struct fkey_table { @@ -1633,16 +1336,18 @@ {"!3", "S-undo"} /*shifted undo key*/ }; -static char **term_get_fkeys_arg; +static char **term_get_fkeys_address; +static KBOARD *term_get_fkeys_kboard; static Lisp_Object term_get_fkeys_1 (); -/* Find the escape codes sent by the function keys for Vfunction_key_map. +/* Find the escape codes sent by the function keys for Vinput_decode_map. This function scans the termcap function key sequence entries, and - adds entries to Vfunction_key_map for each function key it finds. */ - -void -term_get_fkeys (address) + adds entries to Vinput_decode_map for each function key it finds. */ + +static void +term_get_fkeys (address, kboard) char **address; + KBOARD *kboard; { /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp errors during the call. The only errors should be from Fdefine_key @@ -1653,7 +1358,8 @@ refusing to run at all on such a terminal. */ extern Lisp_Object Fidentity (); - term_get_fkeys_arg = address; + term_get_fkeys_address = address; + term_get_fkeys_kboard = kboard; internal_condition_case (term_get_fkeys_1, Qerror, Fidentity); } @@ -1662,17 +1368,18 @@ { int i; - char **address = term_get_fkeys_arg; - + char **address = term_get_fkeys_address; + KBOARD *kboard = term_get_fkeys_kboard; + /* This can happen if CANNOT_DUMP or with strange options. */ - if (!initialized) - Vfunction_key_map = Fmake_sparse_keymap (Qnil); + if (!KEYMAPP (kboard->Vinput_decode_map)) + kboard->Vinput_decode_map = Fmake_sparse_keymap (Qnil); for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++) { char *sequence = tgetstr (keys[i].cap, address); if (sequence) - Fdefine_key (Vfunction_key_map, build_string (sequence), + Fdefine_key (kboard->Vinput_decode_map, build_string (sequence), Fmake_vector (make_number (1), intern (keys[i].name))); } @@ -1692,13 +1399,13 @@ if (k0) /* Define f0 first, so that f10 takes precedence in case the key sequences happens to be the same. */ - Fdefine_key (Vfunction_key_map, build_string (k0), + Fdefine_key (kboard->Vinput_decode_map, build_string (k0), Fmake_vector (make_number (1), intern ("f0"))); - Fdefine_key (Vfunction_key_map, build_string (k_semi), + Fdefine_key (kboard->Vinput_decode_map, build_string (k_semi), Fmake_vector (make_number (1), intern ("f10"))); } else if (k0) - Fdefine_key (Vfunction_key_map, build_string (k0), + Fdefine_key (kboard->Vinput_decode_map, build_string (k0), Fmake_vector (make_number (1), intern (k0_name))); } @@ -1721,7 +1428,7 @@ if (sequence) { sprintf (fkey, "f%d", i); - Fdefine_key (Vfunction_key_map, build_string (sequence), + Fdefine_key (kboard->Vinput_decode_map, build_string (sequence), Fmake_vector (make_number (1), intern (fkey))); } @@ -1737,10 +1444,10 @@ if (!tgetstr (cap1, address)) \ { \ char *sequence = tgetstr (cap2, address); \ - if (sequence) \ - Fdefine_key (Vfunction_key_map, build_string (sequence), \ - Fmake_vector (make_number (1), \ - intern (sym))); \ + if (sequence) \ + Fdefine_key (kboard->Vinput_decode_map, build_string (sequence), \ + Fmake_vector (make_number (1), \ + intern (sym))); \ } /* if there's no key_next keycap, map key_npage to `next' keysym */ @@ -2142,10 +1849,10 @@ from them. Some display attributes may not be used together with color; the termcap capability `NC' specifies which ones. */ -#define MAY_USE_WITH_COLORS_P(ATTR) \ - (TN_max_colors > 0 \ - ? (TN_no_color_video & (ATTR)) == 0 \ - : 1) +#define MAY_USE_WITH_COLORS_P(tty, ATTR) \ + (tty->TN_max_colors > 0 \ + ? (tty->TN_no_color_video & (ATTR)) == 0 \ + : 1) /* Turn appearances of face FACE_ID on tty frame F on. FACE_ID is a realized face ID number, in the face cache. */ @@ -2158,12 +1865,13 @@ struct face *face = FACE_FROM_ID (f, face_id); long fg = face->foreground; long bg = face->background; + struct tty_display_info *tty = FRAME_TTY (f); /* Do this first because TS_end_standout_mode may be the same as TS_exit_attribute_mode, which turns all appearances off. */ - if (MAY_USE_WITH_COLORS_P (NC_REVERSE)) + if (MAY_USE_WITH_COLORS_P (tty, NC_REVERSE)) { - if (TN_max_colors > 0) + if (tty->TN_max_colors > 0) { if (fg >= 0 && bg >= 0) { @@ -2177,13 +1885,13 @@ { if (fg == FACE_TTY_DEFAULT_FG_COLOR || bg == FACE_TTY_DEFAULT_BG_COLOR) - toggle_highlight (); + tty_toggle_highlight (tty); } else { if (fg == FACE_TTY_DEFAULT_BG_COLOR || bg == FACE_TTY_DEFAULT_FG_COLOR) - toggle_highlight (); + tty_toggle_highlight (tty); } } else @@ -2194,55 +1902,55 @@ { if (fg == FACE_TTY_DEFAULT_FG_COLOR || bg == FACE_TTY_DEFAULT_BG_COLOR) - toggle_highlight (); + tty_toggle_highlight (tty); } else { if (fg == FACE_TTY_DEFAULT_BG_COLOR || bg == FACE_TTY_DEFAULT_FG_COLOR) - toggle_highlight (); + tty_toggle_highlight (tty); } } } if (face->tty_bold_p) { - if (MAY_USE_WITH_COLORS_P (NC_BOLD)) - OUTPUT1_IF (TS_enter_bold_mode); + if (MAY_USE_WITH_COLORS_P (tty, NC_BOLD)) + OUTPUT1_IF (tty, tty->TS_enter_bold_mode); } else if (face->tty_dim_p) - if (MAY_USE_WITH_COLORS_P (NC_DIM)) - OUTPUT1_IF (TS_enter_dim_mode); + if (MAY_USE_WITH_COLORS_P (tty, NC_DIM)) + OUTPUT1_IF (tty, tty->TS_enter_dim_mode); /* Alternate charset and blinking not yet used. */ if (face->tty_alt_charset_p - && MAY_USE_WITH_COLORS_P (NC_ALT_CHARSET)) - OUTPUT1_IF (TS_enter_alt_charset_mode); + && MAY_USE_WITH_COLORS_P (tty, NC_ALT_CHARSET)) + OUTPUT1_IF (tty, tty->TS_enter_alt_charset_mode); if (face->tty_blinking_p - && MAY_USE_WITH_COLORS_P (NC_BLINK)) - OUTPUT1_IF (TS_enter_blink_mode); - - if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (NC_UNDERLINE)) - OUTPUT1_IF (TS_enter_underline_mode); - - if (TN_max_colors > 0) + && MAY_USE_WITH_COLORS_P (tty, NC_BLINK)) + OUTPUT1_IF (tty, tty->TS_enter_blink_mode); + + if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (tty, NC_UNDERLINE)) + OUTPUT1_IF (tty, tty->TS_enter_underline_mode); + + if (tty->TN_max_colors > 0) { char *ts, *p; - ts = standout_mode ? TS_set_background : TS_set_foreground; + ts = tty->standout_mode ? tty->TS_set_background : tty->TS_set_foreground; if (fg >= 0 && ts) { - p = tparam (ts, NULL, 0, (int) fg); - OUTPUT (p); + p = tparam (ts, NULL, 0, (int) fg); + OUTPUT (tty, p); xfree (p); } - ts = standout_mode ? TS_set_foreground : TS_set_background; + ts = tty->standout_mode ? tty->TS_set_foreground : tty->TS_set_background; if (bg >= 0 && ts) { - p = tparam (ts, NULL, 0, (int) bg); - OUTPUT (p); + p = tparam (ts, NULL, 0, (int) bg); + OUTPUT (tty, p); xfree (p); } } @@ -2257,10 +1965,11 @@ int face_id; { struct face *face = FACE_FROM_ID (f, face_id); + struct tty_display_info *tty = FRAME_TTY (f); xassert (face != NULL); - if (TS_exit_attribute_mode) + if (tty->TS_exit_attribute_mode) { /* Capability "me" will turn off appearance modes double-bright, half-bright, reverse-video, standout, underline. It may or @@ -2272,32 +1981,32 @@ || face->tty_blinking_p || face->tty_underline_p) { - OUTPUT1_IF (TS_exit_attribute_mode); - if (strcmp (TS_exit_attribute_mode, TS_end_standout_mode) == 0) - standout_mode = 0; + OUTPUT1_IF (tty, tty->TS_exit_attribute_mode); + if (strcmp (tty->TS_exit_attribute_mode, tty->TS_end_standout_mode) == 0) + tty->standout_mode = 0; } if (face->tty_alt_charset_p) - OUTPUT_IF (TS_exit_alt_charset_mode); + OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode); } else { /* If we don't have "me" we can only have those appearances that have exit sequences defined. */ if (face->tty_alt_charset_p) - OUTPUT_IF (TS_exit_alt_charset_mode); + OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode); if (face->tty_underline_p) - OUTPUT_IF (TS_exit_underline_mode); + OUTPUT_IF (tty, tty->TS_exit_underline_mode); } /* Switch back to default colors. */ - if (TN_max_colors > 0 + if (tty->TN_max_colors > 0 && ((face->foreground != FACE_TTY_DEFAULT_COLOR && face->foreground != FACE_TTY_DEFAULT_FG_COLOR) || (face->background != FACE_TTY_DEFAULT_COLOR && face->background != FACE_TTY_DEFAULT_BG_COLOR))) - OUTPUT1_IF (TS_orig_pair); + OUTPUT1_IF (tty, tty->TS_orig_pair); } @@ -2306,46 +2015,61 @@ colors FG and BG. */ int -tty_capable_p (f, caps, fg, bg) - struct frame *f; +tty_capable_p (tty, caps, fg, bg) + struct tty_display_info *tty; unsigned caps; unsigned long fg, bg; { -#define TTY_CAPABLE_P_TRY(cap, TS, NC_bit) \ - if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(NC_bit))) \ +#define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \ + if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \ return 0; - TTY_CAPABLE_P_TRY (TTY_CAP_INVERSE, TS_standout_mode, NC_REVERSE); - TTY_CAPABLE_P_TRY (TTY_CAP_UNDERLINE, TS_enter_underline_mode, NC_UNDERLINE); - TTY_CAPABLE_P_TRY (TTY_CAP_BOLD, TS_enter_bold_mode, NC_BOLD); - TTY_CAPABLE_P_TRY (TTY_CAP_DIM, TS_enter_dim_mode, NC_DIM); - TTY_CAPABLE_P_TRY (TTY_CAP_BLINK, TS_enter_blink_mode, NC_BLINK); - TTY_CAPABLE_P_TRY (TTY_CAP_ALT_CHARSET, TS_enter_alt_charset_mode, NC_ALT_CHARSET); + TTY_CAPABLE_P_TRY (tty, TTY_CAP_INVERSE, tty->TS_standout_mode, NC_REVERSE); + TTY_CAPABLE_P_TRY (tty, TTY_CAP_UNDERLINE, tty->TS_enter_underline_mode, NC_UNDERLINE); + TTY_CAPABLE_P_TRY (tty, TTY_CAP_BOLD, tty->TS_enter_bold_mode, NC_BOLD); + TTY_CAPABLE_P_TRY (tty, TTY_CAP_DIM, tty->TS_enter_dim_mode, NC_DIM); + TTY_CAPABLE_P_TRY (tty, TTY_CAP_BLINK, tty->TS_enter_blink_mode, NC_BLINK); + TTY_CAPABLE_P_TRY (tty, TTY_CAP_ALT_CHARSET, tty->TS_enter_alt_charset_mode, NC_ALT_CHARSET); /* We can do it! */ return 1; } - /* 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. */) - (display) - Lisp_Object display; + doc: /* Return non-nil if the tty device TERMINAL can display colors. + +TERMINAL can be a terminal id, a frame or nil (meaning the selected +frame's terminal). This function always returns nil if TERMINAL +is not on a tty device. */) + (terminal) + Lisp_Object terminal; { - return TN_max_colors > 0 ? Qt : Qnil; + struct terminal *t = get_tty_terminal (terminal, 0); + if (!t) + return Qnil; + else + return t->display_info.tty->TN_max_colors > 0 ? Qt : Qnil; } /* 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. */) - (display) - Lisp_Object display; + doc: /* Return the number of colors supported by the tty device TERMINAL. + +TERMINAL can be a terminal id, a frame or nil (meaning the selected +frame's terminal). This function always returns 0 if TERMINAL +is not on a tty device. */) + (terminal) + Lisp_Object terminal; { - return make_number (TN_max_colors); + struct terminal *t = get_tty_terminal (terminal, 0); + if (!t) + return make_number (0); + else + return make_number (t->display_info.tty->TN_max_colors); } #ifndef WINDOWSNT @@ -2363,48 +2087,46 @@ /* Save or restore the default color-related capabilities of this terminal. */ static void -tty_default_color_capabilities (save) - int save; +tty_default_color_capabilities (struct tty_display_info *tty, int save) { if (save) { if (default_orig_pair) xfree (default_orig_pair); - default_orig_pair = TS_orig_pair ? xstrdup (TS_orig_pair) : NULL; + default_orig_pair = tty->TS_orig_pair ? xstrdup (tty->TS_orig_pair) : NULL; if (default_set_foreground) xfree (default_set_foreground); - default_set_foreground = TS_set_foreground ? xstrdup (TS_set_foreground) + default_set_foreground = tty->TS_set_foreground ? xstrdup (tty->TS_set_foreground) : NULL; if (default_set_background) xfree (default_set_background); - default_set_background = TS_set_background ? xstrdup (TS_set_background) + default_set_background = tty->TS_set_background ? xstrdup (tty->TS_set_background) : NULL; - default_max_colors = TN_max_colors; - default_max_pairs = TN_max_pairs; - default_no_color_video = TN_no_color_video; + default_max_colors = tty->TN_max_colors; + default_max_pairs = tty->TN_max_pairs; + default_no_color_video = tty->TN_no_color_video; } else { - TS_orig_pair = default_orig_pair; - TS_set_foreground = default_set_foreground; - TS_set_background = default_set_background; - TN_max_colors = default_max_colors; - TN_max_pairs = default_max_pairs; - TN_no_color_video = default_no_color_video; + tty->TS_orig_pair = default_orig_pair; + tty->TS_set_foreground = default_set_foreground; + tty->TS_set_background = default_set_background; + tty->TN_max_colors = default_max_colors; + tty->TN_max_pairs = default_max_pairs; + tty->TN_no_color_video = default_no_color_video; } } /* Setup one of the standard tty color schemes according to MODE. MODE's value is generally the number of colors which we want to support; zero means set up for the default capabilities, the ones - we saw at term_init time; -1 means turn off color support. */ -void -tty_setup_colors (mode) - int mode; + we saw at init_tty time; -1 means turn off color support. */ +static void +tty_setup_colors (struct tty_display_info *tty, int mode) { /* Canonicalize all negative values of MODE. */ if (mode < -1) @@ -2413,27 +2135,27 @@ switch (mode) { case -1: /* no colors at all */ - TN_max_colors = 0; - TN_max_pairs = 0; - TN_no_color_video = 0; - TS_set_foreground = TS_set_background = TS_orig_pair = NULL; + tty->TN_max_colors = 0; + tty->TN_max_pairs = 0; + tty->TN_no_color_video = 0; + tty->TS_set_foreground = tty->TS_set_background = tty->TS_orig_pair = NULL; break; case 0: /* default colors, if any */ default: - tty_default_color_capabilities (0); + tty_default_color_capabilities (tty, 0); break; case 8: /* 8 standard ANSI colors */ - TS_orig_pair = "\033[0m"; + tty->TS_orig_pair = "\033[0m"; #ifdef TERMINFO - TS_set_foreground = "\033[3%p1%dm"; - TS_set_background = "\033[4%p1%dm"; + tty->TS_set_foreground = "\033[3%p1%dm"; + tty->TS_set_background = "\033[4%p1%dm"; #else - TS_set_foreground = "\033[3%dm"; - TS_set_background = "\033[4%dm"; + tty->TS_set_foreground = "\033[3%dm"; + tty->TS_set_background = "\033[4%dm"; #endif - TN_max_colors = 8; - TN_max_pairs = 64; - TN_no_color_video = 0; + tty->TN_max_colors = 8; + tty->TN_max_pairs = 64; + tty->TN_no_color_video = 0; break; } } @@ -2484,7 +2206,7 @@ if (mode != old_mode) { - tty_setup_colors (mode); + tty_setup_colors (FRAME_TTY (f), mode); /* This recomputes all the faces given the new color definitions. */ call0 (intern ("tty-set-up-initial-frame-faces")); @@ -2495,6 +2217,241 @@ #endif /* !WINDOWSNT */ + +/* Return the tty display object specified by TERMINAL. */ + +struct terminal * +get_tty_terminal (Lisp_Object terminal, int throw) +{ + struct terminal *t = get_terminal (terminal, throw); + + if (t && t->type != output_termcap) + { + if (throw) + error ("Device %d is not a termcap terminal device", t->id); + else + return NULL; + } + + return t; +} + +/* Return an active termcap device that uses the tty device with the + given name. + + This function ignores suspended devices. + + Returns NULL if the named terminal device is not opened. */ + +struct terminal * +get_named_tty (name) + char *name; +{ + struct terminal *t; + + if (!name) + abort (); + + for (t = terminal_list; t; t = t->next_terminal) + { + if (t->type == output_termcap + && !strcmp (t->display_info.tty->name, name) + && TERMINAL_ACTIVE_P (t)) + return t; + } + + return 0; +} + + +DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0, + doc: /* Return the type of the tty device that TERMINAL uses. +Returns nil if TERMINAL is not on a tty device. + +TERMINAL can be a terminal id, a frame or nil (meaning the selected +frame's terminal). */) + (terminal) + Lisp_Object terminal; +{ + struct terminal *t = get_terminal (terminal, 1); + + if (t->type != output_termcap) + return Qnil; + + if (t->display_info.tty->type) + return build_string (t->display_info.tty->type); + else + return Qnil; +} + +DEFUN ("controlling-tty-p", Fcontrolling_tty_p, Scontrolling_tty_p, 0, 1, 0, + doc: /* Return non-nil if TERMINAL is on the controlling tty of the Emacs process. + +TERMINAL can be a terminal id, a frame or nil (meaning the selected +frame's terminal). This function always returns nil if TERMINAL +is not on a tty device. */) + (terminal) + Lisp_Object terminal; +{ + struct terminal *t = get_terminal (terminal, 1); + + if (t->type != output_termcap || strcmp (t->display_info.tty->name, DEV_TTY)) + return Qnil; + else + return Qt; +} + +DEFUN ("tty-no-underline", Ftty_no_underline, Stty_no_underline, 0, 1, 0, + doc: /* Declare that the tty used by TERMINAL does not handle underlining. +This is used to override the terminfo data, for certain terminals that +do not really do underlining, but say that they do. This function has +no effect if used on a non-tty terminal. + +TERMINAL can be a terminal id, a frame or nil (meaning the selected +frame's terminal). This function always returns nil if TERMINAL +is not on a tty device. */) + (terminal) + Lisp_Object terminal; +{ + struct terminal *t = get_terminal (terminal, 1); + + if (t->type == output_termcap) + t->display_info.tty->TS_enter_underline_mode = 0; + return Qnil; +} + + + +DEFUN ("suspend-tty", Fsuspend_tty, Ssuspend_tty, 0, 1, 0, + doc: /* Suspend the terminal device TTY. + +The device is restored to its default state, and Emacs ceases all +access to the tty 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 terminal id, a frame, or nil for the terminal 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 +terminal device. + +`suspend-tty' does nothing if it is called on a device that is already +suspended. + +A suspended tty may be resumed by calling `resume-tty' on it. */) + (tty) + Lisp_Object tty; +{ + struct terminal *t = get_tty_terminal (tty, 1); + FILE *f; + + if (!t) + error ("Unknown tty device"); + + f = t->display_info.tty->input; + + if (f) + { + /* First run `suspend-tty-functions' and then clean up the tty + state because `suspend-tty-functions' might need to change + the tty state. */ + if (!NILP (Vrun_hooks)) + { + Lisp_Object args[2]; + args[0] = intern ("suspend-tty-functions"); + XSETTERMINAL (args[1], t); + Frun_hook_with_args (2, args); + } + + reset_sys_modes (t->display_info.tty); + + delete_keyboard_wait_descriptor (fileno (f)); + + fclose (f); + if (f != t->display_info.tty->output) + fclose (t->display_info.tty->output); + + t->display_info.tty->input = 0; + t->display_info.tty->output = 0; + + if (FRAMEP (t->display_info.tty->top_frame)) + FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0); + + } + + /* Clear display hooks to prevent further output. */ + clear_tty_hooks (t); + + 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 terminal are revived. + +It is an error to resume a terminal while another terminal is active +on the same device. + +This function runs `resume-tty-functions' after resuming the terminal. +The functions are run with one arg, the id of the resumed terminal +device. + +`resume-tty' does nothing if it is called on a device that is not +suspended. + +TTY may be a terminal id, a frame, or nil for the terminal device of +the currently selected frame. */) + (tty) + Lisp_Object tty; +{ + struct terminal *t = get_tty_terminal (tty, 1); + int fd; + + if (!t) + error ("Unknown tty device"); + + if (!t->display_info.tty->input) + { + if (get_named_tty (t->display_info.tty->name)) + error ("Cannot resume display while another display is active on the same device"); + + fd = emacs_open (t->display_info.tty->name, O_RDWR | O_NOCTTY, 0); + + if (fd == -1) + error ("Can not reopen tty device %s: %s", t->display_info.tty->name, strerror (errno)); + + if (strcmp (t->display_info.tty->name, DEV_TTY)) + dissociate_if_controlling_tty (fd); + + t->display_info.tty->output = fdopen (fd, "w+"); + t->display_info.tty->input = t->display_info.tty->output; + + add_keyboard_wait_descriptor (fd); + + if (FRAMEP (t->display_info.tty->top_frame)) + FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1); + + init_sys_modes (t->display_info.tty); + + /* Run `resume-tty-functions'. */ + if (!NILP (Vrun_hooks)) + { + Lisp_Object args[2]; + args[0] = intern ("resume-tty-functions"); + XSETTERMINAL (args[1], t); + Frun_hook_with_args (2, args); + } + } + + set_tty_hooks (t); + + return Qnil; +} + + /*********************************************************************** Mouse ***********************************************************************/ @@ -2517,10 +2474,13 @@ static void term_show_mouse_face (enum draw_glyphs_face draw) { - struct window *w = XWINDOW (Qmouse_face_window); + struct window *w = XWINDOW (mouse_face_window); int save_x, save_y; int i; + struct frame *f = XFRAME (w->frame); + struct tty_display_info *tty = FRAME_TTY (f); + if (/* If window is in the process of being destroyed, don't bother to do anything. */ w->current_matrix != NULL @@ -2533,8 +2493,8 @@ the highlight region. */ /* Save current cursor co-ordinates */ - save_y = curY; - save_x = curX; + save_y = curY (tty); + save_x = curX (tty); /* Note that mouse_face_beg_row etc. are window relative. */ for (i = mouse_face_beg_row; i <= mouse_face_end_row; i++) @@ -2576,29 +2536,29 @@ pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos + WINDOW_LEFT_EDGE_X (w); - cursor_to (pos_y, pos_x); + cursor_to (f, pos_y, pos_x); if (draw == DRAW_MOUSE_FACE) { - write_glyphs_with_face (row->glyphs[TEXT_AREA] + start_hpos, + tty_write_glyphs_with_face (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs, mouse_face_face_id); } else /* draw == DRAW_NORMAL_TEXT */ - write_glyphs (row->glyphs[TEXT_AREA] + start_hpos, nglyphs); + write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs); } - cursor_to (save_y, save_x); + cursor_to (f, save_y, save_x); } } static void term_clear_mouse_face () { - if (!NILP (Qmouse_face_window)) + if (!NILP (mouse_face_window)) term_show_mouse_face (DRAW_NORMAL_TEXT); mouse_face_beg_row = mouse_face_beg_col = -1; mouse_face_end_row = mouse_face_end_col = -1; - Qmouse_face_window = Qnil; + mouse_face_window = Qnil; } /* Find the glyph matrix position of buffer position POS in window W. @@ -2695,7 +2655,7 @@ if (!WINDOWP (window)) return; - if (!EQ (window, Qmouse_face_window)) + if (!EQ (window, mouse_face_window)) term_clear_mouse_face (); w = XWINDOW (window); @@ -2778,7 +2738,7 @@ noverlays = sort_overlays (overlay_vec, noverlays, w); /* Check mouse-face highlighting. */ - if (!(EQ (window, Qmouse_face_window) + if (!(EQ (window, mouse_face_window) && y >= mouse_face_beg_row && y <= mouse_face_end_row && (y > mouse_face_beg_row @@ -2828,7 +2788,7 @@ = !fast_find_position (w, XFASTINT (after), &mouse_face_end_col, &mouse_face_end_row); - Qmouse_face_window = window; + mouse_face_window = window; mouse_face_face_id = face_at_buffer_position (w, pos, 0, 0, @@ -2863,7 +2823,7 @@ = !fast_find_position (w, XFASTINT (after), &mouse_face_end_col, &mouse_face_end_row); - Qmouse_face_window = window; + mouse_face_window = window; mouse_face_face_id = face_at_buffer_position (w, pos, 0, 0, @@ -3036,10 +2996,9 @@ } int -handle_one_term_event (Gpm_Event *event, struct input_event* hold_quit) +handle_one_term_event (struct tty_display_info *tty, Gpm_Event *event, struct input_event* hold_quit) { - struct frame *f = SELECTED_FRAME (); - int fd; + struct frame *f = XFRAME (tty->top_frame); struct input_event ie; int do_help = 0; int count = 0; @@ -3049,24 +3008,10 @@ ie.arg = Qnil; if (event->type & (GPM_MOVE | GPM_DRAG)) { - unsigned char buf[6 * sizeof (short)]; - unsigned short *arg = (unsigned short *) buf + 1; - const char *name; - previous_help_echo_string = help_echo_string; help_echo_string = Qnil; - /* Display mouse pointer */ - buf[sizeof(short) - 1] = 2; /* set selection */ - - arg[0] = arg[2] = (unsigned short) event->x + gpm_zerobased; - arg[1] = arg[3] = (unsigned short) event->y + gpm_zerobased; - arg[4] = (unsigned short) 3; - - name = ttyname (0); - fd = open (name, O_WRONLY); - ioctl (fd, TIOCLINUX, buf + sizeof (short) - 1); - close (fd); + Gpm_DrawPointer (event->x, event->y, fileno (tty->output)); if (!term_mouse_movement (f, event)) help_echo_string = previous_help_echo_string; @@ -3109,13 +3054,25 @@ return count; } -DEFUN ("term-open-connection", Fterm_open_connection, Sterm_open_connection, +DEFUN ("gpm-mouse-start", Fgpm_mouse_start, Sgpm_mouse_start, 0, 0, 0, - doc: /* Open a connection to Gpm. */) + doc: /* Open a connection to Gpm. +Gpm-mouse can only be activated for one tty at a time. */) () { + struct frame *f = SELECTED_FRAME (); + struct tty_display_info *tty + = ((f)->output_method == output_termcap + ? (f)->terminal->display_info.tty : NULL); Gpm_Connect connection; + if (!tty) + error ("Gpm-mouse only works in the GNU/Linux console"); + if (gpm_tty == tty) + return Qnil; /* Already activated, nothing to do. */ + if (gpm_tty) + error ("Gpm-mouse can only be activated for one tty at a time"); + connection.eventMask = ~0; connection.defaultMask = ~GPM_HARD; connection.maxMod = ~0; @@ -3123,26 +3080,38 @@ gpm_zerobased = 1; if (Gpm_Open (&connection, 0) < 0) - return Qnil; + error ("Gpm-mouse failed to connect to the gpm daemon"); else { - term_gpm = 1; - reset_sys_modes (); - init_sys_modes (); + gpm_tty = tty; + /* `init_sys_modes' arranges for mouse movements sent through gpm_fd + to generate SIGIOs. Apparently we need to call reset_sys_modes + before calling init_sys_modes. */ + reset_sys_modes (tty); + init_sys_modes (tty); add_gpm_wait_descriptor (gpm_fd); - return Qt; + return Qnil; } } -DEFUN ("term-close-connection", Fterm_close_connection, Sterm_close_connection, +DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop, Sgpm_mouse_stop, 0, 0, 0, doc: /* Close a connection to Gpm. */) () { - delete_gpm_wait_descriptor (gpm_fd); - while (Gpm_Close()); /* close all the stack */ - term_gpm = 0; - return Qnil; + struct frame *f = SELECTED_FRAME (); + struct tty_display_info *tty + = ((f)->output_method == output_termcap + ? (f)->terminal->display_info.tty : NULL); + + if (!tty || gpm_tty != tty) + return Qnil; /* Not activated on this terminal, nothing to do. */ + + if (gpm_fd >= 0) + delete_gpm_wait_descriptor (gpm_fd); + while (Gpm_Close()); /* close all the stack */ + gpm_tty = NULL; + return Qnil; } #endif /* HAVE_GPM */ @@ -3151,87 +3120,359 @@ Initialization ***********************************************************************/ +/* Initialize the tty-dependent part of frame F. The frame must + already have its device initialized. */ + void -term_init (terminal_type) - char *terminal_type; +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_TERMINAL (f)->display_info.tty; + + f->output_data.tty = t; +} + +/* Delete the tty-dependent part of frame F. */ + +static void +delete_tty_output (struct frame *f) +{ + if (! FRAME_TERMCAP_P (f)) + abort (); + + xfree (f->output_data.tty); +} + + +/* Reset the hooks in TERMINAL. */ + +static void +clear_tty_hooks (struct terminal *terminal) +{ + terminal->rif = 0; + terminal->cursor_to_hook = 0; + terminal->raw_cursor_to_hook = 0; + terminal->clear_to_end_hook = 0; + terminal->clear_frame_hook = 0; + terminal->clear_end_of_line_hook = 0; + terminal->ins_del_lines_hook = 0; + terminal->insert_glyphs_hook = 0; + terminal->write_glyphs_hook = 0; + terminal->delete_glyphs_hook = 0; + terminal->ring_bell_hook = 0; + terminal->reset_terminal_modes_hook = 0; + terminal->set_terminal_modes_hook = 0; + terminal->update_begin_hook = 0; + terminal->update_end_hook = 0; + terminal->set_terminal_window_hook = 0; + terminal->mouse_position_hook = 0; + terminal->frame_rehighlight_hook = 0; + terminal->frame_raise_lower_hook = 0; + terminal->fullscreen_hook = 0; + terminal->set_vertical_scroll_bar_hook = 0; + terminal->condemn_scroll_bars_hook = 0; + terminal->redeem_scroll_bar_hook = 0; + terminal->judge_scroll_bars_hook = 0; + terminal->read_socket_hook = 0; + terminal->frame_up_to_date_hook = 0; + + /* Leave these two set, or suspended frames are not deleted + correctly. */ + terminal->delete_frame_hook = &delete_tty_output; + terminal->delete_terminal_hook = &delete_tty; +} + +/* Initialize hooks in TERMINAL with the values needed for a tty. */ + +static void +set_tty_hooks (struct terminal *terminal) { - char *area; + terminal->rif = 0; /* ttys don't support window-based redisplay. */ + + terminal->cursor_to_hook = &tty_cursor_to; + terminal->raw_cursor_to_hook = &tty_raw_cursor_to; + + terminal->clear_to_end_hook = &tty_clear_to_end; + terminal->clear_frame_hook = &tty_clear_frame; + terminal->clear_end_of_line_hook = &tty_clear_end_of_line; + + terminal->ins_del_lines_hook = &tty_ins_del_lines; + + terminal->insert_glyphs_hook = &tty_insert_glyphs; + terminal->write_glyphs_hook = &tty_write_glyphs; + terminal->delete_glyphs_hook = &tty_delete_glyphs; + + terminal->ring_bell_hook = &tty_ring_bell; + + terminal->reset_terminal_modes_hook = &tty_reset_terminal_modes; + terminal->set_terminal_modes_hook = &tty_set_terminal_modes; + terminal->update_begin_hook = 0; /* Not needed. */ + terminal->update_end_hook = &tty_update_end; + terminal->set_terminal_window_hook = &tty_set_terminal_window; + + terminal->mouse_position_hook = 0; /* Not needed. */ + terminal->frame_rehighlight_hook = 0; /* Not needed. */ + terminal->frame_raise_lower_hook = 0; /* Not needed. */ + + terminal->set_vertical_scroll_bar_hook = 0; /* Not needed. */ + terminal->condemn_scroll_bars_hook = 0; /* Not needed. */ + terminal->redeem_scroll_bar_hook = 0; /* Not needed. */ + terminal->judge_scroll_bars_hook = 0; /* Not needed. */ + + terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */ + terminal->frame_up_to_date_hook = 0; /* Not needed. */ + + terminal->delete_frame_hook = &delete_tty_output; + terminal->delete_terminal_hook = &delete_tty; +} + +/* Drop the controlling terminal if fd is the same device. */ +static void +dissociate_if_controlling_tty (int fd) +{ +#ifndef WINDOWSNT + 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; +#elif defined (CYGWIN) + setsid (); + 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 */ + } +#endif /* !WINDOWSNT */ +} + +static void maybe_fatal(); + +/* 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., "/dev/tty". + 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 terminal * +init_tty (char *name, char *terminal_type, int must_succeed) +{ + char *area = NULL; char **address = &area; char *buffer = NULL; int buffer_size = 4096; - register char *p; + register char *p = NULL; int status; - struct frame *sf = XFRAME (selected_frame); + struct tty_display_info *tty = NULL; + struct terminal *terminal = NULL; + int ctty = 0; /* 1 if asked to open controlling tty. */ + + if (!terminal_type) + maybe_fatal (must_succeed, 0, 0, + "Unknown terminal type", + "Unknown terminal type"); + + if (name == NULL) + name = DEV_TTY; + if (!strcmp (name, DEV_TTY)) + ctty = 1; + + /* If we already have a terminal on the given device, use that. If + all such terminals are suspended, create a new one instead. */ + /* XXX Perhaps this should be made explicit by having init_tty + always create a new terminal and separating terminal and frame + creation on Lisp level. */ + terminal = get_named_tty (name); + if (terminal) + return terminal; + + terminal = create_terminal (); + 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; + + terminal->type = output_termcap; + terminal->display_info.tty = tty; + tty->terminal = terminal; + + tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm)); + Wcm_clear (tty); + +#ifndef WINDOWSNT + set_tty_hooks (terminal); + + { + int fd; + FILE *file; + +#ifdef O_IGNORE_CTTY + if (!ctty) + /* Open the terminal device. Don't recognize it as our + controlling terminal, and don't make it the controlling tty + if we don't have one at the moment. */ + fd = emacs_open (name, O_RDWR | O_IGNORE_CTTY | O_NOCTTY, 0); + else +#else + /* Alas, O_IGNORE_CTTY is a GNU extension that seems to be only + defined on Hurd. On other systems, we need to explicitly + 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); +#endif /* O_IGNORE_CTTY */ + + if (fd < 0) + maybe_fatal (must_succeed, buffer, terminal, + "Could not open file: %s", + "Could not open file: %s", + name); + if (!isatty (fd)) + { + close (fd); + maybe_fatal (must_succeed, buffer, terminal, + "Not a tty device: %s", + "Not a tty device: %s", + name); + } + +#ifndef O_IGNORE_CTTY + if (!ctty) + dissociate_if_controlling_tty (fd); +#endif + + file = fdopen (fd, "w+"); + tty->name = xstrdup (name); + terminal->name = xstrdup (name); + tty->input = file; + tty->output = file; + } + + tty->type = xstrdup (terminal_type); + + add_keyboard_wait_descriptor (fileno (tty->input)); + +#endif encode_terminal_src_size = 0; encode_terminal_dst_size = 0; #ifdef HAVE_GPM - mouse_position_hook = term_mouse_position; - Qmouse_face_window = Qnil; + terminal->mouse_position_hook = term_mouse_position; + mouse_face_window = Qnil; #endif #ifdef WINDOWSNT - initialize_w32_display (); - - Wcm_clear (); - - area = (char *) xmalloc (2044); - - FrameRows = FRAME_LINES (sf); - FrameCols = FRAME_COLS (sf); - specified_window = FRAME_LINES (sf); - - delete_in_insert_mode = 1; - - UseTabs = 0; - 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. */ - - line_ins_del_ok = 0; - char_ins_del_ok = 1; + initialize_w32_display (terminal); + /* The following two are inaccessible from w32console.c. */ + terminal->delete_frame_hook = &delete_tty_output; + terminal->delete_terminal_hook = &delete_tty; + + tty->name = xstrdup (name); + terminal->name = xstrdup (name); + tty->type = xstrdup (terminal_type); + + tty->output = stdout; + tty->input = stdin; + add_keyboard_wait_descriptor (0); + + Wcm_clear (tty); + + { + struct frame *f = XFRAME (selected_frame); + + FrameRows (tty) = FRAME_LINES (f); + FrameCols (tty) = FRAME_COLS (f); + tty->specified_window = FRAME_LINES (f); + + FRAME_CAN_HAVE_SCROLL_BARS (f) = 0; + FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none; + } + tty->delete_in_insert_mode = 1; + + UseTabs (tty) = 0; + terminal->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. */ + terminal->line_ins_del_ok = 0; + terminal->char_ins_del_ok = 1; baud_rate = 19200; - FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0; - FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none; - TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */ - - return; + tty->TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */ + #else /* not WINDOWSNT */ - Wcm_clear (); + 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 - fatal ("Cannot open terminfo database file"); + maybe_fatal (must_succeed, buffer, terminal, + "Cannot open terminfo database file", + "Cannot open terminfo database file"); #else - fatal ("Cannot open termcap database file"); + maybe_fatal (must_succeed, buffer, terminal, + "Cannot open termcap database file", + "Cannot open termcap database file"); #endif } if (status == 0) { #ifdef TERMINFO - fatal ("Terminal type %s is not defined.\n\ + maybe_fatal (must_succeed, buffer, terminal, + "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 - fatal ("Terminal type %s is not defined.\n\ + maybe_fatal (must_succeed, buffer, terminal, + "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 } @@ -3242,219 +3483,237 @@ #endif area = (char *) xmalloc (buffer_size); - TS_ins_line = tgetstr ("al", address); - TS_ins_multi_lines = tgetstr ("AL", address); - TS_bell = tgetstr ("bl", address); - BackTab = tgetstr ("bt", address); - TS_clr_to_bottom = tgetstr ("cd", address); - TS_clr_line = tgetstr ("ce", address); - TS_clr_frame = tgetstr ("cl", address); - ColPosition = NULL; /* tgetstr ("ch", address); */ - AbsPosition = tgetstr ("cm", address); - CR = tgetstr ("cr", address); - TS_set_scroll_region = tgetstr ("cs", address); - TS_set_scroll_region_1 = tgetstr ("cS", address); - RowPosition = tgetstr ("cv", address); - TS_del_char = tgetstr ("dc", address); - TS_del_multi_chars = tgetstr ("DC", address); - TS_del_line = tgetstr ("dl", address); - TS_del_multi_lines = tgetstr ("DL", address); - TS_delete_mode = tgetstr ("dm", address); - TS_end_delete_mode = tgetstr ("ed", address); - TS_end_insert_mode = tgetstr ("ei", address); - Home = tgetstr ("ho", address); - TS_ins_char = tgetstr ("ic", address); - TS_ins_multi_chars = tgetstr ("IC", address); - TS_insert_mode = tgetstr ("im", address); - TS_pad_inserted_char = tgetstr ("ip", address); - TS_end_keypad_mode = tgetstr ("ke", address); - TS_keypad_mode = tgetstr ("ks", address); - LastLine = tgetstr ("ll", address); - Right = tgetstr ("nd", address); - Down = tgetstr ("do", address); - if (!Down) - Down = tgetstr ("nl", address); /* Obsolete name for "do" */ + tty->TS_ins_line = tgetstr ("al", address); + tty->TS_ins_multi_lines = tgetstr ("AL", address); + tty->TS_bell = tgetstr ("bl", address); + BackTab (tty) = tgetstr ("bt", address); + tty->TS_clr_to_bottom = tgetstr ("cd", address); + tty->TS_clr_line = tgetstr ("ce", address); + tty->TS_clr_frame = tgetstr ("cl", address); + ColPosition (tty) = NULL; /* tgetstr ("ch", address); */ + AbsPosition (tty) = tgetstr ("cm", address); + CR (tty) = tgetstr ("cr", address); + tty->TS_set_scroll_region = tgetstr ("cs", address); + tty->TS_set_scroll_region_1 = tgetstr ("cS", address); + RowPosition (tty) = tgetstr ("cv", address); + tty->TS_del_char = tgetstr ("dc", address); + tty->TS_del_multi_chars = tgetstr ("DC", address); + tty->TS_del_line = tgetstr ("dl", address); + tty->TS_del_multi_lines = tgetstr ("DL", address); + tty->TS_delete_mode = tgetstr ("dm", address); + tty->TS_end_delete_mode = tgetstr ("ed", address); + tty->TS_end_insert_mode = tgetstr ("ei", address); + Home (tty) = tgetstr ("ho", address); + tty->TS_ins_char = tgetstr ("ic", address); + tty->TS_ins_multi_chars = tgetstr ("IC", address); + tty->TS_insert_mode = tgetstr ("im", address); + tty->TS_pad_inserted_char = tgetstr ("ip", address); + tty->TS_end_keypad_mode = tgetstr ("ke", address); + tty->TS_keypad_mode = tgetstr ("ks", address); + LastLine (tty) = tgetstr ("ll", address); + Right (tty) = tgetstr ("nd", address); + Down (tty) = tgetstr ("do", address); + if (!Down (tty)) + Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do" */ #ifdef VMS /* VMS puts a carriage return before each linefeed, so it is not safe to use linefeeds. */ - if (Down && Down[0] == '\n' && Down[1] == '\0') - Down = 0; + if (Down (tty) && Down (tty)[0] == '\n' && Down (tty)[1] == '\0') + Down (tty) = 0; #endif /* VMS */ if (tgetflag ("bs")) - Left = "\b"; /* can't possibly be longer! */ + Left (tty) = "\b"; /* can't possibly be longer! */ else /* (Actually, "bs" is obsolete...) */ - Left = tgetstr ("le", address); - if (!Left) - Left = tgetstr ("bc", address); /* Obsolete name for "le" */ - TS_pad_char = tgetstr ("pc", address); - TS_repeat = tgetstr ("rp", address); - TS_end_standout_mode = tgetstr ("se", address); - TS_fwd_scroll = tgetstr ("sf", address); - TS_standout_mode = tgetstr ("so", address); - TS_rev_scroll = tgetstr ("sr", address); - Wcm.cm_tab = tgetstr ("ta", address); - TS_end_termcap_modes = tgetstr ("te", address); - TS_termcap_modes = tgetstr ("ti", address); - Up = tgetstr ("up", address); - TS_visible_bell = tgetstr ("vb", address); - TS_cursor_normal = tgetstr ("ve", address); - TS_cursor_visible = tgetstr ("vs", address); - TS_cursor_invisible = tgetstr ("vi", address); - TS_set_window = tgetstr ("wi", address); - - TS_enter_underline_mode = tgetstr ("us", address); - TS_exit_underline_mode = tgetstr ("ue", address); - TS_enter_bold_mode = tgetstr ("md", address); - TS_enter_dim_mode = tgetstr ("mh", address); - TS_enter_blink_mode = tgetstr ("mb", address); - TS_enter_reverse_mode = tgetstr ("mr", address); - TS_enter_alt_charset_mode = tgetstr ("as", address); - TS_exit_alt_charset_mode = tgetstr ("ae", address); - TS_exit_attribute_mode = tgetstr ("me", address); - - MultiUp = tgetstr ("UP", address); - MultiDown = tgetstr ("DO", address); - MultiLeft = tgetstr ("LE", address); - MultiRight = tgetstr ("RI", address); + Left (tty) = tgetstr ("le", address); + if (!Left (tty)) + Left (tty) = tgetstr ("bc", address); /* Obsolete name for "le" */ + tty->TS_pad_char = tgetstr ("pc", address); + tty->TS_repeat = tgetstr ("rp", address); + tty->TS_end_standout_mode = tgetstr ("se", address); + tty->TS_fwd_scroll = tgetstr ("sf", address); + tty->TS_standout_mode = tgetstr ("so", address); + tty->TS_rev_scroll = tgetstr ("sr", address); + tty->Wcm->cm_tab = tgetstr ("ta", address); + tty->TS_end_termcap_modes = tgetstr ("te", address); + tty->TS_termcap_modes = tgetstr ("ti", address); + Up (tty) = tgetstr ("up", address); + tty->TS_visible_bell = tgetstr ("vb", address); + tty->TS_cursor_normal = tgetstr ("ve", address); + tty->TS_cursor_visible = tgetstr ("vs", address); + tty->TS_cursor_invisible = tgetstr ("vi", address); + tty->TS_set_window = tgetstr ("wi", address); + + tty->TS_enter_underline_mode = tgetstr ("us", address); + tty->TS_exit_underline_mode = tgetstr ("ue", address); + tty->TS_enter_bold_mode = tgetstr ("md", address); + tty->TS_enter_dim_mode = tgetstr ("mh", address); + tty->TS_enter_blink_mode = tgetstr ("mb", address); + tty->TS_enter_reverse_mode = tgetstr ("mr", address); + tty->TS_enter_alt_charset_mode = tgetstr ("as", address); + tty->TS_exit_alt_charset_mode = tgetstr ("ae", address); + tty->TS_exit_attribute_mode = tgetstr ("me", address); + + MultiUp (tty) = tgetstr ("UP", address); + MultiDown (tty) = tgetstr ("DO", address); + MultiLeft (tty) = tgetstr ("LE", address); + MultiRight (tty) = tgetstr ("RI", address); /* SVr4/ANSI color suppert. If "op" isn't available, don't support color because we can't switch back to the default foreground and background. */ - TS_orig_pair = tgetstr ("op", address); - if (TS_orig_pair) + tty->TS_orig_pair = tgetstr ("op", address); + if (tty->TS_orig_pair) { - TS_set_foreground = tgetstr ("AF", address); - TS_set_background = tgetstr ("AB", address); - if (!TS_set_foreground) + tty->TS_set_foreground = tgetstr ("AF", address); + tty->TS_set_background = tgetstr ("AB", address); + if (!tty->TS_set_foreground) { /* SVr4. */ - TS_set_foreground = tgetstr ("Sf", address); - TS_set_background = tgetstr ("Sb", address); + tty->TS_set_foreground = tgetstr ("Sf", address); + tty->TS_set_background = tgetstr ("Sb", address); } - TN_max_colors = tgetnum ("Co"); - TN_max_pairs = tgetnum ("pa"); - - TN_no_color_video = tgetnum ("NC"); - if (TN_no_color_video == -1) - TN_no_color_video = 0; + tty->TN_max_colors = tgetnum ("Co"); + tty->TN_max_pairs = tgetnum ("pa"); + + tty->TN_no_color_video = tgetnum ("NC"); + if (tty->TN_no_color_video == -1) + tty->TN_no_color_video = 0; } - tty_default_color_capabilities (1); - - MagicWrap = tgetflag ("xn"); + tty_default_color_capabilities (tty, 1); + + MagicWrap (tty) = tgetflag ("xn"); /* Since we make MagicWrap terminals look like AutoWrap, we need to have the former flag imply the latter. */ - AutoWrap = MagicWrap || tgetflag ("am"); - memory_below_frame = tgetflag ("db"); - TF_hazeltine = tgetflag ("hz"); - must_write_spaces = tgetflag ("in"); - meta_key = tgetflag ("km") || tgetflag ("MT"); - TF_insmode_motion = tgetflag ("mi"); - TF_standout_motion = tgetflag ("ms"); - TF_underscore = tgetflag ("ul"); - TF_teleray = tgetflag ("xt"); - - term_get_fkeys (address); - + AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am"); + terminal->memory_below_frame = tgetflag ("db"); + tty->TF_hazeltine = tgetflag ("hz"); + terminal->must_write_spaces = tgetflag ("in"); + tty->meta_key = tgetflag ("km") || tgetflag ("MT"); + tty->TF_insmode_motion = tgetflag ("mi"); + tty->TF_standout_motion = tgetflag ("ms"); + tty->TF_underscore = tgetflag ("ul"); + tty->TF_teleray = tgetflag ("xt"); + +#endif /* !WINDOWSNT */ +#ifdef MULTI_KBOARD + terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD)); + init_kboard (terminal->kboard); + terminal->kboard->next_kboard = all_kboards; + all_kboards = terminal->kboard; + terminal->kboard->reference_count++; + /* Don't let the initial kboard remain current longer than necessary. + That would cause problems if a file loaded on startup tries to + prompt in the mini-buffer. */ + if (current_kboard == initial_kboard) + current_kboard = terminal->kboard; +#ifndef WINDOWSNT + term_get_fkeys (address, terminal->kboard); +#endif +#endif + +#ifndef WINDOWSNT /* Get frame size from system, or else from termcap. */ { int height, width; - get_frame_size (&width, &height); - FRAME_COLS (sf) = width; - FRAME_LINES (sf) = height; + get_tty_size (fileno (tty->input), &width, &height); + FrameCols (tty) = width; + FrameRows (tty) = height; } - if (FRAME_COLS (sf) <= 0) - SET_FRAME_COLS (sf, tgetnum ("co")); - else - /* Keep width and external_width consistent */ - SET_FRAME_COLS (sf, FRAME_COLS (sf)); - if (FRAME_LINES (sf) <= 0) - FRAME_LINES (sf) = tgetnum ("li"); - - if (FRAME_LINES (sf) < 3 || FRAME_COLS (sf) < 3) - fatal ("Screen size %dx%d is too small", - FRAME_LINES (sf), FRAME_COLS (sf)); - - min_padding_speed = tgetnum ("pb"); - TabWidth = tgetnum ("tw"); + if (FrameCols (tty) <= 0) + FrameCols (tty) = tgetnum ("co"); + if (FrameRows (tty) <= 0) + FrameRows (tty) = tgetnum ("li"); + + if (FrameRows (tty) < 3 || FrameCols (tty) < 3) + maybe_fatal (must_succeed, NULL, terminal, + "Screen size %dx%d is too small" + "Screen size %dx%d is too small", + FrameCols (tty), FrameRows (tty)); + +#if 0 /* This is not used anywhere. */ + tty->terminal->min_padding_speed = tgetnum ("pb"); +#endif + + TabWidth (tty) = tgetnum ("tw"); #ifdef VMS /* These capabilities commonly use ^J. I don't know why, but sending them on VMS does not work; it causes following spaces to be lost, sometimes. For now, the simplest fix is to avoid using these capabilities ever. */ - if (Down && Down[0] == '\n') - Down = 0; + if (Down (tty) && Down (tty)[0] == '\n') + Down (tty) = 0; #endif /* VMS */ - if (!TS_bell) - TS_bell = "\07"; - - if (!TS_fwd_scroll) - TS_fwd_scroll = Down; - - PC = TS_pad_char ? *TS_pad_char : 0; - - if (TabWidth < 0) - TabWidth = 8; + if (!tty->TS_bell) + tty->TS_bell = "\07"; + + if (!tty->TS_fwd_scroll) + tty->TS_fwd_scroll = Down (tty); + + PC = tty->TS_pad_char ? *tty->TS_pad_char : 0; + + if (TabWidth (tty) < 0) + TabWidth (tty) = 8; /* Turned off since /etc/termcap seems to have :ta= for most terminals and newer termcap doc does not seem to say there is a default. - if (!Wcm.cm_tab) - Wcm.cm_tab = "\t"; + if (!tty->Wcm->cm_tab) + tty->Wcm->cm_tab = "\t"; */ /* We don't support standout modes that use `magic cookies', so turn off any that do. */ - if (TS_standout_mode && tgetnum ("sg") >= 0) + if (tty->TS_standout_mode && tgetnum ("sg") >= 0) { - TS_standout_mode = 0; - TS_end_standout_mode = 0; + tty->TS_standout_mode = 0; + tty->TS_end_standout_mode = 0; } - if (TS_enter_underline_mode && tgetnum ("ug") >= 0) + if (tty->TS_enter_underline_mode && tgetnum ("ug") >= 0) { - TS_enter_underline_mode = 0; - TS_exit_underline_mode = 0; + tty->TS_enter_underline_mode = 0; + tty->TS_exit_underline_mode = 0; } /* If there's no standout mode, try to use underlining instead. */ - if (TS_standout_mode == 0) + if (tty->TS_standout_mode == 0) { - TS_standout_mode = TS_enter_underline_mode; - TS_end_standout_mode = TS_exit_underline_mode; + tty->TS_standout_mode = tty->TS_enter_underline_mode; + tty->TS_end_standout_mode = tty->TS_exit_underline_mode; } /* If no `se' string, try using a `me' string instead. If that fails, we can't use standout mode at all. */ - if (TS_end_standout_mode == 0) + if (tty->TS_end_standout_mode == 0) { char *s = tgetstr ("me", address); if (s != 0) - TS_end_standout_mode = s; + tty->TS_end_standout_mode = s; else - TS_standout_mode = 0; + tty->TS_standout_mode = 0; } - if (TF_teleray) + if (tty->TF_teleray) { - Wcm.cm_tab = 0; + tty->Wcm->cm_tab = 0; /* We can't support standout mode, because it uses magic cookies. */ - TS_standout_mode = 0; + tty->TS_standout_mode = 0; /* But that means we cannot rely on ^M to go to column zero! */ - CR = 0; + CR (tty) = 0; /* LF can't be trusted either -- can alter hpos */ /* if move at column 0 thru a line with TS_standout_mode */ - Down = 0; + Down (tty) = 0; } /* Special handling for certain terminal types known to need it */ if (!strcmp (terminal_type, "supdup")) { - memory_below_frame = 1; - Wcm.cm_losewrap = 1; + terminal->memory_below_frame = 1; + tty->Wcm->cm_losewrap = 1; } if (!strncmp (terminal_type, "c10", 3) || !strcmp (terminal_type, "perq")) @@ -3471,102 +3730,140 @@ It would be simpler if the :wi string could go in the termcap entry, but it can't because it is not fully valid. If it were in the termcap entry, it would confuse other programs. */ - if (!TS_set_window) + if (!tty->TS_set_window) { - p = TS_termcap_modes; + p = tty->TS_termcap_modes; while (*p && strcmp (p, "\033v ")) p++; if (*p) - TS_set_window = "\033v%C %C %C %C "; + tty->TS_set_window = "\033v%C %C %C %C "; } /* Termcap entry often fails to have :in: flag */ - must_write_spaces = 1; + terminal->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, TS_termcap_modes); + strcpy (area, tty->TS_termcap_modes); strcat (area, "\033\007!"); - TS_termcap_modes = area; + tty->TS_termcap_modes = area; area += strlen (area) + 1; - p = AbsPosition; + p = AbsPosition (tty); /* Change all %+ parameters to %C, to handle - values above 96 correctly for the C100. */ + values above 96 correctly for the C100. */ while (*p) - { - if (p[0] == '%' && p[1] == '+') - p[1] = 'C'; - p++; - } + { + if (p[0] == '%' && p[1] == '+') + p[1] = 'C'; + p++; + } } - FrameRows = FRAME_LINES (sf); - FrameCols = FRAME_COLS (sf); - specified_window = FRAME_LINES (sf); - - if (Wcm_init () == -1) /* can't do cursor motion */ + tty->specified_window = FrameRows (tty); + + if (Wcm_init (tty) == -1) /* can't do cursor motion */ + { + maybe_fatal (must_succeed, NULL, terminal, + "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 */ - if (FRAME_LINES (sf) <= 0 - || FRAME_COLS (sf) <= 0) - fatal ("The frame size has not been specified"); - - delete_in_insert_mode - = TS_delete_mode && TS_insert_mode - && !strcmp (TS_delete_mode, TS_insert_mode); - - se_is_so = (TS_standout_mode - && TS_end_standout_mode - && !strcmp (TS_standout_mode, TS_end_standout_mode)); - - UseTabs = tabs_safe_p () && TabWidth == 8; - - scroll_region_ok - = (Wcm.cm_abs - && (TS_set_window || TS_set_scroll_region || TS_set_scroll_region_1)); - - line_ins_del_ok = (((TS_ins_line || TS_ins_multi_lines) - && (TS_del_line || TS_del_multi_lines)) - || (scroll_region_ok && TS_fwd_scroll && TS_rev_scroll)); - - char_ins_del_ok = ((TS_ins_char || TS_insert_mode - || TS_pad_inserted_char || TS_ins_multi_chars) - && (TS_del_char || TS_del_multi_chars)); - - fast_clear_end_of_line = TS_clr_line != 0; - - init_baud_rate (); - if (read_socket_hook) /* Baudrate is somewhat */ - /* meaningless in this case */ - baud_rate = 9600; - - FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0; - FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none; -#endif /* WINDOWSNT */ - - xfree (buffer); + terminal_type); + } + + if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0) + maybe_fatal (must_succeed, NULL, terminal, + "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 + && !strcmp (tty->TS_delete_mode, tty->TS_insert_mode); + + tty->se_is_so = (tty->TS_standout_mode + && tty->TS_end_standout_mode + && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode)); + + UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8; + + terminal->scroll_region_ok + = (tty->Wcm->cm_abs + && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1)); + + terminal->line_ins_del_ok + = (((tty->TS_ins_line || tty->TS_ins_multi_lines) + && (tty->TS_del_line || tty->TS_del_multi_lines)) + || (terminal->scroll_region_ok + && tty->TS_fwd_scroll && tty->TS_rev_scroll)); + + terminal->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)); + + terminal->fast_clear_end_of_line = tty->TS_clr_line != 0; + + init_baud_rate (fileno (tty->input)); + +#ifdef AIXHFT + /* The HFT system on AIX doesn't optimize for scrolling, so it's + really ugly at times. */ + terminal->line_ins_del_ok = 0; + terminal->char_ins_del_ok = 0; +#endif + + /* Don't do this. I think termcap may still need the buffer. */ + /* xfree (buffer); */ + +#endif /* not WINDOWSNT */ + + /* Init system terminal modes (RAW or CBREAK, etc.). */ + init_sys_modes (tty); + + return terminal; +} + +/* Auxiliary error-handling function for init_tty. + Free BUFFER and delete TERMINAL, then call error or fatal + with str1 or str2, respectively, according to MUST_SUCCEED. */ + +static void +maybe_fatal (must_succeed, buffer, terminal, str1, str2, arg1, arg2) + int must_succeed; + char *buffer; + struct terminal *terminal; + char *str1, *str2, *arg1, *arg2; +{ + if (buffer) + xfree (buffer); + + if (terminal) + delete_tty (terminal); + + if (must_succeed) + fatal (str2, arg1, arg2); + else + error (str1, arg1, arg2); + + abort (); } /* VARARGS 1 */ @@ -3581,16 +3878,105 @@ exit (1); } -DEFUN ("tty-no-underline", Ftty_no_underline, Stty_no_underline, 0, 0, 0, - doc: /* Declare that this terminal does not handle underlining. -This is used to override the terminfo data, for certain terminals that -do not really do underlining, but say that they do. */) - () + + +/* Delete the given tty terminal, closing all frames on it. */ + +static void +delete_tty (struct terminal *terminal) { - TS_enter_underline_mode = 0; - return Qnil; + struct tty_display_info *tty; + Lisp_Object tail, frame; + int last_terminal; + + /* Protect against recursive calls. Fdelete_frame in + delete_terminal calls us back when it deletes our last frame. */ + if (!terminal->name) + return; + + if (terminal->type != output_termcap) + abort (); + + tty = terminal->display_info.tty; + + last_terminal = 1; + FOR_EACH_FRAME (tail, frame) + { + struct frame *f = XFRAME (frame); + if (FRAME_LIVE_P (f) && (!FRAME_TERMCAP_P (f) || FRAME_TTY (f) != tty)) + { + last_terminal = 0; + break; + } + } + if (last_terminal) + error ("Attempt to delete the sole terminal device with live frames"); + + if (tty == tty_list) + tty_list = tty->next; + else + { + struct tty_display_info *p; + for (p = tty_list; p && p->next != tty; p = p->next) + ; + + if (! p) + /* This should not happen. */ + abort (); + + p->next = tty->next; + tty->next = 0; + } + + /* reset_sys_modes needs a valid device, so this call needs to be + before delete_terminal. */ + reset_sys_modes (tty); + + delete_terminal (terminal); + + if (tty->name) + xfree (tty->name); + + if (tty->type) + xfree (tty->type); + + if (tty->input) + { + delete_keyboard_wait_descriptor (fileno (tty->input)); + if (tty->input != stdin) + fclose (tty->input); + } + if (tty->output && tty->output != stdout && tty->output != tty->input) + fclose (tty->output); + if (tty->termscript) + fclose (tty->termscript); + + if (tty->old_tty) + xfree (tty->old_tty); + + if (tty->Wcm) + xfree (tty->Wcm); + + bzero (tty, sizeof (struct tty_display_info)); + xfree (tty); } + + +/* Mark the pointers in the tty_display_info objects. + Called by the Fgarbage_collector. */ + +void +mark_ttys (void) +{ + struct tty_display_info *tty; + + for (tty = tty_list; tty; tty = tty->next) + mark_object (tty->top_frame); +} + + + void syms_of_term () { @@ -3603,10 +3989,18 @@ system_uses_terminfo = 0; #endif - DEFVAR_LISP ("ring-bell-function", &Vring_bell_function, - doc: /* Non-nil means call this function to ring the bell. -The function should accept no arguments. */); - Vring_bell_function = 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 terminal id to be suspended. +See `suspend-tty'. */); + Vsuspend_tty_functions = Qnil; + + + 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 terminal id that was revived. +See `resume-tty'. */); + Vresume_tty_functions = Qnil; DEFVAR_BOOL ("visible-cursor", &visible_cursor, doc: /* Non-nil means to make the cursor very visible. @@ -3618,15 +4012,19 @@ defsubr (&Stty_display_color_p); defsubr (&Stty_display_color_cells); defsubr (&Stty_no_underline); + defsubr (&Stty_type); + defsubr (&Scontrolling_tty_p); + defsubr (&Ssuspend_tty); + defsubr (&Sresume_tty); #ifdef HAVE_GPM - defsubr (&Sterm_open_connection); - defsubr (&Sterm_close_connection); - - staticpro (&Qmouse_face_window); + defsubr (&Sgpm_mouse_start); + defsubr (&Sgpm_mouse_stop); + + staticpro (&mouse_face_window); #endif /* HAVE_GPM */ - - fullscreen_hook = NULL; } + + /* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193 (do not change this comment) */