X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/7c752c8099915f10ec6e99d60ea20196111a94a1..490468dcffd66ab9ea64bc1204ac9692dc530e8c:/src/term.c diff --git a/src/term.c b/src/term.c index eaac25c681..6cdfa8d435 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,8 +19,7 @@ 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 @@ -31,21 +30,33 @@ Boston, MA 02111-1307, USA. */ #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" -#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))); +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 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)); @@ -146,6 +157,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, @@ -158,6 +170,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 @@ -170,6 +183,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 @@ -203,10 +217,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 @@ -220,6 +236,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. */ @@ -406,13 +423,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 @@ -426,7 +446,7 @@ extern char *tgetstr (); void ring_bell () { - if (! NILP (Vring_bell_function)) + if (!NILP (Vring_bell_function)) { Lisp_Object function; @@ -437,105 +457,97 @@ 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'); + 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'); + } + 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 (); + standout_requested = 0; } - - 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 @@ -546,26 +558,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) @@ -599,7 +607,7 @@ turn_off_highlight () } } -void +static void turn_on_highlight () { if (TN_standout_width < 0) @@ -610,13 +618,26 @@ turn_on_highlight () } } +static void +toggle_highlight () +{ + if (standout_mode) + turn_off_highlight (); + else + turn_on_highlight (); +} + /* Make cursor invisible. */ static void tty_hide_cursor () { - OUTPUT_IF (TS_cursor_invisible); + if (tty_cursor_hidden == 0) + { + tty_cursor_hidden = 1; + OUTPUT_IF (TS_cursor_invisible); + } } @@ -625,8 +646,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); + } } @@ -669,12 +694,13 @@ highlight_if_desired () /* Write a standout marker or end-standout marker at the front of the line at vertical position vpos. */ -void +static 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))) + if (flag + || (TS_end_standout_mode && !TF_teleray && !se_is_so + && !(TF_xs && TN_standout_width == 0))) { cmgoto (vpos, 0); cmplus (TN_standout_width); @@ -704,7 +730,7 @@ reassert_line_highlight (highlight, vpos) 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); + write_standout_marker (inverse_video ? !highlight : highlight, vpos); } /* Call this when about to modify line at position VPOS @@ -946,7 +972,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; @@ -954,7 +979,10 @@ encode_terminal_code (src, dst, src_len, dst_len, consumed) 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); @@ -972,11 +1000,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 @@ -993,12 +1023,14 @@ 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]); } } @@ -1038,6 +1070,8 @@ write_glyphs (string, 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)) @@ -1046,8 +1080,8 @@ write_glyphs (string, len) return; } - highlight_if_desired (); 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. */ @@ -1076,13 +1110,14 @@ write_glyphs (string, len) break; /* Turn appearance modes of the face of the run on. */ + highlight_if_desired (); 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); @@ -1101,6 +1136,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. */ @@ -1131,7 +1167,7 @@ insert_glyphs (start, len) register int len; { char *buf; - struct glyph *glyph; + struct glyph *glyph = NULL; struct frame *f, *sf; if (len <= 0) @@ -1145,7 +1181,6 @@ insert_glyphs (start, len) sf = XFRAME (selected_frame); f = updating_frame ? updating_frame : sf; - highlight_if_desired (); if (TS_ins_multi_chars) { @@ -1164,6 +1199,8 @@ insert_glyphs (start, len) while (len-- > 0) { int produced, consumed; + unsigned char conversion_buffer[1024]; + int conversion_buffer_size = sizeof conversion_buffer; OUTPUT1_IF (TS_ins_char); if (!start) @@ -1173,6 +1210,7 @@ insert_glyphs (start, len) } else { + highlight_if_desired (); turn_on_face (f, start->face_id); glyph = start; ++start; @@ -1188,8 +1226,8 @@ 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); } @@ -1205,7 +1243,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 (); @@ -1821,7 +1862,7 @@ 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) @@ -1852,6 +1893,17 @@ produce_glyphs (it) 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 @@ -1904,7 +1956,7 @@ 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 = '\\'; @@ -1921,7 +1973,7 @@ 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 = '$'; @@ -1973,8 +2025,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) { @@ -2000,32 +2098,20 @@ turn_on_face (f, face_id) && 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); } @@ -2055,7 +2141,11 @@ 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); @@ -2192,7 +2282,7 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", TS_clr_to_bottom = tgetstr ("cd", address); TS_clr_line = tgetstr ("ce", address); TS_clr_frame = tgetstr ("cl", address); - ColPosition = tgetstr ("ch", address); + ColPosition = NULL; /* tgetstr ("ch", address); */ AbsPosition = tgetstr ("cm", address); CR = tgetstr ("cr", address); TS_set_scroll_region = tgetstr ("cs", address);