X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/acfcd5cdf125bca6bc4a1ee716ba28e6d9414913..2a36494c42a1963846ea8c2dde48a7450d433c2a:/src/term.c?ds=sidebyside diff --git a/src/term.c b/src/term.c index 91cd9ed319..c6782efa60 100644 --- a/src/term.c +++ b/src/term.c @@ -1,6 +1,6 @@ -/* terminal control module for terminals described by TERMCAP - Copyright (C) 1985, 86, 87, 93, 94, 95, 98 - Free Software Foundation, Inc. +/* Terminal control module for terminals described by TERMCAP + Copyright (C) 1985, 86, 87, 93, 94, 95, 98, 2000, 2001, 2002 + Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -19,362 +19,134 @@ along with GNU Emacs; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* New redisplay, TTY faces by Gerd Moellmann . */ - +/* New redisplay, TTY faces by Gerd Moellmann . */ #include #include #include #include + +#include + +#include "lisp.h" #include "termchar.h" #include "termopts.h" -#include "lisp.h" #include "charset.h" #include "coding.h" +#include "keyboard.h" #include "frame.h" #include "disptab.h" #include "termhooks.h" -#include "keyboard.h" #include "dispextern.h" #include "window.h" +#include "keymap.h" + +/* For now, don't try to include termcap.h. On some systems, + configure finds a non-standard termcap.h that the main build + won't find. */ -#ifdef HAVE_TERMCAP_H +#if defined HAVE_TERMCAP_H && 0 #include +#else +extern void tputs P_ ((const char *, int, int (*)(int))); +extern int tgetent P_ ((char *, const char *)); +extern int tgetflag P_ ((char *id)); +extern int tgetnum P_ ((char *id)); #endif #include "cm.h" #ifdef HAVE_X_WINDOWS #include "xterm.h" #endif +#ifdef MAC_OS +#include "macterm.h" +#endif + +#ifndef O_RDWR +#define O_RDWR 2 +#endif 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 max(a, b) ((a) > (b) ? (a) : (b)) -#define min(a, b) ((a) < (b) ? (a) : (b)) - -#define OUTPUT(a) \ - tputs (a, (int) (FRAME_HEIGHT (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_HEIGHT (XFRAME (selected_frame)) \ - - curY), cmputc); \ - } while (0) - -#define OUTPUT1_IF(a) do { if (a) tputs (a, 1, cmputc); } while (0) +static void tty_show_cursor P_ ((struct tty_display_info *)); +static void tty_hide_cursor P_ ((struct tty_display_info *)); + +void delete_initial_display P_ ((struct display *)); +void delete_tty P_ ((struct display *)); +void create_tty_output P_ ((struct frame *)); +void delete_tty_output P_ ((struct frame *)); + +#define OUTPUT(tty, a) \ + emacs_tputs ((tty), a, \ + (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) /* Function to use to ring the bell. */ Lisp_Object Vring_bell_function; -/* Terminal characteristics that higher levels want to look at. - These are all extern'd in termchar.h */ +/* Functions to call after a tty was deleted. */ +Lisp_Object Vdelete_tty_after_functions; -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 */ +/* Chain of all displays currently in use. */ +struct display *display_list; -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 */ +/* The initial display device, created by initial_term_init. */ +struct display *initial_display; -/* 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. */ +/* 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 (*change_line_highlight_hook) P_ ((int, int, int, int)); -void (*reassert_line_highlight_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, struct input_event *, int, int)); - -void (*frame_up_to_date_hook) P_ ((struct frame *)); - -/* Return the current position of the mouse. - - Set *f to the frame the mouse is in, or zero if the mouse is in no - Emacs frame. If it is set to zero, all the other arguments are - garbage. - - If the motion started in a scroll bar, set *bar_window to the - scroll bar's window, *part to the part the mouse is currently over, - *x to the position of the mouse along the scroll bar, and *y to the - overall length of the scroll bar. - - Otherwise, set *bar_window to Qnil, and *x and *y to the column and - row of the character cell the mouse is over. - - Set *time to the time the mouse was at the returned position. - - This should clear mouse_moved until the next motion - event arrives. */ -void (*mouse_position_hook) P_ ((FRAME_PTR *f, int insist, - Lisp_Object *bar_window, - enum scroll_bar_part *part, - Lisp_Object *x, - Lisp_Object *y, - unsigned long *time)); - -/* When reading from a minibuffer in a different frame, Emacs wants - to shift the highlight from the selected frame to the mini-buffer's - frame; under X, this means it lies about where the focus is. - This hook tells the window system code to re-decide where to put - the highlight. */ -void (*frame_rehighlight_hook) P_ ((FRAME_PTR f)); - -/* If we're displaying frames using a window system that can stack - frames on top of each other, this hook allows you to bring a frame - to the front, or bury it behind all the other windows. If this - hook is zero, that means the device we're displaying on doesn't - support overlapping frames, so there's no need to raise or lower - anything. - - If RAISE is non-zero, F is brought to the front, before all other - windows. If RAISE is zero, F is sent to the back, behind all other - windows. */ -void (*frame_raise_lower_hook) P_ ((FRAME_PTR f, int raise)); - -/* Set the vertical scroll bar for WINDOW to have its upper left corner - at (TOP, LEFT), and be LENGTH rows high. Set its handle to - indicate that we are displaying PORTION characters out of a total - of WHOLE characters, starting at POSITION. If WINDOW doesn't yet - have a scroll bar, create one for it. */ - -void (*set_vertical_scroll_bar_hook) - P_ ((struct window *window, - int portion, int whole, int position)); - - -/* The following three hooks are used when we're doing a thorough - redisplay of the frame. We don't explicitly know which scroll bars - are going to be deleted, because keeping track of when windows go - away is a real pain - can you say set-window-configuration? - Instead, we just assert at the beginning of redisplay that *all* - scroll bars are to be removed, and then save scroll bars from the - fiery pit when we actually redisplay their window. */ - -/* Arrange for all scroll bars on FRAME to be removed at the next call - to `*judge_scroll_bars_hook'. A scroll bar may be spared if - `*redeem_scroll_bar_hook' is applied to its window before the judgment. - - This should be applied to each frame each time its window tree is - redisplayed, even if it is not displaying scroll bars at the moment; - if the HAS_SCROLL_BARS flag has just been turned off, only calling - this and the judge_scroll_bars_hook will get rid of them. - - If non-zero, this hook should be safe to apply to any frame, - whether or not it can support scroll bars, and whether or not it is - currently displaying them. */ -void (*condemn_scroll_bars_hook) P_ ((FRAME_PTR frame)); - -/* Unmark WINDOW's scroll bar for deletion in this judgement cycle. - Note that it's okay to redeem a scroll bar that is not condemned. */ -void (*redeem_scroll_bar_hook) P_ ((struct window *window)); - -/* Remove all scroll bars on FRAME that haven't been saved since the - last call to `*condemn_scroll_bars_hook'. - - This should be applied to each frame after each time its window - tree is redisplayed, even if it is not displaying scroll bars at the - moment; if the HAS_SCROLL_BARS flag has just been turned off, only - calling this and condemn_scroll_bars_hook will get rid of them. - - If non-zero, this hook should be safe to apply to any frame, - whether or not it can support scroll bars, and whether or not it is - currently displaying them. */ -void (*judge_scroll_bars_hook) P_ ((FRAME_PTR FRAME)); - -/* Hook to call in estimate_mode_line_height, if any. */ - -int (* estimate_mode_line_height_hook) P_ ((struct frame *f, enum face_id)); - - -/* 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) */ - -/* "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. */ +Lisp_Object Qframe_tty_name, Qframe_tty_type; -char *TS_enter_reverse_mode; -/* "us"/"ue" -- start/end underlining. */ -char *TS_exit_underline_mode, *TS_enter_underline_mode; +/* Meaning of bits in no_color_video. Each bit set means that the + corresponding attribute cannot be combined with colors. */ -/* "ug" -- number of blanks left by underline. */ - -int TN_magic_cookie_glitch_ul; - -/* "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. */ - -int TF_xs; /* Nonzero for "xs". If set together with - TN_standout_width == 0, it means don't bother - to write any end-standout cookies. */ - -int TN_standout_width; /* termcap sg number: width occupied by standout - markers */ - -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 */ +enum no_color_bit +{ + NC_STANDOUT = 1 << 0, + NC_UNDERLINE = 1 << 1, + NC_REVERSE = 1 << 2, + NC_BLINK = 1 << 3, + NC_DIM = 1 << 4, + NC_BOLD = 1 << 5, + NC_INVIS = 1 << 6, + NC_PROTECT = 1 << 7, + NC_ALT_CHARSET = 1 << 8 +}; /* internal state */ /* The largest frame width in any call to calculate_costs. */ -int max_frame_width; +int max_frame_cols; /* The largest frame height in any call to calculate_costs. */ -int max_frame_height; - -/* Number of chars of space used for standout marker at beginning of line, - or'd with 0100. Zero if no standout marker at all. - The length of these vectors is max_frame_height. - - Used IFF TN_standout_width >= 0. */ - -static char *chars_wasted; -static char *copybuf; - -/* nonzero means supposed to write text in standout mode. */ - -int standout_requested; - -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_height - specified_window_size - lines from those operations. */ - -int specified_window; +int max_frame_lines; /* Frame currently being redisplayed; 0 if not currently redisplaying. (Direct output does not count). */ @@ -391,7 +163,6 @@ extern char *tgetstr (); #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 @@ -405,7 +176,9 @@ extern char *tgetstr (); void ring_bell () { - if (! NILP (Vring_bell_function)) + struct frame *f = XFRAME (selected_frame); + + if (!NILP (Vring_bell_function)) { Lisp_Object function; @@ -416,105 +189,107 @@ ring_bell () 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; - return; - } - - if (! FRAME_TERMCAP_P (XFRAME (selected_frame))) - { - (*ring_bell_hook) (); - return; } - OUTPUT (TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell); + else if (FRAME_DISPLAY (f)->ring_bell_hook) + (*FRAME_DISPLAY (f)->ring_bell_hook) (); } void -set_terminal_modes () +tty_ring_bell () { - if (! FRAME_TERMCAP_P (XFRAME (selected_frame))) - { - (*set_terminal_modes_hook) (); - return; - } - OUTPUT_IF (TS_termcap_modes); - OUTPUT_IF (TS_cursor_visible); - OUTPUT_IF (TS_keypad_mode); - losecursor (); + struct frame *f = XFRAME (selected_frame); + struct tty_display_info *tty = FRAME_TTY (f); + + OUTPUT (tty, (tty->TS_visible_bell && visible_bell + ? tty->TS_visible_bell + : tty->TS_bell)); } -void -reset_terminal_modes () +void tty_set_terminal_modes (struct display *display) { - if (! FRAME_TERMCAP_P (XFRAME (selected_frame))) - { - if (reset_terminal_modes_hook) - (*reset_terminal_modes_hook) (); - return; - } - if (TN_standout_width < 0) - 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); + struct tty_display_info *tty = display->display_info.tty; + + OUTPUT_IF (tty, tty->TS_termcap_modes); + OUTPUT_IF (tty, tty->TS_cursor_visible); + OUTPUT_IF (tty, tty->TS_keypad_mode); + losecursor (tty); +} + +void tty_reset_terminal_modes (struct display *display) +{ + struct tty_display_info *tty = display->display_info.tty; + + turn_off_highlight (tty); + turn_off_insert (tty); + OUTPUT_IF (tty, tty->TS_end_keypad_mode); + OUTPUT_IF (tty, tty->TS_cursor_normal); + OUTPUT_IF (tty, tty->TS_end_termcap_modes); + OUTPUT_IF (tty, tty->TS_orig_pair); /* Output raw CR so kernel can track the cursor hpos. */ - /* But on magic-cookie terminals this can erase an end-standout marker and - cause the rest of the frame to be in standout, so move down first. */ - if (TN_standout_width >= 0) - cmputc ('\n'); + current_tty = tty; cmputc ('\r'); } void update_begin (f) - FRAME_PTR f; + struct frame *f; { updating_frame = f; - if (! FRAME_TERMCAP_P (updating_frame)) - (*update_begin_hook) (f); - else - tty_hide_cursor (); + if (FRAME_DISPLAY (f)->update_begin_hook) + (*FRAME_DISPLAY (f)->update_begin_hook) (f); } void update_end (f) - FRAME_PTR f; + struct frame *f; { - if (! FRAME_TERMCAP_P (updating_frame)) - { - (*update_end_hook) (f); - updating_frame = 0; - return; - } + if (FRAME_DISPLAY (f)->update_end_hook) + (*FRAME_DISPLAY (f)->update_end_hook) (f); + updating_frame = NULL; +} + +void +tty_update_end (struct frame *f) +{ + struct tty_display_info *tty = FRAME_TTY (f); if (!XWINDOW (selected_window)->cursor_off_p) - tty_show_cursor (); - - turn_off_insert (); - background_highlight (); - standout_requested = 0; - updating_frame = 0; + tty_show_cursor (tty); + turn_off_insert (tty); + background_highlight (tty); } void set_terminal_window (size) int size; { - if (! FRAME_TERMCAP_P (updating_frame)) - { - (*set_terminal_window_hook) (size); - return; - } - specified_window = size ? size : FRAME_HEIGHT (XFRAME (selected_frame)); - if (!scroll_region_ok) - return; - set_scroll_region (0, specified_window); + struct frame *f = (updating_frame + ? updating_frame + : XFRAME (selected_frame)); + + if (FRAME_DISPLAY (f)->set_terminal_window_hook) + (*FRAME_DISPLAY (f)->set_terminal_window_hook) (size); +} + +void +tty_set_terminal_window (int size) +{ + struct frame *f = (updating_frame + ? updating_frame + : XFRAME (selected_frame)); + + struct tty_display_info *tty = FRAME_TTY (f); + + tty->specified_window = size ? size : FRAME_LINES (f); + if (FRAME_SCROLL_REGION_OK (f)) + set_scroll_region (0, tty->specified_window); } void @@ -522,90 +297,96 @@ set_scroll_region (start, stop) int start, 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_HEIGHT (sf), start, - FRAME_HEIGHT (sf) - stop, - FRAME_HEIGHT (sf)); - } + struct frame *f = (updating_frame + ? updating_frame + : XFRAME (selected_frame)); + + 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_WIDTH (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); } + -void -turn_on_insert () +static void +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 () +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 when TN_standout_width (termcap sg) is not specified. - In these terminals, output is affected by the value of standout - mode when the output is written. - - These functions are called on all terminals, but do nothing - on terminals whose standout mode does not work that way. */ +/* Handle highlighting. */ void -turn_off_highlight () +turn_off_highlight (struct tty_display_info *tty) { - if (TN_standout_width < 0) - { - 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; } -void -turn_on_highlight () +static void +turn_on_highlight (struct tty_display_info *tty) { - if (TN_standout_width < 0) - { - 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 (struct tty_display_info *tty) +{ + if (tty->standout_mode) + turn_off_highlight (tty); + else + turn_on_highlight (tty); } /* Make cursor invisible. */ static void -tty_hide_cursor () +tty_hide_cursor (struct tty_display_info *tty) { - OUTPUT_IF (TS_cursor_invisible); + if (tty->cursor_hidden == 0) + { + tty->cursor_hidden = 1; + OUTPUT_IF (tty, tty->TS_cursor_invisible); + } } /* Ensure that cursor is visible. */ static void -tty_show_cursor () +tty_show_cursor (struct tty_display_info *tty) { - OUTPUT_IF (TS_cursor_normal); - OUTPUT_IF (TS_cursor_visible); + if (tty->cursor_hidden) + { + tty->cursor_hidden = 0; + OUTPUT_IF (tty, tty->TS_cursor_normal); + OUTPUT_IF (tty, tty->TS_cursor_visible); + } } @@ -614,144 +395,63 @@ tty_show_cursor () depends on the user option inverse-video. */ void -background_highlight () +background_highlight (struct tty_display_info *tty) { - if (TN_standout_width >= 0) - return; if (inverse_video) - turn_on_highlight (); + turn_on_highlight (tty); else - turn_off_highlight (); + turn_off_highlight (tty); } /* Set standout mode to the mode specified for the text to be output. */ static void -highlight_if_desired () +highlight_if_desired (struct tty_display_info *tty) { - if (TN_standout_width >= 0) - return; - if (!inverse_video == !standout_requested) - turn_off_highlight (); + if (inverse_video) + turn_on_highlight (tty); else - turn_on_highlight (); -} - -/* Handle standout mode for terminals in which TN_standout_width >= 0. - On these terminals, standout is controlled by markers that - live inside the terminal's memory. TN_standout_width is the width - that the marker occupies in memory. Standout runs from the marker - to the end of the line on some terminals, or to the next - turn-off-standout marker (TS_end_standout_mode) string - on other terminals. */ - -/* Write a standout marker or end-standout marker at the front of the line - at vertical position vpos. */ - -void -write_standout_marker (flag, vpos) - int flag, vpos; -{ - if (flag || (TS_end_standout_mode && !TF_teleray && !se_is_so - && !(TF_xs && TN_standout_width == 0))) - { - cmgoto (vpos, 0); - cmplus (TN_standout_width); - OUTPUT (flag ? TS_standout_mode : TS_end_standout_mode); - chars_wasted[curY] = TN_standout_width | 0100; - } + turn_off_highlight (tty); } -/* External interface to control of standout mode. - Call this when about to modify line at position VPOS - and not change whether it is highlighted. */ - -void -reassert_line_highlight (highlight, vpos) - int highlight; - int vpos; -{ - struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame); - if (! FRAME_TERMCAP_P (f)) - { - (*reassert_line_highlight_hook) (highlight, vpos); - return; - } - if (TN_standout_width < 0) - /* Handle terminals where standout takes affect at output time */ - standout_requested = highlight; - else if (chars_wasted && chars_wasted[vpos] == 0) - /* For terminals with standout markers, write one on this line - if there isn't one already. */ - write_standout_marker (highlight, vpos); -} -/* Call this when about to modify line at position VPOS - and change whether it is highlighted. */ +/* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are + frame-relative coordinates. */ void -change_line_highlight (new_highlight, vpos, y, first_unused_hpos) - int new_highlight, vpos, y, first_unused_hpos; +cursor_to (vpos, hpos) + int vpos, hpos; { - standout_requested = new_highlight; - if (! FRAME_TERMCAP_P (updating_frame)) - { - (*change_line_highlight_hook) (new_highlight, vpos, y, first_unused_hpos); - return; - } + struct frame *f = (updating_frame + ? updating_frame + : XFRAME (selected_frame)); - cursor_to (vpos, 0); - - if (TN_standout_width < 0) - background_highlight (); - /* If line starts with a marker, delete the marker */ - else if (TS_clr_line && chars_wasted[curY]) - { - turn_off_insert (); - /* On Teleray, make sure to erase the SO marker. */ - if (TF_teleray) - { - cmgoto (curY - 1, FRAME_WIDTH (XFRAME (selected_frame)) - 4); - OUTPUT ("\033S"); - curY++; /* ESC S moves to next line where the TS_standout_mode was */ - curX = 0; - } - else - cmgoto (curY, 0); /* reposition to kill standout marker */ - } - clear_end_of_line_raw (first_unused_hpos); - reassert_line_highlight (new_highlight, curY); + if (FRAME_DISPLAY (f)->cursor_to_hook) + (*FRAME_DISPLAY (f)->cursor_to_hook) (vpos, hpos); } - - -/* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are - frame-relative coordinates. */ void -cursor_to (vpos, hpos) - int vpos, hpos; +tty_cursor_to (int vpos, int hpos) { - struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame); + 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 (chars_wasted == 0) + if (! tty->costs_set) return; - hpos += chars_wasted[vpos] & 077; - 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) + background_highlight (tty); + if (!tty->TF_insmode_motion) + turn_off_insert (tty); + cmgoto (tty, vpos, hpos); } /* Similar but don't take any account of the wasted characters. */ @@ -760,19 +460,31 @@ void raw_cursor_to (row, col) int row, 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 frame *f = (updating_frame + ? updating_frame + : XFRAME (selected_frame)); + + if (FRAME_DISPLAY (f)->raw_cursor_to_hook) + (*FRAME_DISPLAY (f)->raw_cursor_to_hook) (row, col); +} + +void +tty_raw_cursor_to (int row, int col) +{ + struct frame *f = (updating_frame + ? updating_frame + : XFRAME (selected_frame)); + + struct tty_display_info *tty = FRAME_TTY (f); + + if (curY (tty) == row + && curX (tty) == col) return; - if (!TF_standout_motion) - background_highlight (); - if (!TF_insmode_motion) - turn_off_insert (); - cmgoto (row, col); + if (!tty->TF_standout_motion) + background_highlight (tty); + if (!tty->TF_insmode_motion) + turn_off_insert (tty); + cmgoto (tty, row, col); } /* Erase operations */ @@ -780,27 +492,35 @@ raw_cursor_to (row, col) /* clear from cursor to end of frame */ void clear_to_end () +{ + struct frame *f = (updating_frame + ? updating_frame + : XFRAME (selected_frame)); + + if (FRAME_DISPLAY (f)->clear_to_end_hook) + (*FRAME_DISPLAY (f)->clear_to_end_hook) (); +} + +void +tty_clear_to_end (void) { register int i; + struct frame *f = (updating_frame + ? updating_frame + : XFRAME (selected_frame)); + struct tty_display_info *tty = FRAME_TTY (f); - if (clear_to_end_hook && ! FRAME_TERMCAP_P (updating_frame)) - { - (*clear_to_end_hook) (); - return; - } - if (TS_clr_to_bottom) + if (tty->TS_clr_to_bottom) { - background_highlight (); - OUTPUT (TS_clr_to_bottom); - bzero (chars_wasted + curY, - FRAME_HEIGHT (XFRAME (selected_frame)) - curY); + background_highlight (tty); + OUTPUT (tty, tty->TS_clr_to_bottom); } else { - for (i = curY; i < FRAME_HEIGHT (XFRAME (selected_frame)); i++) + for (i = curY (tty); i < FRAME_LINES (f); i++) { cursor_to (i, 0); - clear_end_of_line_raw (FRAME_WIDTH (XFRAME (selected_frame))); + clear_end_of_line (FRAME_COLS (f)); } } } @@ -810,20 +530,26 @@ clear_to_end () void clear_frame () { - struct frame *sf = XFRAME (selected_frame); - - if (clear_frame_hook - && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : sf))) - { - (*clear_frame_hook) (); - return; - } - if (TS_clr_frame) + struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame)); + + if (FRAME_DISPLAY (f)->clear_frame_hook) + (*FRAME_DISPLAY (f)->clear_frame_hook) (); +} + +void +tty_clear_frame () +{ + struct frame *f = (updating_frame + ? updating_frame + : XFRAME (selected_frame)); + + struct tty_display_info *tty = FRAME_TTY (f); + + if (tty->TS_clr_frame) { - background_highlight (); - OUTPUT (TS_clr_frame); - bzero (chars_wasted, FRAME_HEIGHT (sf)); - cmat (0, 0); + background_highlight (tty); + OUTPUT (tty, tty->TS_clr_frame); + cmat (tty, 0, 0); } else { @@ -832,78 +558,61 @@ clear_frame () } } -/* Clear to end of line, but do not clear any standout marker. - Assumes that the cursor is positioned at a character of real text, - which implies it cannot be before a standout marker - unless the marker has zero width. +/* Clear from cursor to end of line. + Assume that the line is already clear starting at column first_unused_hpos. - Note that the cursor may be moved. */ + 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; { - if (FRAME_TERMCAP_P (XFRAME (selected_frame)) - && chars_wasted != 0 - && TN_standout_width == 0 && curX == 0 && chars_wasted[curY] != 0) - write_glyphs (&space_glyph, 1); - clear_end_of_line_raw (first_unused_hpos); -} - -/* Clear from cursor to end of line. - Assume that the line is already clear starting at column first_unused_hpos. - If the cursor is at a standout marker, erase the marker. + struct frame *f = (updating_frame + ? updating_frame + : XFRAME (selected_frame)); - Note that the cursor may be moved, on terminals lacking a `ce' string. */ + if (FRAME_DISPLAY (f)->clear_end_of_line_hook) + (*FRAME_DISPLAY (f)->clear_end_of_line_hook) (first_unused_hpos); +} void -clear_end_of_line_raw (first_unused_hpos) - int first_unused_hpos; +tty_clear_end_of_line (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 frame *f = (updating_frame + ? updating_frame + : XFRAME (selected_frame)); + struct tty_display_info *tty = FRAME_TTY (f); /* Detect the case where we are called from reset_sys_modes and the costs have never been calculated. Do nothing. */ - if (chars_wasted == 0) + if (! tty->costs_set) return; - first_unused_hpos += chars_wasted[curY] & 077; - if (curX >= first_unused_hpos) + if (curX (tty) >= first_unused_hpos) return; - /* Notice if we are erasing a magic cookie */ - if (curX == 0) - chars_wasted[curY] = 0; - background_highlight (); - if (TS_clr_line) + 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 (); + turn_off_insert (tty); /* Do not write in last row last col with Auto-wrap on. */ - if (AutoWrap && curY == FRAME_HEIGHT (sf) - 1 - && first_unused_hpos == FRAME_WIDTH (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 (tty)) + fputc (' ', TTY_TERMSCRIPT (tty)); + fputc (' ', TTY_OUTPUT (tty)); } - cmplus (first_unused_hpos - curX); + cmplus (tty, first_unused_hpos - curX (tty)); } } @@ -925,15 +634,18 @@ encode_terminal_code (src, dst, src_len, dst_len, consumed) struct glyph *src_start = src, *src_end = src + src_len; unsigned char *dst_start = dst, *dst_end = dst + dst_len; register GLYPH g; - unsigned int c; - unsigned char workbuf[MAX_MULTIBYTE_LENGTH], *buf; + unsigned char workbuf[MAX_MULTIBYTE_LENGTH]; + const unsigned char *buf; int len; register int tlen = GLYPH_TABLE_LENGTH; register Lisp_Object *tbase = GLYPH_TABLE_BASE; int result; struct coding_system *coding; - coding = (CODING_REQUIRE_ENCODING (&terminal_coding) + /* If terminal_coding does any conversion, use it, otherwise use + safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here + because it always return 1 if the member src_multibyte is 1. */ + coding = (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK ? &terminal_coding : &safe_terminal_coding); @@ -951,11 +663,13 @@ encode_terminal_code (src, dst, src_len, dst_len, consumed) { len = 1; buf = " "; + coding->src_multibyte = 0; } else { len = CHAR_STRING (src->u.ch, workbuf); buf = workbuf; + coding->src_multibyte = 1; } } else @@ -972,15 +686,17 @@ encode_terminal_code (src, dst, src_len, dst_len, consumed) workbuf[0] = FAST_GLYPH_CHAR (g); len = 1; buf = workbuf; + coding->src_multibyte = 0; } else { /* We have a string in Vglyph_table. */ len = GLYPH_LENGTH (tbase, g); buf = GLYPH_STRING (tbase, g); + coding->src_multibyte = STRING_MULTIBYTE (tbase[g]); } } - + result = encode_coding (coding, buf, dst, len, dst_end - dst); len -= coding->consumed; dst += coding->produced; @@ -1003,7 +719,7 @@ encode_terminal_code (src, dst, src_len, dst_len, consumed) } src++; } - + *consumed = src - src_start; return (dst - dst_start); } @@ -1013,65 +729,78 @@ void write_glyphs (string, len) register struct glyph *string; register int len; +{ + struct frame *f = (updating_frame + ? updating_frame + : XFRAME (selected_frame)); + + if (FRAME_DISPLAY (f)->write_glyphs_hook) + (*FRAME_DISPLAY (f)->write_glyphs_hook) (string, len); +} + +void +tty_write_glyphs (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[1024]; + int conversion_buffer_size = sizeof conversion_buffer; - if (write_glyphs_hook - && ! FRAME_TERMCAP_P (f)) - { - (*write_glyphs_hook) (string, len); - return; - } + struct frame *f = (updating_frame + ? updating_frame + : XFRAME (selected_frame)); - highlight_if_desired (); - turn_off_insert (); + struct tty_display_info *tty = FRAME_TTY (f); + + 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_HEIGHT (sf) - && (curX + len - (chars_wasted[curY] & 077) == FRAME_WIDTH (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); + /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at the tail. */ terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK; - + while (len > 0) { /* Identify a run of glyphs with the same face. */ int face_id = string->face_id; int n; - + for (n = 1; n < len; ++n) if (string[n].face_id != face_id) break; /* Turn appearance modes of the face of the run on. */ + highlight_if_desired (tty); turn_on_face (f, face_id); while (n > 0) { - /* We use a shared conversion buffer of the current size - (1024 bytes at least). Usually it is sufficient, but if - not, we just repeat the loop. */ + /* We use a fixed size (1024 bytes) of conversion buffer. + Usually it is sufficient, but if not, we just repeat the + loop. */ produced = encode_terminal_code (string, conversion_buffer, n, conversion_buffer_size, &consumed); if (produced > 0) { - fwrite (conversion_buffer, 1, produced, stdout); - if (ferror (stdout)) - clearerr (stdout); - if (termscript) - fwrite (conversion_buffer, 1, produced, termscript); + fwrite (conversion_buffer, 1, produced, + TTY_OUTPUT (tty)); + if (ferror (TTY_OUTPUT (tty))) + clearerr (TTY_OUTPUT (tty)); + if (TTY_TERMSCRIPT (tty)) + fwrite (conversion_buffer, 1, produced, + TTY_TERMSCRIPT (tty)); } len -= consumed; n -= consumed; @@ -1080,8 +809,9 @@ write_glyphs (string, len) /* Turn appearance modes off. */ turn_off_face (f, face_id); + turn_off_highlight (tty); } - + /* We may have to output some codes to terminate the writing. */ if (CODING_REQUIRE_FLUSHING (&terminal_coding)) { @@ -1090,61 +820,69 @@ write_glyphs (string, len) 0, conversion_buffer_size); if (terminal_coding.produced > 0) { - fwrite (conversion_buffer, 1, terminal_coding.produced, stdout); - if (ferror (stdout)) - clearerr (stdout); - if (termscript) + fwrite (conversion_buffer, 1, terminal_coding.produced, + TTY_OUTPUT (tty)); + if (ferror (TTY_OUTPUT (tty))) + clearerr (TTY_OUTPUT (tty)); + if (TTY_TERMSCRIPT (tty)) fwrite (conversion_buffer, 1, terminal_coding.produced, - termscript); + TTY_TERMSCRIPT (tty)); } } - - cmcheckmagic (); + + 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; { - char *buf; - struct glyph *glyph; - struct frame *f, *sf; + struct frame *f = (updating_frame + ? updating_frame + : XFRAME (selected_frame)); if (len <= 0) return; - if (insert_glyphs_hook) - { - (*insert_glyphs_hook) (start, len); - return; - } + if (FRAME_DISPLAY (f)->insert_glyphs_hook) + (*FRAME_DISPLAY (f)->insert_glyphs_hook) (start, len); +} + +void +tty_insert_glyphs (struct glyph *start, int len) +{ + char *buf; + struct glyph *glyph = NULL; + struct frame *f = (updating_frame + ? updating_frame + : XFRAME (selected_frame)); - sf = XFRAME (selected_frame); - f = updating_frame ? updating_frame : sf; - highlight_if_desired (); + struct tty_display_info *tty = FRAME_TTY (f); - if (TS_ins_multi_chars) + if (tty->TS_ins_multi_chars) { - buf = tparam (TS_ins_multi_chars, 0, 0, len); - OUTPUT1 (buf); + buf = tparam (tty->TS_ins_multi_chars, 0, 0, len); + OUTPUT1 (tty, buf); xfree (buf); if (start) write_glyphs (start, len); return; } - turn_on_insert (); - cmplus (len); + turn_on_insert (tty); + cmplus (tty, len); /* The bit CODING_MODE_LAST_BLOCK should be set to 1 only at the tail. */ terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK; while (len-- > 0) { int produced, consumed; + unsigned char conversion_buffer[1024]; + int conversion_buffer_size = sizeof conversion_buffer; - OUTPUT1_IF (TS_ins_char); + OUTPUT1_IF (tty, tty->TS_ins_char); if (!start) { conversion_buffer[0] = SPACEGLYPH; @@ -1152,6 +890,7 @@ insert_glyphs (start, len) } else { + highlight_if_desired (tty); turn_on_face (f, start->face_id); glyph = start; ++start; @@ -1159,7 +898,7 @@ insert_glyphs (start, len) 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--; } @@ -1167,63 +906,78 @@ insert_glyphs (start, len) /* This is the last glyph. */ terminal_coding.mode |= CODING_MODE_LAST_BLOCK; - /* We use shared conversion buffer of the current size (1024 - bytes at least). It is surely sufficient for just one glyph. */ + /* The size of conversion buffer (1024 bytes) is surely + sufficient for just one glyph. */ produced = encode_terminal_code (glyph, conversion_buffer, 1, conversion_buffer_size, &consumed); } if (produced > 0) { - fwrite (conversion_buffer, 1, produced, stdout); - if (ferror (stdout)) - clearerr (stdout); - if (termscript) - fwrite (conversion_buffer, 1, produced, termscript); + fwrite (conversion_buffer, 1, produced, + TTY_OUTPUT (tty)); + if (ferror (TTY_OUTPUT (tty))) + clearerr (TTY_OUTPUT (tty)); + if (TTY_TERMSCRIPT (tty)) + fwrite (conversion_buffer, 1, produced, + TTY_TERMSCRIPT (tty)); } - 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_face (f, glyph->face_id); + turn_off_highlight (tty); + } } - - cmcheckmagic (); + + cmcheckmagic (tty); } void delete_glyphs (n) register int n; { - char *buf; - register int i; + struct frame *f = (updating_frame + ? updating_frame + : XFRAME (selected_frame)); - if (delete_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame)) - { - (*delete_glyphs_hook) (n); - return; - } + if (FRAME_DISPLAY (f)->delete_glyphs_hook) + (*FRAME_DISPLAY (f)->delete_glyphs_hook) (n); +} - if (delete_in_insert_mode) +void +tty_delete_glyphs (int n) +{ + char *buf; + register int i; + struct frame *f = (updating_frame + ? updating_frame + : XFRAME (selected_frame)); + + struct tty_display_info *tty = FRAME_TTY (f); + + if (tty->delete_in_insert_mode) { - turn_on_insert (); + turn_on_insert (tty); } else { - turn_off_insert (); - OUTPUT_IF (TS_delete_mode); + 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. */ @@ -1232,22 +986,29 @@ void ins_del_lines (vpos, n) int vpos, 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 frame *f = (updating_frame + ? updating_frame + : XFRAME (selected_frame)); + + if (FRAME_DISPLAY (f)->ins_del_lines_hook) + (*FRAME_DISPLAY (f)->ins_del_lines_hook) (vpos, n); +} + +void +tty_ins_del_lines (int vpos, int n) +{ + struct frame *f = (updating_frame + ? updating_frame + : XFRAME (selected_frame)); + + struct tty_display_info *tty = FRAME_TTY (f); + char *multi = n > 0 ? tty->TS_ins_multi_lines : tty->TS_del_multi_lines; + char *single = n > 0 ? tty->TS_ins_line : tty->TS_del_line; + char *scroll = n > 0 ? tty->TS_rev_scroll : tty->TS_fwd_scroll; register int i = n > 0 ? n : -n; register char *buf; - if (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 @@ -1255,65 +1016,48 @@ ins_del_lines (vpos, n) /* 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_HEIGHT (sf)) + if (!FRAME_MEMORY_BELOW_FRAME (f) + && vpos + i >= FRAME_LINES (f)) return; - + if (multi) { raw_cursor_to (vpos, 0); - background_highlight (); + 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 (); + 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); + set_scroll_region (vpos, tty->specified_window); if (n < 0) - raw_cursor_to (specified_window - 1, 0); + raw_cursor_to (tty->specified_window - 1, 0); else - raw_cursor_to (vpos, 0); - background_highlight (); + raw_cursor_to (vpos, 0); + background_highlight (tty); while (--i >= 0) - OUTPUTL (scroll, specified_window - vpos); - set_scroll_region (0, specified_window); - } - - if (TN_standout_width >= 0) - { - register int lower_limit - = (scroll_region_ok - ? specified_window - : FRAME_HEIGHT (sf)); - - if (n < 0) - { - bcopy (&chars_wasted[vpos - n], &chars_wasted[vpos], - lower_limit - vpos + n); - bzero (&chars_wasted[lower_limit + n], - n); - } - else - { - bcopy (&chars_wasted[vpos], ©buf[vpos], lower_limit - vpos - n); - bcopy (©buf[vpos], &chars_wasted[vpos + n], - lower_limit - vpos - n); - bzero (&chars_wasted[vpos], n); - } + OUTPUTL (tty, scroll, tty->specified_window - vpos); + set_scroll_region (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_HEIGHT (sf) + n, 0); + cursor_to (FRAME_LINES (f) + n, 0); clear_to_end (); } } @@ -1363,35 +1107,36 @@ per_line_cost (str) #ifndef old /* char_ins_del_cost[n] is cost of inserting N characters. char_ins_del_cost[-n] is cost of deleting N characters. - The length of this vector is based on max_frame_width. */ + The length of this vector is based on max_frame_cols. */ int *char_ins_del_vector; -#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WIDTH ((f))]) +#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))]) #endif /* ARGSUSED */ static void -calculate_ins_del_char_costs (frame) - FRAME_PTR frame; +calculate_ins_del_char_costs (f) + FRAME_PTR 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 { @@ -1399,18 +1144,18 @@ calculate_ins_del_char_costs (frame) 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 { @@ -1419,16 +1164,16 @@ calculate_ins_del_char_costs (frame) } /* Delete costs are at negative offsets */ - p = &char_ins_del_cost (frame)[0]; - for (i = FRAME_WIDTH (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_WIDTH (frame); --i >= 0;) + for (i = FRAME_COLS (f); --i >= 0;) *p++ = (ins_startup_cost += ins_cost_per_char); } @@ -1436,81 +1181,64 @@ void calculate_costs (frame) FRAME_PTR 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); -#ifdef HAVE_X_WINDOWS - if (FRAME_X_P (frame)) + if (FRAME_TERMCAP_P (frame)) { - do_line_insertion_deletion_costs (frame, 0, ".5*", 0, ".5*", - 0, 0, - x_screen_planes (frame)); - scroll_region_cost = 0; - return; - } -#endif + 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); - /* These variables are only used for terminal stuff. They are allocated - once for the terminal frame of X-windows emacs, but not used afterwards. + FRAME_SCROLL_REGION_COST (frame) = string_cost (f); - char_ins_del_vector (i.e., char_ins_del_cost) isn't used because - X turns off char_ins_del_ok. + tty->costs_set = 1; - chars_wasted and copybuf are only used here in term.c in cases where - the term hook isn't called. */ + /* These variables are only used for terminal stuff. They are + allocated once for the terminal frame of X-windows emacs, but not + used afterwards. - max_frame_height = max (max_frame_height, FRAME_HEIGHT (frame)); - max_frame_width = max (max_frame_width, FRAME_WIDTH (frame)); + char_ins_del_vector (i.e., char_ins_del_cost) isn't used because + X turns off char_ins_del_ok. */ - if (chars_wasted != 0) - chars_wasted = (char *) xrealloc (chars_wasted, max_frame_height); - else - chars_wasted = (char *) xmalloc (max_frame_height); + max_frame_lines = max (max_frame_lines, FRAME_LINES (frame)); + max_frame_cols = max (max_frame_cols, FRAME_COLS (frame)); - if (copybuf != 0) - copybuf = (char *) xrealloc (copybuf, max_frame_height); - else - copybuf = (char *) xmalloc (max_frame_height); + 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)); - if (char_ins_del_vector != 0) - char_ins_del_vector - = (int *) xrealloc (char_ins_del_vector, - (sizeof (int) - + 2 * max_frame_width * sizeof (int))); - else - char_ins_del_vector - = (int *) xmalloc (sizeof (int) - + 2 * max_frame_width * sizeof (int)); - - bzero (chars_wasted, max_frame_height); - bzero (copybuf, max_frame_height); - bzero (char_ins_del_vector, (sizeof (int) - + 2 * max_frame_width * 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); + bzero (char_ins_del_vector, (sizeof (int) + + 2 * max_frame_cols * sizeof (int))); - 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_WIDTH (frame) * 2; + 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); - cmcostinit (); /* set up cursor motion costs */ + /* 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 { @@ -1526,86 +1254,86 @@ struct fkey_table { static struct fkey_table keys[] = { - "kh", "home", /* termcap */ - "kl", "left", /* termcap */ - "ku", "up", /* termcap */ - "kr", "right", /* termcap */ - "kd", "down", /* termcap */ - "%8", "prior", /* terminfo */ - "%5", "next", /* terminfo */ - "@7", "end", /* terminfo */ - "@1", "begin", /* terminfo */ - "*6", "select", /* terminfo */ - "%9", "print", /* terminfo */ - "@4", "execute", /* terminfo --- actually the `command' key */ + {"kh", "home"}, /* termcap */ + {"kl", "left"}, /* termcap */ + {"ku", "up"}, /* termcap */ + {"kr", "right"}, /* termcap */ + {"kd", "down"}, /* termcap */ + {"%8", "prior"}, /* terminfo */ + {"%5", "next"}, /* terminfo */ + {"@7", "end"}, /* terminfo */ + {"@1", "begin"}, /* terminfo */ + {"*6", "select"}, /* terminfo */ + {"%9", "print"}, /* terminfo */ + {"@4", "execute"}, /* terminfo --- actually the `command' key */ /* * "insert" --- see below */ - "&8", "undo", /* terminfo */ - "%0", "redo", /* terminfo */ - "%7", "menu", /* terminfo --- actually the `options' key */ - "@0", "find", /* terminfo */ - "@2", "cancel", /* terminfo */ - "%1", "help", /* terminfo */ + {"&8", "undo"}, /* terminfo */ + {"%0", "redo"}, /* terminfo */ + {"%7", "menu"}, /* terminfo --- actually the `options' key */ + {"@0", "find"}, /* terminfo */ + {"@2", "cancel"}, /* terminfo */ + {"%1", "help"}, /* terminfo */ /* * "break" goes here, but can't be reliably intercepted with termcap */ - "&4", "reset", /* terminfo --- actually `restart' */ + {"&4", "reset"}, /* terminfo --- actually `restart' */ /* * "system" and "user" --- no termcaps */ - "kE", "clearline", /* terminfo */ - "kA", "insertline", /* terminfo */ - "kL", "deleteline", /* terminfo */ - "kI", "insertchar", /* terminfo */ - "kD", "deletechar", /* terminfo */ - "kB", "backtab", /* terminfo */ + {"kE", "clearline"}, /* terminfo */ + {"kA", "insertline"}, /* terminfo */ + {"kL", "deleteline"}, /* terminfo */ + {"kI", "insertchar"}, /* terminfo */ + {"kD", "deletechar"}, /* terminfo */ + {"kB", "backtab"}, /* terminfo */ /* * "kp_backtab", "kp-space", "kp-tab" --- no termcaps */ - "@8", "kp-enter", /* terminfo */ + {"@8", "kp-enter"}, /* terminfo */ /* * "kp-f1", "kp-f2", "kp-f3" "kp-f4", * "kp-multiply", "kp-add", "kp-separator", * "kp-subtract", "kp-decimal", "kp-divide", "kp-0"; * --- no termcaps for any of these. */ - "K4", "kp-1", /* terminfo */ + {"K4", "kp-1"}, /* terminfo */ /* * "kp-2" --- no termcap */ - "K5", "kp-3", /* terminfo */ + {"K5", "kp-3"}, /* terminfo */ /* * "kp-4" --- no termcap */ - "K2", "kp-5", /* terminfo */ + {"K2", "kp-5"}, /* terminfo */ /* * "kp-6" --- no termcap */ - "K1", "kp-7", /* terminfo */ + {"K1", "kp-7"}, /* terminfo */ /* * "kp-8" --- no termcap */ - "K3", "kp-9", /* terminfo */ + {"K3", "kp-9"}, /* terminfo */ /* * "kp-equal" --- no termcap */ - "k1", "f1", - "k2", "f2", - "k3", "f3", - "k4", "f4", - "k5", "f5", - "k6", "f6", - "k7", "f7", - "k8", "f8", - "k9", "f9", + {"k1", "f1"}, + {"k2", "f2"}, + {"k3", "f3"}, + {"k4", "f4"}, + {"k5", "f5"}, + {"k6", "f6"}, + {"k7", "f7"}, + {"k8", "f8"}, + {"k9", "f9"} }; static char **term_get_fkeys_arg; static Lisp_Object term_get_fkeys_1 (); /* Find the escape codes sent by the function keys for Vfunction_key_map. - This function scans the termcap function key sequence entries, and + This function scans the termcap function key sequence entries, and adds entries to Vfunction_key_map for each function key it finds. */ void @@ -1657,12 +1385,15 @@ term_get_fkeys_1 () if (k_semi) { + 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), + Fmake_vector (make_number (1), intern ("f0"))); Fdefine_key (Vfunction_key_map, build_string (k_semi), Fmake_vector (make_number (1), intern ("f10"))); - k0_name = "f0"; } - - if (k0) + else if (k0) Fdefine_key (Vfunction_key_map, build_string (k0), Fmake_vector (make_number (1), intern (k0_name))); } @@ -1707,7 +1438,7 @@ term_get_fkeys_1 () Fmake_vector (make_number (1), \ intern (sym))); \ } - + /* if there's no key_next keycap, map key_npage to `next' keysym */ CONDITIONAL_REASSIGN ("%5", "kN", "next"); /* if there's no key_prev keycap, map key_ppage to `previous' keysym */ @@ -1747,7 +1478,7 @@ static void append_glyph P_ ((struct it *)); for which to produce glyphs; IT->face_id contains the character's face. Padding glyphs are appended if IT->c has a IT->pixel_width > 1. */ - + static void append_glyph (it) struct it *it; @@ -1760,8 +1491,8 @@ append_glyph (it) + it->glyph_row->used[it->area]); end = it->glyph_row->glyphs[1 + it->area]; - for (i = 0; - i < it->pixel_width && glyph < end; + for (i = 0; + i < it->pixel_width && glyph < end; ++i) { glyph->type = CHAR_GLYPH; @@ -1771,20 +1502,32 @@ append_glyph (it) glyph->padding_p = i > 0; glyph->charpos = CHARPOS (it->position); glyph->object = it->object; - + ++it->glyph_row->used[it->area]; ++glyph; } } -/* Produce glyphs for the display element described by IT. The - function fills output fields of IT with pixel information like the - pixel width and height of a character, and maybe produces glyphs at +/* Produce glyphs for the display element described by IT. *IT + specifies what we want to produce a glyph for (character, image, ...), + and where in the glyph matrix we currently are (glyph row and hpos). + produce_glyphs fills in output fields of *IT with information such as the + pixel width and height of a character, and maybe output actual glyphs at the same time if IT->glyph_row is non-null. See the explanation of - struct display_iterator in dispextern.h for an overview. */ + struct display_iterator in dispextern.h for an overview. + + produce_glyphs also stores the result of glyph width, ascent + etc. computations in *IT. -void + IT->glyph_row may be null, in which case produce_glyphs does not + actually fill in the glyphs. This is used in the move_* functions + in xdisp.c for text width and height computations. + + Callers usually don't call produce_glyphs directly; + instead they use the macro PRODUCE_GLYPHS. */ + +void produce_glyphs (it) struct it *it; { @@ -1793,7 +1536,7 @@ produce_glyphs (it) || it->what == IT_COMPOSITION || it->what == IT_IMAGE || it->what == IT_STRETCH); - + /* Nothing but characters are supported on terminal frames. For a composition sequence, it->c is the first character of the sequence. */ @@ -1810,10 +1553,10 @@ produce_glyphs (it) it->pixel_width = it->nglyphs = 0; else if (it->c == '\t') { - int absolute_x = (it->current_x - it->prompt_width + int absolute_x = (it->current_x + it->continuation_lines_width); - int next_tab_x - = (((1 + absolute_x + it->tab_width - 1) + int next_tab_x + = (((1 + absolute_x + it->tab_width - 1) / it->tab_width) * it->tab_width); int nspaces; @@ -1824,23 +1567,34 @@ produce_glyphs (it) continued line. So, we will get the right number of spaces here. */ nspaces = next_tab_x - absolute_x; - + if (it->glyph_row) { int n = nspaces; - + it->c = ' '; it->pixel_width = it->len = 1; - + while (n--) append_glyph (it); - + it->c = '\t'; } it->pixel_width = nspaces; it->nglyphs = nspaces; } + else if (SINGLE_BYTE_CHAR_P (it->c)) + { + /* Coming here means that it->c is from display table, thus we + must send the code as is to the terminal. Although there's + no way to know how many columns it occupies on a screen, it + is a good assumption that a single byte code has 1-column + width. */ + it->pixel_width = it->nglyphs = 1; + if (it->glyph_row) + append_glyph (it); + } else { /* A multi-byte character. The display width is fixed for all @@ -1851,12 +1605,12 @@ produce_glyphs (it) it->pixel_width = CHARSET_WIDTH (charset); it->nglyphs = it->pixel_width; - + if (it->glyph_row) append_glyph (it); } - /* Advance current_x by the pixel width as a convenience for + /* Advance current_x by the pixel width as a convenience for the caller. */ if (it->area == TEXT_AREA) it->current_x += it->pixel_width; @@ -1877,12 +1631,12 @@ produce_special_glyphs (it, what) enum display_element_type what; { struct it temp_it; - + temp_it = *it; temp_it.dp = NULL; temp_it.what = IT_CHARACTER; temp_it.len = 1; - temp_it.object = 0; + temp_it.object = make_number (0); bzero (&temp_it.current, sizeof temp_it.current); if (what == IT_CONTINUATION) @@ -1893,11 +1647,11 @@ produce_special_glyphs (it, what) && GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (it->dp)))) { temp_it.c = FAST_GLYPH_CHAR (XINT (DISP_CONTINUE_GLYPH (it->dp))); - temp_it.len = CHAR_LEN (temp_it.c); + temp_it.len = CHAR_BYTES (temp_it.c); } else temp_it.c = '\\'; - + produce_glyphs (&temp_it); it->pixel_width = temp_it.pixel_width; it->nglyphs = temp_it.pixel_width; @@ -1910,11 +1664,11 @@ produce_special_glyphs (it, what) && GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (it->dp)))) { temp_it.c = FAST_GLYPH_CHAR (XINT (DISP_TRUNC_GLYPH (it->dp))); - temp_it.len = CHAR_LEN (temp_it.c); + temp_it.len = CHAR_BYTES (temp_it.c); } else temp_it.c = '$'; - + produce_glyphs (&temp_it); it->pixel_width = temp_it.pixel_width; it->nglyphs = temp_it.pixel_width; @@ -1924,26 +1678,20 @@ produce_special_glyphs (it, what) } -/* Return an estimation of the pixel height of mode or top lines on - frame F. FACE_ID specifies what line's height to estimate. */ - -int -estimate_mode_line_height (f, face_id) - struct frame *f; - enum face_id face_id; -{ - if (estimate_mode_line_height_hook) - return estimate_mode_line_height_hook (f, face_id); - else - return 1; -} - - /*********************************************************************** Faces ***********************************************************************/ +/* Value is non-zero if attribute ATTR may be used. ATTR should be + one of the enumerators from enum no_color_bit, or a bit set built + 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(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. */ @@ -1953,57 +1701,97 @@ turn_on_face (f, face_id) int face_id; { 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); - xassert (face != NULL); + /* 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 (tty, NC_REVERSE)) + { + if (tty->TN_max_colors > 0) + { + if (fg >= 0 && bg >= 0) + { + /* If the terminal supports colors, we can set them + below without using reverse video. The face's fg + and bg colors are set as they should appear on + the screen, i.e. they take the inverse-video'ness + of the face already into account. */ + } + else if (inverse_video) + { + if (fg == FACE_TTY_DEFAULT_FG_COLOR + || bg == FACE_TTY_DEFAULT_BG_COLOR) + toggle_highlight (tty); + } + else + { + if (fg == FACE_TTY_DEFAULT_BG_COLOR + || bg == FACE_TTY_DEFAULT_FG_COLOR) + toggle_highlight (tty); + } + } + else + { + /* If we can't display colors, use reverse video + if the face specifies that. */ + if (inverse_video) + { + if (fg == FACE_TTY_DEFAULT_FG_COLOR + || bg == FACE_TTY_DEFAULT_BG_COLOR) + toggle_highlight (tty); + } + else + { + if (fg == FACE_TTY_DEFAULT_BG_COLOR + || bg == FACE_TTY_DEFAULT_FG_COLOR) + toggle_highlight (tty); + } + } + } if (face->tty_bold_p) - 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) - 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) - OUTPUT1_IF (TS_enter_alt_charset_mode); - - if (face->tty_blinking_p) - OUTPUT1_IF (TS_enter_blink_mode); + if (face->tty_alt_charset_p + && MAY_USE_WITH_COLORS_P (tty, NC_ALT_CHARSET)) + OUTPUT1_IF (tty, tty->TS_enter_alt_charset_mode); - if (face->tty_underline_p - /* Don't underline if that's difficult. */ - && TN_magic_cookie_glitch_ul <= 0) - OUTPUT1_IF (TS_enter_underline_mode); + if (face->tty_blinking_p + && MAY_USE_WITH_COLORS_P (tty, NC_BLINK)) + OUTPUT1_IF (tty, tty->TS_enter_blink_mode); - if (face->tty_reverse_p - || face->foreground == FACE_TTY_DEFAULT_BG_COLOR - || face->background == FACE_TTY_DEFAULT_FG_COLOR) - OUTPUT1_IF (TS_enter_reverse_mode); + if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (tty, NC_UNDERLINE)) + OUTPUT1_IF (tty, tty->TS_enter_underline_mode); - if (TN_max_colors > 0) + if (tty->TN_max_colors > 0) { char *p; - - if (face->foreground != FACE_TTY_DEFAULT_COLOR - && face->foreground != FACE_TTY_DEFAULT_FG_COLOR - && face->foreground != FACE_TTY_DEFAULT_BG_COLOR - && TS_set_foreground) + + if (fg >= 0 && tty->TS_set_foreground) { - p = tparam (TS_set_foreground, NULL, 0, (int) face->foreground); - OUTPUT (p); + p = tparam (tty->TS_set_foreground, NULL, 0, (int) fg); + OUTPUT (tty, p); xfree (p); } - if (face->background != FACE_TTY_DEFAULT_COLOR - && face->background != FACE_TTY_DEFAULT_BG_COLOR - && face->background != FACE_TTY_DEFAULT_FG_COLOR - && TS_set_background) + if (bg >= 0 && tty->TS_set_background) { - p = tparam (TS_set_background, NULL, 0, (int) face->background); - OUTPUT (p); + p = tparam (tty->TS_set_background, NULL, 0, (int) bg); + OUTPUT (tty, p); xfree (p); } } } - + /* Turn off appearances of face FACE_ID on tty frame F. */ @@ -2013,10 +1801,11 @@ turn_off_face (f, face_id) 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 @@ -2027,334 +1816,783 @@ turn_off_face (f, face_id) || face->tty_alt_charset_p || face->tty_blinking_p || face->tty_underline_p) - OUTPUT1_IF (TS_exit_attribute_mode); + { + 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 - /* We don't underline if that's difficult. */ - && TN_magic_cookie_glitch_ul <= 0) - OUTPUT_IF (TS_exit_underline_mode); + if (face->tty_underline_p) + 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); +} + + +/* Return non-zero if the terminal on frame F supports all of the + capabilities in CAPS simultaneously, with foreground and background + colors FG and BG. */ + +int +tty_capable_p (tty, caps, fg, bg) + struct tty_display_info *tty; + unsigned caps; + unsigned long fg, bg; +{ +#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, 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 the tty display object specified by DISPLAY. + DISPLAY may be a frame or a string. */ + +static struct display * +get_tty_display (Lisp_Object display) +{ + struct display *d; + + if (! FRAMEP (display) && ! STRINGP (display)) + return 0; + + /* The initial frame does not support colors. */ + if (FRAMEP (display) && FRAME_INITIAL_P (XFRAME (display))) + return 0; + + if (FRAMEP (display)) + { + if (! FRAME_TERMCAP_P (XFRAME (display))) +#if 0 /* XXX We need a predicate as the first argument; find one. */ + wrong_type_argument ("Not a termcap frame", display); +#else /* Until we fix the wrong_type_argument call above, simply throw + a dumb error. */ + error ("DISPLAY is not a termcap frame"); +#endif - + d = FRAME_DISPLAY (XFRAME (display)); + } + else if (STRINGP (display)) + { + char *name = (char *) alloca (SBYTES (display) + 1); + strncpy (name, SDATA (display), SBYTES (display)); + name[SBYTES (display)] = 0; + + d = get_named_tty_display (name); + + if (!d) + error ("There is no tty display on %s", name); + } + + return d; +} + + /* Return non-zero if the terminal is capable to display colors. */ DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p, 0, 1, 0, - "Return non-nil if TTY can display colors on FRAME.") - (frame) + doc: /* Return non-nil if TTY can display colors on DISPLAY. */) + (display) + Lisp_Object display; +{ + struct display *d = get_tty_display (display); + if (!d) + return Qnil; + else + return d->display_info.tty->TN_max_colors > 0 ? Qt : Qnil; +} + +/* Return the number of supported colors. */ +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; +{ + struct display *d = get_tty_display (display); + if (!d) + return Qnil; + else + return make_number (d->display_info.tty->TN_max_colors); +} + +#ifndef WINDOWSNT + +/* Save or restore the default color-related capabilities of this + terminal. */ +static void +tty_default_color_capabilities (struct tty_display_info *tty, int save) +{ + static char + *default_orig_pair, *default_set_foreground, *default_set_background; + static int default_max_colors, default_max_pairs, default_no_color_video; + + if (save) + { + if (default_orig_pair) + xfree (default_orig_pair); + default_orig_pair = tty->TS_orig_pair ? xstrdup (tty->TS_orig_pair) : NULL; + + if (default_set_foreground) + xfree (default_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 = tty->TS_set_background ? xstrdup (tty->TS_set_background) + : NULL; + + default_max_colors = tty->TN_max_colors; + default_max_pairs = tty->TN_max_pairs; + default_no_color_video = tty->TN_no_color_video; + } + else + { + 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 (struct tty_display_info *tty, int mode) +{ + /* Canonicalize all negative values of MODE. */ + if (mode < -1) + mode = -1; + + switch (mode) + { + case -1: /* no colors at all */ + 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 (tty, 0); + break; + case 8: /* 8 standard ANSI colors */ + tty->TS_orig_pair = "\033[0m"; +#ifdef TERMINFO + tty->TS_set_foreground = "\033[3%p1%dm"; + tty->TS_set_background = "\033[4%p1%dm"; +#else + tty->TS_set_foreground = "\033[3%dm"; + tty->TS_set_background = "\033[4%dm"; +#endif + tty->TN_max_colors = 8; + tty->TN_max_pairs = 64; + tty->TN_no_color_video = 0; + break; + } +} + +void +set_tty_color_mode (f, val) + struct frame *f; + Lisp_Object val; +{ + Lisp_Object color_mode_spec, current_mode_spec; + Lisp_Object color_mode, current_mode; + int mode, old_mode; + extern Lisp_Object Qtty_color_mode; + Lisp_Object tty_color_mode_alist; + + tty_color_mode_alist = Fintern_soft (build_string ("tty-color-mode-alist"), + Qnil); + + if (INTEGERP (val)) + color_mode = val; + else + { + if (NILP (tty_color_mode_alist)) + color_mode_spec = Qnil; + else + color_mode_spec = Fassq (val, XSYMBOL (tty_color_mode_alist)->value); + + if (CONSP (color_mode_spec)) + color_mode = XCDR (color_mode_spec); + else + color_mode = Qnil; + } + + current_mode_spec = assq_no_quit (Qtty_color_mode, f->param_alist); + + if (CONSP (current_mode_spec)) + current_mode = XCDR (current_mode_spec); + else + current_mode = Qnil; + if (INTEGERP (color_mode)) + mode = XINT (color_mode); + else + mode = 0; /* meaning default */ + if (INTEGERP (current_mode)) + old_mode = XINT (current_mode); + else + old_mode = 0; + + if (mode != old_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")); + redraw_frame (f); + } +} + +#endif /* !WINDOWSNT */ + + + +struct display * +get_named_tty_display (name) + char *name; +{ + struct display *d; + + for (d = display_list; d; d = d->next_display) { + if (d->type == output_termcap + && ((d->display_info.tty->name == 0 && name == 0) + || (name && d->display_info.tty->name + && !strcmp (d->display_info.tty->name, name)))) + return d; + }; + + return 0; +} + + + +DEFUN ("frame-tty-name", Fframe_tty_name, Sframe_tty_name, 0, 1, 0, + doc: /* Return the name of the TTY device that FRAME is displayed on. */) + (frame) Lisp_Object frame; { - return TN_max_colors > 0 ? Qt : Qnil; + struct frame *f; + + if (NILP (frame)) + { + f = XFRAME (selected_frame); + } + else + { + CHECK_LIVE_FRAME (frame); + f = XFRAME (frame); + } + + if (f->output_method != output_termcap) + wrong_type_argument (Qframe_tty_name, frame); + + if (FRAME_TTY (f)->name) + return build_string (FRAME_TTY (f)->name); + else + return Qnil; } +DEFUN ("frame-tty-type", Fframe_tty_type, Sframe_tty_type, 0, 1, 0, + doc: /* Return the type of the TTY device that FRAME is displayed on. */) + (frame) + Lisp_Object frame; +{ + struct frame *f; + if (NILP (frame)) + { + f = XFRAME (selected_frame); + } + else + { + CHECK_LIVE_FRAME (frame); + f = XFRAME (frame); + } + + if (f->output_method != output_termcap) + wrong_type_argument (Qframe_tty_type, frame); + + if (FRAME_TTY (f)->type) + return build_string (FRAME_TTY (f)->type); + else + return Qnil; +} /*********************************************************************** Initialization ***********************************************************************/ +/* Create the bootstrap display device for the initial frame. + +Returns a display of type output_initial. */ +struct display * +init_initial_display (void) +{ + struct tty_display_info *tty; + + if (initialized || display_list || tty_list) + abort (); + + initial_display = create_display (); + initial_display->type = output_initial; + + initial_display->delete_display_hook = &delete_initial_display; + /* All other hooks are NULL. */ + + return initial_display; +} + +/* Deletes the bootstrap display device. + Called through delete_display_hook. */ void -term_init (terminal_type) - char *terminal_type; +delete_initial_display (struct display *display) +{ + if (display != initial_display) + abort (); + + delete_display (display); + initial_display = NULL; +} + +/* Create a termcap display on the tty device with the given name and + type. + + If NAME is NULL, then use the controlling tty, i.e., stdin/stdout. + Otherwise NAME should be a path to the tty device file, + e.g. "/dev/pts/7". + + TERMINAL_TYPE is the termcap type of the device, e.g. "vt100". + + If MUST_SUCCEED is true, then all errors are fatal. */ +struct display * +term_init (char *name, char *terminal_type, int must_succeed) { char *area; char **address = &area; - char buffer[2044]; + char *buffer = NULL; + int buffer_size = 4096; register char *p; int status; - struct frame *sf = XFRAME (selected_frame); + struct tty_display_info *tty; + struct display *display; + + static void maybe_fatal(); + + if (!terminal_type) + maybe_fatal (must_succeed, 0, 0, + "Unknown terminal type", + "Unknown terminal type"); + + display = get_named_tty_display (name); + if (display) + return display; /* We have already opened a display there. */ + + display = create_display (); + tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info)); + bzero (tty, sizeof (struct tty_display_info)); + tty->next = tty_list; + tty_list = tty; + + display->type = output_termcap; + display->display_info.tty = tty; + tty->display = display; + + tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm)); + Wcm_clear (tty); + + display->rif = 0; /* ttys don't support window-based redisplay. */ + + display->cursor_to_hook = &tty_cursor_to; + display->raw_cursor_to_hook = &tty_raw_cursor_to; + + display->clear_to_end_hook = &tty_clear_to_end; + display->clear_frame_hook = &tty_clear_frame; + display->clear_end_of_line_hook = &tty_clear_end_of_line; + + display->ins_del_lines_hook = &tty_ins_del_lines; + + display->insert_glyphs_hook = &tty_insert_glyphs; + display->write_glyphs_hook = &tty_write_glyphs; + display->delete_glyphs_hook = &tty_delete_glyphs; + + display->ring_bell_hook = &tty_ring_bell; + + display->reset_terminal_modes_hook = &tty_reset_terminal_modes; + display->set_terminal_modes_hook = &tty_set_terminal_modes; + display->update_begin_hook = 0; /* Not needed. */ + display->update_end_hook = &tty_update_end; + display->set_terminal_window_hook = &tty_set_terminal_window; + + display->mouse_position_hook = 0; /* Not needed. */ + display->frame_rehighlight_hook = 0; /* Not needed. */ + display->frame_raise_lower_hook = 0; /* Not needed. */ + + display->set_vertical_scroll_bar_hook = 0; /* Not needed. */ + display->condemn_scroll_bars_hook = 0; /* Not needed. */ + display->redeem_scroll_bar_hook = 0; /* Not needed. */ + display->judge_scroll_bars_hook = 0; /* Not needed. */ + + display->read_socket_hook = &tty_read_avail_input; /* keyboard.c */ + display->frame_up_to_date_hook = 0; /* Not needed. */ + + display->delete_frame_hook = &delete_tty_output; + display->delete_display_hook = &delete_tty; + + if (name) + { + int fd; + FILE *file; + fd = emacs_open (name, O_RDWR, 0); + if (fd < 0) + { + delete_tty (display); + error ("Could not open file: %s", name); + } + file = fdopen (fd, "w+"); + tty->name = xstrdup (name); + tty->input = file; + tty->output = file; + } + else + { + tty->name = 0; + tty->input = stdin; + tty->output = stdout; + } + + tty->type = xstrdup (terminal_type); + + add_keyboard_wait_descriptor (fileno (tty->input)); #ifdef WINDOWSNT initialize_w32_display (); - Wcm_clear (); + Wcm_clear (tty); area = (char *) xmalloc (2044); - if (area == 0) - abort (); + FrameRows (tty) = FRAME_LINES (f); /* XXX */ + FrameCols (tty) = FRAME_COLS (f); /* XXX */ + tty->specified_window = FRAME_LINES (f); /* XXX */ - FrameRows = FRAME_HEIGHT (sf); - FrameCols = FRAME_WIDTH (sf); - specified_window = FRAME_HEIGHT (sf); + tty->display->delete_in_insert_mode = 1; - delete_in_insert_mode = 1; - - UseTabs = 0; - scroll_region_ok = 0; + UseTabs (tty) = 0; + display->scroll_region_ok = 0; /* Seems to insert lines when it's not supposed to, messing up the display. In doing a trace, it didn't seem to be called much, so I don't think we're losing anything by turning it off. */ - - line_ins_del_ok = 0; - char_ins_del_ok = 1; + display->line_ins_del_ok = 0; + display->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; + FRAME_CAN_HAVE_SCROLL_BARS (f) = 0; /* XXX */ + FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none; /* XXX */ TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */ - return; + return display; #else /* not WINDOWSNT */ - Wcm_clear (); + Wcm_clear (tty); + buffer = (char *) xmalloc (buffer_size); status = tgetent (buffer, terminal_type); if (status < 0) { #ifdef TERMINFO - fatal ("Cannot open terminfo database file"); + maybe_fatal (must_succeed, buffer, display, + "Cannot open terminfo database file", + "Cannot open terminfo database file"); #else - fatal ("Cannot open termcap database file"); + maybe_fatal (must_succeed, buffer, display, + "Cannot open termcap database file", + "Cannot open termcap database file"); #endif } if (status == 0) { #ifdef TERMINFO - fatal ("Terminal type %s is not defined.\n\ + maybe_fatal (must_succeed, buffer, display, + "Terminal type %s is not defined", + "Terminal type %s is not defined.\n\ If that is not the actual type of terminal you have,\n\ use the Bourne shell command `TERM=... export TERM' (C-shell:\n\ `setenv TERM ...') to specify the correct type. It may be necessary\n\ to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.", - terminal_type); + terminal_type); #else - fatal ("Terminal type %s is not defined.\n\ + maybe_fatal (must_succeed, buffer, display, + "Terminal type %s is not defined", + "Terminal type %s is not defined.\n\ If that is not the actual type of terminal you have,\n\ use the Bourne shell command `TERM=... export TERM' (C-shell:\n\ `setenv TERM ...') to specify the correct type. It may be necessary\n\ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", - terminal_type); + terminal_type); #endif } -#ifdef TERMINFO - area = (char *) xmalloc (2044); -#else - area = (char *) xmalloc (strlen (buffer)); -#endif /* not TERMINFO */ - if (area == 0) - abort (); - 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 = 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" */ +#ifndef TERMINFO + if (strlen (buffer) >= buffer_size) + abort (); + buffer_size = strlen (buffer); +#endif + area = (char *) xmalloc (buffer_size); + + 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); - TN_magic_cookie_glitch_ul = tgetnum ("ug"); - 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"); + + 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; } - 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_xs = tgetflag ("xs"); - TF_teleray = tgetflag ("xt"); + AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am"); + display->memory_below_frame = tgetflag ("db"); + tty->TF_hazeltine = tgetflag ("hz"); + display->must_write_spaces = tgetflag ("in"); + tty->meta_key = tgetflag ("km") || tgetflag ("MT"); + tty->TF_insmode_motion = tgetflag ("mi"); + tty->TF_standout_motion = tgetflag ("ms"); + tty->TF_underscore = tgetflag ("ul"); + tty->TF_teleray = tgetflag ("xt"); term_get_fkeys (address); /* Get frame size from system, or else from termcap. */ { int height, width; - get_frame_size (&width, &height); - FRAME_WIDTH (sf) = width; - FRAME_HEIGHT (sf) = height; + get_tty_size (fileno (TTY_INPUT (tty)), &width, &height); + FrameCols (tty) = width; + FrameRows (tty) = height; } - if (FRAME_WIDTH (sf) <= 0) - SET_FRAME_WIDTH (sf, tgetnum ("co")); - else - /* Keep width and external_width consistent */ - SET_FRAME_WIDTH (sf, FRAME_WIDTH (sf)); - if (FRAME_HEIGHT (sf) <= 0) - FRAME_HEIGHT (sf) = tgetnum ("li"); - - if (FRAME_HEIGHT (sf) < 3 || FRAME_WIDTH (sf) < 3) - fatal ("Screen size %dx%d is too small", - FRAME_HEIGHT (sf), FRAME_WIDTH (sf)); + 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, display, + "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->display->min_padding_speed = tgetnum ("pb"); +#endif - min_padding_speed = tgetnum ("pb"); - TN_standout_width = tgetnum ("sg"); - TabWidth = tgetnum ("tw"); + 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 (!tty->TS_bell) + tty->TS_bell = "\07"; - if (!TS_fwd_scroll) - TS_fwd_scroll = Down; + if (!tty->TS_fwd_scroll) + tty->TS_fwd_scroll = Down (tty); - PC = TS_pad_char ? *TS_pad_char : 0; + PC = tty->TS_pad_char ? *tty->TS_pad_char : 0; + + if (TabWidth (tty) < 0) + TabWidth (tty) = 8; - if (TabWidth < 0) - TabWidth = 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"; */ - if (TS_standout_mode == 0) + /* We don't support standout modes that use `magic cookies', so + turn off any that do. */ + if (tty->TS_standout_mode && tgetnum ("sg") >= 0) + { + tty->TS_standout_mode = 0; + tty->TS_end_standout_mode = 0; + } + if (tty->TS_enter_underline_mode && tgetnum ("ug") >= 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 (tty->TS_standout_mode == 0) { - TN_standout_width = tgetnum ("ug"); - TS_end_standout_mode = tgetstr ("ue", address); - TS_standout_mode = tgetstr ("us", address); + 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; - /* Teleray: most programs want a space in front of TS_standout_mode, - but Emacs can do without it (and give one extra column). */ - TS_standout_mode = "\033RD"; - TN_standout_width = 1; + tty->Wcm->cm_tab = 0; + /* We can't support standout mode, because it uses magic cookies. */ + 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; + display->memory_below_frame = 1; + tty->Wcm->cm_losewrap = 1; } if (!strncmp (terminal_type, "c10", 3) || !strcmp (terminal_type, "perq")) @@ -2371,104 +2609,152 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", 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; + display->must_write_spaces = 1; /* :ti string typically fails to have \E^G! in it */ /* This limits scope of insert-char to one line. */ - strcpy (area, 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_HEIGHT (sf); - FrameCols = FRAME_WIDTH (sf); - specified_window = FRAME_HEIGHT (sf); + tty->specified_window = FrameRows (tty); - if (Wcm_init () == -1) /* can't do cursor motion */ + if (Wcm_init (tty) == -1) /* can't do cursor motion */ + { + maybe_fatal (must_succeed, NULL, display, + "Terminal type \"%s\" is not powerful enough to run Emacs", #ifdef VMS - fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\ + "Terminal type \"%s\" is not powerful enough to run Emacs.\n\ It lacks the ability to position the cursor.\n\ If that is not the actual type of terminal you have, use either the\n\ DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\ or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.", - terminal_type); #else /* not VMS */ # ifdef TERMINFO - fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\ + "Terminal type \"%s\" is not powerful enough to run Emacs.\n\ It lacks the ability to position the cursor.\n\ If that is not the actual type of terminal you have,\n\ use the Bourne shell command `TERM=... export TERM' (C-shell:\n\ `setenv TERM ...') to specify the correct type. It may be necessary\n\ to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.", - terminal_type); # else /* TERMCAP */ - fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\ + "Terminal type \"%s\" is not powerful enough to run Emacs.\n\ It lacks the ability to position the cursor.\n\ If that is not the actual type of terminal you have,\n\ use the Bourne shell command `TERM=... export TERM' (C-shell:\n\ `setenv TERM ...') to specify the correct type. It may be necessary\n\ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", - terminal_type); # endif /* TERMINFO */ #endif /*VMS */ - if (FRAME_HEIGHT (sf) <= 0 - || FRAME_WIDTH (sf) <= 0) - fatal ("The frame size has not been specified"); + terminal_type); + } - delete_in_insert_mode - = TS_delete_mode && TS_insert_mode - && !strcmp (TS_delete_mode, TS_insert_mode); + if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0) + maybe_fatal (must_succeed, NULL, display, + "Could not determine the frame size", + "Could not determine the frame size"); - se_is_so = (TS_standout_mode - && TS_end_standout_mode - && !strcmp (TS_standout_mode, TS_end_standout_mode)); + tty->delete_in_insert_mode + = tty->TS_delete_mode && tty->TS_insert_mode + && !strcmp (tty->TS_delete_mode, tty->TS_insert_mode); - /* Remove width of standout marker from usable width of line */ - if (TN_standout_width > 0) - SET_FRAME_WIDTH (sf, FRAME_WIDTH (sf) - TN_standout_width); + tty->se_is_so = (tty->TS_standout_mode + && tty->TS_end_standout_mode + && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode)); - UseTabs = tabs_safe_p () && TabWidth == 8; + UseTabs (tty) = tabs_safe_p (fileno (TTY_INPUT (tty))) && TabWidth (tty) == 8; - scroll_region_ok - = (Wcm.cm_abs - && (TS_set_window || TS_set_scroll_region || TS_set_scroll_region_1)); + display->scroll_region_ok + = (tty->Wcm->cm_abs + && (tty->TS_set_window || tty->TS_set_scroll_region || tty->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)); + display->line_ins_del_ok + = (((tty->TS_ins_line || tty->TS_ins_multi_lines) + && (tty->TS_del_line || tty->TS_del_multi_lines)) + || (display->scroll_region_ok + && tty->TS_fwd_scroll && tty->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)); + display->char_ins_del_ok + = ((tty->TS_ins_char || tty->TS_insert_mode + || tty->TS_pad_inserted_char || tty->TS_ins_multi_chars) + && (tty->TS_del_char || tty->TS_del_multi_chars)); - fast_clear_end_of_line = TS_clr_line != 0; + display->fast_clear_end_of_line = tty->TS_clr_line != 0; - init_baud_rate (); - if (read_socket_hook) /* Baudrate is somewhat */ - /* meaningless in this case */ - baud_rate = 9600; + init_baud_rate (fileno (TTY_INPUT (tty))); - FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0; - FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none; -#endif /* WINDOWSNT */ +#ifdef AIXHFT + /* The HFT system on AIX doesn't optimize for scrolling, so it's + really ugly at times. */ + display->line_ins_del_ok = 0; + display->char_ins_del_ok = 0; +#endif + +#ifdef MULTI_KBOARD + tty->kboard = (KBOARD *) xmalloc (sizeof (KBOARD)); + init_kboard (tty->kboard); + tty->kboard->next_kboard = all_kboards; + all_kboards = tty->kboard; + /* 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 = tty->kboard; + tty->kboard->reference_count++; +#endif + + /* Don't do this. I think termcap may still need the buffer. */ + /* xfree (buffer); */ + + /* Init system terminal modes (RAW or CBREAK, etc.). */ + init_sys_modes (tty); + + return display; +#endif /* not WINDOWSNT */ +} + +/* Auxiliary error-handling function for term_init. + Free BUFFER and delete DISPLAY, then call error or fatal + with str1 or str2, respectively, according to MUST_SUCCEED. +*/ +static void +maybe_fatal (must_succeed, buffer, display, str1, str2, arg1, arg2) + int must_succeed; + char *buffer; + struct display *display; + char *str1, *str2, *arg1, *arg2; +{ + if (buffer) + xfree (buffer); + + if (display) + delete_tty (display); + + if (must_succeed) + fatal (str2, arg1, arg2); + else + error (str1, arg1, arg2); + + abort (); } /* VARARGS 1 */ @@ -2483,12 +2769,222 @@ fatal (str, arg1, arg2) exit (1); } + + +DEFUN ("delete-tty", Fdelete_tty, Sdelete_tty, 0, 1, 0, + doc: /* Delete all frames on the terminal named TTY, and close the device. +If omitted, TTY defaults to the controlling terminal. + +This function runs `delete-tty-after-functions' after closing the +tty. The functions are run with one arg, the frame to be deleted. */) + (tty) + Lisp_Object tty; +{ + struct display *d; + char *name = 0; + + CHECK_STRING (tty); + + if (SBYTES (tty) > 0) + { + name = (char *) alloca (SBYTES (tty) + 1); + strncpy (name, SDATA (tty), SBYTES (tty)); + name[SBYTES (tty)] = 0; + } + + d = get_named_tty_display (name); + + if (! d) + error ("No such terminal device: %s", name); + + delete_tty (d); +} + +static int deleting_tty = 0; + +void +delete_tty (struct display *display) +{ + struct tty_display_info *tty; + Lisp_Object tail, frame; + char *tty_name; + + if (deleting_tty) + /* We get a recursive call when we delete the last frame on this + display. */ + return; + + deleting_tty = 1; + + if (display->type != output_termcap) + abort (); + + tty = display->display_info.tty; + + if (tty == tty_list) + tty_list = tty->next; + else + { + 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; + } + + FOR_EACH_FRAME (tail, frame) + { + struct frame *f = XFRAME (frame); + if (FRAME_TERMCAP_P (f) && FRAME_LIVE_P (f) && FRAME_TTY (f) == tty) + { + Fdelete_frame (frame, Qt); + f->output_data.tty = 0; + } + } + + /* reset_sys_modes needs a valid display, so this call needs to be + before delete_display. */ + reset_sys_modes (tty); + + delete_display (display); + + tty_name = tty->name; + if (tty->type) + xfree (tty->type); + + if (tty->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); + +#ifdef MULTI_KBOARD + if (tty->kboard && --tty->kboard->reference_count > 0) + abort (); + if (tty->kboard) + delete_kboard (tty->kboard); +#endif + + bzero (tty, sizeof (struct tty_display_info)); + xfree (tty); + deleting_tty = 0; + + /* Run `delete-tty-after-functions'. */ + if (!NILP (Vrun_hooks)) + { + Lisp_Object args[2]; + args[0] = intern ("delete-tty-after-functions"); + if (tty_name) + { + args[1] = build_string (tty_name); + xfree (tty_name); + } + else + args[1] = Qnil; + Frun_hook_with_args (2, args); + } +} + + + +/* Initialize the tty-dependent part of frame F. The frame must + already have its display initialized. */ +void +create_tty_output (struct frame *f) +{ + struct tty_output *t; + + if (! FRAME_TERMCAP_P (f)) + abort (); + + t = xmalloc (sizeof (struct tty_output)); + bzero (t, sizeof (struct tty_output)); + + t->display_info = FRAME_DISPLAY (f)->display_info.tty; + + f->output_data.tty = t; +} + +/* Delete the tty-dependent part of frame F. */ +void +delete_tty_output (struct frame *f) +{ + if (! FRAME_TERMCAP_P (f)) + abort (); + + xfree (f->output_data.tty); +} + + + + +/* Mark the pointers in the tty_display_info objects. + Called by the Fgarbage_collector. */ +void +mark_ttys () +{ + struct tty_display_info *tty; + Lisp_Object *p; + for (tty = tty_list; tty; tty = tty->next) + { + if (tty->top_frame) + mark_object (tty->top_frame); + } +} + + + +/* Create a new display object and add it to the display list. */ +struct display * +create_display (void) +{ + struct display *dev = (struct display *) xmalloc (sizeof (struct display)); + + bzero (dev, sizeof (struct display)); + dev->next_display = display_list; + display_list = dev; + + return dev; +} + +/* Remove a display from the display list and free its memory. */ +void +delete_display (struct display *dev) +{ + struct display **dp; + for (dp = &display_list; *dp != dev; dp = &(*dp)->next_display) + if (! *dp) + abort (); + *dp = dev->next_display; + + bzero (dev, sizeof (struct display)); + xfree (dev); +} + + + void syms_of_term () { DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo, - "Non-nil means the system uses terminfo rather than termcap.\n\ -This variable can be used by terminal emulator packages."); + doc: /* Non-nil means the system uses terminfo rather than termcap. +This variable can be used by terminal emulator packages. */); #ifdef TERMINFO system_uses_terminfo = 1; #else @@ -2496,10 +2992,33 @@ This variable can be used by terminal emulator packages."); #endif DEFVAR_LISP ("ring-bell-function", &Vring_bell_function, - "Non-nil means call this function to ring the bell.\n\ -The function should accept no arguments."); + doc: /* Non-nil means call this function to ring the bell. +The function should accept no arguments. */); Vring_bell_function = Qnil; + DEFVAR_LISP ("delete-tty-after-functions", &Vdelete_tty_after_functions, + doc: /* Functions to be run after deleting a tty. +The functions are run with one argument, the name of the tty to be deleted. +See `delete-tty'. */); + Vdelete_tty_after_functions = Qnil; + + Qframe_tty_name = intern ("frame-tty-name"); + staticpro (&Qframe_tty_name); + + Qframe_tty_type = intern ("frame-tty-type"); + staticpro (&Qframe_tty_type); + defsubr (&Stty_display_color_p); + defsubr (&Stty_display_color_cells); + defsubr (&Sframe_tty_name); + defsubr (&Sframe_tty_type); + defsubr (&Sdelete_tty); + + Fprovide (intern ("multi-tty"), Qnil); + } + + +/* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193 + (do not change this comment) */