diff options
Diffstat (limited to 'src/term.c')
-rw-r--r-- | src/term.c | 487 |
1 files changed, 279 insertions, 208 deletions
diff --git a/src/term.c b/src/term.c index 06695d1ec61..f8104e0304e 100644 --- a/src/term.c +++ b/src/term.c @@ -1,5 +1,5 @@ /* Terminal control module for terminals described by TERMCAP - Copyright (C) 1985-1987, 1993-1995, 1998, 2000-2017 Free Software + Copyright (C) 1985-1987, 1993-1995, 1998, 2000-2022 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -73,11 +73,10 @@ static void clear_tty_hooks (struct terminal *terminal); static void set_tty_hooks (struct terminal *terminal); static void dissociate_if_controlling_tty (int fd); static void delete_tty (struct terminal *); -static _Noreturn void maybe_fatal (bool, struct terminal *, - const char *, const char *, ...) +static AVOID maybe_fatal (bool, struct terminal *, const char *, const char *, + ...) ATTRIBUTE_FORMAT_PRINTF (3, 5) ATTRIBUTE_FORMAT_PRINTF (4, 5); -static _Noreturn void vfatal (const char *str, va_list ap) - ATTRIBUTE_FORMAT_PRINTF (1, 0); +static AVOID vfatal (const char *, va_list) ATTRIBUTE_FORMAT_PRINTF (1, 0); #define OUTPUT(tty, a) \ @@ -106,14 +105,14 @@ struct tty_display_info *tty_list; enum no_color_bit { - NC_STANDOUT = 1 << 0, - NC_UNDERLINE = 1 << 1, - NC_REVERSE = 1 << 2, - NC_ITALIC = 1 << 3, - NC_DIM = 1 << 4, - NC_BOLD = 1 << 5, - NC_INVIS = 1 << 6, - NC_PROTECT = 1 << 7 + NC_STANDOUT = 1 << 0, + NC_UNDERLINE = 1 << 1, + NC_REVERSE = 1 << 2, + NC_ITALIC = 1 << 3, + NC_DIM = 1 << 4, + NC_BOLD = 1 << 5, + NC_STRIKE_THROUGH = 1 << 6, + NC_PROTECT = 1 << 7 }; /* internal state */ @@ -146,7 +145,7 @@ tty_ring_bell (struct frame *f) OUTPUT (tty, (tty->TS_visible_bell && visible_bell ? tty->TS_visible_bell : tty->TS_bell)); - fflush_unlocked (tty->output); + fflush (tty->output); } } @@ -171,10 +170,9 @@ tty_send_additional_strings (struct terminal *terminal, Lisp_Object sym) Lisp_Object string = XCAR (extra_codes); if (STRINGP (string)) { - fwrite_unlocked (SDATA (string), 1, SBYTES (string), tty->output); + fwrite (SDATA (string), 1, SBYTES (string), tty->output); if (tty->termscript) - fwrite_unlocked (SDATA (string), 1, SBYTES (string), - tty->termscript); + fwrite (SDATA (string), 1, SBYTES (string), tty->termscript); } } } @@ -202,7 +200,7 @@ tty_set_terminal_modes (struct terminal *terminal) OUTPUT_IF (tty, tty->TS_keypad_mode); losecursor (tty); tty_send_additional_strings (terminal, Qtty_mode_set_strings); - fflush_unlocked (tty->output); + fflush (tty->output); } } @@ -225,7 +223,7 @@ tty_reset_terminal_modes (struct terminal *terminal) /* Output raw CR so kernel can track the cursor hpos. */ current_tty = tty; cmputc ('\r'); - fflush_unlocked (tty->output); + fflush (tty->output); } } @@ -240,7 +238,7 @@ tty_update_end (struct frame *f) tty_show_cursor (tty); tty_turn_off_insert (tty); tty_background_highlight (tty); - fflush_unlocked (tty->output); + fflush (tty->output); } /* The implementation of set_terminal_window for termcap frames. */ @@ -502,8 +500,8 @@ tty_clear_end_of_line (struct frame *f, int first_unused_hpos) for (i = curX (tty); i < first_unused_hpos; i++) { if (tty->termscript) - fputc_unlocked (' ', tty->termscript); - fputc_unlocked (' ', tty->output); + putc (' ', tty->termscript); + putc (' ', tty->output); } cmplus (tty, first_unused_hpos - curX (tty)); } @@ -551,13 +549,14 @@ encode_terminal_code (struct glyph *src, int src_len, { if (src->type == COMPOSITE_GLYPH) { - struct composition *cmp UNINIT; + struct composition *cmp; Lisp_Object gstring UNINIT; int i; nbytes = buf - encode_terminal_src; if (src->u.cmp.automatic) { + cmp = NULL; gstring = composition_gstring_from_id (src->u.cmp.id); required = src->slice.cmp.to - src->slice.cmp.from + 1; } @@ -565,8 +564,8 @@ encode_terminal_code (struct glyph *src, int src_len, { cmp = composition_table[src->u.cmp.id]; required = cmp->glyph_len; - required *= MAX_MULTIBYTE_LENGTH; } + required *= MAX_MULTIBYTE_LENGTH; if (encode_terminal_src_size - nbytes < required) { @@ -577,7 +576,7 @@ encode_terminal_code (struct glyph *src, int src_len, buf = encode_terminal_src + nbytes; } - if (src->u.cmp.automatic) + if (!cmp) for (i = src->slice.cmp.from; i <= src->slice.cmp.to; i++) { Lisp_Object g = LGSTRING_GLYPH (gstring, i); @@ -776,11 +775,10 @@ tty_write_glyphs (struct frame *f, struct glyph *string, int len) if (coding->produced > 0) { block_input (); - fwrite_unlocked (conversion_buffer, 1, coding->produced, tty->output); - clearerr_unlocked (tty->output); + fwrite (conversion_buffer, 1, coding->produced, tty->output); + clearerr (tty->output); if (tty->termscript) - fwrite_unlocked (conversion_buffer, 1, coding->produced, - tty->termscript); + fwrite (conversion_buffer, 1, coding->produced, tty->termscript); unblock_input (); } string += n; @@ -793,7 +791,7 @@ tty_write_glyphs (struct frame *f, struct glyph *string, int len) cmcheckmagic (tty); } -#ifdef HAVE_GPM /* Only used by GPM code. */ +#ifndef DOS_NT static void tty_write_glyphs_with_face (register struct frame *f, register struct glyph *string, @@ -837,11 +835,10 @@ tty_write_glyphs_with_face (register struct frame *f, register struct glyph *str if (coding->produced > 0) { block_input (); - fwrite_unlocked (conversion_buffer, 1, coding->produced, tty->output); - clearerr_unlocked (tty->output); + fwrite (conversion_buffer, 1, coding->produced, tty->output); + clearerr (tty->output); if (tty->termscript) - fwrite_unlocked (conversion_buffer, 1, coding->produced, - tty->termscript); + fwrite (conversion_buffer, 1, coding->produced, tty->termscript); unblock_input (); } @@ -851,6 +848,7 @@ tty_write_glyphs_with_face (register struct frame *f, register struct glyph *str cmcheckmagic (tty); } + #endif /* An implementation of insert_glyphs for termcap frames. */ @@ -923,11 +921,10 @@ tty_insert_glyphs (struct frame *f, struct glyph *start, int len) if (coding->produced > 0) { block_input (); - fwrite_unlocked (conversion_buffer, 1, coding->produced, tty->output); - clearerr_unlocked (tty->output); + fwrite (conversion_buffer, 1, coding->produced, tty->output); + clearerr (tty->output); if (tty->termscript) - fwrite_unlocked (conversion_buffer, 1, coding->produced, - tty->termscript); + fwrite (conversion_buffer, 1, coding->produced, tty->termscript); unblock_input (); } @@ -1089,7 +1086,6 @@ int *char_ins_del_vector; #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))]) -/* ARGSUSED */ static void calculate_ins_del_char_costs (struct frame *f) { @@ -1201,7 +1197,9 @@ calculate_costs (struct frame *frame) calculate_ins_del_char_costs (frame); /* Don't use TS_repeat if its padding is worse than sending the chars */ - if (tty->TS_repeat && per_line_cost (tty->TS_repeat) * baud_rate < 9000) + if (tty->TS_repeat + && (baud_rate <= 0 + || per_line_cost (tty->TS_repeat) < 9000 / baud_rate)) tty->RPov = string_cost (tty->TS_repeat); else tty->RPov = FRAME_COLS (frame) * 2; @@ -1350,7 +1348,8 @@ term_get_fkeys_1 (void) char **address = term_get_fkeys_address; KBOARD *kboard = term_get_fkeys_kboard; - /* This can happen if CANNOT_DUMP or with strange options. */ + /* This can happen if Emacs is starting up from scratch, or with + strange options. */ if (!KEYMAPP (KVAR (kboard, Vinput_decode_map))) kset_input_decode_map (kboard, Fmake_sparse_keymap (Qnil)); @@ -1359,8 +1358,7 @@ term_get_fkeys_1 (void) char *sequence = tgetstr (keys[i].cap, address); if (sequence) Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (sequence), - Fmake_vector (make_number (1), - intern (keys[i].name))); + make_vector (1, intern (keys[i].name)), Qnil); } /* The uses of the "k0" capability are inconsistent; sometimes it @@ -1379,13 +1377,13 @@ term_get_fkeys_1 (void) /* Define f0 first, so that f10 takes precedence in case the key sequences happens to be the same. */ Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (k0), - Fmake_vector (make_number (1), intern ("f0"))); + make_vector (1, intern ("f0")), Qnil); Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (k_semi), - Fmake_vector (make_number (1), intern ("f10"))); + make_vector (1, intern ("f10")), Qnil); } else if (k0) Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (k0), - Fmake_vector (make_number (1), intern (k0_name))); + make_vector (1, intern (k0_name)), Qnil); } /* Set up cookies for numbered function keys above f10. */ @@ -1407,9 +1405,10 @@ term_get_fkeys_1 (void) if (sequence) { sprintf (fkey, "f%d", i); - Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (sequence), - Fmake_vector (make_number (1), - intern (fkey))); + Fdefine_key (KVAR (kboard, Vinput_decode_map), + build_string (sequence), + make_vector (1, intern (fkey)), + Qnil); } } } @@ -1425,8 +1424,7 @@ term_get_fkeys_1 (void) char *sequence = tgetstr (cap2, address); \ if (sequence) \ Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (sequence), \ - Fmake_vector (make_number (1), \ - intern (sym))); \ + make_vector (1, intern (sym)), Qnil); \ } /* if there's no key_next keycap, map key_npage to `next' keysym */ @@ -1591,13 +1589,13 @@ produce_glyphs (struct it *it) + it->continuation_lines_width); int x0 = absolute_x; /* Adjust for line numbers. */ - if (!NILP (Vdisplay_line_numbers)) + if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p) absolute_x -= it->lnum_pixel_width; int next_tab_x = (((1 + absolute_x + it->tab_width - 1) / it->tab_width) * it->tab_width); - if (!NILP (Vdisplay_line_numbers)) + if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p) next_tab_x += it->lnum_pixel_width; int nspaces; @@ -1634,9 +1632,13 @@ produce_glyphs (struct it *it) } else { - Lisp_Object charset_list = FRAME_TERMINAL (it->f)->charset_list; + struct terminal *t = FRAME_TERMINAL (it->f); + Lisp_Object charset_list = t->charset_list, char_glyph; - if (char_charset (it->char_to_display, charset_list, NULL)) + if (char_charset (it->char_to_display, charset_list, NULL) + && (char_glyph = terminal_glyph_code (t, it->char_to_display), + NILP (char_glyph) + || (FIXNUMP (char_glyph) && XFIXNUM (char_glyph) >= 0))) { it->pixel_width = CHARACTER_WIDTH (it->char_to_display); it->nglyphs = it->pixel_width; @@ -1860,12 +1862,24 @@ produce_glyphless_glyph (struct it *it, Lisp_Object acronym) acronym = CHAR_TABLE_REF (Vglyphless_char_display, it->c); if (CONSP (acronym)) acronym = XCDR (acronym); - buf[0] = '['; str = STRINGP (acronym) ? SSDATA (acronym) : ""; - for (len = 0; len < 6 && str[len] && ASCII_CHAR_P (str[len]); len++) - buf[1 + len] = str[len]; - buf[1 + len] = ']'; - len += 2; + /* A special kludgey feature for single-character acronyms: + don't put them in a box, effectively treating them as a + replacement character. */ + if (STRINGP (acronym) && SCHARS (acronym) == 1) + { + buf[0] = str[0]; + len = 1; + } + else + { + buf[0] = '['; + for (len = 0; + len < 6 && str[len] && ASCII_CHAR_P (str[len]); len++) + buf[1 + len] = str[len]; + buf[1 + len] = ']'; + len += 2; + } } else { @@ -1937,6 +1951,10 @@ turn_on_face (struct frame *f, int face_id) if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (tty, NC_UNDERLINE)) OUTPUT1_IF (tty, tty->TS_enter_underline_mode); + if (face->tty_strike_through_p + && MAY_USE_WITH_COLORS_P (tty, NC_STRIKE_THROUGH)) + OUTPUT1_IF (tty, tty->TS_enter_strike_through_mode); + if (tty->TN_max_colors > 0) { const char *ts; @@ -1977,7 +1995,8 @@ turn_off_face (struct frame *f, int face_id) if (face->tty_bold_p || face->tty_italic_p || face->tty_reverse_p - || face->tty_underline_p) + || face->tty_underline_p + || face->tty_strike_through_p) { OUTPUT1_IF (tty, tty->TS_exit_attribute_mode); if (strcmp (tty->TS_exit_attribute_mode, tty->TS_end_standout_mode) == 0) @@ -2012,11 +2031,20 @@ tty_capable_p (struct tty_display_info *tty, unsigned int caps) 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_ITALIC, tty->TS_enter_italic_mode, NC_ITALIC); + 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_ITALIC, tty->TS_enter_italic_mode, NC_ITALIC); + TTY_CAPABLE_P_TRY (tty, + TTY_CAP_STRIKE_THROUGH, tty->TS_enter_strike_through_mode, + NC_STRIKE_THROUGH); /* We can do it! */ return 1; @@ -2050,14 +2078,14 @@ TERMINAL does not refer to a text terminal. */) { struct terminal *t = decode_tty_terminal (terminal); - return make_number (t ? t->display_info.tty->TN_max_colors : 0); + return make_fixnum (t ? t->display_info.tty->TN_max_colors : 0); } #ifndef DOS_NT /* Declare here rather than in the function, as in the rest of Emacs, to work around an HPUX compiler bug (?). See - https://lists.gnu.org/archive/html/emacs-devel/2007-08/msg00410.html */ + https://lists.gnu.org/r/emacs-devel/2007-08/msg00410.html */ static int default_max_colors; static int default_no_color_video; static char *default_orig_pair; @@ -2137,7 +2165,7 @@ set_tty_color_mode (struct tty_display_info *tty, struct frame *f) tem = assq_no_quit (Qtty_color_mode, f->param_alist); val = CONSP (tem) ? XCDR (tem) : Qnil; - if (INTEGERP (val)) + if (FIXNUMP (val)) color_mode = val; else if (SYMBOLP (tty_color_mode_alist)) { @@ -2147,7 +2175,7 @@ set_tty_color_mode (struct tty_display_info *tty, struct frame *f) else color_mode = Qnil; - mode = TYPE_RANGED_INTEGERP (int, color_mode) ? XINT (color_mode) : 0; + mode = TYPE_RANGED_FIXNUMP (int, color_mode) ? XFIXNUM (color_mode) : 0; if (mode != tty->previous_color_mode) { @@ -2160,6 +2188,14 @@ set_tty_color_mode (struct tty_display_info *tty, struct frame *f) #endif /* !DOS_NT */ +char * +tty_type_name (Lisp_Object terminal) +{ + struct terminal *t = decode_tty_terminal (terminal); + + return t? t->display_info.tty->type: NULL; +} + DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0, doc: /* Return the type of the tty device that TERMINAL uses. Returns nil if TERMINAL is not on a tty device. @@ -2168,10 +2204,9 @@ TERMINAL can be a terminal object, a frame, or nil (meaning the selected frame's terminal). */) (Lisp_Object terminal) { - struct terminal *t = decode_tty_terminal (terminal); + char *name = tty_type_name (terminal); - return (t && t->display_info.tty->type - ? build_string (t->display_info.tty->type) : Qnil); + return (name? build_string (name) : Qnil); } DEFUN ("controlling-tty-p", Fcontrolling_tty_p, Scontrolling_tty_p, 0, 1, 0, @@ -2264,9 +2299,9 @@ A suspended tty may be resumed by calling `resume-tty' on it. */) delete_keyboard_wait_descriptor (fileno (f)); #ifndef MSDOS - fclose (f); if (f != t->display_info.tty->output) fclose (t->display_info.tty->output); + fclose (f); #endif t->display_info.tty->input = 0; @@ -2347,8 +2382,7 @@ frame's terminal). */) was suspended. */ get_tty_size (fileno (t->display_info.tty->input), &width, &height); if (width != old_width || height != old_height) - change_frame_size (f, width, height - FRAME_MENU_BAR_LINES (f), - 0, 0, 0, 0); + change_frame_size (f, width, height, false, false, false); SET_FRAME_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1); } @@ -2366,30 +2400,52 @@ frame's terminal). */) return Qnil; } +DEFUN ("tty--set-output-buffer-size", Ftty__set_output_buffer_size, + Stty__set_output_buffer_size, 1, 2, 0, doc: + /* Set the output buffer size for a TTY. + +SIZE zero means use the system's default value. If SIZE is +non-zero, this also avoids flushing the output stream. + +TTY may be a terminal object, a frame, or nil (meaning the selected +frame's terminal). + +This function temporarily suspends and resumes the terminal +device. */) + (Lisp_Object size, Lisp_Object tty) +{ + if (!TYPE_RANGED_FIXNUMP (size_t, size)) + error ("Invalid output buffer size"); + Fsuspend_tty (tty); + struct terminal *terminal = decode_tty_terminal (tty); + terminal->display_info.tty->output_buffer_size = XFIXNUM (size); + return Fresume_tty (tty); +} + +DEFUN ("tty--output-buffer-size", Ftty__output_buffer_size, + Stty__output_buffer_size, 0, 1, 0, doc: + /* Return the output buffer size of TTY. + +TTY may be a terminal object, a frame, or nil (meaning the selected +frame's terminal). + +A value of zero means TTY uses the system's default value. */) + (Lisp_Object tty) +{ + struct terminal *terminal = decode_tty_terminal (tty); + if (terminal) + return make_fixnum (terminal->display_info.tty->output_buffer_size); + error ("Not a tty terminal"); +} + /*********************************************************************** Mouse ***********************************************************************/ -#ifdef HAVE_GPM - -#ifndef HAVE_WINDOW_SYSTEM -void -term_mouse_moveto (int x, int y) -{ - /* TODO: how to set mouse position? - const char *name; - int fd; - name = (const char *) ttyname (0); - fd = emacs_open (name, O_WRONLY, 0); - SOME_FUNCTION (x, y, fd); - emacs_close (fd); - last_mouse_x = x; - last_mouse_y = y; */ -} -#endif /* HAVE_WINDOW_SYSTEM */ +#ifndef DOS_NT -/* Implementation of draw_row_with_mouse_face for TTY/GPM. */ +/* Implementation of draw_row_with_mouse_face for TTY/GPM and macOS. */ void tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *row, int start_hpos, int end_hpos, @@ -2407,7 +2463,7 @@ tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *row, pos_y = row->y + WINDOW_TOP_EDGE_Y (w); pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos + WINDOW_LEFT_EDGE_X (w); - /* Save current cursor co-ordinates. */ + /* Save current cursor coordinates. */ save_y = curY (tty); save_x = curX (tty); cursor_to (f, pos_y, pos_x); @@ -2421,31 +2477,32 @@ tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *row, cursor_to (f, save_y, save_x); } -static bool -term_mouse_movement (struct frame *frame, Gpm_Event *event) +#endif + +#ifdef HAVE_GPM + +void +term_mouse_moveto (int x, int y) { - /* Has the mouse moved off the glyph it was on at the last sighting? */ - if (event->x != last_mouse_x || event->y != last_mouse_y) - { - frame->mouse_moved = 1; - note_mouse_highlight (frame, event->x, event->y); - /* Remember which glyph we're now on. */ - last_mouse_x = event->x; - last_mouse_y = event->y; - return 1; - } - return 0; + /* TODO: how to set mouse position? + const char *name; + int fd; + name = (const char *) ttyname (0); + fd = emacs_open (name, O_WRONLY, 0); + SOME_FUNCTION (x, y, fd); + emacs_close (fd); + last_mouse_x = x; + last_mouse_y = y; */ } -/* Return the Time that corresponds to T. Wrap around on overflow. */ +/* Return the current time, as a Time value. Wrap around on overflow. */ static Time -timeval_to_Time (struct timeval const *t) +current_Time (void) { - Time s_1000, ms; - - s_1000 = t->tv_sec; + struct timespec now = current_timespec (); + Time s_1000 = now.tv_sec; s_1000 *= 1000; - ms = t->tv_usec / 1000; + Time ms = now.tv_nsec / 1000000; return s_1000 + ms; } @@ -2467,8 +2524,6 @@ term_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y, Time *timeptr) { - struct timeval now; - *fp = SELECTED_FRAME (); (*fp)->mouse_moved = 0; @@ -2477,8 +2532,7 @@ term_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, XSETINT (*x, last_mouse_x); XSETINT (*y, last_mouse_y); - gettimeofday(&now, 0); - *timeptr = timeval_to_Time (&now); + *timeptr = current_Time (); } /* Prepare a mouse-event in *RESULT for placement in the input queue. @@ -2490,10 +2544,9 @@ static Lisp_Object term_mouse_click (struct input_event *result, Gpm_Event *event, struct frame *f) { - struct timeval now; int i, j; - result->kind = GPM_CLICK_EVENT; + result->kind = MOUSE_CLICK_EVENT; for (i = 0, j = GPM_B_LEFT; i < 3; i++, j >>= 1 ) { if (event->buttons & j) { @@ -2501,8 +2554,7 @@ term_mouse_click (struct input_event *result, Gpm_Event *event, break; } } - gettimeofday(&now, 0); - result->timestamp = timeval_to_Time (&now); + result->timestamp = current_Time (); if (event->type & GPM_UP) result->modifiers = up_modifier; @@ -2547,59 +2599,42 @@ term_mouse_click (struct input_event *result, Gpm_Event *event, } int -handle_one_term_event (struct tty_display_info *tty, Gpm_Event *event, - struct input_event *hold_quit) +handle_one_term_event (struct tty_display_info *tty, Gpm_Event *event) { struct frame *f = XFRAME (tty->top_frame); struct input_event ie; - bool do_help = 0; int count = 0; EVENT_INIT (ie); ie.kind = NO_EVENT; ie.arg = Qnil; - if (event->type & (GPM_MOVE | GPM_DRAG)) { - previous_help_echo_string = help_echo_string; - help_echo_string = Qnil; - - Gpm_DrawPointer (event->x, event->y, fileno (tty->output)); - - if (!term_mouse_movement (f, event)) - help_echo_string = previous_help_echo_string; - - /* If the contents of the global variable help_echo_string - has changed, generate a HELP_EVENT. */ - if (!NILP (help_echo_string) - || !NILP (previous_help_echo_string)) - do_help = 1; - - goto done; - } - else { - f->mouse_moved = 0; - term_mouse_click (&ie, event, f); - } - - done: - if (ie.kind != NO_EVENT) + if (event->type & (GPM_MOVE | GPM_DRAG)) { - kbd_buffer_store_event_hold (&ie, hold_quit); - count++; - } + Gpm_DrawPointer (event->x, event->y, fileno (tty->output)); - if (do_help - && !(hold_quit && hold_quit->kind != NO_EVENT)) + /* Has the mouse moved off the glyph it was on at the last + sighting? */ + if (event->x != last_mouse_x || event->y != last_mouse_y) + { + /* FIXME: These three lines can not be moved into + update_mouse_position unless xterm-mouse gets updated to + generate mouse events via C code. See + https://lists.gnu.org/archive/html/emacs-devel/2020-11/msg00163.html */ + last_mouse_x = event->x; + last_mouse_y = event->y; + f->mouse_moved = 1; + + count += update_mouse_position (f, event->x, event->y); + } + } + else { - Lisp_Object frame; - - if (f) - XSETFRAME (frame, f); - else - frame = Qnil; - - gen_help_event (help_echo_string, frame, help_echo_window, - help_echo_object, help_echo_pos); + f->mouse_moved = 0; + term_mouse_click (&ie, event, f); + ie.arg = tty_handle_tab_bar_click (f, event->x, event->y, + (ie.modifiers & down_modifier) != 0, &ie); + kbd_buffer_store_event (&ie); count++; } @@ -2721,7 +2756,7 @@ typedef struct tty_menu_struct /* Create a brand new menu structure. */ -static tty_menu * +static tty_menu * ATTRIBUTE_MALLOC tty_menu_create (void) { return xzalloc (sizeof *tty_menu_create ()); @@ -2793,20 +2828,19 @@ tty_menu_calc_size (tty_menu *menu, int *width, int *height) static void mouse_get_xy (int *x, int *y) { - struct frame *sf = SELECTED_FRAME (); - Lisp_Object lmx = Qnil, lmy = Qnil, lisp_dummy; - enum scroll_bar_part part_dummy; - Time time_dummy; - - if (FRAME_TERMINAL (sf)->mouse_position_hook) - (*FRAME_TERMINAL (sf)->mouse_position_hook) (&sf, -1, - &lisp_dummy, &part_dummy, - &lmx, &lmy, - &time_dummy); + Lisp_Object lmx = Qnil, lmy = Qnil; + Lisp_Object mouse = mouse_position (tty_menu_calls_mouse_position_function); + + if (EQ (selected_frame, XCAR (mouse))) + { + lmx = XCAR (XCDR (mouse)); + lmy = XCDR (XCDR (mouse)); + } + if (!NILP (lmx)) { - *x = XINT (lmx); - *y = XINT (lmy); + *x = XFIXNUM (lmx); + *y = XFIXNUM (lmy); } } @@ -3044,18 +3078,18 @@ read_menu_input (struct frame *sf, int *x, int *y, int min_y, int max_y, bool usable_input = 1; mi_result st = MI_CONTINUE; struct tty_display_info *tty = FRAME_TTY (sf); - Lisp_Object saved_mouse_tracking = do_mouse_tracking; + Lisp_Object old_track_mouse = track_mouse; /* Signal the keyboard reading routines we are displaying a menu on this terminal. */ tty->showing_menu = 1; /* We want mouse movements be reported by read_menu_command. */ - do_mouse_tracking = Qt; + track_mouse = Qt; do { cmd = read_menu_command (); } while (NILP (cmd)); tty->showing_menu = 0; - do_mouse_tracking = saved_mouse_tracking; + track_mouse = old_track_mouse; if (EQ (cmd, Qt) || EQ (cmd, Qtty_menu_exit) /* If some input switched frames under our feet, exit the @@ -3132,15 +3166,15 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx, SAFE_NALLOCA (state, 1, menu->panecount); memset (state, 0, sizeof (*state)); faces[0] - = lookup_derived_face (sf, intern ("tty-menu-disabled-face"), + = lookup_derived_face (NULL, sf, intern ("tty-menu-disabled-face"), DEFAULT_FACE_ID, 1); faces[1] - = lookup_derived_face (sf, intern ("tty-menu-enabled-face"), + = lookup_derived_face (NULL, sf, intern ("tty-menu-enabled-face"), DEFAULT_FACE_ID, 1); selectface = intern ("tty-menu-selected-face"); - faces[2] = lookup_derived_face (sf, selectface, + faces[2] = lookup_derived_face (NULL, sf, selectface, faces[0], 1); - faces[3] = lookup_derived_face (sf, selectface, + faces[3] = lookup_derived_face (NULL, sf, selectface, faces[1], 1); /* Make sure the menu title is always displayed with @@ -3338,7 +3372,7 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx, which calls tty_show_cursor. Re-hide it, so it doesn't show through the menus. */ tty_hide_cursor (tty); - fflush_unlocked (tty->output); + fflush (tty->output); } sf->mouse_moved = 0; @@ -3346,7 +3380,7 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx, while (statecount--) free_saved_screen (state[statecount].screen_behind); tty_show_cursor (tty); /* Turn cursor back on. */ - fflush_unlocked (tty->output); + fflush (tty->output); /* Clean up any mouse events that are waiting inside Emacs event queue. These events are likely to be generated before the menu was even @@ -3403,20 +3437,25 @@ tty_menu_help_callback (char const *help_string, int pane, int item) pane_name = first_item[MENU_ITEMS_ITEM_NAME]; /* (menu-item MENU-NAME PANE-NUMBER) */ - menu_object = list3 (Qmenu_item, pane_name, make_number (pane)); + menu_object = list3 (Qmenu_item, pane_name, make_fixnum (pane)); show_help_echo (help_string ? build_string (help_string) : Qnil, - Qnil, menu_object, make_number (item)); + Qnil, menu_object, make_fixnum (item)); } +struct tty_pop_down_menu +{ + tty_menu *menu; + struct buffer *buffer; +}; + static void -tty_pop_down_menu (Lisp_Object arg) +tty_pop_down_menu (void *arg) { - tty_menu *menu = XSAVE_POINTER (arg, 0); - struct buffer *orig_buffer = XSAVE_POINTER (arg, 1); + struct tty_pop_down_menu *data = arg; block_input (); - tty_menu_destroy (menu); - set_buffer_internal (orig_buffer); + tty_menu_destroy (data->menu); + set_buffer_internal (data->buffer); unblock_input (); } @@ -3472,7 +3511,7 @@ tty_menu_new_item_coords (struct frame *f, int which, int *x, int *y) pos = AREF (items, i + 3); if (NILP (str)) return; - ix = XINT (pos); + ix = XFIXNUM (pos); if (ix <= *x /* We use <= so the blank between 2 items on a TTY is considered part of the previous item. */ @@ -3483,14 +3522,14 @@ tty_menu_new_item_coords (struct frame *f, int which, int *x, int *y) if (which == TTYM_NEXT) { if (i < last_i) - *x = XINT (AREF (items, i + 4 + 3)); + *x = XFIXNUM (AREF (items, i + 4 + 3)); else *x = 0; /* Wrap around to the first item. */ } else if (prev_x < 0) { /* Wrap around to the last item. */ - *x = XINT (AREF (items, last_i + 3)); + *x = XFIXNUM (AREF (items, last_i + 3)); } else *x = prev_x; @@ -3515,7 +3554,7 @@ tty_menu_show (struct frame *f, int x, int y, int menuflags, int dispwidth, dispheight; int i, j, lines, maxlines; int maxwidth; - ptrdiff_t specpdl_count; + specpdl_ref specpdl_count; eassert (FRAME_TERMCAP_P (f)); @@ -3697,8 +3736,9 @@ tty_menu_show (struct frame *f, int x, int y, int menuflags, /* We save and restore the current buffer because tty_menu_activate triggers redisplay, which switches buffers at will. */ - record_unwind_protect (tty_pop_down_menu, - make_save_ptr_ptr (menu, current_buffer)); + record_unwind_protect_ptr (tty_pop_down_menu, + &((struct tty_pop_down_menu) + {menu, current_buffer})); specbind (Qoverriding_terminal_local_map, Fsymbol_value (Qtty_menu_navigation_map)); @@ -3748,7 +3788,7 @@ tty_menu_show (struct frame *f, int x, int y, int menuflags, case TTYM_NEXT: case TTYM_PREV: tty_menu_new_item_coords (f, status, &item_x, &item_y); - entry = Fcons (make_number (item_x), make_number (item_y)); + entry = Fcons (make_fixnum (item_x), make_fixnum (item_y)); break; case TTYM_FAILURE: @@ -3770,9 +3810,7 @@ tty_menu_show (struct frame *f, int x, int y, int menuflags, tty_menu_end: - SAFE_FREE (); - unbind_to (specpdl_count, Qnil); - return entry; + return SAFE_FREE_UNBIND_TO (specpdl_count, entry); } #endif /* !MSDOS */ @@ -3841,6 +3879,9 @@ clear_tty_hooks (struct terminal *terminal) terminal->update_begin_hook = 0; terminal->update_end_hook = 0; terminal->set_terminal_window_hook = 0; + /* Don't clear the defined_color_hook, as that makes it impossible + to unload or load a theme when some TTY frame is suspended. */ + /* terminal->defined_color_hook = 0; */ terminal->mouse_position_hook = 0; terminal->frame_rehighlight_hook = 0; terminal->frame_raise_lower_hook = 0; @@ -3884,6 +3925,7 @@ set_tty_hooks (struct terminal *terminal) terminal->menu_show_hook = &tty_menu_show; #endif terminal->set_terminal_window_hook = &tty_set_terminal_window; + terminal->defined_color_hook = &tty_defined_color; /* xfaces.c */ terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */ terminal->delete_frame_hook = &tty_free_frame_resources; terminal->delete_terminal_hook = &delete_tty; @@ -4004,6 +4046,7 @@ init_tty (const char *name, const char *terminal_type, bool must_succeed) char const *diagnostic = (fd < 0) ? "Could not open file: %s" : "Not a tty device: %s"; emacs_close (fd); + delete_terminal_internal (terminal); maybe_fatal (must_succeed, terminal, diagnostic, diagnostic, name); } @@ -4120,6 +4163,7 @@ use the Bourne shell command 'TERM=...; export TERM' (C-shell:\n\ 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); + tty->TS_enter_strike_through_mode = tgetstr ("smxx", address); MultiUp (tty) = tgetstr ("UP", address); MultiDown (tty) = tgetstr ("DO", address); @@ -4144,10 +4188,10 @@ use the Bourne shell command 'TERM=...; export TERM' (C-shell:\n\ tty->TN_max_colors = tgetnum ("Co"); #ifdef TERMINFO - /* Non-standard support for 24-bit colors. */ { const char *fg = tigetstr ("setf24"); const char *bg = tigetstr ("setb24"); + /* Non-standard support for 24-bit colors. */ if (fg && bg && fg != (char *) (intptr_t) -1 && bg != (char *) (intptr_t) -1) @@ -4156,6 +4200,25 @@ use the Bourne shell command 'TERM=...; export TERM' (C-shell:\n\ tty->TS_set_background = bg; tty->TN_max_colors = 16777216; } + /* Standard support for 24-bit colors. */ + else if (tigetflag ("RGB") > 0) + { + /* If the used Terminfo library supports only 16-bit + signed values, tgetnum("Co") and tigetnum("colors") + could return 32767. */ + tty->TN_max_colors = 16777216; + } + /* Fall back to xterm+direct (semicolon version) if Tc is set + (de-facto standard introduced by tmux) or if requested by + the COLORTERM environment variable. */ + else if ((tigetflag ("Tc") > 0) + || ((bg = getenv ("COLORTERM")) != NULL + && strcasecmp (bg, "truecolor") == 0)) + { + tty->TS_set_foreground = "\033[%?%p1%{8}%<%t3%p1%d%e38;2;%p1%{65536}%/%d;%p1%{256}%/%{255}%&%d;%p1%{255}%&%d%;m"; + tty->TS_set_background = "\033[%?%p1%{8}%<%t4%p1%d%e48;2;%p1%{65536}%/%d;%p1%{256}%/%{255}%&%d;%p1%{255}%&%d%;m"; + tty->TN_max_colors = 16777216; + } } #endif @@ -4237,8 +4300,8 @@ use the Bourne shell command 'TERM=...; export TERM' (C-shell:\n\ #ifdef HAVE_GPM terminal->mouse_position_hook = term_mouse_position; - tty->mouse_highlight.mouse_face_window = Qnil; #endif + tty->mouse_highlight.mouse_face_window = Qnil; terminal->kboard = allocate_kboard (Qnil); terminal->kboard->reference_count++; @@ -4390,11 +4453,10 @@ use the Bourne shell command 'TERM=...; export TERM' (C-shell:\n\ static void vfatal (const char *str, va_list ap) { - fprintf (stderr, "emacs: "); + fputs ("emacs: ", stderr); vfprintf (stderr, str, ap); - if (!(strlen (str) > 0 && str[strlen (str) - 1] == '\n')) - fprintf (stderr, "\n"); - fflush (stderr); + if (! (str[0] && str[strlen (str) - 1] == '\n')) + putc ('\n', stderr); exit (1); } @@ -4517,6 +4579,13 @@ What means \"very visible\" is up to your terminal. It may make the cursor bigger, or it may make it blink, or it may do nothing at all. */); visible_cursor = 1; + DEFVAR_BOOL ("tty-menu-calls-mouse-position-function", + tty_menu_calls_mouse_position_function, + doc: /* Non-nil means TTY menu code will call `mouse-position-function'. +This should be set if the function in `mouse-position-function' does not +trigger redisplay. */); + tty_menu_calls_mouse_position_function = 0; + defsubr (&Stty_display_color_p); defsubr (&Stty_display_color_cells); defsubr (&Stty_no_underline); @@ -4525,6 +4594,8 @@ bigger, or it may make it blink, or it may do nothing at all. */); defsubr (&Stty_top_frame); defsubr (&Ssuspend_tty); defsubr (&Sresume_tty); + defsubr (&Stty__set_output_buffer_size); + defsubr (&Stty__output_buffer_size); #ifdef HAVE_GPM defsubr (&Sgpm_mouse_start); defsubr (&Sgpm_mouse_stop); |