1 /* Terminal control module for terminals described by TERMCAP
2 Copyright (C) 1985-1987, 1993-1995, 1998, 2000-2014 Free Software
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20 /* New redisplay, TTY faces by Gerd Moellmann <gerd@gnu.org>. */
33 #include "character.h"
37 #include "composite.h"
41 #include "termhooks.h"
42 #include "dispextern.h"
45 #include "blockinput.h"
46 #include "syssignal.h"
48 #include "intervals.h"
51 static int been_here
= -1;
55 #include "../lwlib/lwlib.h"
65 /* The name of the default console device. */
67 #define DEV_TTY "CONOUT$"
70 #define DEV_TTY "/dev/tty"
73 static void tty_set_scroll_region (struct frame
*f
, int start
, int stop
);
74 static void turn_on_face (struct frame
*, int face_id
);
75 static void turn_off_face (struct frame
*, int face_id
);
76 static void tty_turn_off_highlight (struct tty_display_info
*);
77 static void tty_show_cursor (struct tty_display_info
*);
78 static void tty_hide_cursor (struct tty_display_info
*);
79 static void tty_background_highlight (struct tty_display_info
*tty
);
80 static struct terminal
*get_tty_terminal (Lisp_Object
, bool);
81 static void clear_tty_hooks (struct terminal
*terminal
);
82 static void set_tty_hooks (struct terminal
*terminal
);
83 static void dissociate_if_controlling_tty (int fd
);
84 static void delete_tty (struct terminal
*);
85 static _Noreturn
void maybe_fatal (bool, struct terminal
*,
86 const char *, const char *, ...)
87 ATTRIBUTE_FORMAT_PRINTF (3, 5) ATTRIBUTE_FORMAT_PRINTF (4, 5);
88 static _Noreturn
void vfatal (const char *str
, va_list ap
)
89 ATTRIBUTE_FORMAT_PRINTF (1, 0);
92 #define OUTPUT(tty, a) \
93 emacs_tputs ((tty), a, \
94 FRAME_TOTAL_LINES (XFRAME (selected_frame)) - curY (tty), \
97 #define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
98 #define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
100 #define OUTPUT_IF(tty, a) \
106 #define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
108 /* Display space properties. */
110 /* Chain of all tty device parameters. */
111 struct tty_display_info
*tty_list
;
113 /* Meaning of bits in no_color_video. Each bit set means that the
114 corresponding attribute cannot be combined with colors. */
118 NC_STANDOUT
= 1 << 0,
119 NC_UNDERLINE
= 1 << 1,
130 /* The largest frame width in any call to calculate_costs. */
132 static int max_frame_cols
;
134 static Lisp_Object Qtty_mode_set_strings
;
135 static Lisp_Object Qtty_mode_reset_strings
;
140 #include <sys/fcntl.h>
142 /* The device for which we have enabled gpm support (or NULL). */
143 struct tty_display_info
*gpm_tty
= NULL
;
145 /* Last recorded mouse coordinates. */
146 static int last_mouse_x
, last_mouse_y
;
147 #endif /* HAVE_GPM */
149 /* Ring the bell on a tty. */
152 tty_ring_bell (struct frame
*f
)
154 struct tty_display_info
*tty
= FRAME_TTY (f
);
158 OUTPUT (tty
, (tty
->TS_visible_bell
&& visible_bell
159 ? tty
->TS_visible_bell
161 fflush (tty
->output
);
165 /* Set up termcap modes for Emacs. */
168 tty_send_additional_strings (struct terminal
*terminal
, Lisp_Object sym
)
170 Lisp_Object lisp_terminal
;
171 Lisp_Object extra_codes
;
172 struct tty_display_info
*tty
= terminal
->display_info
.tty
;
174 XSETTERMINAL (lisp_terminal
, terminal
);
175 for (extra_codes
= Fterminal_parameter (lisp_terminal
, sym
);
177 extra_codes
= XCDR (extra_codes
))
179 Lisp_Object string
= XCAR (extra_codes
);
180 if (STRINGP (string
))
182 fwrite (SDATA (string
), 1, SBYTES (string
), tty
->output
);
184 fwrite (SDATA (string
), 1, SBYTES (string
), tty
->termscript
);
190 tty_set_terminal_modes (struct terminal
*terminal
)
192 struct tty_display_info
*tty
= terminal
->display_info
.tty
;
196 if (tty
->TS_termcap_modes
)
197 OUTPUT (tty
, tty
->TS_termcap_modes
);
200 /* Output enough newlines to scroll all the old screen contents
201 off the screen, so it won't be overwritten and lost. */
204 for (i
= 0; i
< FRAME_TOTAL_LINES (XFRAME (selected_frame
)); i
++)
208 OUTPUT_IF (tty
, visible_cursor
? tty
->TS_cursor_visible
: tty
->TS_cursor_normal
);
209 OUTPUT_IF (tty
, tty
->TS_keypad_mode
);
211 tty_send_additional_strings (terminal
, Qtty_mode_set_strings
);
212 fflush (tty
->output
);
216 /* Reset termcap modes before exiting Emacs. */
219 tty_reset_terminal_modes (struct terminal
*terminal
)
221 struct tty_display_info
*tty
= terminal
->display_info
.tty
;
225 tty_send_additional_strings (terminal
, Qtty_mode_reset_strings
);
226 tty_turn_off_highlight (tty
);
227 tty_turn_off_insert (tty
);
228 OUTPUT_IF (tty
, tty
->TS_end_keypad_mode
);
229 OUTPUT_IF (tty
, tty
->TS_cursor_normal
);
230 OUTPUT_IF (tty
, tty
->TS_end_termcap_modes
);
231 OUTPUT_IF (tty
, tty
->TS_orig_pair
);
232 /* Output raw CR so kernel can track the cursor hpos. */
235 fflush (tty
->output
);
239 /* Flag the end of a display update on a termcap terminal. */
242 tty_update_end (struct frame
*f
)
244 struct tty_display_info
*tty
= FRAME_TTY (f
);
246 if (!XWINDOW (selected_window
)->cursor_off_p
)
247 tty_show_cursor (tty
);
248 tty_turn_off_insert (tty
);
249 tty_background_highlight (tty
);
250 fflush (tty
->output
);
253 /* The implementation of set_terminal_window for termcap frames. */
256 tty_set_terminal_window (struct frame
*f
, int size
)
258 struct tty_display_info
*tty
= FRAME_TTY (f
);
260 tty
->specified_window
= size
? size
: FRAME_TOTAL_LINES (f
);
261 if (FRAME_SCROLL_REGION_OK (f
))
262 tty_set_scroll_region (f
, 0, tty
->specified_window
);
266 tty_set_scroll_region (struct frame
*f
, int start
, int stop
)
269 struct tty_display_info
*tty
= FRAME_TTY (f
);
271 if (tty
->TS_set_scroll_region
)
272 buf
= tparam (tty
->TS_set_scroll_region
, 0, 0, start
, stop
- 1, 0, 0);
273 else if (tty
->TS_set_scroll_region_1
)
274 buf
= tparam (tty
->TS_set_scroll_region_1
, 0, 0,
275 FRAME_TOTAL_LINES (f
), start
,
276 FRAME_TOTAL_LINES (f
) - stop
,
277 FRAME_TOTAL_LINES (f
));
279 buf
= tparam (tty
->TS_set_window
, 0, 0, start
, 0, stop
, FRAME_COLS (f
));
288 tty_turn_on_insert (struct tty_display_info
*tty
)
290 if (!tty
->insert_mode
)
291 OUTPUT (tty
, tty
->TS_insert_mode
);
292 tty
->insert_mode
= 1;
296 tty_turn_off_insert (struct tty_display_info
*tty
)
298 if (tty
->insert_mode
)
299 OUTPUT (tty
, tty
->TS_end_insert_mode
);
300 tty
->insert_mode
= 0;
303 /* Handle highlighting. */
306 tty_turn_off_highlight (struct tty_display_info
*tty
)
308 if (tty
->standout_mode
)
309 OUTPUT_IF (tty
, tty
->TS_end_standout_mode
);
310 tty
->standout_mode
= 0;
314 tty_turn_on_highlight (struct tty_display_info
*tty
)
316 if (!tty
->standout_mode
)
317 OUTPUT_IF (tty
, tty
->TS_standout_mode
);
318 tty
->standout_mode
= 1;
322 tty_toggle_highlight (struct tty_display_info
*tty
)
324 if (tty
->standout_mode
)
325 tty_turn_off_highlight (tty
);
327 tty_turn_on_highlight (tty
);
331 /* Make cursor invisible. */
334 tty_hide_cursor (struct tty_display_info
*tty
)
336 if (tty
->cursor_hidden
== 0)
338 tty
->cursor_hidden
= 1;
340 w32con_hide_cursor ();
342 OUTPUT_IF (tty
, tty
->TS_cursor_invisible
);
348 /* Ensure that cursor is visible. */
351 tty_show_cursor (struct tty_display_info
*tty
)
353 if (tty
->cursor_hidden
)
355 tty
->cursor_hidden
= 0;
357 w32con_show_cursor ();
359 OUTPUT_IF (tty
, tty
->TS_cursor_normal
);
361 OUTPUT_IF (tty
, tty
->TS_cursor_visible
);
367 /* Set standout mode to the state it should be in for
368 empty space inside windows. What this is,
369 depends on the user option inverse-video. */
372 tty_background_highlight (struct tty_display_info
*tty
)
375 tty_turn_on_highlight (tty
);
377 tty_turn_off_highlight (tty
);
380 /* Set standout mode to the mode specified for the text to be output. */
383 tty_highlight_if_desired (struct tty_display_info
*tty
)
386 tty_turn_on_highlight (tty
);
388 tty_turn_off_highlight (tty
);
392 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
393 frame-relative coordinates. */
396 tty_cursor_to (struct frame
*f
, int vpos
, int hpos
)
398 struct tty_display_info
*tty
= FRAME_TTY (f
);
400 /* Detect the case where we are called from reset_sys_modes
401 and the costs have never been calculated. Do nothing. */
402 if (! tty
->costs_set
)
405 if (curY (tty
) == vpos
406 && curX (tty
) == hpos
)
408 if (!tty
->TF_standout_motion
)
409 tty_background_highlight (tty
);
410 if (!tty
->TF_insmode_motion
)
411 tty_turn_off_insert (tty
);
412 cmgoto (tty
, vpos
, hpos
);
415 /* Similar but don't take any account of the wasted characters. */
418 tty_raw_cursor_to (struct frame
*f
, int row
, int col
)
420 struct tty_display_info
*tty
= FRAME_TTY (f
);
422 if (curY (tty
) == row
423 && curX (tty
) == col
)
425 if (!tty
->TF_standout_motion
)
426 tty_background_highlight (tty
);
427 if (!tty
->TF_insmode_motion
)
428 tty_turn_off_insert (tty
);
429 cmgoto (tty
, row
, col
);
432 /* Erase operations */
434 /* Clear from cursor to end of frame on a termcap device. */
437 tty_clear_to_end (struct frame
*f
)
440 struct tty_display_info
*tty
= FRAME_TTY (f
);
442 if (tty
->TS_clr_to_bottom
)
444 tty_background_highlight (tty
);
445 OUTPUT (tty
, tty
->TS_clr_to_bottom
);
449 for (i
= curY (tty
); i
< FRAME_TOTAL_LINES (f
); i
++)
452 clear_end_of_line (f
, FRAME_COLS (f
));
457 /* Clear an entire termcap frame. */
460 tty_clear_frame (struct frame
*f
)
462 struct tty_display_info
*tty
= FRAME_TTY (f
);
464 if (tty
->TS_clr_frame
)
466 tty_background_highlight (tty
);
467 OUTPUT (tty
, tty
->TS_clr_frame
);
477 /* An implementation of clear_end_of_line for termcap frames.
479 Note that the cursor may be moved, on terminals lacking a `ce' string. */
482 tty_clear_end_of_line (struct frame
*f
, int first_unused_hpos
)
485 struct tty_display_info
*tty
= FRAME_TTY (f
);
487 /* Detect the case where we are called from reset_sys_modes
488 and the costs have never been calculated. Do nothing. */
489 if (! tty
->costs_set
)
492 if (curX (tty
) >= first_unused_hpos
)
494 tty_background_highlight (tty
);
495 if (tty
->TS_clr_line
)
497 OUTPUT1 (tty
, tty
->TS_clr_line
);
500 { /* have to do it the hard way */
501 tty_turn_off_insert (tty
);
503 /* Do not write in last row last col with Auto-wrap on. */
505 && curY (tty
) == FrameRows (tty
) - 1
506 && first_unused_hpos
== FrameCols (tty
))
509 for (i
= curX (tty
); i
< first_unused_hpos
; i
++)
512 fputc (' ', tty
->termscript
);
513 fputc (' ', tty
->output
);
515 cmplus (tty
, first_unused_hpos
- curX (tty
));
519 /* Buffers to store the source and result of code conversion for terminal. */
520 static unsigned char *encode_terminal_src
;
521 static unsigned char *encode_terminal_dst
;
522 /* Allocated sizes of the above buffers. */
523 static ptrdiff_t encode_terminal_src_size
;
524 static ptrdiff_t encode_terminal_dst_size
;
526 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes.
527 Set CODING->produced to the byte-length of the resulting byte
528 sequence, and return a pointer to that byte sequence. */
531 encode_terminal_code (struct glyph
*src
, int src_len
,
532 struct coding_system
*coding
)
534 struct glyph
*src_end
= src
+ src_len
;
536 ptrdiff_t nchars
, nbytes
, required
;
537 ptrdiff_t tlen
= GLYPH_TABLE_LENGTH
;
538 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
539 Lisp_Object charset_list
;
541 /* Allocate sufficient size of buffer to store all characters in
542 multibyte-form. But, it may be enlarged on demand if
543 Vglyph_table contains a string or a composite glyph is
545 if (min (PTRDIFF_MAX
, SIZE_MAX
) / MAX_MULTIBYTE_LENGTH
< src_len
)
546 memory_full (SIZE_MAX
);
548 required
*= MAX_MULTIBYTE_LENGTH
;
549 if (encode_terminal_src_size
< required
)
551 encode_terminal_src
= xrealloc (encode_terminal_src
, required
);
552 encode_terminal_src_size
= required
;
555 charset_list
= coding_charset_list (coding
);
557 buf
= encode_terminal_src
;
559 while (src
< src_end
)
561 if (src
->type
== COMPOSITE_GLYPH
)
563 struct composition
*cmp
IF_LINT (= NULL
);
564 Lisp_Object gstring
IF_LINT (= Qnil
);
567 nbytes
= buf
- encode_terminal_src
;
568 if (src
->u
.cmp
.automatic
)
570 gstring
= composition_gstring_from_id (src
->u
.cmp
.id
);
571 required
= src
->slice
.cmp
.to
- src
->slice
.cmp
.from
+ 1;
575 cmp
= composition_table
[src
->u
.cmp
.id
];
576 required
= cmp
->glyph_len
;
577 required
*= MAX_MULTIBYTE_LENGTH
;
580 if (encode_terminal_src_size
- nbytes
< required
)
582 encode_terminal_src
=
583 xpalloc (encode_terminal_src
, &encode_terminal_src_size
,
584 required
- (encode_terminal_src_size
- nbytes
),
586 buf
= encode_terminal_src
+ nbytes
;
589 if (src
->u
.cmp
.automatic
)
590 for (i
= src
->slice
.cmp
.from
; i
<= src
->slice
.cmp
.to
; i
++)
592 Lisp_Object g
= LGSTRING_GLYPH (gstring
, i
);
593 int c
= LGLYPH_CHAR (g
);
595 if (! char_charset (c
, charset_list
, NULL
))
597 buf
+= CHAR_STRING (c
, buf
);
601 for (i
= 0; i
< cmp
->glyph_len
; i
++)
603 int c
= COMPOSITION_GLYPH (cmp
, i
);
605 /* TAB in a composition means display glyphs with
606 padding space on the left or right. */
609 if (char_charset (c
, charset_list
, NULL
))
611 if (CHAR_WIDTH (c
) == 0
612 && i
> 0 && COMPOSITION_GLYPH (cmp
, i
- 1) == '\t')
613 /* Should be left-padded */
615 buf
+= CHAR_STRING (' ', buf
);
621 buf
+= CHAR_STRING (c
, buf
);
625 /* We must skip glyphs to be padded for a wide character. */
626 else if (! CHAR_GLYPH_PADDING_P (*src
))
633 SET_GLYPH_FROM_CHAR_GLYPH (g
, src
[0]);
635 if (GLYPH_INVALID_P (g
) || GLYPH_SIMPLE_P (tbase
, tlen
, g
))
637 /* This glyph doesn't have an entry in Vglyph_table. */
642 /* This glyph has an entry in Vglyph_table,
643 so process any alias before testing for simpleness. */
644 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
646 if (GLYPH_SIMPLE_P (tbase
, tlen
, g
))
647 /* We set the multi-byte form of a character in G
648 (that should be an ASCII character) at WORKBUF. */
651 /* We have a string in Vglyph_table. */
652 string
= tbase
[GLYPH_CHAR (g
)];
657 nbytes
= buf
- encode_terminal_src
;
658 if (encode_terminal_src_size
- nbytes
< MAX_MULTIBYTE_LENGTH
)
660 encode_terminal_src
=
661 xpalloc (encode_terminal_src
, &encode_terminal_src_size
,
662 MAX_MULTIBYTE_LENGTH
, -1, 1);
663 buf
= encode_terminal_src
+ nbytes
;
666 || char_charset (c
, charset_list
, NULL
))
668 /* Store the multibyte form of C at BUF. */
669 buf
+= CHAR_STRING (c
, buf
);
674 /* C is not encodable. */
677 while (src
+ 1 < src_end
&& CHAR_GLYPH_PADDING_P (src
[1]))
687 if (! STRING_MULTIBYTE (string
))
688 string
= string_to_multibyte (string
);
689 nbytes
= buf
- encode_terminal_src
;
690 if (encode_terminal_src_size
- nbytes
< SBYTES (string
))
692 encode_terminal_src
=
693 xpalloc (encode_terminal_src
, &encode_terminal_src_size
,
695 - (encode_terminal_src_size
- nbytes
)),
697 buf
= encode_terminal_src
+ nbytes
;
699 memcpy (buf
, SDATA (string
), SBYTES (string
));
700 buf
+= SBYTES (string
);
701 nchars
+= SCHARS (string
);
709 coding
->produced
= 0;
713 nbytes
= buf
- encode_terminal_src
;
714 coding
->source
= encode_terminal_src
;
715 if (encode_terminal_dst_size
== 0)
717 encode_terminal_dst
= xrealloc (encode_terminal_dst
,
718 encode_terminal_src_size
);
719 encode_terminal_dst_size
= encode_terminal_src_size
;
721 coding
->destination
= encode_terminal_dst
;
722 coding
->dst_bytes
= encode_terminal_dst_size
;
723 encode_coding_object (coding
, Qnil
, 0, 0, nchars
, nbytes
, Qnil
);
724 /* coding->destination may have been reallocated. */
725 encode_terminal_dst
= coding
->destination
;
726 encode_terminal_dst_size
= coding
->dst_bytes
;
728 return (encode_terminal_dst
);
733 /* An implementation of write_glyphs for termcap frames. */
736 tty_write_glyphs (struct frame
*f
, struct glyph
*string
, int len
)
738 unsigned char *conversion_buffer
;
739 struct coding_system
*coding
;
742 struct tty_display_info
*tty
= FRAME_TTY (f
);
744 tty_turn_off_insert (tty
);
745 tty_hide_cursor (tty
);
747 /* Don't dare write in last column of bottom line, if Auto-Wrap,
748 since that would scroll the whole frame on some terminals. */
751 && curY (tty
) + 1 == FRAME_TOTAL_LINES (f
)
752 && (curX (tty
) + len
) == FRAME_COLS (f
))
759 /* If terminal_coding does any conversion, use it, otherwise use
760 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
761 because it always return 1 if the member src_multibyte is 1. */
762 coding
= (FRAME_TERMINAL_CODING (f
)->common_flags
& CODING_REQUIRE_ENCODING_MASK
763 ? FRAME_TERMINAL_CODING (f
) : &safe_terminal_coding
);
764 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
766 coding
->mode
&= ~CODING_MODE_LAST_BLOCK
;
768 for (stringlen
= len
; stringlen
!= 0; stringlen
-= n
)
770 /* Identify a run of glyphs with the same face. */
771 int face_id
= string
->face_id
;
773 for (n
= 1; n
< stringlen
; ++n
)
774 if (string
[n
].face_id
!= face_id
)
777 /* Turn appearance modes of the face of the run on. */
778 tty_highlight_if_desired (tty
);
779 turn_on_face (f
, face_id
);
782 /* This is the last run. */
783 coding
->mode
|= CODING_MODE_LAST_BLOCK
;
784 conversion_buffer
= encode_terminal_code (string
, n
, coding
);
785 if (coding
->produced
> 0)
788 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->output
);
789 if (ferror (tty
->output
))
790 clearerr (tty
->output
);
792 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->termscript
);
797 /* Turn appearance modes off. */
798 turn_off_face (f
, face_id
);
799 tty_turn_off_highlight (tty
);
805 #ifdef HAVE_GPM /* Only used by GPM code. */
808 tty_write_glyphs_with_face (register struct frame
*f
, register struct glyph
*string
,
809 register int len
, register int face_id
)
811 unsigned char *conversion_buffer
;
812 struct coding_system
*coding
;
814 struct tty_display_info
*tty
= FRAME_TTY (f
);
816 tty_turn_off_insert (tty
);
817 tty_hide_cursor (tty
);
819 /* Don't dare write in last column of bottom line, if Auto-Wrap,
820 since that would scroll the whole frame on some terminals. */
823 && curY (tty
) + 1 == FRAME_TOTAL_LINES (f
)
824 && (curX (tty
) + len
) == FRAME_COLS (f
))
831 /* If terminal_coding does any conversion, use it, otherwise use
832 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
833 because it always return 1 if the member src_multibyte is 1. */
834 coding
= (FRAME_TERMINAL_CODING (f
)->common_flags
& CODING_REQUIRE_ENCODING_MASK
835 ? FRAME_TERMINAL_CODING (f
) : &safe_terminal_coding
);
836 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
838 coding
->mode
&= ~CODING_MODE_LAST_BLOCK
;
840 /* Turn appearance modes of the face. */
841 tty_highlight_if_desired (tty
);
842 turn_on_face (f
, face_id
);
844 coding
->mode
|= CODING_MODE_LAST_BLOCK
;
845 conversion_buffer
= encode_terminal_code (string
, len
, coding
);
846 if (coding
->produced
> 0)
849 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->output
);
850 if (ferror (tty
->output
))
851 clearerr (tty
->output
);
853 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->termscript
);
857 /* Turn appearance modes off. */
858 turn_off_face (f
, face_id
);
859 tty_turn_off_highlight (tty
);
865 /* An implementation of insert_glyphs for termcap frames. */
868 tty_insert_glyphs (struct frame
*f
, struct glyph
*start
, int len
)
871 struct glyph
*glyph
= NULL
;
872 unsigned char *conversion_buffer
;
873 unsigned char space
[1];
874 struct coding_system
*coding
;
876 struct tty_display_info
*tty
= FRAME_TTY (f
);
878 if (tty
->TS_ins_multi_chars
)
880 buf
= tparam (tty
->TS_ins_multi_chars
, 0, 0, len
, 0, 0, 0);
884 write_glyphs (f
, start
, len
);
888 tty_turn_on_insert (tty
);
892 space
[0] = SPACEGLYPH
;
894 /* If terminal_coding does any conversion, use it, otherwise use
895 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
896 because it always return 1 if the member src_multibyte is 1. */
897 coding
= (FRAME_TERMINAL_CODING (f
)->common_flags
& CODING_REQUIRE_ENCODING_MASK
898 ? FRAME_TERMINAL_CODING (f
) : &safe_terminal_coding
);
899 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
901 coding
->mode
&= ~CODING_MODE_LAST_BLOCK
;
905 OUTPUT1_IF (tty
, tty
->TS_ins_char
);
908 conversion_buffer
= space
;
909 coding
->produced
= 1;
913 tty_highlight_if_desired (tty
);
914 turn_on_face (f
, start
->face_id
);
917 /* We must open sufficient space for a character which
918 occupies more than one column. */
919 while (len
&& CHAR_GLYPH_PADDING_P (*start
))
921 OUTPUT1_IF (tty
, tty
->TS_ins_char
);
926 /* This is the last glyph. */
927 coding
->mode
|= CODING_MODE_LAST_BLOCK
;
929 conversion_buffer
= encode_terminal_code (glyph
, 1, coding
);
932 if (coding
->produced
> 0)
935 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->output
);
936 if (ferror (tty
->output
))
937 clearerr (tty
->output
);
939 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->termscript
);
943 OUTPUT1_IF (tty
, tty
->TS_pad_inserted_char
);
946 turn_off_face (f
, glyph
->face_id
);
947 tty_turn_off_highlight (tty
);
954 /* An implementation of delete_glyphs for termcap frames. */
957 tty_delete_glyphs (struct frame
*f
, int n
)
962 struct tty_display_info
*tty
= FRAME_TTY (f
);
964 if (tty
->delete_in_insert_mode
)
966 tty_turn_on_insert (tty
);
970 tty_turn_off_insert (tty
);
971 OUTPUT_IF (tty
, tty
->TS_delete_mode
);
974 if (tty
->TS_del_multi_chars
)
976 buf
= tparam (tty
->TS_del_multi_chars
, 0, 0, n
, 0, 0, 0);
981 for (i
= 0; i
< n
; i
++)
982 OUTPUT1 (tty
, tty
->TS_del_char
);
983 if (!tty
->delete_in_insert_mode
)
984 OUTPUT_IF (tty
, tty
->TS_end_delete_mode
);
987 /* An implementation of ins_del_lines for termcap frames. */
990 tty_ins_del_lines (struct frame
*f
, int vpos
, int n
)
992 struct tty_display_info
*tty
= FRAME_TTY (f
);
994 n
> 0 ? tty
->TS_ins_multi_lines
: tty
->TS_del_multi_lines
;
995 const char *single
= n
> 0 ? tty
->TS_ins_line
: tty
->TS_del_line
;
996 const char *scroll
= n
> 0 ? tty
->TS_rev_scroll
: tty
->TS_fwd_scroll
;
1001 /* If the lines below the insertion are being pushed
1002 into the end of the window, this is the same as clearing;
1003 and we know the lines are already clear, since the matching
1004 deletion has already been done. So can ignore this. */
1005 /* If the lines below the deletion are blank lines coming
1006 out of the end of the window, don't bother,
1007 as there will be a matching inslines later that will flush them. */
1008 if (FRAME_SCROLL_REGION_OK (f
)
1009 && vpos
+ i
>= tty
->specified_window
)
1011 if (!FRAME_MEMORY_BELOW_FRAME (f
)
1012 && vpos
+ i
>= FRAME_TOTAL_LINES (f
))
1017 raw_cursor_to (f
, vpos
, 0);
1018 tty_background_highlight (tty
);
1019 buf
= tparam (multi
, 0, 0, i
, 0, 0, 0);
1025 raw_cursor_to (f
, vpos
, 0);
1026 tty_background_highlight (tty
);
1028 OUTPUT (tty
, single
);
1029 if (tty
->TF_teleray
)
1034 tty_set_scroll_region (f
, vpos
, tty
->specified_window
);
1036 raw_cursor_to (f
, tty
->specified_window
- 1, 0);
1038 raw_cursor_to (f
, vpos
, 0);
1039 tty_background_highlight (tty
);
1041 OUTPUTL (tty
, scroll
, tty
->specified_window
- vpos
);
1042 tty_set_scroll_region (f
, 0, tty
->specified_window
);
1045 if (!FRAME_SCROLL_REGION_OK (f
)
1046 && FRAME_MEMORY_BELOW_FRAME (f
)
1049 cursor_to (f
, FRAME_TOTAL_LINES (f
) + n
, 0);
1054 /* Compute cost of sending "str", in characters,
1055 not counting any line-dependent padding. */
1058 string_cost (const char *str
)
1062 tputs (str
, 0, evalcost
);
1066 /* Compute cost of sending "str", in characters,
1067 counting any line-dependent padding at one line. */
1070 string_cost_one_line (const char *str
)
1074 tputs (str
, 1, evalcost
);
1078 /* Compute per line amount of line-dependent padding,
1079 in tenths of characters. */
1082 per_line_cost (const char *str
)
1086 tputs (str
, 0, evalcost
);
1089 tputs (str
, 10, evalcost
);
1093 /* char_ins_del_cost[n] is cost of inserting N characters.
1094 char_ins_del_cost[-n] is cost of deleting N characters.
1095 The length of this vector is based on max_frame_cols. */
1097 int *char_ins_del_vector
;
1099 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
1103 calculate_ins_del_char_costs (struct frame
*f
)
1105 struct tty_display_info
*tty
= FRAME_TTY (f
);
1106 int ins_startup_cost
, del_startup_cost
;
1107 int ins_cost_per_char
, del_cost_per_char
;
1111 if (tty
->TS_ins_multi_chars
)
1113 ins_cost_per_char
= 0;
1114 ins_startup_cost
= string_cost_one_line (tty
->TS_ins_multi_chars
);
1116 else if (tty
->TS_ins_char
|| tty
->TS_pad_inserted_char
1117 || (tty
->TS_insert_mode
&& tty
->TS_end_insert_mode
))
1119 ins_startup_cost
= (30 * (string_cost (tty
->TS_insert_mode
)
1120 + string_cost (tty
->TS_end_insert_mode
))) / 100;
1121 ins_cost_per_char
= (string_cost_one_line (tty
->TS_ins_char
)
1122 + string_cost_one_line (tty
->TS_pad_inserted_char
));
1126 ins_startup_cost
= 9999;
1127 ins_cost_per_char
= 0;
1130 if (tty
->TS_del_multi_chars
)
1132 del_cost_per_char
= 0;
1133 del_startup_cost
= string_cost_one_line (tty
->TS_del_multi_chars
);
1135 else if (tty
->TS_del_char
)
1137 del_startup_cost
= (string_cost (tty
->TS_delete_mode
)
1138 + string_cost (tty
->TS_end_delete_mode
));
1139 if (tty
->delete_in_insert_mode
)
1140 del_startup_cost
/= 2;
1141 del_cost_per_char
= string_cost_one_line (tty
->TS_del_char
);
1145 del_startup_cost
= 9999;
1146 del_cost_per_char
= 0;
1149 /* Delete costs are at negative offsets */
1150 p
= &char_ins_del_cost (f
)[0];
1151 for (i
= FRAME_COLS (f
); --i
>= 0;)
1152 *--p
= (del_startup_cost
+= del_cost_per_char
);
1154 /* Doing nothing is free */
1155 p
= &char_ins_del_cost (f
)[0];
1158 /* Insert costs are at positive offsets */
1159 for (i
= FRAME_COLS (f
); --i
>= 0;)
1160 *p
++ = (ins_startup_cost
+= ins_cost_per_char
);
1164 calculate_costs (struct frame
*frame
)
1166 FRAME_COST_BAUD_RATE (frame
) = baud_rate
;
1168 if (FRAME_TERMCAP_P (frame
))
1170 struct tty_display_info
*tty
= FRAME_TTY (frame
);
1171 register const char *f
= (tty
->TS_set_scroll_region
1172 ? tty
->TS_set_scroll_region
1173 : tty
->TS_set_scroll_region_1
);
1175 FRAME_SCROLL_REGION_COST (frame
) = string_cost (f
);
1179 /* These variables are only used for terminal stuff. They are
1180 allocated once for the terminal frame of X-windows emacs, but not
1183 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1184 X turns off char_ins_del_ok. */
1186 max_frame_cols
= max (max_frame_cols
, FRAME_COLS (frame
));
1187 if ((min (PTRDIFF_MAX
, SIZE_MAX
) / sizeof (int) - 1) / 2
1189 memory_full (SIZE_MAX
);
1191 char_ins_del_vector
=
1192 xrealloc (char_ins_del_vector
,
1193 (sizeof (int) + 2 * sizeof (int) * max_frame_cols
));
1195 memset (char_ins_del_vector
, 0,
1196 (sizeof (int) + 2 * sizeof (int) * max_frame_cols
));
1199 if (f
&& (!tty
->TS_ins_line
&& !tty
->TS_del_line
))
1200 do_line_insertion_deletion_costs (frame
,
1201 tty
->TS_rev_scroll
, tty
->TS_ins_multi_lines
,
1202 tty
->TS_fwd_scroll
, tty
->TS_del_multi_lines
,
1205 do_line_insertion_deletion_costs (frame
,
1206 tty
->TS_ins_line
, tty
->TS_ins_multi_lines
,
1207 tty
->TS_del_line
, tty
->TS_del_multi_lines
,
1210 calculate_ins_del_char_costs (frame
);
1212 /* Don't use TS_repeat if its padding is worse than sending the chars */
1213 if (tty
->TS_repeat
&& per_line_cost (tty
->TS_repeat
) * baud_rate
< 9000)
1214 tty
->RPov
= string_cost (tty
->TS_repeat
);
1216 tty
->RPov
= FRAME_COLS (frame
) * 2;
1218 cmcostinit (FRAME_TTY (frame
)); /* set up cursor motion costs */
1223 const char *cap
, *name
;
1226 /* Termcap capability names that correspond directly to X keysyms.
1227 Some of these (marked "terminfo") aren't supplied by old-style
1228 (Berkeley) termcap entries. They're listed in X keysym order;
1229 except we put the keypad keys first, so that if they clash with
1230 other keys (as on the IBM PC keyboard) they get overridden.
1233 static const struct fkey_table keys
[] =
1235 {"kh", "home"}, /* termcap */
1236 {"kl", "left"}, /* termcap */
1237 {"ku", "up"}, /* termcap */
1238 {"kr", "right"}, /* termcap */
1239 {"kd", "down"}, /* termcap */
1240 {"%8", "prior"}, /* terminfo */
1241 {"%5", "next"}, /* terminfo */
1242 {"@7", "end"}, /* terminfo */
1243 {"@1", "begin"}, /* terminfo */
1244 {"*6", "select"}, /* terminfo */
1245 {"%9", "print"}, /* terminfo */
1246 {"@4", "execute"}, /* terminfo --- actually the `command' key */
1248 * "insert" --- see below
1250 {"&8", "undo"}, /* terminfo */
1251 {"%0", "redo"}, /* terminfo */
1252 {"%7", "menu"}, /* terminfo --- actually the `options' key */
1253 {"@0", "find"}, /* terminfo */
1254 {"@2", "cancel"}, /* terminfo */
1255 {"%1", "help"}, /* terminfo */
1257 * "break" goes here, but can't be reliably intercepted with termcap
1259 {"&4", "reset"}, /* terminfo --- actually `restart' */
1261 * "system" and "user" --- no termcaps
1263 {"kE", "clearline"}, /* terminfo */
1264 {"kA", "insertline"}, /* terminfo */
1265 {"kL", "deleteline"}, /* terminfo */
1266 {"kI", "insertchar"}, /* terminfo */
1267 {"kD", "deletechar"}, /* terminfo */
1268 {"kB", "backtab"}, /* terminfo */
1270 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1272 {"@8", "kp-enter"}, /* terminfo */
1274 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1275 * "kp-multiply", "kp-add", "kp-separator",
1276 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1277 * --- no termcaps for any of these.
1279 {"K4", "kp-1"}, /* terminfo */
1281 * "kp-2" --- no termcap
1283 {"K5", "kp-3"}, /* terminfo */
1285 * "kp-4" --- no termcap
1287 {"K2", "kp-5"}, /* terminfo */
1289 * "kp-6" --- no termcap
1291 {"K1", "kp-7"}, /* terminfo */
1293 * "kp-8" --- no termcap
1295 {"K3", "kp-9"}, /* terminfo */
1297 * "kp-equal" --- no termcap
1309 {"&0", "S-cancel"}, /*shifted cancel key*/
1310 {"&9", "S-begin"}, /*shifted begin key*/
1311 {"*0", "S-find"}, /*shifted find key*/
1312 {"*1", "S-execute"}, /*shifted execute? actually shifted command key*/
1313 {"*4", "S-delete"}, /*shifted delete-character key*/
1314 {"*7", "S-end"}, /*shifted end key*/
1315 {"*8", "S-clearline"}, /*shifted clear-to end-of-line key*/
1316 {"#1", "S-help"}, /*shifted help key*/
1317 {"#2", "S-home"}, /*shifted home key*/
1318 {"#3", "S-insert"}, /*shifted insert-character key*/
1319 {"#4", "S-left"}, /*shifted left-arrow key*/
1320 {"%d", "S-menu"}, /*shifted menu? actually shifted options key*/
1321 {"%c", "S-next"}, /*shifted next key*/
1322 {"%e", "S-prior"}, /*shifted previous key*/
1323 {"%f", "S-print"}, /*shifted print key*/
1324 {"%g", "S-redo"}, /*shifted redo key*/
1325 {"%i", "S-right"}, /*shifted right-arrow key*/
1326 {"!3", "S-undo"} /*shifted undo key*/
1330 static char **term_get_fkeys_address
;
1331 static KBOARD
*term_get_fkeys_kboard
;
1332 static Lisp_Object
term_get_fkeys_1 (void);
1334 /* Find the escape codes sent by the function keys for Vinput_decode_map.
1335 This function scans the termcap function key sequence entries, and
1336 adds entries to Vinput_decode_map for each function key it finds. */
1339 term_get_fkeys (char **address
, KBOARD
*kboard
)
1341 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1342 errors during the call. The only errors should be from Fdefine_key
1343 when given a key sequence containing an invalid prefix key. If the
1344 termcap defines function keys which use a prefix that is already bound
1345 to a command by the default bindings, we should silently ignore that
1346 function key specification, rather than giving the user an error and
1347 refusing to run at all on such a terminal. */
1349 term_get_fkeys_address
= address
;
1350 term_get_fkeys_kboard
= kboard
;
1351 internal_condition_case (term_get_fkeys_1
, Qerror
, Fidentity
);
1355 term_get_fkeys_1 (void)
1359 char **address
= term_get_fkeys_address
;
1360 KBOARD
*kboard
= term_get_fkeys_kboard
;
1362 /* This can happen if CANNOT_DUMP or with strange options. */
1363 if (!KEYMAPP (KVAR (kboard
, Vinput_decode_map
)))
1364 kset_input_decode_map (kboard
, Fmake_sparse_keymap (Qnil
));
1366 for (i
= 0; i
< ARRAYELTS (keys
); i
++)
1368 char *sequence
= tgetstr (keys
[i
].cap
, address
);
1370 Fdefine_key (KVAR (kboard
, Vinput_decode_map
), build_string (sequence
),
1371 Fmake_vector (make_number (1),
1372 intern (keys
[i
].name
)));
1375 /* The uses of the "k0" capability are inconsistent; sometimes it
1376 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1377 We will attempt to politely accommodate both systems by testing for
1378 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1381 const char *k_semi
= tgetstr ("k;", address
);
1382 const char *k0
= tgetstr ("k0", address
);
1383 const char *k0_name
= "f10";
1388 /* Define f0 first, so that f10 takes precedence in case the
1389 key sequences happens to be the same. */
1390 Fdefine_key (KVAR (kboard
, Vinput_decode_map
), build_string (k0
),
1391 Fmake_vector (make_number (1), intern ("f0")));
1392 Fdefine_key (KVAR (kboard
, Vinput_decode_map
), build_string (k_semi
),
1393 Fmake_vector (make_number (1), intern ("f10")));
1396 Fdefine_key (KVAR (kboard
, Vinput_decode_map
), build_string (k0
),
1397 Fmake_vector (make_number (1), intern (k0_name
)));
1400 /* Set up cookies for numbered function keys above f10. */
1402 char fcap
[3], fkey
[4];
1404 fcap
[0] = 'F'; fcap
[2] = '\0';
1405 for (i
= 11; i
< 64; i
++)
1408 fcap
[1] = '1' + i
- 11;
1410 fcap
[1] = 'A' + i
- 20;
1412 fcap
[1] = 'a' + i
- 46;
1415 char *sequence
= tgetstr (fcap
, address
);
1418 sprintf (fkey
, "f%d", i
);
1419 Fdefine_key (KVAR (kboard
, Vinput_decode_map
), build_string (sequence
),
1420 Fmake_vector (make_number (1),
1428 * Various mappings to try and get a better fit.
1431 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1432 if (!tgetstr (cap1, address)) \
1434 char *sequence = tgetstr (cap2, address); \
1436 Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (sequence), \
1437 Fmake_vector (make_number (1), \
1441 /* if there's no key_next keycap, map key_npage to `next' keysym */
1442 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1443 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1444 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1445 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1446 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1447 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1448 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1449 #undef CONDITIONAL_REASSIGN
1454 #endif /* not DOS_NT */
1457 /***********************************************************************
1458 Character Display Information
1459 ***********************************************************************/
1460 static void append_glyph (struct it
*);
1461 static void append_composite_glyph (struct it
*);
1462 static void produce_composite_glyph (struct it
*);
1463 static void append_glyphless_glyph (struct it
*, int, const char *);
1464 static void produce_glyphless_glyph (struct it
*, Lisp_Object
);
1466 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1467 terminal frames if IT->glyph_row != NULL. IT->char_to_display is
1468 the character for which to produce glyphs; IT->face_id contains the
1469 character's face. Padding glyphs are appended if IT->c has a
1470 IT->pixel_width > 1. */
1473 append_glyph (struct it
*it
)
1475 struct glyph
*glyph
, *end
;
1478 eassert (it
->glyph_row
);
1479 glyph
= (it
->glyph_row
->glyphs
[it
->area
]
1480 + it
->glyph_row
->used
[it
->area
]);
1481 end
= it
->glyph_row
->glyphs
[1 + it
->area
];
1483 /* If the glyph row is reversed, we need to prepend the glyph rather
1485 if (it
->glyph_row
->reversed_p
&& it
->area
== TEXT_AREA
)
1488 int move_by
= it
->pixel_width
;
1490 /* Make room for the new glyphs. */
1491 if (move_by
> end
- glyph
) /* don't overstep end of this area */
1492 move_by
= end
- glyph
;
1493 for (g
= glyph
- 1; g
>= it
->glyph_row
->glyphs
[it
->area
]; g
--)
1495 glyph
= it
->glyph_row
->glyphs
[it
->area
];
1496 end
= glyph
+ move_by
;
1499 /* BIDI Note: we put the glyphs of a "multi-pixel" character left to
1500 right, even in the REVERSED_P case, since (a) all of its u.ch are
1501 identical, and (b) the PADDING_P flag needs to be set for the
1502 leftmost one, because we write to the terminal left-to-right. */
1504 i
< it
->pixel_width
&& glyph
< end
;
1507 glyph
->type
= CHAR_GLYPH
;
1508 glyph
->pixel_width
= 1;
1509 glyph
->u
.ch
= it
->char_to_display
;
1510 glyph
->face_id
= it
->face_id
;
1511 glyph
->padding_p
= i
> 0;
1512 glyph
->charpos
= CHARPOS (it
->position
);
1513 glyph
->object
= it
->object
;
1516 glyph
->resolved_level
= it
->bidi_it
.resolved_level
;
1517 eassert ((it
->bidi_it
.type
& 7) == it
->bidi_it
.type
);
1518 glyph
->bidi_type
= it
->bidi_it
.type
;
1522 glyph
->resolved_level
= 0;
1523 glyph
->bidi_type
= UNKNOWN_BT
;
1526 ++it
->glyph_row
->used
[it
->area
];
1531 /* For external use. */
1533 tty_append_glyph (struct it
*it
)
1539 /* Produce glyphs for the display element described by IT. *IT
1540 specifies what we want to produce a glyph for (character, image, ...),
1541 and where in the glyph matrix we currently are (glyph row and hpos).
1542 produce_glyphs fills in output fields of *IT with information such as the
1543 pixel width and height of a character, and maybe output actual glyphs at
1544 the same time if IT->glyph_row is non-null. For an overview, see
1545 the explanation in dispextern.h, before the definition of the
1546 display_element_type enumeration.
1548 produce_glyphs also stores the result of glyph width, ascent
1549 etc. computations in *IT.
1551 IT->glyph_row may be null, in which case produce_glyphs does not
1552 actually fill in the glyphs. This is used in the move_* functions
1553 in xdisp.c for text width and height computations.
1555 Callers usually don't call produce_glyphs directly;
1556 instead they use the macro PRODUCE_GLYPHS. */
1559 produce_glyphs (struct it
*it
)
1561 /* If a hook is installed, let it do the work. */
1563 /* Nothing but characters are supported on terminal frames. */
1564 eassert (it
->what
== IT_CHARACTER
1565 || it
->what
== IT_COMPOSITION
1566 || it
->what
== IT_STRETCH
1567 || it
->what
== IT_GLYPHLESS
);
1569 if (it
->what
== IT_STRETCH
)
1571 produce_stretch_glyph (it
);
1575 if (it
->what
== IT_COMPOSITION
)
1577 produce_composite_glyph (it
);
1581 if (it
->what
== IT_GLYPHLESS
)
1583 produce_glyphless_glyph (it
, Qnil
);
1587 if (it
->char_to_display
>= 040 && it
->char_to_display
< 0177)
1589 it
->pixel_width
= it
->nglyphs
= 1;
1593 else if (it
->char_to_display
== '\n')
1594 it
->pixel_width
= it
->nglyphs
= 0;
1595 else if (it
->char_to_display
== '\t')
1597 int absolute_x
= (it
->current_x
1598 + it
->continuation_lines_width
);
1600 = (((1 + absolute_x
+ it
->tab_width
- 1)
1605 /* If part of the TAB has been displayed on the previous line
1606 which is continued now, continuation_lines_width will have
1607 been incremented already by the part that fitted on the
1608 continued line. So, we will get the right number of spaces
1610 nspaces
= next_tab_x
- absolute_x
;
1616 it
->char_to_display
= ' ';
1617 it
->pixel_width
= it
->len
= 1;
1623 it
->pixel_width
= nspaces
;
1624 it
->nglyphs
= nspaces
;
1626 else if (CHAR_BYTE8_P (it
->char_to_display
))
1628 /* Coming here means that we must send the raw 8-bit byte as is
1629 to the terminal. Although there's no way to know how many
1630 columns it occupies on a screen, it is a good assumption that
1631 a single byte code has 1-column width. */
1632 it
->pixel_width
= it
->nglyphs
= 1;
1638 Lisp_Object charset_list
= FRAME_TERMINAL (it
->f
)->charset_list
;
1640 if (char_charset (it
->char_to_display
, charset_list
, NULL
))
1642 it
->pixel_width
= CHAR_WIDTH (it
->char_to_display
);
1643 it
->nglyphs
= it
->pixel_width
;
1649 Lisp_Object acronym
= lookup_glyphless_char_display (-1, it
);
1651 eassert (it
->what
== IT_GLYPHLESS
);
1652 produce_glyphless_glyph (it
, acronym
);
1657 /* Advance current_x by the pixel width as a convenience for
1659 if (it
->area
== TEXT_AREA
)
1660 it
->current_x
+= it
->pixel_width
;
1661 it
->ascent
= it
->max_ascent
= it
->phys_ascent
= it
->max_phys_ascent
= 0;
1662 it
->descent
= it
->max_descent
= it
->phys_descent
= it
->max_phys_descent
= 1;
1665 /* Append glyphs to IT's glyph_row for the composition IT->cmp_id.
1666 Called from produce_composite_glyph for terminal frames if
1667 IT->glyph_row != NULL. IT->face_id contains the character's
1671 append_composite_glyph (struct it
*it
)
1673 struct glyph
*glyph
;
1675 eassert (it
->glyph_row
);
1676 glyph
= it
->glyph_row
->glyphs
[it
->area
] + it
->glyph_row
->used
[it
->area
];
1677 if (glyph
< it
->glyph_row
->glyphs
[1 + it
->area
])
1679 /* If the glyph row is reversed, we need to prepend the glyph
1680 rather than append it. */
1681 if (it
->glyph_row
->reversed_p
&& it
->area
== TEXT_AREA
)
1685 /* Make room for the new glyph. */
1686 for (g
= glyph
- 1; g
>= it
->glyph_row
->glyphs
[it
->area
]; g
--)
1688 glyph
= it
->glyph_row
->glyphs
[it
->area
];
1690 glyph
->type
= COMPOSITE_GLYPH
;
1691 glyph
->pixel_width
= it
->pixel_width
;
1692 glyph
->u
.cmp
.id
= it
->cmp_it
.id
;
1693 if (it
->cmp_it
.ch
< 0)
1695 glyph
->u
.cmp
.automatic
= 0;
1696 glyph
->u
.cmp
.id
= it
->cmp_it
.id
;
1700 glyph
->u
.cmp
.automatic
= 1;
1701 glyph
->u
.cmp
.id
= it
->cmp_it
.id
;
1702 glyph
->slice
.cmp
.from
= it
->cmp_it
.from
;
1703 glyph
->slice
.cmp
.to
= it
->cmp_it
.to
- 1;
1706 glyph
->face_id
= it
->face_id
;
1707 glyph
->padding_p
= 0;
1708 glyph
->charpos
= CHARPOS (it
->position
);
1709 glyph
->object
= it
->object
;
1712 glyph
->resolved_level
= it
->bidi_it
.resolved_level
;
1713 eassert ((it
->bidi_it
.type
& 7) == it
->bidi_it
.type
);
1714 glyph
->bidi_type
= it
->bidi_it
.type
;
1718 glyph
->resolved_level
= 0;
1719 glyph
->bidi_type
= UNKNOWN_BT
;
1722 ++it
->glyph_row
->used
[it
->area
];
1728 /* Produce a composite glyph for iterator IT. IT->cmp_id is the ID of
1729 the composition. We simply produces components of the composition
1730 assuming that the terminal has a capability to layout/render it
1734 produce_composite_glyph (struct it
*it
)
1736 if (it
->cmp_it
.ch
< 0)
1738 struct composition
*cmp
= composition_table
[it
->cmp_it
.id
];
1740 it
->pixel_width
= cmp
->width
;
1744 Lisp_Object gstring
= composition_gstring_from_id (it
->cmp_it
.id
);
1746 it
->pixel_width
= composition_gstring_width (gstring
, it
->cmp_it
.from
,
1747 it
->cmp_it
.to
, NULL
);
1751 append_composite_glyph (it
);
1755 /* Append a glyph for a glyphless character to IT->glyph_row. FACE_ID
1756 is a face ID to be used for the glyph. What is actually appended
1757 are glyphs of type CHAR_GLYPH whose characters are in STR (which
1758 comes from it->nglyphs bytes). */
1761 append_glyphless_glyph (struct it
*it
, int face_id
, const char *str
)
1763 struct glyph
*glyph
, *end
;
1766 eassert (it
->glyph_row
);
1767 glyph
= it
->glyph_row
->glyphs
[it
->area
] + it
->glyph_row
->used
[it
->area
];
1768 end
= it
->glyph_row
->glyphs
[1 + it
->area
];
1770 /* If the glyph row is reversed, we need to prepend the glyph rather
1772 if (it
->glyph_row
->reversed_p
&& it
->area
== TEXT_AREA
)
1775 int move_by
= it
->pixel_width
;
1777 /* Make room for the new glyphs. */
1778 if (move_by
> end
- glyph
) /* don't overstep end of this area */
1779 move_by
= end
- glyph
;
1780 for (g
= glyph
- 1; g
>= it
->glyph_row
->glyphs
[it
->area
]; g
--)
1782 glyph
= it
->glyph_row
->glyphs
[it
->area
];
1783 end
= glyph
+ move_by
;
1788 glyph
->type
= CHAR_GLYPH
;
1789 glyph
->pixel_width
= 1;
1790 glyph
->face_id
= face_id
;
1791 glyph
->padding_p
= 0;
1792 glyph
->charpos
= CHARPOS (it
->position
);
1793 glyph
->object
= it
->object
;
1796 glyph
->resolved_level
= it
->bidi_it
.resolved_level
;
1797 eassert ((it
->bidi_it
.type
& 7) == it
->bidi_it
.type
);
1798 glyph
->bidi_type
= it
->bidi_it
.type
;
1802 glyph
->resolved_level
= 0;
1803 glyph
->bidi_type
= UNKNOWN_BT
;
1806 /* BIDI Note: we put the glyphs of characters left to right, even in
1807 the REVERSED_P case because we write to the terminal
1809 for (i
= 0; i
< it
->nglyphs
&& glyph
< end
; ++i
)
1812 glyph
[0] = glyph
[-1];
1813 glyph
->u
.ch
= str
[i
];
1814 ++it
->glyph_row
->used
[it
->area
];
1819 /* Produce glyphs for a glyphless character for iterator IT.
1820 IT->glyphless_method specifies which method to use for displaying
1821 the character. See the description of enum
1822 glyphless_display_method in dispextern.h for the details.
1824 ACRONYM, if non-nil, is an acronym string for the character.
1826 The glyphs actually produced are of type CHAR_GLYPH. */
1829 produce_glyphless_glyph (struct it
*it
, Lisp_Object acronym
)
1831 int len
, face_id
= merge_glyphless_glyph_face (it
);
1832 char buf
[sizeof "\\x" + max (6, (sizeof it
->c
* CHAR_BIT
+ 3) / 4)];
1833 char const *str
= " ";
1835 if (it
->glyphless_method
== GLYPHLESS_DISPLAY_THIN_SPACE
)
1837 /* As there's no way to produce a thin space, we produce a space
1838 of canonical width. */
1841 else if (it
->glyphless_method
== GLYPHLESS_DISPLAY_EMPTY_BOX
)
1843 len
= CHAR_WIDTH (it
->c
);
1848 len
= sprintf (buf
, "[%.*s]", len
, str
);
1853 if (it
->glyphless_method
== GLYPHLESS_DISPLAY_ACRONYM
)
1855 if (! STRINGP (acronym
) && CHAR_TABLE_P (Vglyphless_char_display
))
1856 acronym
= CHAR_TABLE_REF (Vglyphless_char_display
, it
->c
);
1857 if (CONSP (acronym
))
1858 acronym
= XCDR (acronym
);
1860 str
= STRINGP (acronym
) ? SSDATA (acronym
) : "";
1861 for (len
= 0; len
< 6 && str
[len
] && ASCII_CHAR_P (str
[len
]); len
++)
1862 buf
[1 + len
] = str
[len
];
1868 eassert (it
->glyphless_method
== GLYPHLESS_DISPLAY_HEX_CODE
);
1869 len
= (it
->c
< 0x10000 ? sprintf (buf
, "\\u%04X", it
->c
)
1870 : it
->c
<= MAX_UNICODE_CHAR
? sprintf (buf
, "\\U%06X", it
->c
)
1871 : sprintf (buf
, "\\x%06X", it
->c
));
1876 it
->pixel_width
= len
;
1879 append_glyphless_glyph (it
, face_id
, str
);
1883 /***********************************************************************
1885 ***********************************************************************/
1887 /* Value is non-zero if attribute ATTR may be used. ATTR should be
1888 one of the enumerators from enum no_color_bit, or a bit set built
1889 from them. Some display attributes may not be used together with
1890 color; the termcap capability `NC' specifies which ones. */
1892 #define MAY_USE_WITH_COLORS_P(tty, ATTR) \
1893 (tty->TN_max_colors > 0 \
1894 ? (tty->TN_no_color_video & (ATTR)) == 0 \
1897 /* Turn appearances of face FACE_ID on tty frame F on.
1898 FACE_ID is a realized face ID number, in the face cache. */
1901 turn_on_face (struct frame
*f
, int face_id
)
1903 struct face
*face
= FACE_FROM_ID (f
, face_id
);
1904 unsigned long fg
= face
->foreground
;
1905 unsigned long bg
= face
->background
;
1906 struct tty_display_info
*tty
= FRAME_TTY (f
);
1908 /* Use reverse video if the face specifies that.
1909 Do this first because TS_end_standout_mode may be the same
1910 as TS_exit_attribute_mode, which turns all appearances off. */
1911 if (MAY_USE_WITH_COLORS_P (tty
, NC_REVERSE
)
1913 ? fg
== FACE_TTY_DEFAULT_FG_COLOR
|| bg
== FACE_TTY_DEFAULT_BG_COLOR
1914 : fg
== FACE_TTY_DEFAULT_BG_COLOR
|| bg
== FACE_TTY_DEFAULT_FG_COLOR
))
1915 tty_toggle_highlight (tty
);
1917 if (face
->tty_bold_p
&& MAY_USE_WITH_COLORS_P (tty
, NC_BOLD
))
1918 OUTPUT1_IF (tty
, tty
->TS_enter_bold_mode
);
1920 if (face
->tty_italic_p
&& MAY_USE_WITH_COLORS_P (tty
, NC_ITALIC
))
1922 if (tty
->TS_enter_italic_mode
)
1923 OUTPUT1 (tty
, tty
->TS_enter_italic_mode
);
1925 /* Italics mode is unavailable on many terminals. In that
1926 case, map slant to dimmed text; we want italic text to
1927 appear different and dimming is not otherwise used. */
1928 OUTPUT1 (tty
, tty
->TS_enter_dim_mode
);
1931 if (face
->tty_underline_p
&& MAY_USE_WITH_COLORS_P (tty
, NC_UNDERLINE
))
1932 OUTPUT1_IF (tty
, tty
->TS_enter_underline_mode
);
1934 if (tty
->TN_max_colors
> 0)
1939 ts
= tty
->standout_mode
? tty
->TS_set_background
: tty
->TS_set_foreground
;
1940 if (face_tty_specified_color (fg
) && ts
)
1942 p
= tparam (ts
, NULL
, 0, fg
, 0, 0, 0);
1947 ts
= tty
->standout_mode
? tty
->TS_set_foreground
: tty
->TS_set_background
;
1948 if (face_tty_specified_color (bg
) && ts
)
1950 p
= tparam (ts
, NULL
, 0, bg
, 0, 0, 0);
1958 /* Turn off appearances of face FACE_ID on tty frame F. */
1961 turn_off_face (struct frame
*f
, int face_id
)
1963 struct face
*face
= FACE_FROM_ID (f
, face_id
);
1964 struct tty_display_info
*tty
= FRAME_TTY (f
);
1966 eassert (face
!= NULL
);
1968 if (tty
->TS_exit_attribute_mode
)
1970 /* Capability "me" will turn off appearance modes double-bright,
1971 half-bright, reverse-video, standout, underline. It may or
1972 may not turn off alt-char-mode. */
1973 if (face
->tty_bold_p
1974 || face
->tty_italic_p
1975 || face
->tty_reverse_p
1976 || face
->tty_underline_p
)
1978 OUTPUT1_IF (tty
, tty
->TS_exit_attribute_mode
);
1979 if (strcmp (tty
->TS_exit_attribute_mode
, tty
->TS_end_standout_mode
) == 0)
1980 tty
->standout_mode
= 0;
1985 /* If we don't have "me" we can only have those appearances
1986 that have exit sequences defined. */
1987 if (face
->tty_underline_p
)
1988 OUTPUT_IF (tty
, tty
->TS_exit_underline_mode
);
1991 /* Switch back to default colors. */
1992 if (tty
->TN_max_colors
> 0
1993 && ((face
->foreground
!= FACE_TTY_DEFAULT_COLOR
1994 && face
->foreground
!= FACE_TTY_DEFAULT_FG_COLOR
)
1995 || (face
->background
!= FACE_TTY_DEFAULT_COLOR
1996 && face
->background
!= FACE_TTY_DEFAULT_BG_COLOR
)))
1997 OUTPUT1_IF (tty
, tty
->TS_orig_pair
);
2001 /* Return true if the terminal on frame F supports all of the
2002 capabilities in CAPS simultaneously. */
2005 tty_capable_p (struct tty_display_info
*tty
, unsigned int caps
)
2007 #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
2008 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
2011 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_INVERSE
, tty
->TS_standout_mode
, NC_REVERSE
);
2012 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_UNDERLINE
, tty
->TS_enter_underline_mode
, NC_UNDERLINE
);
2013 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_BOLD
, tty
->TS_enter_bold_mode
, NC_BOLD
);
2014 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_DIM
, tty
->TS_enter_dim_mode
, NC_DIM
);
2015 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_ITALIC
, tty
->TS_enter_italic_mode
, NC_ITALIC
);
2021 /* Return non-zero if the terminal is capable to display colors. */
2023 DEFUN ("tty-display-color-p", Ftty_display_color_p
, Stty_display_color_p
,
2025 doc
: /* Return non-nil if the tty device TERMINAL can display colors.
2027 TERMINAL can be a terminal object, a frame, or nil (meaning the
2028 selected frame's terminal). This function always returns nil if
2029 TERMINAL does not refer to a text terminal. */)
2030 (Lisp_Object terminal
)
2032 struct terminal
*t
= get_tty_terminal (terminal
, 0);
2036 return t
->display_info
.tty
->TN_max_colors
> 0 ? Qt
: Qnil
;
2039 /* Return the number of supported colors. */
2040 DEFUN ("tty-display-color-cells", Ftty_display_color_cells
,
2041 Stty_display_color_cells
, 0, 1, 0,
2042 doc
: /* Return the number of colors supported by the tty device TERMINAL.
2044 TERMINAL can be a terminal object, a frame, or nil (meaning the
2045 selected frame's terminal). This function always returns 0 if
2046 TERMINAL does not refer to a text terminal. */)
2047 (Lisp_Object terminal
)
2049 struct terminal
*t
= get_tty_terminal (terminal
, 0);
2051 return make_number (0);
2053 return make_number (t
->display_info
.tty
->TN_max_colors
);
2058 /* Declare here rather than in the function, as in the rest of Emacs,
2059 to work around an HPUX compiler bug (?). See
2060 http://lists.gnu.org/archive/html/emacs-devel/2007-08/msg00410.html */
2061 static int default_max_colors
;
2062 static int default_max_pairs
;
2063 static int default_no_color_video
;
2064 static char *default_orig_pair
;
2065 static char *default_set_foreground
;
2066 static char *default_set_background
;
2068 /* Save or restore the default color-related capabilities of this
2071 tty_default_color_capabilities (struct tty_display_info
*tty
, bool save
)
2076 dupstring (&default_orig_pair
, tty
->TS_orig_pair
);
2077 dupstring (&default_set_foreground
, tty
->TS_set_foreground
);
2078 dupstring (&default_set_background
, tty
->TS_set_background
);
2079 default_max_colors
= tty
->TN_max_colors
;
2080 default_max_pairs
= tty
->TN_max_pairs
;
2081 default_no_color_video
= tty
->TN_no_color_video
;
2085 tty
->TS_orig_pair
= default_orig_pair
;
2086 tty
->TS_set_foreground
= default_set_foreground
;
2087 tty
->TS_set_background
= default_set_background
;
2088 tty
->TN_max_colors
= default_max_colors
;
2089 tty
->TN_max_pairs
= default_max_pairs
;
2090 tty
->TN_no_color_video
= default_no_color_video
;
2094 /* Setup one of the standard tty color schemes according to MODE.
2095 MODE's value is generally the number of colors which we want to
2096 support; zero means set up for the default capabilities, the ones
2097 we saw at init_tty time; -1 means turn off color support. */
2099 tty_setup_colors (struct tty_display_info
*tty
, int mode
)
2101 /* Canonicalize all negative values of MODE. */
2107 case -1: /* no colors at all */
2108 tty
->TN_max_colors
= 0;
2109 tty
->TN_max_pairs
= 0;
2110 tty
->TN_no_color_video
= 0;
2111 tty
->TS_set_foreground
= tty
->TS_set_background
= tty
->TS_orig_pair
= NULL
;
2113 case 0: /* default colors, if any */
2115 tty_default_color_capabilities (tty
, 0);
2117 case 8: /* 8 standard ANSI colors */
2118 tty
->TS_orig_pair
= "\033[0m";
2120 tty
->TS_set_foreground
= "\033[3%p1%dm";
2121 tty
->TS_set_background
= "\033[4%p1%dm";
2123 tty
->TS_set_foreground
= "\033[3%dm";
2124 tty
->TS_set_background
= "\033[4%dm";
2126 tty
->TN_max_colors
= 8;
2127 tty
->TN_max_pairs
= 64;
2128 tty
->TN_no_color_video
= 0;
2134 set_tty_color_mode (struct tty_display_info
*tty
, struct frame
*f
)
2136 Lisp_Object tem
, val
;
2137 Lisp_Object color_mode
;
2139 Lisp_Object tty_color_mode_alist
2140 = Fintern_soft (build_string ("tty-color-mode-alist"), Qnil
);
2142 tem
= assq_no_quit (Qtty_color_mode
, f
->param_alist
);
2143 val
= CONSP (tem
) ? XCDR (tem
) : Qnil
;
2147 else if (SYMBOLP (tty_color_mode_alist
))
2149 tem
= Fassq (val
, Fsymbol_value (tty_color_mode_alist
));
2150 color_mode
= CONSP (tem
) ? XCDR (tem
) : Qnil
;
2155 mode
= TYPE_RANGED_INTEGERP (int, color_mode
) ? XINT (color_mode
) : 0;
2157 if (mode
!= tty
->previous_color_mode
)
2159 tty
->previous_color_mode
= mode
;
2160 tty_setup_colors (tty
, mode
);
2161 /* This recomputes all the faces given the new color definitions. */
2162 safe_call (1, intern ("tty-set-up-initial-frame-faces"));
2166 #endif /* !DOS_NT */
2170 /* Return the tty display object specified by TERMINAL. */
2172 static struct terminal
*
2173 get_tty_terminal (Lisp_Object terminal
, bool throw)
2175 struct terminal
*t
= get_terminal (terminal
, throw);
2177 if (t
&& t
->type
!= output_termcap
&& t
->type
!= output_msdos_raw
)
2180 error ("Device %d is not a termcap terminal device", t
->id
);
2188 /* Return an active termcap device that uses the tty device with the
2191 This function ignores suspended devices.
2193 Returns NULL if the named terminal device is not opened. */
2196 get_named_tty (const char *name
)
2202 for (t
= terminal_list
; t
; t
= t
->next_terminal
)
2204 if ((t
->type
== output_termcap
|| t
->type
== output_msdos_raw
)
2205 && !strcmp (t
->display_info
.tty
->name
, name
)
2206 && TERMINAL_ACTIVE_P (t
))
2214 DEFUN ("tty-type", Ftty_type
, Stty_type
, 0, 1, 0,
2215 doc
: /* Return the type of the tty device that TERMINAL uses.
2216 Returns nil if TERMINAL is not on a tty device.
2218 TERMINAL can be a terminal object, a frame, or nil (meaning the
2219 selected frame's terminal). */)
2220 (Lisp_Object terminal
)
2222 struct terminal
*t
= get_terminal (terminal
, 1);
2224 if (t
->type
!= output_termcap
&& t
->type
!= output_msdos_raw
)
2227 if (t
->display_info
.tty
->type
)
2228 return build_string (t
->display_info
.tty
->type
);
2233 DEFUN ("controlling-tty-p", Fcontrolling_tty_p
, Scontrolling_tty_p
, 0, 1, 0,
2234 doc
: /* Return non-nil if TERMINAL is the controlling tty of the Emacs process.
2236 TERMINAL can be a terminal object, a frame, or nil (meaning the
2237 selected frame's terminal). This function always returns nil if
2238 TERMINAL is not on a tty device. */)
2239 (Lisp_Object terminal
)
2241 struct terminal
*t
= get_terminal (terminal
, 1);
2243 if ((t
->type
!= output_termcap
&& t
->type
!= output_msdos_raw
)
2244 || strcmp (t
->display_info
.tty
->name
, DEV_TTY
) != 0)
2250 DEFUN ("tty-no-underline", Ftty_no_underline
, Stty_no_underline
, 0, 1, 0,
2251 doc
: /* Declare that the tty used by TERMINAL does not handle underlining.
2252 This is used to override the terminfo data, for certain terminals that
2253 do not really do underlining, but say that they do. This function has
2254 no effect if used on a non-tty terminal.
2256 TERMINAL can be a terminal object, a frame or nil (meaning the
2257 selected frame's terminal). This function always returns nil if
2258 TERMINAL does not refer to a text terminal. */)
2259 (Lisp_Object terminal
)
2261 struct terminal
*t
= get_terminal (terminal
, 1);
2263 if (t
->type
== output_termcap
)
2264 t
->display_info
.tty
->TS_enter_underline_mode
= 0;
2268 DEFUN ("tty-top-frame", Ftty_top_frame
, Stty_top_frame
, 0, 1, 0,
2269 doc
: /* Return the topmost terminal frame on TERMINAL.
2270 TERMINAL can be a terminal object, a frame or nil (meaning the
2271 selected frame's terminal). This function returns nil if TERMINAL
2272 does not refer to a text terminal. Otherwise, it returns the
2273 top-most frame on the text terminal. */)
2274 (Lisp_Object terminal
)
2276 struct terminal
*t
= get_terminal (terminal
, 1);
2278 if (t
->type
== output_termcap
)
2279 return t
->display_info
.tty
->top_frame
;
2285 DEFUN ("suspend-tty", Fsuspend_tty
, Ssuspend_tty
, 0, 1, 0,
2286 doc
: /* Suspend the terminal device TTY.
2288 The device is restored to its default state, and Emacs ceases all
2289 access to the tty device. Frames that use the device are not deleted,
2290 but input is not read from them and if they change, their display is
2293 TTY may be a terminal object, a frame, or nil for the terminal device
2294 of the currently selected frame.
2296 This function runs `suspend-tty-functions' after suspending the
2297 device. The functions are run with one arg, the id of the suspended
2300 `suspend-tty' does nothing if it is called on a device that is already
2303 A suspended tty may be resumed by calling `resume-tty' on it. */)
2306 struct terminal
*t
= get_tty_terminal (tty
, 1);
2310 error ("Unknown tty device");
2312 f
= t
->display_info
.tty
->input
;
2316 /* First run `suspend-tty-functions' and then clean up the tty
2317 state because `suspend-tty-functions' might need to change
2319 Lisp_Object args
[2];
2320 args
[0] = intern ("suspend-tty-functions");
2321 XSETTERMINAL (args
[1], t
);
2322 Frun_hook_with_args (2, args
);
2324 reset_sys_modes (t
->display_info
.tty
);
2325 delete_keyboard_wait_descriptor (fileno (f
));
2329 if (f
!= t
->display_info
.tty
->output
)
2330 fclose (t
->display_info
.tty
->output
);
2333 t
->display_info
.tty
->input
= 0;
2334 t
->display_info
.tty
->output
= 0;
2336 if (FRAMEP (t
->display_info
.tty
->top_frame
))
2337 SET_FRAME_VISIBLE (XFRAME (t
->display_info
.tty
->top_frame
), 0);
2341 /* Clear display hooks to prevent further output. */
2342 clear_tty_hooks (t
);
2347 DEFUN ("resume-tty", Fresume_tty
, Sresume_tty
, 0, 1, 0,
2348 doc
: /* Resume the previously suspended terminal device TTY.
2349 The terminal is opened and reinitialized. Frames that are on the
2350 suspended terminal are revived.
2352 It is an error to resume a terminal while another terminal is active
2355 This function runs `resume-tty-functions' after resuming the terminal.
2356 The functions are run with one arg, the id of the resumed terminal
2359 `resume-tty' does nothing if it is called on a device that is not
2362 TTY may be a terminal object, a frame, or nil (meaning the selected
2363 frame's terminal). */)
2366 struct terminal
*t
= get_tty_terminal (tty
, 1);
2370 error ("Unknown tty device");
2372 if (!t
->display_info
.tty
->input
)
2374 if (get_named_tty (t
->display_info
.tty
->name
))
2375 error ("Cannot resume display while another display is active on the same device");
2378 t
->display_info
.tty
->output
= stdout
;
2379 t
->display_info
.tty
->input
= stdin
;
2381 fd
= emacs_open (t
->display_info
.tty
->name
, O_RDWR
| O_NOCTTY
, 0);
2382 t
->display_info
.tty
->input
= t
->display_info
.tty
->output
2383 = fd
< 0 ? 0 : fdopen (fd
, "w+");
2385 if (! t
->display_info
.tty
->input
)
2387 int open_errno
= errno
;
2389 report_file_errno ("Cannot reopen tty device",
2390 build_string (t
->display_info
.tty
->name
),
2394 if (!O_IGNORE_CTTY
&& strcmp (t
->display_info
.tty
->name
, DEV_TTY
) != 0)
2395 dissociate_if_controlling_tty (fd
);
2398 add_keyboard_wait_descriptor (fd
);
2400 if (FRAMEP (t
->display_info
.tty
->top_frame
))
2402 struct frame
*f
= XFRAME (t
->display_info
.tty
->top_frame
);
2404 int old_height
= FRAME_COLS (f
);
2405 int old_width
= FRAME_TOTAL_LINES (f
);
2407 /* Check if terminal/window size has changed while the frame
2409 get_tty_size (fileno (t
->display_info
.tty
->input
), &width
, &height
);
2410 if (width
!= old_width
|| height
!= old_height
)
2411 change_frame_size (f
, width
, height
- FRAME_MENU_BAR_LINES (f
),
2413 SET_FRAME_VISIBLE (XFRAME (t
->display_info
.tty
->top_frame
), 1);
2417 init_sys_modes (t
->display_info
.tty
);
2420 /* Run `resume-tty-functions'. */
2421 Lisp_Object args
[2];
2422 args
[0] = intern ("resume-tty-functions");
2423 XSETTERMINAL (args
[1], t
);
2424 Frun_hook_with_args (2, args
);
2434 /***********************************************************************
2436 ***********************************************************************/
2440 #ifndef HAVE_WINDOW_SYSTEM
2442 term_mouse_moveto (int x
, int y
)
2444 /* TODO: how to set mouse position?
2447 name = (const char *) ttyname (0);
2448 fd = emacs_open (name, O_WRONLY, 0);
2449 SOME_FUNCTION (x, y, fd);
2452 last_mouse_y = y; */
2454 #endif /* HAVE_WINDOW_SYSTEM */
2456 /* Implementation of draw_row_with_mouse_face for TTY/GPM. */
2458 tty_draw_row_with_mouse_face (struct window
*w
, struct glyph_row
*row
,
2459 int start_hpos
, int end_hpos
,
2460 enum draw_glyphs_face draw
)
2462 int nglyphs
= end_hpos
- start_hpos
;
2463 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2464 struct tty_display_info
*tty
= FRAME_TTY (f
);
2465 int face_id
= tty
->mouse_highlight
.mouse_face_face_id
;
2466 int save_x
, save_y
, pos_x
, pos_y
;
2468 if (end_hpos
>= row
->used
[TEXT_AREA
])
2469 nglyphs
= row
->used
[TEXT_AREA
] - start_hpos
;
2471 pos_y
= row
->y
+ WINDOW_TOP_EDGE_Y (w
);
2472 pos_x
= row
->used
[LEFT_MARGIN_AREA
] + start_hpos
+ WINDOW_LEFT_EDGE_X (w
);
2474 /* Save current cursor co-ordinates. */
2475 save_y
= curY (tty
);
2476 save_x
= curX (tty
);
2477 cursor_to (f
, pos_y
, pos_x
);
2479 if (draw
== DRAW_MOUSE_FACE
)
2480 tty_write_glyphs_with_face (f
, row
->glyphs
[TEXT_AREA
] + start_hpos
,
2482 else if (draw
== DRAW_NORMAL_TEXT
)
2483 write_glyphs (f
, row
->glyphs
[TEXT_AREA
] + start_hpos
, nglyphs
);
2485 cursor_to (f
, save_y
, save_x
);
2489 term_mouse_movement (struct frame
*frame
, Gpm_Event
*event
)
2491 /* Has the mouse moved off the glyph it was on at the last sighting? */
2492 if (event
->x
!= last_mouse_x
|| event
->y
!= last_mouse_y
)
2494 frame
->mouse_moved
= 1;
2495 note_mouse_highlight (frame
, event
->x
, event
->y
);
2496 /* Remember which glyph we're now on. */
2497 last_mouse_x
= event
->x
;
2498 last_mouse_y
= event
->y
;
2504 /* Return the Time that corresponds to T. Wrap around on overflow. */
2506 timeval_to_Time (struct timeval
const *t
)
2512 ms
= t
->tv_usec
/ 1000;
2516 /* Return the current position of the mouse.
2518 Set *f to the frame the mouse is in, or zero if the mouse is in no
2519 Emacs frame. If it is set to zero, all the other arguments are
2522 Set *bar_window to Qnil, and *x and *y to the column and
2523 row of the character cell the mouse is over.
2525 Set *timeptr to the time the mouse was at the returned position.
2527 This clears mouse_moved until the next motion
2530 term_mouse_position (struct frame
**fp
, int insist
, Lisp_Object
*bar_window
,
2531 enum scroll_bar_part
*part
, Lisp_Object
*x
,
2532 Lisp_Object
*y
, Time
*timeptr
)
2536 *fp
= SELECTED_FRAME ();
2537 (*fp
)->mouse_moved
= 0;
2542 XSETINT (*x
, last_mouse_x
);
2543 XSETINT (*y
, last_mouse_y
);
2544 gettimeofday(&now
, 0);
2545 *timeptr
= timeval_to_Time (&now
);
2548 /* Prepare a mouse-event in *RESULT for placement in the input queue.
2550 If the event is a button press, then note that we have grabbed
2554 term_mouse_click (struct input_event
*result
, Gpm_Event
*event
,
2560 result
->kind
= GPM_CLICK_EVENT
;
2561 for (i
= 0, j
= GPM_B_LEFT
; i
< 3; i
++, j
>>= 1 )
2563 if (event
->buttons
& j
) {
2564 result
->code
= i
; /* button number */
2568 gettimeofday(&now
, 0);
2569 result
->timestamp
= timeval_to_Time (&now
);
2571 if (event
->type
& GPM_UP
)
2572 result
->modifiers
= up_modifier
;
2573 else if (event
->type
& GPM_DOWN
)
2574 result
->modifiers
= down_modifier
;
2576 result
->modifiers
= 0;
2578 if (event
->type
& GPM_SINGLE
)
2579 result
->modifiers
|= click_modifier
;
2581 if (event
->type
& GPM_DOUBLE
)
2582 result
->modifiers
|= double_modifier
;
2584 if (event
->type
& GPM_TRIPLE
)
2585 result
->modifiers
|= triple_modifier
;
2587 if (event
->type
& GPM_DRAG
)
2588 result
->modifiers
|= drag_modifier
;
2590 if (!(event
->type
& (GPM_MOVE
| GPM_DRAG
))) {
2593 if (event
->modifiers
& (1 << 0))
2594 result
->modifiers
|= shift_modifier
;
2597 if (event
->modifiers
& (1 << 2))
2598 result
->modifiers
|= ctrl_modifier
;
2600 /* 1 << KG_ALT || KG_ALTGR */
2601 if (event
->modifiers
& (1 << 3)
2602 || event
->modifiers
& (1 << 1))
2603 result
->modifiers
|= meta_modifier
;
2606 XSETINT (result
->x
, event
->x
);
2607 XSETINT (result
->y
, event
->y
);
2608 XSETFRAME (result
->frame_or_window
, f
);
2614 handle_one_term_event (struct tty_display_info
*tty
, Gpm_Event
*event
, struct input_event
* hold_quit
)
2616 struct frame
*f
= XFRAME (tty
->top_frame
);
2617 struct input_event ie
;
2625 if (event
->type
& (GPM_MOVE
| GPM_DRAG
)) {
2626 previous_help_echo_string
= help_echo_string
;
2627 help_echo_string
= Qnil
;
2629 Gpm_DrawPointer (event
->x
, event
->y
, fileno (tty
->output
));
2631 if (!term_mouse_movement (f
, event
))
2632 help_echo_string
= previous_help_echo_string
;
2634 /* If the contents of the global variable help_echo_string
2635 has changed, generate a HELP_EVENT. */
2636 if (!NILP (help_echo_string
)
2637 || !NILP (previous_help_echo_string
))
2644 term_mouse_click (&ie
, event
, f
);
2648 if (ie
.kind
!= NO_EVENT
)
2650 kbd_buffer_store_event_hold (&ie
, hold_quit
);
2655 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
2660 XSETFRAME (frame
, f
);
2664 gen_help_event (help_echo_string
, frame
, help_echo_window
,
2665 help_echo_object
, help_echo_pos
);
2672 DEFUN ("gpm-mouse-start", Fgpm_mouse_start
, Sgpm_mouse_start
,
2674 doc
: /* Open a connection to Gpm.
2675 Gpm-mouse can only be activated for one tty at a time. */)
2678 struct frame
*f
= SELECTED_FRAME ();
2679 struct tty_display_info
*tty
2680 = ((f
)->output_method
== output_termcap
2681 ? (f
)->terminal
->display_info
.tty
: NULL
);
2682 Gpm_Connect connection
;
2685 error ("Gpm-mouse only works in the GNU/Linux console");
2687 return Qnil
; /* Already activated, nothing to do. */
2689 error ("Gpm-mouse can only be activated for one tty at a time");
2691 connection
.eventMask
= ~0;
2692 connection
.defaultMask
= ~GPM_HARD
;
2693 connection
.maxMod
= ~0;
2694 connection
.minMod
= 0;
2697 if (Gpm_Open (&connection
, 0) < 0)
2698 error ("Gpm-mouse failed to connect to the gpm daemon");
2702 /* `init_sys_modes' arranges for mouse movements sent through gpm_fd
2703 to generate SIGIOs. Apparently we need to call reset_sys_modes
2704 before calling init_sys_modes. */
2705 reset_sys_modes (tty
);
2706 init_sys_modes (tty
);
2707 add_gpm_wait_descriptor (gpm_fd
);
2716 delete_gpm_wait_descriptor (fd
);
2717 while (Gpm_Close()); /* close all the stack */
2721 DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop
, Sgpm_mouse_stop
,
2723 doc
: /* Close a connection to Gpm. */)
2726 struct frame
*f
= SELECTED_FRAME ();
2727 struct tty_display_info
*tty
2728 = ((f
)->output_method
== output_termcap
2729 ? (f
)->terminal
->display_info
.tty
: NULL
);
2731 if (!tty
|| gpm_tty
!= tty
)
2732 return Qnil
; /* Not activated on this terminal, nothing to do. */
2737 #endif /* HAVE_GPM */
2740 /***********************************************************************
2742 ***********************************************************************/
2744 #if !defined (MSDOS)
2746 /* TTY menu implementation and main ideas are borrowed from msdos.c.
2748 However, unlike on MSDOS, where the menu text is drawn directly to
2749 the display video memory, on a TTY we use display_string (see
2750 display_tty_menu_item in xdisp.c) to put the glyphs produced from
2751 the menu items into the frame's 'desired_matrix' glyph matrix, and
2752 then call update_frame_with_menu to deliver the results to the
2753 glass. The previous contents of the screen, in the form of the
2754 current_matrix, is stashed away, and used to restore screen
2755 contents when the menu selection changes or when the final
2756 selection is made and the menu should be popped down.
2758 The idea of this implementation was suggested by Gerd Moellmann. */
2760 #define TTYM_FAILURE -1
2761 #define TTYM_SUCCESS 1
2762 #define TTYM_NO_SELECT 2
2763 #define TTYM_IA_SELECT 3
2767 /* These hold text of the current and the previous menu help messages. */
2768 static const char *menu_help_message
, *prev_menu_help_message
;
2769 /* Pane number and item number of the menu item which generated the
2770 last menu help message. */
2771 static int menu_help_paneno
, menu_help_itemno
;
2773 static Lisp_Object Qtty_menu_navigation_map
, Qtty_menu_exit
;
2774 static Lisp_Object Qtty_menu_prev_item
, Qtty_menu_next_item
;
2775 static Lisp_Object Qtty_menu_next_menu
, Qtty_menu_prev_menu
;
2776 static Lisp_Object Qtty_menu_select
, Qtty_menu_ignore
;
2777 static Lisp_Object Qtty_menu_mouse_movement
;
2779 typedef struct tty_menu_struct
2783 struct tty_menu_struct
**submenu
;
2784 int *panenumber
; /* Also used as enabled flag. */
2785 ptrdiff_t allocated
;
2788 const char **help_text
;
2791 /* Create a brand new menu structure. */
2794 tty_menu_create (void)
2796 return xzalloc (sizeof *tty_menu_create ());
2799 /* Allocate some (more) memory for MENU ensuring that there is room for one
2803 tty_menu_make_room (tty_menu
*menu
)
2805 if (menu
->allocated
== menu
->count
)
2807 ptrdiff_t allocated
= menu
->allocated
;
2808 menu
->text
= xpalloc (menu
->text
, &allocated
, 1, -1, sizeof *menu
->text
);
2809 menu
->text
= xrealloc (menu
->text
, allocated
* sizeof *menu
->text
);
2810 menu
->submenu
= xrealloc (menu
->submenu
,
2811 allocated
* sizeof *menu
->submenu
);
2812 menu
->panenumber
= xrealloc (menu
->panenumber
,
2813 allocated
* sizeof *menu
->panenumber
);
2814 menu
->help_text
= xrealloc (menu
->help_text
,
2815 allocated
* sizeof *menu
->help_text
);
2816 menu
->allocated
= allocated
;
2820 /* Search the given menu structure for a given pane number. */
2823 tty_menu_search_pane (tty_menu
*menu
, int pane
)
2828 for (i
= 0; i
< menu
->count
; i
++)
2829 if (menu
->submenu
[i
])
2831 if (pane
== menu
->panenumber
[i
])
2832 return menu
->submenu
[i
];
2833 try = tty_menu_search_pane (menu
->submenu
[i
], pane
);
2837 return (tty_menu
*) 0;
2840 /* Determine how much screen space a given menu needs. */
2843 tty_menu_calc_size (tty_menu
*menu
, int *width
, int *height
)
2845 int i
, h2
, w2
, maxsubwidth
, maxheight
;
2847 maxsubwidth
= menu
->width
;
2848 maxheight
= menu
->count
;
2849 for (i
= 0; i
< menu
->count
; i
++)
2851 if (menu
->submenu
[i
])
2853 tty_menu_calc_size (menu
->submenu
[i
], &w2
, &h2
);
2854 if (w2
> maxsubwidth
) maxsubwidth
= w2
;
2855 if (i
+ h2
> maxheight
) maxheight
= i
+ h2
;
2858 *width
= maxsubwidth
;
2859 *height
= maxheight
;
2863 mouse_get_xy (int *x
, int *y
)
2865 struct frame
*sf
= SELECTED_FRAME ();
2866 Lisp_Object lmx
= Qnil
, lmy
= Qnil
, lisp_dummy
;
2867 enum scroll_bar_part part_dummy
;
2870 if (FRAME_TERMINAL (sf
)->mouse_position_hook
)
2871 (*FRAME_TERMINAL (sf
)->mouse_position_hook
) (&sf
, -1,
2872 &lisp_dummy
, &part_dummy
,
2882 /* Display MENU at (X,Y) using FACES, starting with FIRST_ITEM
2886 tty_menu_display (tty_menu
*menu
, int x
, int y
, int pn
, int *faces
,
2887 int mx
, int my
, int first_item
, bool disp_help
)
2889 int i
, face
, width
, enabled
, mousehere
, row
, col
;
2890 struct frame
*sf
= SELECTED_FRAME ();
2891 struct tty_display_info
*tty
= FRAME_TTY (sf
);
2892 /* Don't try to display more menu items than the console can display
2893 using the available screen lines. Exclude the echo area line, as
2894 it will be overwritten by the help-echo anyway. */
2895 int max_items
= min (menu
->count
- first_item
, FRAME_TOTAL_LINES (sf
) - 1 - y
);
2897 menu_help_message
= NULL
;
2899 width
= menu
->width
;
2900 col
= cursorX (tty
);
2901 row
= cursorY (tty
);
2902 for (i
= 0; i
< max_items
; i
++)
2904 int max_width
= width
+ 2; /* +2 for padding blanks on each side */
2905 int j
= i
+ first_item
;
2907 if (menu
->submenu
[j
])
2908 max_width
+= 2; /* for displaying " >" after the item */
2910 = (!menu
->submenu
[j
] && menu
->panenumber
[j
]) || (menu
->submenu
[j
]);
2911 mousehere
= (y
+ i
== my
&& x
<= mx
&& mx
< x
+ max_width
);
2912 face
= faces
[enabled
+ mousehere
* 2];
2913 /* Display the menu help string for the i-th menu item even if
2914 the menu item is currently disabled. That's what the GUI
2916 if (disp_help
&& enabled
+ mousehere
* 2 >= 2)
2918 menu_help_message
= menu
->help_text
[j
];
2919 menu_help_paneno
= pn
- 1;
2920 menu_help_itemno
= j
;
2922 /* Take note of the coordinates of the active menu item, to
2923 display the cursor there. */
2929 display_tty_menu_item (menu
->text
[j
], max_width
, face
, x
, y
+ i
,
2930 menu
->submenu
[j
] != NULL
);
2932 update_frame_with_menu (sf
, row
, col
);
2935 /* --------------------------- X Menu emulation ---------------------- */
2937 /* Create a new pane and place it on the outer-most level. */
2940 tty_menu_add_pane (tty_menu
*menu
, const char *txt
)
2944 tty_menu_make_room (menu
);
2945 menu
->submenu
[menu
->count
] = tty_menu_create ();
2946 menu
->text
[menu
->count
] = (char *)txt
;
2947 menu
->panenumber
[menu
->count
] = ++menu
->panecount
;
2948 menu
->help_text
[menu
->count
] = NULL
;
2951 /* Update the menu width, if necessary. */
2952 len
= menu_item_width ((const unsigned char *) txt
);
2953 if (len
> menu
->width
)
2956 return menu
->panecount
;
2959 /* Create a new item in a menu pane. */
2962 tty_menu_add_selection (tty_menu
*menu
, int pane
,
2963 char *txt
, bool enable
, char const *help_text
)
2969 menu
= tty_menu_search_pane (menu
, pane
);
2973 tty_menu_make_room (menu
);
2974 menu
->submenu
[menu
->count
] = (tty_menu
*) 0;
2975 menu
->text
[menu
->count
] = txt
;
2976 menu
->panenumber
[menu
->count
] = enable
;
2977 menu
->help_text
[menu
->count
] = help_text
;
2980 /* Update the menu width, if necessary. */
2981 len
= menu_item_width ((const unsigned char *) txt
);
2982 if (len
> menu
->width
)
2988 /* Decide where the menu would be placed if requested at (X,Y). */
2991 tty_menu_locate (tty_menu
*menu
, int x
, int y
,
2992 int *ulx
, int *uly
, int *width
, int *height
)
2994 tty_menu_calc_size (menu
, width
, height
);
3000 struct tty_menu_state
3002 struct glyph_matrix
*screen_behind
;
3008 /* Save away the contents of frame F's current frame matrix, and
3009 enable all its rows. Value is a glyph matrix holding the contents
3010 of F's current frame matrix with all its glyph rows enabled. */
3012 static struct glyph_matrix
*
3013 save_and_enable_current_matrix (struct frame
*f
)
3016 struct glyph_matrix
*saved
= xzalloc (sizeof *saved
);
3017 saved
->nrows
= f
->current_matrix
->nrows
;
3018 saved
->rows
= xzalloc (saved
->nrows
* sizeof *saved
->rows
);
3020 for (i
= 0; i
< saved
->nrows
; ++i
)
3022 struct glyph_row
*from
= f
->current_matrix
->rows
+ i
;
3023 struct glyph_row
*to
= saved
->rows
+ i
;
3024 ptrdiff_t nbytes
= from
->used
[TEXT_AREA
] * sizeof (struct glyph
);
3026 to
->glyphs
[TEXT_AREA
] = xmalloc (nbytes
);
3027 memcpy (to
->glyphs
[TEXT_AREA
], from
->glyphs
[TEXT_AREA
], nbytes
);
3028 to
->used
[TEXT_AREA
] = from
->used
[TEXT_AREA
];
3029 /* Make sure every row is enabled, or else update_frame will not
3030 redraw them. (Rows that are identical to what is already on
3031 screen will not be redrawn anyway.) */
3032 to
->enabled_p
= true;
3033 to
->hash
= from
->hash
;
3039 /* Restore the contents of frame F's desired frame matrix from SAVED,
3040 and free memory associated with SAVED. */
3043 restore_desired_matrix (struct frame
*f
, struct glyph_matrix
*saved
)
3047 for (i
= 0; i
< saved
->nrows
; ++i
)
3049 struct glyph_row
*from
= saved
->rows
+ i
;
3050 struct glyph_row
*to
= f
->desired_matrix
->rows
+ i
;
3051 ptrdiff_t nbytes
= from
->used
[TEXT_AREA
] * sizeof (struct glyph
);
3053 eassert (to
->glyphs
[TEXT_AREA
] != from
->glyphs
[TEXT_AREA
]);
3054 memcpy (to
->glyphs
[TEXT_AREA
], from
->glyphs
[TEXT_AREA
], nbytes
);
3055 to
->used
[TEXT_AREA
] = from
->used
[TEXT_AREA
];
3056 to
->enabled_p
= from
->enabled_p
;
3057 to
->hash
= from
->hash
;
3062 free_saved_screen (struct glyph_matrix
*saved
)
3067 return; /* Already freed! */
3069 for (i
= 0; i
< saved
->nrows
; ++i
)
3071 struct glyph_row
*from
= saved
->rows
+ i
;
3073 xfree (from
->glyphs
[TEXT_AREA
]);
3076 xfree (saved
->rows
);
3080 /* Update the display of frame F from its saved contents. */
3082 screen_update (struct frame
*f
, struct glyph_matrix
*mtx
)
3084 restore_desired_matrix (f
, mtx
);
3085 update_frame_with_menu (f
, -1, -1);
3091 MI_ITEM_SELECTED
= 1,
3094 MI_SCROLL_FORWARD
= 4,
3098 /* Read user input and return X and Y coordinates where that input
3099 puts us. We only consider mouse movement and click events, and
3100 keyboard movement commands; the rest are ignored. */
3102 read_menu_input (struct frame
*sf
, int *x
, int *y
, int min_y
, int max_y
,
3107 *first_time
= false;
3108 sf
->mouse_moved
= 1;
3113 bool usable_input
= 1;
3114 mi_result st
= MI_CONTINUE
;
3115 struct tty_display_info
*tty
= FRAME_TTY (sf
);
3116 Lisp_Object saved_mouse_tracking
= do_mouse_tracking
;
3118 /* Signal the keyboard reading routines we are displaying a menu
3119 on this terminal. */
3120 tty
->showing_menu
= 1;
3121 /* We want mouse movements be reported by read_menu_command. */
3122 do_mouse_tracking
= Qt
;
3124 cmd
= read_menu_command ();
3125 } while (NILP (cmd
));
3126 tty
->showing_menu
= 0;
3127 do_mouse_tracking
= saved_mouse_tracking
;
3129 if (EQ (cmd
, Qt
) || EQ (cmd
, Qtty_menu_exit
)
3130 /* If some input switched frames under our feet, exit the
3131 menu, since the menu faces are no longer valid, and the
3132 menu is no longer relevant anyway. */
3133 || sf
!= SELECTED_FRAME ())
3134 return MI_QUIT_MENU
;
3135 if (EQ (cmd
, Qtty_menu_mouse_movement
))
3136 mouse_get_xy (x
, y
);
3137 else if (EQ (cmd
, Qtty_menu_next_menu
))
3142 else if (EQ (cmd
, Qtty_menu_prev_menu
))
3147 else if (EQ (cmd
, Qtty_menu_next_item
))
3152 st
= MI_SCROLL_FORWARD
;
3154 else if (EQ (cmd
, Qtty_menu_prev_item
))
3159 st
= MI_SCROLL_BACK
;
3161 else if (EQ (cmd
, Qtty_menu_select
))
3162 st
= MI_ITEM_SELECTED
;
3163 else if (!EQ (cmd
, Qtty_menu_ignore
))
3166 sf
->mouse_moved
= 1;
3172 /* Display menu, wait for user's response, and return that response. */
3174 tty_menu_activate (tty_menu
*menu
, int *pane
, int *selidx
,
3175 int x0
, int y0
, char **txt
,
3176 void (*help_callback
)(char const *, int, int),
3177 bool kbd_navigation
)
3179 struct tty_menu_state
*state
;
3180 int statecount
, x
, y
, i
;
3181 bool leave
, onepane
;
3182 int result
IF_LINT (= 0);
3183 int title_faces
[4]; /* Face to display the menu title. */
3184 int faces
[4], buffers_num_deleted
= 0;
3185 struct frame
*sf
= SELECTED_FRAME ();
3186 struct tty_display_info
*tty
= FRAME_TTY (sf
);
3188 Lisp_Object selectface
;
3192 /* Don't allow non-positive x0 and y0, lest the menu will wrap
3193 around the display. */
3199 state
= alloca (menu
->panecount
* sizeof (struct tty_menu_state
));
3200 memset (state
, 0, sizeof (*state
));
3202 = lookup_derived_face (sf
, intern ("tty-menu-disabled-face"),
3203 DEFAULT_FACE_ID
, 1);
3205 = lookup_derived_face (sf
, intern ("tty-menu-enabled-face"),
3206 DEFAULT_FACE_ID
, 1);
3207 selectface
= intern ("tty-menu-selected-face");
3208 faces
[2] = lookup_derived_face (sf
, selectface
,
3210 faces
[3] = lookup_derived_face (sf
, selectface
,
3213 /* Make sure the menu title is always displayed with
3214 `tty-menu-selected-face', no matter where the mouse pointer is. */
3215 for (i
= 0; i
< 4; i
++)
3216 title_faces
[i
] = faces
[3];
3220 /* Don't let the title for the "Buffers" popup menu include a
3221 digit (which is ugly).
3223 This is a terrible kludge, but I think the "Buffers" case is
3224 the only one where the title includes a number, so it doesn't
3225 seem to be necessary to make this more general. */
3226 if (strncmp (menu
->text
[0], "Buffers 1", 9) == 0)
3228 menu
->text
[0][7] = '\0';
3229 buffers_num_deleted
= 1;
3232 /* Force update of the current frame, so that the desired and the
3233 current matrices are identical. */
3234 update_frame_with_menu (sf
, -1, -1);
3235 state
[0].menu
= menu
;
3236 state
[0].screen_behind
= save_and_enable_current_matrix (sf
);
3238 /* Display the menu title. We subtract 1 from x0 and y0 because we
3239 want to interpret them as zero-based column and row coordinates,
3240 and also because we want the first item of the menu, not its
3241 title, to appear at x0,y0. */
3242 tty_menu_display (menu
, x0
- 1, y0
- 1, 1, title_faces
, x0
- 1, y0
- 1, 0, 0);
3244 /* Turn off the cursor. Otherwise it shows through the menu
3245 panes, which is ugly. */
3246 col
= cursorX (tty
);
3247 row
= cursorY (tty
);
3248 tty_hide_cursor (tty
);
3250 if (buffers_num_deleted
)
3251 menu
->text
[0][7] = ' ';
3252 onepane
= menu
->count
== 1 && menu
->submenu
[0];
3255 menu
->width
= menu
->submenu
[0]->width
;
3256 state
[0].menu
= menu
->submenu
[0];
3260 state
[0].menu
= menu
;
3262 state
[0].x
= x0
- 1;
3264 state
[0].pane
= onepane
;
3273 mi_result input_status
;
3274 int min_y
= state
[0].y
;
3275 int max_y
= min (min_y
+ state
[0].menu
->count
, FRAME_TOTAL_LINES (sf
) - 1) - 1;
3277 input_status
= read_menu_input (sf
, &x
, &y
, min_y
, max_y
, &first_time
);
3281 switch (input_status
)
3284 /* Remove the last help-echo, so that it doesn't
3285 re-appear after "Quit". */
3286 show_help_echo (Qnil
, Qnil
, Qnil
, Qnil
);
3287 result
= TTYM_NO_SELECT
;
3301 case MI_SCROLL_FORWARD
:
3302 if (y
- min_y
== state
[0].menu
->count
- 1 - first_item
)
3311 case MI_SCROLL_BACK
:
3312 if (first_item
== 0)
3315 first_item
= state
[0].menu
->count
- 1 - (y
- min_y
);
3322 /* MI_ITEM_SELECTED is handled below, so nothing to do. */
3326 if (sf
->mouse_moved
&& input_status
!= MI_QUIT_MENU
)
3328 sf
->mouse_moved
= 0;
3329 result
= TTYM_IA_SELECT
;
3330 for (i
= 0; i
< statecount
; i
++)
3331 if (state
[i
].x
<= x
&& x
< state
[i
].x
+ state
[i
].menu
->width
+ 2)
3333 int dy
= y
- state
[i
].y
+ first_item
;
3334 if (0 <= dy
&& dy
< state
[i
].menu
->count
)
3336 if (!state
[i
].menu
->submenu
[dy
])
3338 if (state
[i
].menu
->panenumber
[dy
])
3339 result
= TTYM_SUCCESS
;
3341 result
= TTYM_IA_SELECT
;
3343 *pane
= state
[i
].pane
- 1;
3345 /* We hit some part of a menu, so drop extra menus that
3346 have been opened. That does not include an open and
3348 if (i
!= statecount
- 2
3349 || state
[i
].menu
->submenu
[dy
] != state
[i
+ 1].menu
)
3350 while (i
!= statecount
- 1)
3353 screen_update (sf
, state
[statecount
].screen_behind
);
3354 state
[statecount
].screen_behind
= NULL
;
3356 if (i
== statecount
- 1 && state
[i
].menu
->submenu
[dy
])
3358 tty_menu_display (state
[i
].menu
,
3362 faces
, x
, y
, first_item
, 1);
3363 state
[statecount
].menu
= state
[i
].menu
->submenu
[dy
];
3364 state
[statecount
].pane
= state
[i
].menu
->panenumber
[dy
];
3365 state
[statecount
].screen_behind
3366 = save_and_enable_current_matrix (sf
);
3368 = state
[i
].x
+ state
[i
].menu
->width
+ 2;
3369 state
[statecount
].y
= y
;
3374 tty_menu_display (state
[statecount
- 1].menu
,
3375 state
[statecount
- 1].x
,
3376 state
[statecount
- 1].y
,
3377 state
[statecount
- 1].pane
,
3378 faces
, x
, y
, first_item
, 1);
3379 /* The call to display help-echo below will move the cursor,
3380 so remember its current position as computed by
3381 tty_menu_display. */
3382 col
= cursorX (tty
);
3383 row
= cursorY (tty
);
3386 /* Display the help-echo message for the currently-selected menu
3388 if ((menu_help_message
|| prev_menu_help_message
)
3389 && menu_help_message
!= prev_menu_help_message
)
3391 help_callback (menu_help_message
,
3392 menu_help_paneno
, menu_help_itemno
);
3393 /* Move the cursor to the beginning of the current menu
3394 item, so that screen readers and other accessibility aids
3395 know where the active region is. */
3396 cursor_to (sf
, row
, col
);
3397 prev_menu_help_message
= menu_help_message
;
3399 /* Both tty_menu_display and help_callback invoke update_end,
3400 which calls tty_show_cursor. Re-hide it, so it doesn't show
3401 through the menus. */
3402 tty_hide_cursor (tty
);
3403 fflush (tty
->output
);
3406 sf
->mouse_moved
= 0;
3407 screen_update (sf
, state
[0].screen_behind
);
3408 while (statecount
--)
3409 free_saved_screen (state
[statecount
].screen_behind
);
3410 tty_show_cursor (tty
); /* Turn cursor back on. */
3411 fflush (tty
->output
);
3413 /* Clean up any mouse events that are waiting inside Emacs event queue.
3414 These events are likely to be generated before the menu was even
3415 displayed, probably because the user pressed and released the button
3416 (which invoked the menu) too quickly. If we don't remove these events,
3417 Emacs will process them after we return and surprise the user. */
3418 discard_mouse_events ();
3419 if (!kbd_buffer_events_waiting ())
3420 clear_input_pending ();
3424 /* Dispose of a menu. */
3427 tty_menu_destroy (tty_menu
*menu
)
3430 if (menu
->allocated
)
3432 for (i
= 0; i
< menu
->count
; i
++)
3433 if (menu
->submenu
[i
])
3434 tty_menu_destroy (menu
->submenu
[i
]);
3436 xfree (menu
->submenu
);
3437 xfree (menu
->panenumber
);
3438 xfree (menu
->help_text
);
3441 menu_help_message
= prev_menu_help_message
= NULL
;
3444 /* Show help HELP_STRING, or clear help if HELP_STRING is null.
3446 PANE is the pane number, and ITEM is the menu item number in
3447 the menu (currently not used). */
3450 tty_menu_help_callback (char const *help_string
, int pane
, int item
)
3452 Lisp_Object
*first_item
;
3453 Lisp_Object pane_name
;
3454 Lisp_Object menu_object
;
3456 first_item
= XVECTOR (menu_items
)->contents
;
3457 if (EQ (first_item
[0], Qt
))
3458 pane_name
= first_item
[MENU_ITEMS_PANE_NAME
];
3459 else if (EQ (first_item
[0], Qquote
))
3460 /* This shouldn't happen, see xmenu_show. */
3461 pane_name
= empty_unibyte_string
;
3463 pane_name
= first_item
[MENU_ITEMS_ITEM_NAME
];
3465 /* (menu-item MENU-NAME PANE-NUMBER) */
3466 menu_object
= list3 (Qmenu_item
, pane_name
, make_number (pane
));
3467 show_help_echo (help_string
? build_string (help_string
) : Qnil
,
3468 Qnil
, menu_object
, make_number (item
));
3472 tty_pop_down_menu (Lisp_Object arg
)
3474 tty_menu
*menu
= XSAVE_POINTER (arg
, 0);
3477 tty_menu_destroy (menu
);
3481 /* Return the zero-based index of the last menu-bar item on frame F. */
3483 tty_menu_last_menubar_item (struct frame
*f
)
3487 eassert (FRAME_TERMCAP_P (f
) && FRAME_LIVE_P (f
));
3488 if (FRAME_TERMCAP_P (f
) && FRAME_LIVE_P (f
))
3490 Lisp_Object items
= FRAME_MENU_BAR_ITEMS (f
);
3492 while (i
< ASIZE (items
))
3496 str
= AREF (items
, i
+ 1);
3501 i
-= 4; /* Went one too far! */
3506 /* Find in frame F's menu bar the menu item that is next or previous
3507 to the item at X/Y, and return that item's position in X/Y. WHICH
3508 says which one--next or previous--item to look for. X and Y are
3509 measured in character cells. This should only be called on TTY
3512 tty_menu_new_item_coords (struct frame
*f
, int which
, int *x
, int *y
)
3514 eassert (FRAME_TERMCAP_P (f
) && FRAME_LIVE_P (f
));
3515 if (FRAME_TERMCAP_P (f
) && FRAME_LIVE_P (f
))
3517 Lisp_Object items
= FRAME_MENU_BAR_ITEMS (f
);
3518 int last_i
= tty_menu_last_menubar_item (f
);
3521 /* This loop assumes a single menu-bar line, and will fail to
3522 find an item if it is not in the first line. Note that
3523 make_lispy_event in keyboard.c makes the same assumption. */
3524 for (i
= 0, prev_x
= -1; i
< ASIZE (items
); i
+= 4)
3526 Lisp_Object pos
, str
;
3529 str
= AREF (items
, i
+ 1);
3530 pos
= AREF (items
, i
+ 3);
3535 /* We use <= so the blank between 2 items on a TTY is
3536 considered part of the previous item. */
3537 && *x
<= ix
+ menu_item_width (SDATA (str
)))
3539 /* Found current item. Now compute the X coordinate of
3540 the previous or next item. */
3541 if (which
== TTYM_NEXT
)
3544 *x
= XINT (AREF (items
, i
+ 4 + 3));
3546 *x
= 0; /* Wrap around to the first item. */
3548 else if (prev_x
< 0)
3550 /* Wrap around to the last item. */
3551 *x
= XINT (AREF (items
, last_i
+ 3));
3562 /* WINDOWSNT uses this as menu_show_hook, see w32console.c. */
3564 tty_menu_show (struct frame
*f
, int x
, int y
, int menuflags
,
3565 Lisp_Object title
, const char **error_name
)
3568 int pane
, selidx
, lpane
, status
;
3569 Lisp_Object entry
, pane_prefix
;
3571 int ulx
, uly
, width
, height
;
3573 int dispwidth
, dispheight
;
3574 int i
, j
, lines
, maxlines
;
3576 ptrdiff_t specpdl_count
;
3578 eassert (FRAME_TERMCAP_P (f
));
3581 if (menu_items_n_panes
== 0)
3584 if (menu_items_used
<= MENU_ITEMS_PANE_LENGTH
)
3586 *error_name
= "Empty menu";
3590 /* Make the menu on that window. */
3591 menu
= tty_menu_create ();
3593 /* Don't GC while we prepare and show the menu, because we give the
3594 menu functions pointers to the contents of strings. */
3595 specpdl_count
= inhibit_garbage_collection ();
3597 /* Avoid crashes if, e.g., another client will connect while we
3599 temporarily_switch_to_single_kboard (f
);
3601 /* Adjust coordinates to be root-window-relative. */
3602 item_x
= x
+= f
->left_pos
;
3603 item_y
= y
+= f
->top_pos
;
3605 /* Create all the necessary panes and their items. */
3606 maxwidth
= maxlines
= lines
= i
= 0;
3607 lpane
= TTYM_FAILURE
;
3608 while (i
< menu_items_used
)
3610 if (EQ (AREF (menu_items
, i
), Qt
))
3612 /* Create a new pane. */
3613 Lisp_Object pane_name
, prefix
;
3614 const char *pane_string
;
3616 maxlines
= max (maxlines
, lines
);
3618 pane_name
= AREF (menu_items
, i
+ MENU_ITEMS_PANE_NAME
);
3619 prefix
= AREF (menu_items
, i
+ MENU_ITEMS_PANE_PREFIX
);
3620 pane_string
= (NILP (pane_name
)
3621 ? "" : SSDATA (pane_name
));
3622 if ((menuflags
& MENU_KEYMAPS
) && !NILP (prefix
))
3625 lpane
= tty_menu_add_pane (menu
, pane_string
);
3626 if (lpane
== TTYM_FAILURE
)
3628 tty_menu_destroy (menu
);
3629 *error_name
= "Can't create pane";
3633 i
+= MENU_ITEMS_PANE_LENGTH
;
3635 /* Find the width of the widest item in this pane. */
3637 while (j
< menu_items_used
)
3640 item
= AREF (menu_items
, j
);
3648 width
= SBYTES (item
);
3649 if (width
> maxwidth
)
3652 j
+= MENU_ITEMS_ITEM_LENGTH
;
3655 /* Ignore a nil in the item list.
3656 It's meaningful only for dialog boxes. */
3657 else if (EQ (AREF (menu_items
, i
), Qquote
))
3661 /* Create a new item within current pane. */
3662 Lisp_Object item_name
, enable
, descrip
, help
;
3664 char const *help_string
;
3666 item_name
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
);
3667 enable
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_ENABLE
);
3668 descrip
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
);
3669 help
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_HELP
);
3670 help_string
= STRINGP (help
) ? SSDATA (help
) : NULL
;
3672 if (!NILP (descrip
))
3674 /* If alloca is fast, use that to make the space,
3675 to reduce gc needs. */
3676 item_data
= (char *) alloca (maxwidth
+ SBYTES (descrip
) + 1);
3677 memcpy (item_data
, SSDATA (item_name
), SBYTES (item_name
));
3678 for (j
= SCHARS (item_name
); j
< maxwidth
; j
++)
3680 memcpy (item_data
+ j
, SSDATA (descrip
), SBYTES (descrip
));
3681 item_data
[j
+ SBYTES (descrip
)] = 0;
3684 item_data
= SSDATA (item_name
);
3686 if (lpane
== TTYM_FAILURE
3687 || (! tty_menu_add_selection (menu
, lpane
, item_data
,
3688 !NILP (enable
), help_string
)))
3690 tty_menu_destroy (menu
);
3691 *error_name
= "Can't add selection to menu";
3695 i
+= MENU_ITEMS_ITEM_LENGTH
;
3700 maxlines
= max (maxlines
, lines
);
3702 /* All set and ready to fly. */
3703 dispwidth
= f
->text_cols
;
3704 dispheight
= f
->text_lines
;
3705 x
= min (x
, dispwidth
);
3706 y
= min (y
, dispheight
);
3709 tty_menu_locate (menu
, x
, y
, &ulx
, &uly
, &width
, &height
);
3710 if (ulx
+ width
> dispwidth
)
3712 x
-= (ulx
+ width
) - dispwidth
;
3713 ulx
= dispwidth
- width
;
3715 if (uly
+ height
> dispheight
)
3717 y
-= (uly
+ height
) - dispheight
;
3718 uly
= dispheight
- height
;
3721 if (FRAME_HAS_MINIBUF_P (f
) && uly
+ height
> dispheight
- 2)
3723 /* Move the menu away of the echo area, to avoid overwriting the
3724 menu with help echo messages or vice versa. */
3725 if (BUFFERP (echo_area_buffer
[0]) && WINDOWP (echo_area_window
))
3727 y
-= WINDOW_TOTAL_LINES (XWINDOW (echo_area_window
)) + 1;
3728 uly
-= WINDOW_TOTAL_LINES (XWINDOW (echo_area_window
)) + 1;
3737 if (ulx
< 0) x
-= ulx
;
3738 if (uly
< 0) y
-= uly
;
3741 /* This code doesn't make sense on a TTY, since it can easily annul
3742 the adjustments above that carefully avoid truncation of the menu
3743 items. I think it was written to fix some problem that only
3747 /* If position was not given by a mouse click, adjust so upper left
3748 corner of the menu as a whole ends up at given coordinates. This
3749 is what x-popup-menu says in its documentation. */
3751 y
+= 1.5 * height
/ (maxlines
+ 2);
3757 record_unwind_protect (tty_pop_down_menu
, make_save_ptr (menu
));
3759 specbind (Qoverriding_terminal_local_map
,
3760 Fsymbol_value (Qtty_menu_navigation_map
));
3761 status
= tty_menu_activate (menu
, &pane
, &selidx
, x
, y
, &datap
,
3762 tty_menu_help_callback
,
3763 menuflags
& MENU_KBD_NAVIGATION
);
3764 entry
= pane_prefix
= Qnil
;
3769 /* Find the item number SELIDX in pane number PANE. */
3771 while (i
< menu_items_used
)
3773 if (EQ (AREF (menu_items
, i
), Qt
))
3777 = AREF (menu_items
, i
+ MENU_ITEMS_PANE_PREFIX
);
3779 i
+= MENU_ITEMS_PANE_LENGTH
;
3788 = AREF (menu_items
, i
+ MENU_ITEMS_ITEM_VALUE
);
3789 if (menuflags
& MENU_KEYMAPS
)
3791 entry
= Fcons (entry
, Qnil
);
3792 if (!NILP (pane_prefix
))
3793 entry
= Fcons (pane_prefix
, entry
);
3799 i
+= MENU_ITEMS_ITEM_LENGTH
;
3806 tty_menu_new_item_coords (f
, status
, &item_x
, &item_y
);
3807 entry
= Fcons (make_number (item_x
), make_number (item_y
));
3811 *error_name
= "Can't activate menu";
3812 case TTYM_IA_SELECT
:
3814 case TTYM_NO_SELECT
:
3815 /* If the selected frame was changed while we displayed a menu,
3816 throw to top level in order to undo any temporary settings
3817 made by TTY menu code. */
3818 if (f
!= SELECTED_FRAME ())
3820 /* Make "Cancel" equivalent to C-g unless FOR_CLICK (which means
3821 the menu was invoked with a mouse event as POSITION). */
3822 if (!(menuflags
& MENU_FOR_CLICK
))
3823 Fsignal (Qquit
, Qnil
);
3829 unbind_to (specpdl_count
, Qnil
);
3837 /***********************************************************************
3839 ***********************************************************************/
3841 /* Initialize the tty-dependent part of frame F. The frame must
3842 already have its device initialized. */
3845 create_tty_output (struct frame
*f
)
3847 struct tty_output
*t
= xzalloc (sizeof *t
);
3849 eassert (FRAME_TERMCAP_P (f
));
3851 t
->display_info
= FRAME_TERMINAL (f
)->display_info
.tty
;
3853 f
->output_data
.tty
= t
;
3856 /* Delete frame F's face cache, and its tty-dependent part. */
3859 tty_free_frame_resources (struct frame
*f
)
3861 eassert (FRAME_TERMCAP_P (f
));
3862 free_frame_faces (f
);
3863 xfree (f
->output_data
.tty
);
3868 /* Delete frame F's face cache. */
3871 tty_free_frame_resources (struct frame
*f
)
3873 eassert (FRAME_TERMCAP_P (f
) || FRAME_MSDOS_P (f
));
3874 free_frame_faces (f
);
3878 /* Reset the hooks in TERMINAL. */
3881 clear_tty_hooks (struct terminal
*terminal
)
3884 terminal
->cursor_to_hook
= 0;
3885 terminal
->raw_cursor_to_hook
= 0;
3886 terminal
->clear_to_end_hook
= 0;
3887 terminal
->clear_frame_hook
= 0;
3888 terminal
->clear_end_of_line_hook
= 0;
3889 terminal
->ins_del_lines_hook
= 0;
3890 terminal
->insert_glyphs_hook
= 0;
3891 terminal
->write_glyphs_hook
= 0;
3892 terminal
->delete_glyphs_hook
= 0;
3893 terminal
->ring_bell_hook
= 0;
3894 terminal
->reset_terminal_modes_hook
= 0;
3895 terminal
->set_terminal_modes_hook
= 0;
3896 terminal
->update_begin_hook
= 0;
3897 terminal
->update_end_hook
= 0;
3898 terminal
->set_terminal_window_hook
= 0;
3899 terminal
->mouse_position_hook
= 0;
3900 terminal
->frame_rehighlight_hook
= 0;
3901 terminal
->frame_raise_lower_hook
= 0;
3902 terminal
->fullscreen_hook
= 0;
3903 terminal
->menu_show_hook
= 0;
3904 terminal
->set_vertical_scroll_bar_hook
= 0;
3905 terminal
->set_horizontal_scroll_bar_hook
= 0;
3906 terminal
->condemn_scroll_bars_hook
= 0;
3907 terminal
->redeem_scroll_bar_hook
= 0;
3908 terminal
->judge_scroll_bars_hook
= 0;
3909 terminal
->read_socket_hook
= 0;
3910 terminal
->frame_up_to_date_hook
= 0;
3912 /* Leave these two set, or suspended frames are not deleted
3914 terminal
->delete_frame_hook
= &tty_free_frame_resources
;
3915 terminal
->delete_terminal_hook
= &delete_tty
;
3918 /* Initialize hooks in TERMINAL with the values needed for a tty. */
3921 set_tty_hooks (struct terminal
*terminal
)
3923 terminal
->cursor_to_hook
= &tty_cursor_to
;
3924 terminal
->raw_cursor_to_hook
= &tty_raw_cursor_to
;
3925 terminal
->clear_to_end_hook
= &tty_clear_to_end
;
3926 terminal
->clear_frame_hook
= &tty_clear_frame
;
3927 terminal
->clear_end_of_line_hook
= &tty_clear_end_of_line
;
3928 terminal
->ins_del_lines_hook
= &tty_ins_del_lines
;
3929 terminal
->insert_glyphs_hook
= &tty_insert_glyphs
;
3930 terminal
->write_glyphs_hook
= &tty_write_glyphs
;
3931 terminal
->delete_glyphs_hook
= &tty_delete_glyphs
;
3932 terminal
->ring_bell_hook
= &tty_ring_bell
;
3933 terminal
->reset_terminal_modes_hook
= &tty_reset_terminal_modes
;
3934 terminal
->set_terminal_modes_hook
= &tty_set_terminal_modes
;
3935 terminal
->update_end_hook
= &tty_update_end
;
3937 terminal
->menu_show_hook
= &x_menu_show
;
3939 terminal
->menu_show_hook
= &tty_menu_show
;
3941 terminal
->set_terminal_window_hook
= &tty_set_terminal_window
;
3942 terminal
->read_socket_hook
= &tty_read_avail_input
; /* keyboard.c */
3943 terminal
->delete_frame_hook
= &tty_free_frame_resources
;
3944 terminal
->delete_terminal_hook
= &delete_tty
;
3945 /* Other hooks are NULL by default. */
3948 /* If FD is the controlling terminal, drop it. */
3950 dissociate_if_controlling_tty (int fd
)
3952 /* If tcgetpgrp succeeds, fd is the controlling terminal,
3953 so dissociate it by invoking setsid. */
3954 if (tcgetpgrp (fd
) >= 0 && setsid () < 0)
3957 /* setsid failed, presumably because Emacs is already a process
3958 group leader. Fall back on the obsolescent way to dissociate
3959 a controlling tty. */
3961 block_tty_out_signal (&oldset
);
3962 ioctl (fd
, TIOCNOTTY
, 0);
3963 unblock_tty_out_signal (&oldset
);
3968 /* Create a termcap display on the tty device with the given name and
3971 If NAME is NULL, then use the controlling tty, i.e., "/dev/tty".
3972 Otherwise NAME should be a path to the tty device file,
3975 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
3977 If MUST_SUCCEED is true, then all errors are fatal. */
3980 init_tty (const char *name
, const char *terminal_type
, bool must_succeed
)
3983 char **address
= &area
;
3985 struct tty_display_info
*tty
= NULL
;
3986 struct terminal
*terminal
= NULL
;
3988 bool ctty
= false; /* True if asked to open controlling tty. */
3991 maybe_fatal (must_succeed
, 0,
3992 "Unknown terminal type",
3993 "Unknown terminal type");
3997 if (!strcmp (name
, DEV_TTY
))
4000 /* If we already have a terminal on the given device, use that. If
4001 all such terminals are suspended, create a new one instead. */
4002 /* XXX Perhaps this should be made explicit by having init_tty
4003 always create a new terminal and separating terminal and frame
4004 creation on Lisp level. */
4005 terminal
= get_named_tty (name
);
4009 terminal
= create_terminal (output_termcap
, NULL
);
4012 maybe_fatal (0, 0, "Attempt to create another terminal %s", "",
4015 tty
= &the_only_display_info
;
4017 tty
= xzalloc (sizeof *tty
);
4019 tty
->top_frame
= Qnil
;
4020 tty
->next
= tty_list
;
4023 terminal
->display_info
.tty
= tty
;
4024 tty
->terminal
= terminal
;
4026 tty
->Wcm
= xmalloc (sizeof *tty
->Wcm
);
4029 encode_terminal_src_size
= 0;
4030 encode_terminal_dst_size
= 0;
4034 set_tty_hooks (terminal
);
4037 /* Open the terminal device. */
4039 /* If !ctty, don't recognize it as our controlling terminal, and
4040 don't make it the controlling tty if we don't have one now.
4042 Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
4043 defined on Hurd. On other systems, we need to explicitly
4044 dissociate ourselves from the controlling tty when we want to
4045 open a frame on the same terminal. */
4046 int flags
= O_RDWR
| O_NOCTTY
| (ctty
? 0 : O_IGNORE_CTTY
);
4047 int fd
= emacs_open (name
, flags
, 0);
4048 tty
->input
= tty
->output
4049 = ((fd
< 0 || ! isatty (fd
))
4051 : fdopen (fd
, "w+"));
4055 char const *diagnostic
4056 = (fd
< 0) ? "Could not open file: %s" : "Not a tty device: %s";
4058 maybe_fatal (must_succeed
, terminal
, diagnostic
, diagnostic
, name
);
4061 tty
->name
= xstrdup (name
);
4062 terminal
->name
= xstrdup (name
);
4064 if (!O_IGNORE_CTTY
&& !ctty
)
4065 dissociate_if_controlling_tty (fd
);
4068 tty
->type
= xstrdup (terminal_type
);
4070 add_keyboard_wait_descriptor (fileno (tty
->input
));
4074 /* On some systems, tgetent tries to access the controlling
4076 block_tty_out_signal (&oldset
);
4077 status
= tgetent (tty
->termcap_term_buffer
, terminal_type
);
4078 if (tty
->termcap_term_buffer
[TERMCAP_BUFFER_SIZE
- 1])
4080 unblock_tty_out_signal (&oldset
);
4085 maybe_fatal (must_succeed
, terminal
,
4086 "Cannot open terminfo database file",
4087 "Cannot open terminfo database file");
4089 maybe_fatal (must_succeed
, terminal
,
4090 "Cannot open termcap database file",
4091 "Cannot open termcap database file");
4096 maybe_fatal (must_succeed
, terminal
,
4097 "Terminal type %s is not defined",
4098 "Terminal type %s is not defined.\n\
4099 If that is not the actual type of terminal you have,\n\
4100 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
4101 `setenv TERM ...') to specify the correct type. It may be necessary\n"
4103 "to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
4105 "to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
4110 area
= tty
->termcap_strings_buffer
;
4111 tty
->TS_ins_line
= tgetstr ("al", address
);
4112 tty
->TS_ins_multi_lines
= tgetstr ("AL", address
);
4113 tty
->TS_bell
= tgetstr ("bl", address
);
4114 BackTab (tty
) = tgetstr ("bt", address
);
4115 tty
->TS_clr_to_bottom
= tgetstr ("cd", address
);
4116 tty
->TS_clr_line
= tgetstr ("ce", address
);
4117 tty
->TS_clr_frame
= tgetstr ("cl", address
);
4118 ColPosition (tty
) = NULL
; /* tgetstr ("ch", address); */
4119 AbsPosition (tty
) = tgetstr ("cm", address
);
4120 CR (tty
) = tgetstr ("cr", address
);
4121 tty
->TS_set_scroll_region
= tgetstr ("cs", address
);
4122 tty
->TS_set_scroll_region_1
= tgetstr ("cS", address
);
4123 RowPosition (tty
) = tgetstr ("cv", address
);
4124 tty
->TS_del_char
= tgetstr ("dc", address
);
4125 tty
->TS_del_multi_chars
= tgetstr ("DC", address
);
4126 tty
->TS_del_line
= tgetstr ("dl", address
);
4127 tty
->TS_del_multi_lines
= tgetstr ("DL", address
);
4128 tty
->TS_delete_mode
= tgetstr ("dm", address
);
4129 tty
->TS_end_delete_mode
= tgetstr ("ed", address
);
4130 tty
->TS_end_insert_mode
= tgetstr ("ei", address
);
4131 Home (tty
) = tgetstr ("ho", address
);
4132 tty
->TS_ins_char
= tgetstr ("ic", address
);
4133 tty
->TS_ins_multi_chars
= tgetstr ("IC", address
);
4134 tty
->TS_insert_mode
= tgetstr ("im", address
);
4135 tty
->TS_pad_inserted_char
= tgetstr ("ip", address
);
4136 tty
->TS_end_keypad_mode
= tgetstr ("ke", address
);
4137 tty
->TS_keypad_mode
= tgetstr ("ks", address
);
4138 LastLine (tty
) = tgetstr ("ll", address
);
4139 Right (tty
) = tgetstr ("nd", address
);
4140 Down (tty
) = tgetstr ("do", address
);
4142 Down (tty
) = tgetstr ("nl", address
); /* Obsolete name for "do". */
4143 if (tgetflag ("bs"))
4144 Left (tty
) = "\b"; /* Can't possibly be longer! */
4145 else /* (Actually, "bs" is obsolete...) */
4146 Left (tty
) = tgetstr ("le", address
);
4148 Left (tty
) = tgetstr ("bc", address
); /* Obsolete name for "le". */
4149 tty
->TS_pad_char
= tgetstr ("pc", address
);
4150 tty
->TS_repeat
= tgetstr ("rp", address
);
4151 tty
->TS_end_standout_mode
= tgetstr ("se", address
);
4152 tty
->TS_fwd_scroll
= tgetstr ("sf", address
);
4153 tty
->TS_standout_mode
= tgetstr ("so", address
);
4154 tty
->TS_rev_scroll
= tgetstr ("sr", address
);
4155 tty
->Wcm
->cm_tab
= tgetstr ("ta", address
);
4156 tty
->TS_end_termcap_modes
= tgetstr ("te", address
);
4157 tty
->TS_termcap_modes
= tgetstr ("ti", address
);
4158 Up (tty
) = tgetstr ("up", address
);
4159 tty
->TS_visible_bell
= tgetstr ("vb", address
);
4160 tty
->TS_cursor_normal
= tgetstr ("ve", address
);
4161 tty
->TS_cursor_visible
= tgetstr ("vs", address
);
4162 tty
->TS_cursor_invisible
= tgetstr ("vi", address
);
4163 tty
->TS_set_window
= tgetstr ("wi", address
);
4165 tty
->TS_enter_underline_mode
= tgetstr ("us", address
);
4166 tty
->TS_exit_underline_mode
= tgetstr ("ue", address
);
4167 tty
->TS_enter_bold_mode
= tgetstr ("md", address
);
4168 tty
->TS_enter_italic_mode
= tgetstr ("ZH", address
);
4169 tty
->TS_enter_dim_mode
= tgetstr ("mh", address
);
4170 tty
->TS_enter_reverse_mode
= tgetstr ("mr", address
);
4171 tty
->TS_enter_alt_charset_mode
= tgetstr ("as", address
);
4172 tty
->TS_exit_alt_charset_mode
= tgetstr ("ae", address
);
4173 tty
->TS_exit_attribute_mode
= tgetstr ("me", address
);
4175 MultiUp (tty
) = tgetstr ("UP", address
);
4176 MultiDown (tty
) = tgetstr ("DO", address
);
4177 MultiLeft (tty
) = tgetstr ("LE", address
);
4178 MultiRight (tty
) = tgetstr ("RI", address
);
4180 /* SVr4/ANSI color support. If "op" isn't available, don't support
4181 color because we can't switch back to the default foreground and
4183 tty
->TS_orig_pair
= tgetstr ("op", address
);
4184 if (tty
->TS_orig_pair
)
4186 tty
->TS_set_foreground
= tgetstr ("AF", address
);
4187 tty
->TS_set_background
= tgetstr ("AB", address
);
4188 if (!tty
->TS_set_foreground
)
4191 tty
->TS_set_foreground
= tgetstr ("Sf", address
);
4192 tty
->TS_set_background
= tgetstr ("Sb", address
);
4195 tty
->TN_max_colors
= tgetnum ("Co");
4196 tty
->TN_max_pairs
= tgetnum ("pa");
4198 tty
->TN_no_color_video
= tgetnum ("NC");
4199 if (tty
->TN_no_color_video
== -1)
4200 tty
->TN_no_color_video
= 0;
4203 tty_default_color_capabilities (tty
, 1);
4205 MagicWrap (tty
) = tgetflag ("xn");
4206 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
4207 the former flag imply the latter. */
4208 AutoWrap (tty
) = MagicWrap (tty
) || tgetflag ("am");
4209 tty
->memory_below_frame
= tgetflag ("db");
4210 tty
->TF_hazeltine
= tgetflag ("hz");
4211 tty
->must_write_spaces
= tgetflag ("in");
4212 tty
->meta_key
= tgetflag ("km") || tgetflag ("MT");
4213 tty
->TF_insmode_motion
= tgetflag ("mi");
4214 tty
->TF_standout_motion
= tgetflag ("ms");
4215 tty
->TF_underscore
= tgetflag ("ul");
4216 tty
->TF_teleray
= tgetflag ("xt");
4221 struct frame
*f
= XFRAME (selected_frame
);
4224 initialize_w32_display (terminal
, &width
, &height
);
4226 FrameRows (tty
) = height
;
4227 FrameCols (tty
) = width
;
4228 tty
->specified_window
= height
;
4230 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_none
;
4231 FRAME_HAS_HORIZONTAL_SCROLL_BARS (f
) = 0;
4232 tty
->char_ins_del_ok
= 1;
4238 if (strcmp (terminal_type
, "internal") == 0)
4239 terminal
->type
= output_msdos_raw
;
4240 initialize_msdos_display (terminal
);
4242 get_tty_size (fileno (tty
->input
), &width
, &height
);
4243 FrameCols (tty
) = width
;
4244 FrameRows (tty
) = height
;
4245 tty
->char_ins_del_ok
= 0;
4246 init_baud_rate (fileno (tty
->input
));
4249 tty
->output
= stdout
;
4251 /* The following two are inaccessible from w32console.c. */
4252 terminal
->delete_frame_hook
= &tty_free_frame_resources
;
4253 terminal
->delete_terminal_hook
= &delete_tty
;
4255 tty
->name
= xstrdup (name
);
4256 terminal
->name
= xstrdup (name
);
4257 tty
->type
= xstrdup (terminal_type
);
4259 add_keyboard_wait_descriptor (0);
4261 tty
->delete_in_insert_mode
= 1;
4264 tty
->scroll_region_ok
= 0;
4266 /* Seems to insert lines when it's not supposed to, messing up the
4267 display. In doing a trace, it didn't seem to be called much, so I
4268 don't think we're losing anything by turning it off. */
4269 tty
->line_ins_del_ok
= 0;
4271 tty
->TN_max_colors
= 16; /* Must be non-zero for tty-display-color-p. */
4275 terminal
->mouse_position_hook
= term_mouse_position
;
4276 tty
->mouse_highlight
.mouse_face_window
= Qnil
;
4279 terminal
->kboard
= allocate_kboard (Qnil
);
4280 terminal
->kboard
->reference_count
++;
4281 /* Don't let the initial kboard remain current longer than necessary.
4282 That would cause problems if a file loaded on startup tries to
4283 prompt in the mini-buffer. */
4284 if (current_kboard
== initial_kboard
)
4285 current_kboard
= terminal
->kboard
;
4287 term_get_fkeys (address
, terminal
->kboard
);
4289 /* Get frame size from system, or else from termcap. */
4292 get_tty_size (fileno (tty
->input
), &width
, &height
);
4293 FrameCols (tty
) = width
;
4294 FrameRows (tty
) = height
;
4297 if (FrameCols (tty
) <= 0)
4298 FrameCols (tty
) = tgetnum ("co");
4299 if (FrameRows (tty
) <= 0)
4300 FrameRows (tty
) = tgetnum ("li");
4302 if (FrameRows (tty
) < 3 || FrameCols (tty
) < 3)
4303 maybe_fatal (must_succeed
, terminal
,
4304 "Screen size %dx%d is too small",
4305 "Screen size %dx%d is too small",
4306 FrameCols (tty
), FrameRows (tty
));
4308 TabWidth (tty
) = tgetnum ("tw");
4311 tty
->TS_bell
= "\07";
4313 if (!tty
->TS_fwd_scroll
)
4314 tty
->TS_fwd_scroll
= Down (tty
);
4316 PC
= tty
->TS_pad_char
? *tty
->TS_pad_char
: 0;
4318 if (TabWidth (tty
) < 0)
4321 /* Turned off since /etc/termcap seems to have :ta= for most terminals
4322 and newer termcap doc does not seem to say there is a default.
4323 if (!tty->Wcm->cm_tab)
4324 tty->Wcm->cm_tab = "\t";
4327 /* We don't support standout modes that use `magic cookies', so
4328 turn off any that do. */
4329 if (tty
->TS_standout_mode
&& tgetnum ("sg") >= 0)
4331 tty
->TS_standout_mode
= 0;
4332 tty
->TS_end_standout_mode
= 0;
4334 if (tty
->TS_enter_underline_mode
&& tgetnum ("ug") >= 0)
4336 tty
->TS_enter_underline_mode
= 0;
4337 tty
->TS_exit_underline_mode
= 0;
4340 /* If there's no standout mode, try to use underlining instead. */
4341 if (tty
->TS_standout_mode
== 0)
4343 tty
->TS_standout_mode
= tty
->TS_enter_underline_mode
;
4344 tty
->TS_end_standout_mode
= tty
->TS_exit_underline_mode
;
4347 /* If no `se' string, try using a `me' string instead.
4348 If that fails, we can't use standout mode at all. */
4349 if (tty
->TS_end_standout_mode
== 0)
4351 char *s
= tgetstr ("me", address
);
4353 tty
->TS_end_standout_mode
= s
;
4355 tty
->TS_standout_mode
= 0;
4358 if (tty
->TF_teleray
)
4360 tty
->Wcm
->cm_tab
= 0;
4361 /* We can't support standout mode, because it uses magic cookies. */
4362 tty
->TS_standout_mode
= 0;
4363 /* But that means we cannot rely on ^M to go to column zero! */
4365 /* LF can't be trusted either -- can alter hpos. */
4366 /* If move at column 0 thru a line with TS_standout_mode. */
4370 tty
->specified_window
= FrameRows (tty
);
4372 if (Wcm_init (tty
) == -1) /* Can't do cursor motion. */
4374 maybe_fatal (must_succeed
, terminal
,
4375 "Terminal type \"%s\" is not powerful enough to run Emacs",
4376 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
4377 It lacks the ability to position the cursor.\n\
4378 If that is not the actual type of terminal you have,\n\
4379 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
4380 `setenv TERM ...') to specify the correct type. It may be necessary\n"
4382 "to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
4383 # else /* TERMCAP */
4384 "to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
4385 # endif /* TERMINFO */
4389 if (FrameRows (tty
) <= 0 || FrameCols (tty
) <= 0)
4390 maybe_fatal (must_succeed
, terminal
,
4391 "Could not determine the frame size",
4392 "Could not determine the frame size");
4394 tty
->delete_in_insert_mode
4395 = tty
->TS_delete_mode
&& tty
->TS_insert_mode
4396 && !strcmp (tty
->TS_delete_mode
, tty
->TS_insert_mode
);
4398 UseTabs (tty
) = tabs_safe_p (fileno (tty
->input
)) && TabWidth (tty
) == 8;
4400 tty
->scroll_region_ok
4402 && (tty
->TS_set_window
|| tty
->TS_set_scroll_region
|| tty
->TS_set_scroll_region_1
));
4404 tty
->line_ins_del_ok
4405 = (((tty
->TS_ins_line
|| tty
->TS_ins_multi_lines
)
4406 && (tty
->TS_del_line
|| tty
->TS_del_multi_lines
))
4407 || (tty
->scroll_region_ok
4408 && tty
->TS_fwd_scroll
&& tty
->TS_rev_scroll
));
4410 tty
->char_ins_del_ok
4411 = ((tty
->TS_ins_char
|| tty
->TS_insert_mode
4412 || tty
->TS_pad_inserted_char
|| tty
->TS_ins_multi_chars
)
4413 && (tty
->TS_del_char
|| tty
->TS_del_multi_chars
));
4415 init_baud_rate (fileno (tty
->input
));
4417 #endif /* not DOS_NT */
4419 /* Init system terminal modes (RAW or CBREAK, etc.). */
4420 init_sys_modes (tty
);
4427 vfatal (const char *str
, va_list ap
)
4429 fprintf (stderr
, "emacs: ");
4430 vfprintf (stderr
, str
, ap
);
4431 if (!(strlen (str
) > 0 && str
[strlen (str
) - 1] == '\n'))
4432 fprintf (stderr
, "\n");
4438 /* Auxiliary error-handling function for init_tty.
4439 Delete TERMINAL, then call error or fatal with str1 or str2,
4440 respectively, according to whether MUST_SUCCEED is true. */
4443 maybe_fatal (bool must_succeed
, struct terminal
*terminal
,
4444 const char *str1
, const char *str2
, ...)
4447 va_start (ap
, str2
);
4449 delete_tty (terminal
);
4458 fatal (const char *str
, ...)
4467 /* Delete the given tty terminal, closing all frames on it. */
4470 delete_tty (struct terminal
*terminal
)
4472 struct tty_display_info
*tty
;
4474 /* Protect against recursive calls. delete_frame in
4475 delete_terminal calls us back when it deletes our last frame. */
4476 if (!terminal
->name
)
4479 eassert (terminal
->type
== output_termcap
);
4481 tty
= terminal
->display_info
.tty
;
4483 if (tty
== tty_list
)
4484 tty_list
= tty
->next
;
4487 struct tty_display_info
*p
;
4488 for (p
= tty_list
; p
&& p
->next
!= tty
; p
= p
->next
)
4492 /* This should not happen. */
4495 p
->next
= tty
->next
;
4499 /* reset_sys_modes needs a valid device, so this call needs to be
4500 before delete_terminal. */
4501 reset_sys_modes (tty
);
4503 delete_terminal (terminal
);
4510 delete_keyboard_wait_descriptor (fileno (tty
->input
));
4511 if (tty
->input
!= stdin
)
4512 fclose (tty
->input
);
4514 if (tty
->output
&& tty
->output
!= stdout
&& tty
->output
!= tty
->input
)
4515 fclose (tty
->output
);
4516 if (tty
->termscript
)
4517 fclose (tty
->termscript
);
4519 xfree (tty
->old_tty
);
4527 DEFVAR_BOOL ("system-uses-terminfo", system_uses_terminfo
,
4528 doc
: /* Non-nil means the system uses terminfo rather than termcap.
4529 This variable can be used by terminal emulator packages. */);
4531 system_uses_terminfo
= 1;
4533 system_uses_terminfo
= 0;
4536 DEFVAR_LISP ("suspend-tty-functions", Vsuspend_tty_functions
,
4537 doc
: /* Functions run after suspending a tty.
4538 The functions are run with one argument, the terminal object to be suspended.
4539 See `suspend-tty'. */);
4540 Vsuspend_tty_functions
= Qnil
;
4543 DEFVAR_LISP ("resume-tty-functions", Vresume_tty_functions
,
4544 doc
: /* Functions run after resuming a tty.
4545 The functions are run with one argument, the terminal object that was revived.
4546 See `resume-tty'. */);
4547 Vresume_tty_functions
= Qnil
;
4549 DEFVAR_BOOL ("visible-cursor", visible_cursor
,
4550 doc
: /* Non-nil means to make the cursor very visible.
4551 This only has an effect when running in a text terminal.
4552 What means \"very visible\" is up to your terminal. It may make the cursor
4553 bigger, or it may make it blink, or it may do nothing at all. */);
4556 defsubr (&Stty_display_color_p
);
4557 defsubr (&Stty_display_color_cells
);
4558 defsubr (&Stty_no_underline
);
4559 defsubr (&Stty_type
);
4560 defsubr (&Scontrolling_tty_p
);
4561 defsubr (&Stty_top_frame
);
4562 defsubr (&Ssuspend_tty
);
4563 defsubr (&Sresume_tty
);
4565 defsubr (&Sgpm_mouse_start
);
4566 defsubr (&Sgpm_mouse_stop
);
4567 #endif /* HAVE_GPM */
4570 default_orig_pair
= NULL
;
4571 default_set_foreground
= NULL
;
4572 default_set_background
= NULL
;
4573 #endif /* !DOS_NT */
4575 encode_terminal_src
= NULL
;
4576 encode_terminal_dst
= NULL
;
4578 DEFSYM (Qtty_mode_set_strings
, "tty-mode-set-strings");
4579 DEFSYM (Qtty_mode_reset_strings
, "tty-mode-reset-strings");
4582 DEFSYM (Qtty_menu_next_item
, "tty-menu-next-item");
4583 DEFSYM (Qtty_menu_prev_item
, "tty-menu-prev-item");
4584 DEFSYM (Qtty_menu_next_menu
, "tty-menu-next-menu");
4585 DEFSYM (Qtty_menu_prev_menu
, "tty-menu-prev-menu");
4586 DEFSYM (Qtty_menu_select
, "tty-menu-select");
4587 DEFSYM (Qtty_menu_ignore
, "tty-menu-ignore");
4588 DEFSYM (Qtty_menu_exit
, "tty-menu-exit");
4589 DEFSYM (Qtty_menu_mouse_movement
, "tty-menu-mouse-movement");
4590 DEFSYM (Qtty_menu_navigation_map
, "tty-menu-navigation-map");