X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/d2fdb076c0e052a54ad55c2d38a764b6780a27fb..54b8bcb515a96a1c6ef304809fd9087d3b73c653:/src/term.c diff --git a/src/term.c b/src/term.c index d3b1b25007..6326d4b680 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 + Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -19,26 +19,31 @@ 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 "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" -#ifdef HAVE_TERMCAP_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. */ + +#if defined HAVE_TERMCAP_H && 0 #include #else extern void tputs P_ ((const char *, int, int (*)(int))); @@ -51,15 +56,15 @@ extern int tgetnum P_ ((char *id)); #ifdef HAVE_X_WINDOWS #include "xterm.h" #endif +#ifdef macintosh +#include "macterm.h" +#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) @@ -113,9 +118,6 @@ 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)); @@ -151,6 +153,7 @@ void (*frame_up_to_date_hook) P_ ((struct frame *)); 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, @@ -163,6 +166,7 @@ void (*mouse_position_hook) P_ ((FRAME_PTR *f, int insist, 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 @@ -175,6 +179,7 @@ void (*frame_rehighlight_hook) P_ ((FRAME_PTR f)); 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 @@ -208,10 +213,12 @@ void (*set_vertical_scroll_bar_hook) 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 @@ -225,6 +232,7 @@ void (*redeem_scroll_bar_hook) P_ ((struct window *window)); 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. */ @@ -314,10 +322,6 @@ char *TS_enter_reverse_mode; char *TS_exit_underline_mode, *TS_enter_underline_mode; -/* "ug" -- number of blanks left by underline. */ - -int TN_magic_cookie_glitch_ul; - /* "as"/"ae" -- start/end alternate character set. Not really supported, yet. */ @@ -353,13 +357,6 @@ int TF_underscore; /* termcap ul flag: _ underlines if over-struck on 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 */ @@ -377,18 +374,7 @@ int max_frame_width; 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 costs_set = 0; /* Nonzero if costs have been calculated. */ int insert_mode; /* Nonzero when in insert mode. */ int standout_mode; /* Nonzero when in standout mode. */ @@ -411,13 +397,16 @@ FRAME_PTR updating_frame; static int system_uses_terminfo; +/* Flag used in tty_show/hide_cursor. */ + +static int tty_cursor_hidden; + char *tparam (); 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 @@ -431,7 +420,7 @@ extern char *tgetstr (); void ring_bell () { - if (! NILP (Vring_bell_function)) + if (!NILP (Vring_bell_function)) { Lisp_Object function; @@ -442,105 +431,90 @@ 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_TERMCAP_P (XFRAME (selected_frame))) + (*ring_bell_hook) (); + else + OUTPUT (TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell); } void set_terminal_modes () { - if (! FRAME_TERMCAP_P (XFRAME (selected_frame))) + 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 (); } - OUTPUT_IF (TS_termcap_modes); - OUTPUT_IF (TS_cursor_visible); - OUTPUT_IF (TS_keypad_mode); - losecursor (); + else + (*set_terminal_modes_hook) (); } void reset_terminal_modes () { - if (! FRAME_TERMCAP_P (XFRAME (selected_frame))) + 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); - /* 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'); - cmputc ('\r'); + turn_off_highlight (); + turn_off_insert (); + OUTPUT_IF (TS_end_keypad_mode); + OUTPUT_IF (TS_cursor_normal); + OUTPUT_IF (TS_end_termcap_modes); + OUTPUT_IF (TS_orig_pair); + /* Output raw CR so kernel can track the cursor hpos. */ + cmputc ('\r'); + } + else if (reset_terminal_modes_hook) + (*reset_terminal_modes_hook) (); } void update_begin (f) - 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_TERMCAP_P (f)) + update_begin_hook (f); } void update_end (f) - FRAME_PTR f; + struct frame *f; { - if (! FRAME_TERMCAP_P (updating_frame)) + if (FRAME_TERMCAP_P (f)) { - (*update_end_hook) (f); - updating_frame = 0; - return; + if (!XWINDOW (selected_window)->cursor_off_p) + tty_show_cursor (); + turn_off_insert (); + background_highlight (); } - - if (!XWINDOW (selected_window)->cursor_off_p) - tty_show_cursor (); + else + update_end_hook (f); - turn_off_insert (); - background_highlight (); - standout_requested = 0; - updating_frame = 0; + updating_frame = NULL; } void set_terminal_window (size) int size; { - if (! FRAME_TERMCAP_P (updating_frame)) + if (FRAME_TERMCAP_P (updating_frame)) { - (*set_terminal_window_hook) (size); - return; + specified_window = size ? size : FRAME_HEIGHT (updating_frame); + if (scroll_region_ok) + set_scroll_region (0, specified_window); } - specified_window = size ? size : FRAME_HEIGHT (XFRAME (selected_frame)); - if (!scroll_region_ok) - return; - set_scroll_region (0, specified_window); + else + set_terminal_window_hook (size); } void @@ -551,26 +525,22 @@ set_scroll_region (start, stop) struct frame *sf = XFRAME (selected_frame); if (TS_set_scroll_region) - { - buf = tparam (TS_set_scroll_region, 0, 0, start, stop - 1); - } + 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)); - } + buf = tparam (TS_set_scroll_region_1, 0, 0, + FRAME_HEIGHT (sf), start, + FRAME_HEIGHT (sf) - stop, + FRAME_HEIGHT (sf)); else - { - buf = tparam (TS_set_window, 0, 0, start, 0, stop, FRAME_WIDTH (sf)); - } + buf = tparam (TS_set_window, 0, 0, start, 0, stop, FRAME_WIDTH (sf)); + OUTPUT (buf); xfree (buf); losecursor (); } + -void +static void turn_on_insert () { if (!insert_mode) @@ -586,33 +556,31 @@ turn_off_insert () 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 () { - if (TN_standout_width < 0) - { - if (standout_mode) - OUTPUT_IF (TS_end_standout_mode); - standout_mode = 0; - } + if (standout_mode) + OUTPUT_IF (TS_end_standout_mode); + standout_mode = 0; } -void +static void turn_on_highlight () { - if (TN_standout_width < 0) - { - if (!standout_mode) - OUTPUT_IF (TS_standout_mode); - standout_mode = 1; - } + if (!standout_mode) + OUTPUT_IF (TS_standout_mode); + standout_mode = 1; +} + +static void +toggle_highlight () +{ + if (standout_mode) + turn_off_highlight (); + else + turn_on_highlight (); } @@ -621,7 +589,11 @@ turn_on_highlight () static void tty_hide_cursor () { - OUTPUT_IF (TS_cursor_invisible); + if (tty_cursor_hidden == 0) + { + tty_cursor_hidden = 1; + OUTPUT_IF (TS_cursor_invisible); + } } @@ -630,8 +602,12 @@ tty_hide_cursor () static void tty_show_cursor () { - OUTPUT_IF (TS_cursor_normal); - OUTPUT_IF (TS_cursor_visible); + if (tty_cursor_hidden) + { + tty_cursor_hidden = 0; + OUTPUT_IF (TS_cursor_normal); + OUTPUT_IF (TS_cursor_visible); + } } @@ -642,8 +618,6 @@ tty_show_cursor () void background_highlight () { - if (TN_standout_width >= 0) - return; if (inverse_video) turn_on_highlight (); else @@ -655,98 +629,10 @@ background_highlight () static void highlight_if_desired () { - if (TN_standout_width >= 0) - return; - if (!inverse_video == !standout_requested) - turn_off_highlight (); - else + if (inverse_video) 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; - } -} - -/* 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. */ - -void -change_line_highlight (new_highlight, vpos, y, first_unused_hpos) - int new_highlight, vpos, y, first_unused_hpos; -{ - standout_requested = new_highlight; - if (! FRAME_TERMCAP_P (updating_frame)) - { - (*change_line_highlight_hook) (new_highlight, vpos, y, first_unused_hpos); - return; - } - - 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); + else + turn_off_highlight (); } @@ -767,10 +653,9 @@ cursor_to (vpos, hpos) /* 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 (! costs_set) return; - hpos += chars_wasted[vpos] & 077; if (curY == vpos && curX == hpos) return; if (!TF_standout_motion) @@ -818,15 +703,13 @@ clear_to_end () { background_highlight (); OUTPUT (TS_clr_to_bottom); - bzero (chars_wasted + curY, - FRAME_HEIGHT (XFRAME (selected_frame)) - curY); } else { for (i = curY; i < FRAME_HEIGHT (XFRAME (selected_frame)); i++) { cursor_to (i, 0); - clear_end_of_line_raw (FRAME_WIDTH (XFRAME (selected_frame))); + clear_end_of_line (FRAME_WIDTH (XFRAME (selected_frame))); } } } @@ -848,7 +731,6 @@ clear_frame () { background_highlight (); OUTPUT (TS_clr_frame); - bzero (chars_wasted, FRAME_HEIGHT (sf)); cmat (0, 0); } else @@ -858,32 +740,13 @@ 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. - - Note that the cursor may be moved. */ - -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. Note that the cursor may be moved, on terminals lacking a `ce' string. */ void -clear_end_of_line_raw (first_unused_hpos) +clear_end_of_line (first_unused_hpos) int first_unused_hpos; { register int i; @@ -899,15 +762,11 @@ clear_end_of_line_raw (first_unused_hpos) /* 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 (! costs_set) return; - first_unused_hpos += chars_wasted[curY] & 077; if (curX >= 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) { @@ -951,7 +810,6 @@ 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; int len; register int tlen = GLYPH_TABLE_LENGTH; @@ -1061,13 +919,14 @@ write_glyphs (string, len) } turn_off_insert (); + tty_hide_cursor (); /* 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))) + && (curX + len) == FRAME_WIDTH (sf)) len --; if (len <= 0) return; @@ -1115,6 +974,7 @@ write_glyphs (string, len) /* Turn appearance modes off. */ turn_off_face (f, face_id); + turn_off_highlight (); } /* We may have to output some codes to terminate the writing. */ @@ -1145,7 +1005,7 @@ insert_glyphs (start, len) register int len; { char *buf; - struct glyph *glyph; + struct glyph *glyph = NULL; struct frame *f, *sf; if (len <= 0) @@ -1159,7 +1019,6 @@ insert_glyphs (start, len) sf = XFRAME (selected_frame); f = updating_frame ? updating_frame : sf; - highlight_if_desired (); if (TS_ins_multi_chars) { @@ -1189,6 +1048,7 @@ insert_glyphs (start, len) } else { + highlight_if_desired (); turn_on_face (f, start->face_id); glyph = start; ++start; @@ -1221,7 +1081,10 @@ insert_glyphs (start, len) OUTPUT1_IF (TS_pad_inserted_char); if (start) - turn_off_face (f, glyph->face_id); + { + turn_off_face (f, glyph->face_id); + turn_off_highlight (); + } } cmcheckmagic (); @@ -1327,27 +1190,6 @@ ins_del_lines (vpos, n) 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); - } - } if (!scroll_region_ok && memory_below_frame && n < 0) { cursor_to (FRAME_HEIGHT (sf) + n, 0); @@ -1485,23 +1327,12 @@ calculate_costs (frame) once for the terminal frame of X-windows emacs, but not used afterwards. char_ins_del_vector (i.e., char_ins_del_cost) isn't used because - X turns off char_ins_del_ok. - - chars_wasted and copybuf are only used here in term.c in cases where - the term hook isn't called. */ + X turns off char_ins_del_ok. */ max_frame_height = max (max_frame_height, FRAME_HEIGHT (frame)); max_frame_width = max (max_frame_width, FRAME_WIDTH (frame)); - if (chars_wasted != 0) - chars_wasted = (char *) xrealloc (chars_wasted, max_frame_height); - else - chars_wasted = (char *) xmalloc (max_frame_height); - - if (copybuf != 0) - copybuf = (char *) xrealloc (copybuf, max_frame_height); - else - copybuf = (char *) xmalloc (max_frame_height); + costs_set = 1; if (char_ins_del_vector != 0) char_ins_del_vector @@ -1513,8 +1344,6 @@ calculate_costs (frame) = (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))); @@ -1553,79 +1382,79 @@ 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; @@ -2000,8 +1829,54 @@ 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; - 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 (NC_REVERSE)) + { + if (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 (); + } + else + { + if (fg == FACE_TTY_DEFAULT_BG_COLOR + || bg == FACE_TTY_DEFAULT_FG_COLOR) + toggle_highlight (); + } + } + 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 (); + } + else + { + if (fg == FACE_TTY_DEFAULT_BG_COLOR + || bg == FACE_TTY_DEFAULT_FG_COLOR) + toggle_highlight (); + } + } + } if (face->tty_bold_p) { @@ -2021,38 +1896,23 @@ turn_on_face (f, face_id) && MAY_USE_WITH_COLORS_P (NC_BLINK)) OUTPUT1_IF (TS_enter_blink_mode); - if (face->tty_underline_p - /* Don't underline if that's difficult. */ - && TN_magic_cookie_glitch_ul <= 0 - && MAY_USE_WITH_COLORS_P (NC_UNDERLINE)) + if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (NC_UNDERLINE)) OUTPUT1_IF (TS_enter_underline_mode); - if (MAY_USE_WITH_COLORS_P (NC_REVERSE)) - 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 (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 && TS_set_foreground) { - p = tparam (TS_set_foreground, NULL, 0, (int) face->foreground); + p = tparam (TS_set_foreground, NULL, 0, (int) fg); OUTPUT (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 && TS_set_background) { - p = tparam (TS_set_background, NULL, 0, (int) face->background); + p = tparam (TS_set_background, NULL, 0, (int) bg); OUTPUT (p); xfree (p); } @@ -2082,13 +1942,14 @@ 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 (TS_exit_attribute_mode); + if (strcmp (TS_exit_attribute_mode, TS_end_standout_mode) == 0) + standout_mode = 0; + } if (face->tty_alt_charset_p) OUTPUT_IF (TS_exit_alt_charset_mode); - - if (standout_mode) - standout_mode = 0; } else { @@ -2097,9 +1958,7 @@ turn_off_face (f, face_id) if (face->tty_alt_charset_p) OUTPUT_IF (TS_exit_alt_charset_mode); - if (face->tty_underline_p - /* We don't underline if that's difficult. */ - && TN_magic_cookie_glitch_ul <= 0) + if (face->tty_underline_p) OUTPUT_IF (TS_exit_underline_mode); } @@ -2117,14 +1976,145 @@ turn_off_face (f, face_id) 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.") + doc: /* Return non-nil if TTY can display colors on FRAME. */) (frame) Lisp_Object frame; { return TN_max_colors > 0 ? Qt : Qnil; } +#ifndef WINDOWSNT + +/* Save or restore the default color-related capabilities of this + terminal. */ +static void +tty_default_color_capabilities (save) + 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 = TS_orig_pair ? xstrdup (TS_orig_pair) : NULL; + + if (default_set_foreground) + xfree (default_set_foreground); + default_set_foreground = TS_set_foreground ? xstrdup (TS_set_foreground) + : NULL; + + if (default_set_background) + xfree (default_set_background); + default_set_background = TS_set_background ? xstrdup (TS_set_background) + : NULL; + + default_max_colors = TN_max_colors; + default_max_pairs = TN_max_pairs; + default_no_color_video = TN_no_color_video; + } + else + { + TS_orig_pair = default_orig_pair; + TS_set_foreground = default_set_foreground; + TS_set_background = default_set_background; + TN_max_colors = default_max_colors; + TN_max_pairs = default_max_pairs; + TN_no_color_video = default_no_color_video; + } +} + +/* Setup one of the standard tty color schemes according to MODE. + MODE's value is generally the number of colors which we want to + support; zero means set up for the default capabilities, the ones + we saw at term_init time; -1 means turn off color support. */ +void +tty_setup_colors (mode) + int mode; +{ + switch (mode) + { + case -1: /* no colors at all */ + TN_max_colors = 0; + TN_max_pairs = 0; + TN_no_color_video = 0; + TS_set_foreground = TS_set_background = TS_orig_pair = NULL; + break; + case 0: /* default colors, if any */ + default: + tty_default_color_capabilities (0); + break; + case 8: /* 8 standard ANSI colors */ + TS_orig_pair = "\033[0m"; +#ifdef TERMINFO + TS_set_foreground = "\033[3%p1%dm"; + TS_set_background = "\033[4%p1%dm"; +#else + TS_set_foreground = "\033[3%dm"; + TS_set_background = "\033[4%dm"; +#endif + TN_max_colors = 8; + TN_max_pairs = 64; + 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 (NATNUMP (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); + current_mode_spec = assq_no_quit (Qtty_color_mode, f->param_alist); + + if (CONSP (color_mode_spec)) + color_mode = XCDR (color_mode_spec); + else + color_mode = Qnil; + } + if (CONSP (current_mode_spec)) + current_mode = XCDR (current_mode_spec); + else + current_mode = Qnil; + if (NATNUMP (color_mode)) + mode = XINT (color_mode); + else + mode = 0; /* meaning default */ + if (NATNUMP (current_mode)) + old_mode = XINT (current_mode); + else + old_mode = 0; + + if (mode != old_mode) + { + tty_setup_colors (mode); + /* This recomputes all the faces given the new color + definitions. */ + call0 (intern ("tty-set-up-initial-frame-faces")); + redraw_frame (f); + } +} +#endif /* !WINDOWSNT */ /*********************************************************************** @@ -2277,7 +2267,6 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", 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); @@ -2314,6 +2303,8 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", TN_no_color_video = 0; } + tty_default_color_capabilities (1); + MagicWrap = tgetflag ("xn"); /* Since we make MagicWrap terminals look like AutoWrap, we need to have the former flag imply the latter. */ @@ -2325,7 +2316,6 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", TF_insmode_motion = tgetflag ("mi"); TF_standout_motion = tgetflag ("ms"); TF_underscore = tgetflag ("ul"); - TF_xs = tgetflag ("xs"); TF_teleray = tgetflag ("xt"); term_get_fkeys (address); @@ -2351,7 +2341,6 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", FRAME_HEIGHT (sf), FRAME_WIDTH (sf)); min_padding_speed = tgetnum ("pb"); - TN_standout_width = tgetnum ("sg"); TabWidth = tgetnum ("tw"); #ifdef VMS @@ -2380,11 +2369,24 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", Wcm.cm_tab = "\t"; */ + /* We don't support standout modes that use `magic cookies', so + turn off any that do. */ + if (TS_standout_mode && tgetnum ("sg") >= 0) + { + TS_standout_mode = 0; + TS_end_standout_mode = 0; + } + if (TS_enter_underline_mode && tgetnum ("ug") >= 0) + { + TS_enter_underline_mode = 0; + TS_exit_underline_mode = 0; + } + + /* If there's no standout mode, try to use underlining instead. */ if (TS_standout_mode == 0) { - TN_standout_width = tgetnum ("ug"); - TS_end_standout_mode = tgetstr ("ue", address); - TS_standout_mode = tgetstr ("us", address); + TS_standout_mode = TS_enter_underline_mode; + TS_end_standout_mode = TS_exit_underline_mode; } /* If no `se' string, try using a `me' string instead. @@ -2401,10 +2403,8 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", if (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; + /* We can't support standout mode, because it uses magic cookies. */ + TS_standout_mode = 0; /* But that means we cannot rely on ^M to go to column zero! */ CR = 0; /* LF can't be trusted either -- can alter hpos */ @@ -2504,10 +2504,6 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", && TS_end_standout_mode && !strcmp (TS_standout_mode, TS_end_standout_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); - UseTabs = tabs_safe_p () && TabWidth == 8; scroll_region_ok @@ -2550,8 +2546,8 @@ 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 @@ -2559,8 +2555,8 @@ 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; defsubr (&Stty_display_color_p);