1 /* Terminal control module for terminals described by TERMCAP
2 Copyright (C) 1985-1987, 1993-1995, 1998, 2000-2016 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 (at
10 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"
49 static int been_here
= -1;
53 #include "../lwlib/lwlib.h"
59 /* The name of the default console device. */
61 #define DEV_TTY "CONOUT$"
64 #define DEV_TTY "/dev/tty"
67 static void tty_set_scroll_region (struct frame
*f
, int start
, int stop
);
68 static void turn_on_face (struct frame
*, int face_id
);
69 static void turn_off_face (struct frame
*, int face_id
);
70 static void tty_turn_off_highlight (struct tty_display_info
*);
71 static void tty_show_cursor (struct tty_display_info
*);
72 static void tty_hide_cursor (struct tty_display_info
*);
73 static void tty_background_highlight (struct tty_display_info
*tty
);
74 static void clear_tty_hooks (struct terminal
*terminal
);
75 static void set_tty_hooks (struct terminal
*terminal
);
76 static void dissociate_if_controlling_tty (int fd
);
77 static void delete_tty (struct terminal
*);
78 static _Noreturn
void maybe_fatal (bool, struct terminal
*,
79 const char *, const char *, ...)
80 ATTRIBUTE_FORMAT_PRINTF (3, 5) ATTRIBUTE_FORMAT_PRINTF (4, 5);
81 static _Noreturn
void vfatal (const char *str
, va_list ap
)
82 ATTRIBUTE_FORMAT_PRINTF (1, 0);
85 #define OUTPUT(tty, a) \
86 emacs_tputs ((tty), a, \
87 FRAME_TOTAL_LINES (XFRAME (selected_frame)) - curY (tty), \
90 #define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
91 #define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
93 #define OUTPUT_IF(tty, a) \
99 #define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
101 /* Display space properties. */
103 /* Chain of all tty device parameters. */
104 struct tty_display_info
*tty_list
;
106 /* Meaning of bits in no_color_video. Each bit set means that the
107 corresponding attribute cannot be combined with colors. */
111 NC_STANDOUT
= 1 << 0,
112 NC_UNDERLINE
= 1 << 1,
123 /* The largest frame width in any call to calculate_costs. */
125 static int max_frame_cols
;
130 #include <sys/fcntl.h>
132 /* The device for which we have enabled gpm support (or NULL). */
133 struct tty_display_info
*gpm_tty
= NULL
;
135 /* Last recorded mouse coordinates. */
136 static int last_mouse_x
, last_mouse_y
;
137 #endif /* HAVE_GPM */
139 /* Ring the bell on a tty. */
142 tty_ring_bell (struct frame
*f
)
144 struct tty_display_info
*tty
= FRAME_TTY (f
);
148 OUTPUT (tty
, (tty
->TS_visible_bell
&& visible_bell
149 ? tty
->TS_visible_bell
151 fflush (tty
->output
);
155 /* Set up termcap modes for Emacs. */
158 tty_send_additional_strings (struct terminal
*terminal
, Lisp_Object sym
)
160 Lisp_Object lisp_terminal
;
161 Lisp_Object extra_codes
;
162 struct tty_display_info
*tty
= terminal
->display_info
.tty
;
164 XSETTERMINAL (lisp_terminal
, terminal
);
165 for (extra_codes
= Fterminal_parameter (lisp_terminal
, sym
);
167 extra_codes
= XCDR (extra_codes
))
169 Lisp_Object string
= XCAR (extra_codes
);
170 if (STRINGP (string
))
172 fwrite (SDATA (string
), 1, SBYTES (string
), tty
->output
);
174 fwrite (SDATA (string
), 1, SBYTES (string
), tty
->termscript
);
180 tty_set_terminal_modes (struct terminal
*terminal
)
182 struct tty_display_info
*tty
= terminal
->display_info
.tty
;
186 if (tty
->TS_termcap_modes
)
187 OUTPUT (tty
, tty
->TS_termcap_modes
);
190 /* Output enough newlines to scroll all the old screen contents
191 off the screen, so it won't be overwritten and lost. */
194 for (i
= 0; i
< FRAME_TOTAL_LINES (XFRAME (selected_frame
)); i
++)
198 OUTPUT_IF (tty
, visible_cursor
? tty
->TS_cursor_visible
: tty
->TS_cursor_normal
);
199 OUTPUT_IF (tty
, tty
->TS_keypad_mode
);
201 tty_send_additional_strings (terminal
, Qtty_mode_set_strings
);
202 fflush (tty
->output
);
206 /* Reset termcap modes before exiting Emacs. */
209 tty_reset_terminal_modes (struct terminal
*terminal
)
211 struct tty_display_info
*tty
= terminal
->display_info
.tty
;
215 tty_send_additional_strings (terminal
, Qtty_mode_reset_strings
);
216 tty_turn_off_highlight (tty
);
217 tty_turn_off_insert (tty
);
218 OUTPUT_IF (tty
, tty
->TS_end_keypad_mode
);
219 OUTPUT_IF (tty
, tty
->TS_cursor_normal
);
220 OUTPUT_IF (tty
, tty
->TS_end_termcap_modes
);
221 OUTPUT_IF (tty
, tty
->TS_orig_pair
);
222 /* Output raw CR so kernel can track the cursor hpos. */
225 fflush (tty
->output
);
229 /* Flag the end of a display update on a termcap terminal. */
232 tty_update_end (struct frame
*f
)
234 struct tty_display_info
*tty
= FRAME_TTY (f
);
236 if (!XWINDOW (selected_window
)->cursor_off_p
)
237 tty_show_cursor (tty
);
238 tty_turn_off_insert (tty
);
239 tty_background_highlight (tty
);
240 fflush (tty
->output
);
243 /* The implementation of set_terminal_window for termcap frames. */
246 tty_set_terminal_window (struct frame
*f
, int size
)
248 struct tty_display_info
*tty
= FRAME_TTY (f
);
250 tty
->specified_window
= size
? size
: FRAME_TOTAL_LINES (f
);
251 if (FRAME_SCROLL_REGION_OK (f
))
252 tty_set_scroll_region (f
, 0, tty
->specified_window
);
256 tty_set_scroll_region (struct frame
*f
, int start
, int stop
)
259 struct tty_display_info
*tty
= FRAME_TTY (f
);
261 if (tty
->TS_set_scroll_region
)
262 buf
= tparam (tty
->TS_set_scroll_region
, 0, 0, start
, stop
- 1, 0, 0);
263 else if (tty
->TS_set_scroll_region_1
)
264 buf
= tparam (tty
->TS_set_scroll_region_1
, 0, 0,
265 FRAME_TOTAL_LINES (f
), start
,
266 FRAME_TOTAL_LINES (f
) - stop
,
267 FRAME_TOTAL_LINES (f
));
269 buf
= tparam (tty
->TS_set_window
, 0, 0, start
, 0, stop
, FRAME_COLS (f
));
278 tty_turn_on_insert (struct tty_display_info
*tty
)
280 if (!tty
->insert_mode
)
281 OUTPUT (tty
, tty
->TS_insert_mode
);
282 tty
->insert_mode
= 1;
286 tty_turn_off_insert (struct tty_display_info
*tty
)
288 if (tty
->insert_mode
)
289 OUTPUT (tty
, tty
->TS_end_insert_mode
);
290 tty
->insert_mode
= 0;
293 /* Handle highlighting. */
296 tty_turn_off_highlight (struct tty_display_info
*tty
)
298 if (tty
->standout_mode
)
299 OUTPUT_IF (tty
, tty
->TS_end_standout_mode
);
300 tty
->standout_mode
= 0;
304 tty_turn_on_highlight (struct tty_display_info
*tty
)
306 if (!tty
->standout_mode
)
307 OUTPUT_IF (tty
, tty
->TS_standout_mode
);
308 tty
->standout_mode
= 1;
312 tty_toggle_highlight (struct tty_display_info
*tty
)
314 if (tty
->standout_mode
)
315 tty_turn_off_highlight (tty
);
317 tty_turn_on_highlight (tty
);
321 /* Make cursor invisible. */
324 tty_hide_cursor (struct tty_display_info
*tty
)
326 if (tty
->cursor_hidden
== 0)
328 tty
->cursor_hidden
= 1;
330 w32con_hide_cursor ();
332 OUTPUT_IF (tty
, tty
->TS_cursor_invisible
);
338 /* Ensure that cursor is visible. */
341 tty_show_cursor (struct tty_display_info
*tty
)
343 if (tty
->cursor_hidden
)
345 tty
->cursor_hidden
= 0;
347 w32con_show_cursor ();
349 OUTPUT_IF (tty
, tty
->TS_cursor_normal
);
351 OUTPUT_IF (tty
, tty
->TS_cursor_visible
);
357 /* Set standout mode to the state it should be in for
358 empty space inside windows. What this is,
359 depends on the user option inverse-video. */
362 tty_background_highlight (struct tty_display_info
*tty
)
365 tty_turn_on_highlight (tty
);
367 tty_turn_off_highlight (tty
);
370 /* Set standout mode to the mode specified for the text to be output. */
373 tty_highlight_if_desired (struct tty_display_info
*tty
)
376 tty_turn_on_highlight (tty
);
378 tty_turn_off_highlight (tty
);
382 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
383 frame-relative coordinates. */
386 tty_cursor_to (struct frame
*f
, int vpos
, int hpos
)
388 struct tty_display_info
*tty
= FRAME_TTY (f
);
390 /* Detect the case where we are called from reset_sys_modes
391 and the costs have never been calculated. Do nothing. */
392 if (! tty
->costs_set
)
395 if (curY (tty
) == vpos
396 && curX (tty
) == hpos
)
398 if (!tty
->TF_standout_motion
)
399 tty_background_highlight (tty
);
400 if (!tty
->TF_insmode_motion
)
401 tty_turn_off_insert (tty
);
402 cmgoto (tty
, vpos
, hpos
);
405 /* Similar but don't take any account of the wasted characters. */
408 tty_raw_cursor_to (struct frame
*f
, int row
, int col
)
410 struct tty_display_info
*tty
= FRAME_TTY (f
);
412 if (curY (tty
) == row
413 && curX (tty
) == col
)
415 if (!tty
->TF_standout_motion
)
416 tty_background_highlight (tty
);
417 if (!tty
->TF_insmode_motion
)
418 tty_turn_off_insert (tty
);
419 cmgoto (tty
, row
, col
);
422 /* Erase operations */
424 /* Clear from cursor to end of frame on a termcap device. */
427 tty_clear_to_end (struct frame
*f
)
430 struct tty_display_info
*tty
= FRAME_TTY (f
);
432 if (tty
->TS_clr_to_bottom
)
434 tty_background_highlight (tty
);
435 OUTPUT (tty
, tty
->TS_clr_to_bottom
);
439 for (i
= curY (tty
); i
< FRAME_TOTAL_LINES (f
); i
++)
442 clear_end_of_line (f
, FRAME_COLS (f
));
447 /* Clear an entire termcap frame. */
450 tty_clear_frame (struct frame
*f
)
452 struct tty_display_info
*tty
= FRAME_TTY (f
);
454 if (tty
->TS_clr_frame
)
456 tty_background_highlight (tty
);
457 OUTPUT (tty
, tty
->TS_clr_frame
);
467 /* An implementation of clear_end_of_line for termcap frames.
469 Note that the cursor may be moved, on terminals lacking a `ce' string. */
472 tty_clear_end_of_line (struct frame
*f
, int first_unused_hpos
)
475 struct tty_display_info
*tty
= FRAME_TTY (f
);
477 /* Detect the case where we are called from reset_sys_modes
478 and the costs have never been calculated. Do nothing. */
479 if (! tty
->costs_set
)
482 if (curX (tty
) >= first_unused_hpos
)
484 tty_background_highlight (tty
);
485 if (tty
->TS_clr_line
)
487 OUTPUT1 (tty
, tty
->TS_clr_line
);
490 { /* have to do it the hard way */
491 tty_turn_off_insert (tty
);
493 /* Do not write in last row last col with Auto-wrap on. */
495 && curY (tty
) == FrameRows (tty
) - 1
496 && first_unused_hpos
== FrameCols (tty
))
499 for (i
= curX (tty
); i
< first_unused_hpos
; i
++)
502 fputc (' ', tty
->termscript
);
503 fputc (' ', tty
->output
);
505 cmplus (tty
, first_unused_hpos
- curX (tty
));
509 /* Buffers to store the source and result of code conversion for terminal. */
510 static unsigned char *encode_terminal_src
;
511 static unsigned char *encode_terminal_dst
;
512 /* Allocated sizes of the above buffers. */
513 static ptrdiff_t encode_terminal_src_size
;
514 static ptrdiff_t encode_terminal_dst_size
;
516 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes.
517 Set CODING->produced to the byte-length of the resulting byte
518 sequence, and return a pointer to that byte sequence. */
521 encode_terminal_code (struct glyph
*src
, int src_len
,
522 struct coding_system
*coding
)
524 struct glyph
*src_end
= src
+ src_len
;
526 ptrdiff_t nchars
, nbytes
, required
;
527 ptrdiff_t tlen
= GLYPH_TABLE_LENGTH
;
528 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
529 Lisp_Object charset_list
;
531 /* Allocate sufficient size of buffer to store all characters in
532 multibyte-form. But, it may be enlarged on demand if
533 Vglyph_table contains a string or a composite glyph is
535 if (INT_MULTIPLY_WRAPV (src_len
, MAX_MULTIBYTE_LENGTH
, &required
))
536 memory_full (SIZE_MAX
);
537 if (encode_terminal_src_size
< required
)
538 encode_terminal_src
= xpalloc (encode_terminal_src
,
539 &encode_terminal_src_size
,
540 required
- encode_terminal_src_size
,
541 -1, sizeof *encode_terminal_src
);
543 charset_list
= coding_charset_list (coding
);
545 buf
= encode_terminal_src
;
547 while (src
< src_end
)
549 if (src
->type
== COMPOSITE_GLYPH
)
551 struct composition
*cmp
IF_LINT (= NULL
);
552 Lisp_Object gstring
IF_LINT (= Qnil
);
555 nbytes
= buf
- encode_terminal_src
;
556 if (src
->u
.cmp
.automatic
)
558 gstring
= composition_gstring_from_id (src
->u
.cmp
.id
);
559 required
= src
->slice
.cmp
.to
- src
->slice
.cmp
.from
+ 1;
563 cmp
= composition_table
[src
->u
.cmp
.id
];
564 required
= cmp
->glyph_len
;
565 required
*= MAX_MULTIBYTE_LENGTH
;
568 if (encode_terminal_src_size
- nbytes
< required
)
570 encode_terminal_src
=
571 xpalloc (encode_terminal_src
, &encode_terminal_src_size
,
572 required
- (encode_terminal_src_size
- nbytes
),
574 buf
= encode_terminal_src
+ nbytes
;
577 if (src
->u
.cmp
.automatic
)
578 for (i
= src
->slice
.cmp
.from
; i
<= src
->slice
.cmp
.to
; i
++)
580 Lisp_Object g
= LGSTRING_GLYPH (gstring
, i
);
581 int c
= LGLYPH_CHAR (g
);
583 if (! char_charset (c
, charset_list
, NULL
))
585 buf
+= CHAR_STRING (c
, buf
);
589 for (i
= 0; i
< cmp
->glyph_len
; i
++)
591 int c
= COMPOSITION_GLYPH (cmp
, i
);
593 /* TAB in a composition means display glyphs with
594 padding space on the left or right. */
597 if (char_charset (c
, charset_list
, NULL
))
599 if (CHAR_WIDTH (c
) == 0
600 && i
> 0 && COMPOSITION_GLYPH (cmp
, i
- 1) == '\t')
601 /* Should be left-padded */
603 buf
+= CHAR_STRING (' ', buf
);
609 buf
+= CHAR_STRING (c
, buf
);
613 /* We must skip glyphs to be padded for a wide character. */
614 else if (! CHAR_GLYPH_PADDING_P (*src
))
621 SET_GLYPH_FROM_CHAR_GLYPH (g
, src
[0]);
623 if (GLYPH_INVALID_P (g
) || GLYPH_SIMPLE_P (tbase
, tlen
, g
))
625 /* This glyph doesn't have an entry in Vglyph_table. */
630 /* This glyph has an entry in Vglyph_table,
631 so process any alias before testing for simpleness. */
632 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
634 if (GLYPH_SIMPLE_P (tbase
, tlen
, g
))
635 /* We set the multi-byte form of a character in G
636 (that should be an ASCII character) at WORKBUF. */
639 /* We have a string in Vglyph_table. */
640 string
= tbase
[GLYPH_CHAR (g
)];
645 nbytes
= buf
- encode_terminal_src
;
646 if (encode_terminal_src_size
- nbytes
< MAX_MULTIBYTE_LENGTH
)
648 encode_terminal_src
=
649 xpalloc (encode_terminal_src
, &encode_terminal_src_size
,
650 MAX_MULTIBYTE_LENGTH
, -1, 1);
651 buf
= encode_terminal_src
+ nbytes
;
654 || char_charset (c
, charset_list
, NULL
))
656 /* Store the multibyte form of C at BUF. */
657 buf
+= CHAR_STRING (c
, buf
);
662 /* C is not encodable. */
665 while (src
+ 1 < src_end
&& CHAR_GLYPH_PADDING_P (src
[1]))
675 if (! STRING_MULTIBYTE (string
))
676 string
= string_to_multibyte (string
);
677 nbytes
= buf
- encode_terminal_src
;
678 if (encode_terminal_src_size
- nbytes
< SBYTES (string
))
680 encode_terminal_src
=
681 xpalloc (encode_terminal_src
, &encode_terminal_src_size
,
683 - (encode_terminal_src_size
- nbytes
)),
685 buf
= encode_terminal_src
+ nbytes
;
687 memcpy (buf
, SDATA (string
), SBYTES (string
));
688 buf
+= SBYTES (string
);
689 nchars
+= SCHARS (string
);
697 coding
->produced
= 0;
701 nbytes
= buf
- encode_terminal_src
;
702 coding
->source
= encode_terminal_src
;
703 if (encode_terminal_dst_size
== 0)
705 encode_terminal_dst
= xrealloc (encode_terminal_dst
,
706 encode_terminal_src_size
);
707 encode_terminal_dst_size
= encode_terminal_src_size
;
709 coding
->destination
= encode_terminal_dst
;
710 coding
->dst_bytes
= encode_terminal_dst_size
;
711 encode_coding_object (coding
, Qnil
, 0, 0, nchars
, nbytes
, Qnil
);
712 /* coding->destination may have been reallocated. */
713 encode_terminal_dst
= coding
->destination
;
714 encode_terminal_dst_size
= coding
->dst_bytes
;
716 return (encode_terminal_dst
);
721 /* An implementation of write_glyphs for termcap frames. */
724 tty_write_glyphs (struct frame
*f
, struct glyph
*string
, int len
)
726 unsigned char *conversion_buffer
;
727 struct coding_system
*coding
;
730 struct tty_display_info
*tty
= FRAME_TTY (f
);
732 tty_turn_off_insert (tty
);
733 tty_hide_cursor (tty
);
735 /* Don't dare write in last column of bottom line, if Auto-Wrap,
736 since that would scroll the whole frame on some terminals. */
739 && curY (tty
) + 1 == FRAME_TOTAL_LINES (f
)
740 && (curX (tty
) + len
) == FRAME_COLS (f
))
747 /* If terminal_coding does any conversion, use it, otherwise use
748 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
749 because it always return 1 if the member src_multibyte is 1. */
750 coding
= (FRAME_TERMINAL_CODING (f
)->common_flags
& CODING_REQUIRE_ENCODING_MASK
751 ? FRAME_TERMINAL_CODING (f
) : &safe_terminal_coding
);
752 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
754 coding
->mode
&= ~CODING_MODE_LAST_BLOCK
;
756 for (stringlen
= len
; stringlen
!= 0; stringlen
-= n
)
758 /* Identify a run of glyphs with the same face. */
759 int face_id
= string
->face_id
;
761 for (n
= 1; n
< stringlen
; ++n
)
762 if (string
[n
].face_id
!= face_id
)
765 /* Turn appearance modes of the face of the run on. */
766 tty_highlight_if_desired (tty
);
767 turn_on_face (f
, face_id
);
770 /* This is the last run. */
771 coding
->mode
|= CODING_MODE_LAST_BLOCK
;
772 conversion_buffer
= encode_terminal_code (string
, n
, coding
);
773 if (coding
->produced
> 0)
776 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->output
);
777 if (ferror (tty
->output
))
778 clearerr (tty
->output
);
780 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->termscript
);
785 /* Turn appearance modes off. */
786 turn_off_face (f
, face_id
);
787 tty_turn_off_highlight (tty
);
793 #ifdef HAVE_GPM /* Only used by GPM code. */
796 tty_write_glyphs_with_face (register struct frame
*f
, register struct glyph
*string
,
797 register int len
, register int face_id
)
799 unsigned char *conversion_buffer
;
800 struct coding_system
*coding
;
802 struct tty_display_info
*tty
= FRAME_TTY (f
);
804 tty_turn_off_insert (tty
);
805 tty_hide_cursor (tty
);
807 /* Don't dare write in last column of bottom line, if Auto-Wrap,
808 since that would scroll the whole frame on some terminals. */
811 && curY (tty
) + 1 == FRAME_TOTAL_LINES (f
)
812 && (curX (tty
) + len
) == FRAME_COLS (f
))
819 /* If terminal_coding does any conversion, use it, otherwise use
820 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
821 because it always return 1 if the member src_multibyte is 1. */
822 coding
= (FRAME_TERMINAL_CODING (f
)->common_flags
& CODING_REQUIRE_ENCODING_MASK
823 ? FRAME_TERMINAL_CODING (f
) : &safe_terminal_coding
);
824 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
826 coding
->mode
&= ~CODING_MODE_LAST_BLOCK
;
828 /* Turn appearance modes of the face. */
829 tty_highlight_if_desired (tty
);
830 turn_on_face (f
, face_id
);
832 coding
->mode
|= CODING_MODE_LAST_BLOCK
;
833 conversion_buffer
= encode_terminal_code (string
, len
, coding
);
834 if (coding
->produced
> 0)
837 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->output
);
838 if (ferror (tty
->output
))
839 clearerr (tty
->output
);
841 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->termscript
);
845 /* Turn appearance modes off. */
846 turn_off_face (f
, face_id
);
847 tty_turn_off_highlight (tty
);
853 /* An implementation of insert_glyphs for termcap frames. */
856 tty_insert_glyphs (struct frame
*f
, struct glyph
*start
, int len
)
859 struct glyph
*glyph
= NULL
;
860 unsigned char *conversion_buffer
;
861 unsigned char space
[1];
862 struct coding_system
*coding
;
864 struct tty_display_info
*tty
= FRAME_TTY (f
);
866 if (tty
->TS_ins_multi_chars
)
868 buf
= tparam (tty
->TS_ins_multi_chars
, 0, 0, len
, 0, 0, 0);
872 write_glyphs (f
, start
, len
);
876 tty_turn_on_insert (tty
);
880 space
[0] = SPACEGLYPH
;
882 /* If terminal_coding does any conversion, use it, otherwise use
883 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
884 because it always return 1 if the member src_multibyte is 1. */
885 coding
= (FRAME_TERMINAL_CODING (f
)->common_flags
& CODING_REQUIRE_ENCODING_MASK
886 ? FRAME_TERMINAL_CODING (f
) : &safe_terminal_coding
);
887 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
889 coding
->mode
&= ~CODING_MODE_LAST_BLOCK
;
893 OUTPUT1_IF (tty
, tty
->TS_ins_char
);
896 conversion_buffer
= space
;
897 coding
->produced
= 1;
901 tty_highlight_if_desired (tty
);
902 turn_on_face (f
, start
->face_id
);
905 /* We must open sufficient space for a character which
906 occupies more than one column. */
907 while (len
&& CHAR_GLYPH_PADDING_P (*start
))
909 OUTPUT1_IF (tty
, tty
->TS_ins_char
);
914 /* This is the last glyph. */
915 coding
->mode
|= CODING_MODE_LAST_BLOCK
;
917 conversion_buffer
= encode_terminal_code (glyph
, 1, coding
);
920 if (coding
->produced
> 0)
923 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->output
);
924 if (ferror (tty
->output
))
925 clearerr (tty
->output
);
927 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->termscript
);
931 OUTPUT1_IF (tty
, tty
->TS_pad_inserted_char
);
934 turn_off_face (f
, glyph
->face_id
);
935 tty_turn_off_highlight (tty
);
942 /* An implementation of delete_glyphs for termcap frames. */
945 tty_delete_glyphs (struct frame
*f
, int n
)
950 struct tty_display_info
*tty
= FRAME_TTY (f
);
952 if (tty
->delete_in_insert_mode
)
954 tty_turn_on_insert (tty
);
958 tty_turn_off_insert (tty
);
959 OUTPUT_IF (tty
, tty
->TS_delete_mode
);
962 if (tty
->TS_del_multi_chars
)
964 buf
= tparam (tty
->TS_del_multi_chars
, 0, 0, n
, 0, 0, 0);
969 for (i
= 0; i
< n
; i
++)
970 OUTPUT1 (tty
, tty
->TS_del_char
);
971 if (!tty
->delete_in_insert_mode
)
972 OUTPUT_IF (tty
, tty
->TS_end_delete_mode
);
975 /* An implementation of ins_del_lines for termcap frames. */
978 tty_ins_del_lines (struct frame
*f
, int vpos
, int n
)
980 struct tty_display_info
*tty
= FRAME_TTY (f
);
982 n
> 0 ? tty
->TS_ins_multi_lines
: tty
->TS_del_multi_lines
;
983 const char *single
= n
> 0 ? tty
->TS_ins_line
: tty
->TS_del_line
;
984 const char *scroll
= n
> 0 ? tty
->TS_rev_scroll
: tty
->TS_fwd_scroll
;
989 /* If the lines below the insertion are being pushed
990 into the end of the window, this is the same as clearing;
991 and we know the lines are already clear, since the matching
992 deletion has already been done. So can ignore this. */
993 /* If the lines below the deletion are blank lines coming
994 out of the end of the window, don't bother,
995 as there will be a matching inslines later that will flush them. */
996 if (FRAME_SCROLL_REGION_OK (f
)
997 && vpos
+ i
>= tty
->specified_window
)
999 if (!FRAME_MEMORY_BELOW_FRAME (f
)
1000 && vpos
+ i
>= FRAME_TOTAL_LINES (f
))
1005 raw_cursor_to (f
, vpos
, 0);
1006 tty_background_highlight (tty
);
1007 buf
= tparam (multi
, 0, 0, i
, 0, 0, 0);
1013 raw_cursor_to (f
, vpos
, 0);
1014 tty_background_highlight (tty
);
1016 OUTPUT (tty
, single
);
1017 if (tty
->TF_teleray
)
1022 tty_set_scroll_region (f
, vpos
, tty
->specified_window
);
1024 raw_cursor_to (f
, tty
->specified_window
- 1, 0);
1026 raw_cursor_to (f
, vpos
, 0);
1027 tty_background_highlight (tty
);
1029 OUTPUTL (tty
, scroll
, tty
->specified_window
- vpos
);
1030 tty_set_scroll_region (f
, 0, tty
->specified_window
);
1033 if (!FRAME_SCROLL_REGION_OK (f
)
1034 && FRAME_MEMORY_BELOW_FRAME (f
)
1037 cursor_to (f
, FRAME_TOTAL_LINES (f
) + n
, 0);
1042 /* Compute cost of sending "str", in characters,
1043 not counting any line-dependent padding. */
1046 string_cost (const char *str
)
1050 tputs (str
, 0, evalcost
);
1054 /* Compute cost of sending "str", in characters,
1055 counting any line-dependent padding at one line. */
1058 string_cost_one_line (const char *str
)
1062 tputs (str
, 1, evalcost
);
1066 /* Compute per line amount of line-dependent padding,
1067 in tenths of characters. */
1070 per_line_cost (const char *str
)
1074 tputs (str
, 0, evalcost
);
1077 tputs (str
, 10, evalcost
);
1081 /* char_ins_del_cost[n] is cost of inserting N characters.
1082 char_ins_del_cost[-n] is cost of deleting N characters.
1083 The length of this vector is based on max_frame_cols. */
1085 int *char_ins_del_vector
;
1087 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
1091 calculate_ins_del_char_costs (struct frame
*f
)
1093 struct tty_display_info
*tty
= FRAME_TTY (f
);
1094 int ins_startup_cost
, del_startup_cost
;
1095 int ins_cost_per_char
, del_cost_per_char
;
1099 if (tty
->TS_ins_multi_chars
)
1101 ins_cost_per_char
= 0;
1102 ins_startup_cost
= string_cost_one_line (tty
->TS_ins_multi_chars
);
1104 else if (tty
->TS_ins_char
|| tty
->TS_pad_inserted_char
1105 || (tty
->TS_insert_mode
&& tty
->TS_end_insert_mode
))
1107 ins_startup_cost
= (30 * (string_cost (tty
->TS_insert_mode
)
1108 + string_cost (tty
->TS_end_insert_mode
))) / 100;
1109 ins_cost_per_char
= (string_cost_one_line (tty
->TS_ins_char
)
1110 + string_cost_one_line (tty
->TS_pad_inserted_char
));
1114 ins_startup_cost
= 9999;
1115 ins_cost_per_char
= 0;
1118 if (tty
->TS_del_multi_chars
)
1120 del_cost_per_char
= 0;
1121 del_startup_cost
= string_cost_one_line (tty
->TS_del_multi_chars
);
1123 else if (tty
->TS_del_char
)
1125 del_startup_cost
= (string_cost (tty
->TS_delete_mode
)
1126 + string_cost (tty
->TS_end_delete_mode
));
1127 if (tty
->delete_in_insert_mode
)
1128 del_startup_cost
/= 2;
1129 del_cost_per_char
= string_cost_one_line (tty
->TS_del_char
);
1133 del_startup_cost
= 9999;
1134 del_cost_per_char
= 0;
1137 /* Delete costs are at negative offsets */
1138 p
= &char_ins_del_cost (f
)[0];
1139 for (i
= FRAME_COLS (f
); --i
>= 0;)
1140 *--p
= (del_startup_cost
+= del_cost_per_char
);
1142 /* Doing nothing is free */
1143 p
= &char_ins_del_cost (f
)[0];
1146 /* Insert costs are at positive offsets */
1147 for (i
= FRAME_COLS (f
); --i
>= 0;)
1148 *p
++ = (ins_startup_cost
+= ins_cost_per_char
);
1152 calculate_costs (struct frame
*frame
)
1154 FRAME_COST_BAUD_RATE (frame
) = baud_rate
;
1156 if (FRAME_TERMCAP_P (frame
))
1158 struct tty_display_info
*tty
= FRAME_TTY (frame
);
1159 register const char *f
= (tty
->TS_set_scroll_region
1160 ? tty
->TS_set_scroll_region
1161 : tty
->TS_set_scroll_region_1
);
1163 FRAME_SCROLL_REGION_COST (frame
) = string_cost (f
);
1167 /* These variables are only used for terminal stuff. They are
1168 allocated once for the terminal frame of X-windows emacs, but not
1171 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1172 X turns off char_ins_del_ok. */
1174 max_frame_cols
= max (max_frame_cols
, FRAME_COLS (frame
));
1175 if ((min (PTRDIFF_MAX
, SIZE_MAX
) / sizeof (int) - 1) / 2
1177 memory_full (SIZE_MAX
);
1179 char_ins_del_vector
=
1180 xrealloc (char_ins_del_vector
,
1181 (sizeof (int) + 2 * sizeof (int) * max_frame_cols
));
1183 memset (char_ins_del_vector
, 0,
1184 (sizeof (int) + 2 * sizeof (int) * max_frame_cols
));
1187 if (f
&& (!tty
->TS_ins_line
&& !tty
->TS_del_line
))
1188 do_line_insertion_deletion_costs (frame
,
1189 tty
->TS_rev_scroll
, tty
->TS_ins_multi_lines
,
1190 tty
->TS_fwd_scroll
, tty
->TS_del_multi_lines
,
1193 do_line_insertion_deletion_costs (frame
,
1194 tty
->TS_ins_line
, tty
->TS_ins_multi_lines
,
1195 tty
->TS_del_line
, tty
->TS_del_multi_lines
,
1198 calculate_ins_del_char_costs (frame
);
1200 /* Don't use TS_repeat if its padding is worse than sending the chars */
1201 if (tty
->TS_repeat
&& per_line_cost (tty
->TS_repeat
) * baud_rate
< 9000)
1202 tty
->RPov
= string_cost (tty
->TS_repeat
);
1204 tty
->RPov
= FRAME_COLS (frame
) * 2;
1206 cmcostinit (FRAME_TTY (frame
)); /* set up cursor motion costs */
1211 const char *cap
, *name
;
1214 /* Termcap capability names that correspond directly to X keysyms.
1215 Some of these (marked "terminfo") aren't supplied by old-style
1216 (Berkeley) termcap entries. They're listed in X keysym order;
1217 except we put the keypad keys first, so that if they clash with
1218 other keys (as on the IBM PC keyboard) they get overridden.
1221 static const struct fkey_table keys
[] =
1223 {"kh", "home"}, /* termcap */
1224 {"kl", "left"}, /* termcap */
1225 {"ku", "up"}, /* termcap */
1226 {"kr", "right"}, /* termcap */
1227 {"kd", "down"}, /* termcap */
1228 {"%8", "prior"}, /* terminfo */
1229 {"%5", "next"}, /* terminfo */
1230 {"@7", "end"}, /* terminfo */
1231 {"@1", "begin"}, /* terminfo */
1232 {"*6", "select"}, /* terminfo */
1233 {"%9", "print"}, /* terminfo */
1234 {"@4", "execute"}, /* terminfo --- actually the `command' key */
1236 * "insert" --- see below
1238 {"&8", "undo"}, /* terminfo */
1239 {"%0", "redo"}, /* terminfo */
1240 {"%7", "menu"}, /* terminfo --- actually the `options' key */
1241 {"@0", "find"}, /* terminfo */
1242 {"@2", "cancel"}, /* terminfo */
1243 {"%1", "help"}, /* terminfo */
1245 * "break" goes here, but can't be reliably intercepted with termcap
1247 {"&4", "reset"}, /* terminfo --- actually `restart' */
1249 * "system" and "user" --- no termcaps
1251 {"kE", "clearline"}, /* terminfo */
1252 {"kA", "insertline"}, /* terminfo */
1253 {"kL", "deleteline"}, /* terminfo */
1254 {"kI", "insertchar"}, /* terminfo */
1255 {"kD", "deletechar"}, /* terminfo */
1256 {"kB", "backtab"}, /* terminfo */
1258 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1260 {"@8", "kp-enter"}, /* terminfo */
1262 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1263 * "kp-multiply", "kp-add", "kp-separator",
1264 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1265 * --- no termcaps for any of these.
1267 {"K4", "kp-1"}, /* terminfo */
1269 * "kp-2" --- no termcap
1271 {"K5", "kp-3"}, /* terminfo */
1273 * "kp-4" --- no termcap
1275 {"K2", "kp-5"}, /* terminfo */
1277 * "kp-6" --- no termcap
1279 {"K1", "kp-7"}, /* terminfo */
1281 * "kp-8" --- no termcap
1283 {"K3", "kp-9"}, /* terminfo */
1285 * "kp-equal" --- no termcap
1297 {"&0", "S-cancel"}, /*shifted cancel key*/
1298 {"&9", "S-begin"}, /*shifted begin key*/
1299 {"*0", "S-find"}, /*shifted find key*/
1300 {"*1", "S-execute"}, /*shifted execute? actually shifted command key*/
1301 {"*4", "S-delete"}, /*shifted delete-character key*/
1302 {"*7", "S-end"}, /*shifted end key*/
1303 {"*8", "S-clearline"}, /*shifted clear-to end-of-line key*/
1304 {"#1", "S-help"}, /*shifted help key*/
1305 {"#2", "S-home"}, /*shifted home key*/
1306 {"#3", "S-insert"}, /*shifted insert-character key*/
1307 {"#4", "S-left"}, /*shifted left-arrow key*/
1308 {"%d", "S-menu"}, /*shifted menu? actually shifted options key*/
1309 {"%c", "S-next"}, /*shifted next key*/
1310 {"%e", "S-prior"}, /*shifted previous key*/
1311 {"%f", "S-print"}, /*shifted print key*/
1312 {"%g", "S-redo"}, /*shifted redo key*/
1313 {"%i", "S-right"}, /*shifted right-arrow key*/
1314 {"!3", "S-undo"} /*shifted undo key*/
1318 static char **term_get_fkeys_address
;
1319 static KBOARD
*term_get_fkeys_kboard
;
1320 static Lisp_Object
term_get_fkeys_1 (void);
1322 /* Find the escape codes sent by the function keys for Vinput_decode_map.
1323 This function scans the termcap function key sequence entries, and
1324 adds entries to Vinput_decode_map for each function key it finds. */
1327 term_get_fkeys (char **address
, KBOARD
*kboard
)
1329 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1330 errors during the call. The only errors should be from Fdefine_key
1331 when given a key sequence containing an invalid prefix key. If the
1332 termcap defines function keys which use a prefix that is already bound
1333 to a command by the default bindings, we should silently ignore that
1334 function key specification, rather than giving the user an error and
1335 refusing to run at all on such a terminal. */
1337 term_get_fkeys_address
= address
;
1338 term_get_fkeys_kboard
= kboard
;
1339 internal_condition_case (term_get_fkeys_1
, Qerror
, Fidentity
);
1343 term_get_fkeys_1 (void)
1347 char **address
= term_get_fkeys_address
;
1348 KBOARD
*kboard
= term_get_fkeys_kboard
;
1350 /* This can happen if CANNOT_DUMP or with strange options. */
1351 if (!KEYMAPP (KVAR (kboard
, Vinput_decode_map
)))
1352 kset_input_decode_map (kboard
, Fmake_sparse_keymap (Qnil
));
1354 for (i
= 0; i
< ARRAYELTS (keys
); i
++)
1356 char *sequence
= tgetstr (keys
[i
].cap
, address
);
1358 Fdefine_key (KVAR (kboard
, Vinput_decode_map
), build_string (sequence
),
1359 Fmake_vector (make_number (1),
1360 intern (keys
[i
].name
)));
1363 /* The uses of the "k0" capability are inconsistent; sometimes it
1364 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1365 We will attempt to politely accommodate both systems by testing for
1366 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1369 const char *k_semi
= tgetstr ("k;", address
);
1370 const char *k0
= tgetstr ("k0", address
);
1371 const char *k0_name
= "f10";
1376 /* Define f0 first, so that f10 takes precedence in case the
1377 key sequences happens to be the same. */
1378 Fdefine_key (KVAR (kboard
, Vinput_decode_map
), build_string (k0
),
1379 Fmake_vector (make_number (1), intern ("f0")));
1380 Fdefine_key (KVAR (kboard
, Vinput_decode_map
), build_string (k_semi
),
1381 Fmake_vector (make_number (1), intern ("f10")));
1384 Fdefine_key (KVAR (kboard
, Vinput_decode_map
), build_string (k0
),
1385 Fmake_vector (make_number (1), intern (k0_name
)));
1388 /* Set up cookies for numbered function keys above f10. */
1390 char fcap
[3], fkey
[4];
1392 fcap
[0] = 'F'; fcap
[2] = '\0';
1393 for (i
= 11; i
< 64; i
++)
1396 fcap
[1] = '1' + i
- 11;
1398 fcap
[1] = 'A' + i
- 20;
1400 fcap
[1] = 'a' + i
- 46;
1403 char *sequence
= tgetstr (fcap
, address
);
1406 sprintf (fkey
, "f%d", i
);
1407 Fdefine_key (KVAR (kboard
, Vinput_decode_map
), build_string (sequence
),
1408 Fmake_vector (make_number (1),
1416 * Various mappings to try and get a better fit.
1419 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1420 if (!tgetstr (cap1, address)) \
1422 char *sequence = tgetstr (cap2, address); \
1424 Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (sequence), \
1425 Fmake_vector (make_number (1), \
1429 /* if there's no key_next keycap, map key_npage to `next' keysym */
1430 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1431 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1432 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1433 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1434 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1435 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1436 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1437 #undef CONDITIONAL_REASSIGN
1442 #endif /* not DOS_NT */
1445 /***********************************************************************
1446 Character Display Information
1447 ***********************************************************************/
1448 static void append_glyph (struct it
*);
1449 static void append_composite_glyph (struct it
*);
1450 static void produce_composite_glyph (struct it
*);
1451 static void append_glyphless_glyph (struct it
*, int, const char *);
1452 static void produce_glyphless_glyph (struct it
*, Lisp_Object
);
1454 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1455 terminal frames if IT->glyph_row != NULL. IT->char_to_display is
1456 the character for which to produce glyphs; IT->face_id contains the
1457 character's face. Padding glyphs are appended if IT->c has a
1458 IT->pixel_width > 1. */
1461 append_glyph (struct it
*it
)
1463 struct glyph
*glyph
, *end
;
1466 eassert (it
->glyph_row
);
1467 glyph
= (it
->glyph_row
->glyphs
[it
->area
]
1468 + it
->glyph_row
->used
[it
->area
]);
1469 end
= it
->glyph_row
->glyphs
[1 + it
->area
];
1471 /* If the glyph row is reversed, we need to prepend the glyph rather
1473 if (it
->glyph_row
->reversed_p
&& it
->area
== TEXT_AREA
)
1476 int move_by
= it
->pixel_width
;
1478 /* Make room for the new glyphs. */
1479 if (move_by
> end
- glyph
) /* don't overstep end of this area */
1480 move_by
= end
- glyph
;
1481 for (g
= glyph
- 1; g
>= it
->glyph_row
->glyphs
[it
->area
]; g
--)
1483 glyph
= it
->glyph_row
->glyphs
[it
->area
];
1484 end
= glyph
+ move_by
;
1487 /* BIDI Note: we put the glyphs of a "multi-pixel" character left to
1488 right, even in the REVERSED_P case, since (a) all of its u.ch are
1489 identical, and (b) the PADDING_P flag needs to be set for the
1490 leftmost one, because we write to the terminal left-to-right. */
1492 i
< it
->pixel_width
&& glyph
< end
;
1495 glyph
->type
= CHAR_GLYPH
;
1496 glyph
->pixel_width
= 1;
1497 glyph
->u
.ch
= it
->char_to_display
;
1498 glyph
->face_id
= it
->face_id
;
1499 glyph
->padding_p
= i
> 0;
1500 glyph
->charpos
= CHARPOS (it
->position
);
1501 glyph
->object
= it
->object
;
1504 glyph
->resolved_level
= it
->bidi_it
.resolved_level
;
1505 eassert ((it
->bidi_it
.type
& 7) == it
->bidi_it
.type
);
1506 glyph
->bidi_type
= it
->bidi_it
.type
;
1510 glyph
->resolved_level
= 0;
1511 glyph
->bidi_type
= UNKNOWN_BT
;
1514 ++it
->glyph_row
->used
[it
->area
];
1519 /* For external use. */
1521 tty_append_glyph (struct it
*it
)
1527 /* Produce glyphs for the display element described by IT. *IT
1528 specifies what we want to produce a glyph for (character, image, ...),
1529 and where in the glyph matrix we currently are (glyph row and hpos).
1530 produce_glyphs fills in output fields of *IT with information such as the
1531 pixel width and height of a character, and maybe output actual glyphs at
1532 the same time if IT->glyph_row is non-null. For an overview, see
1533 the explanation in dispextern.h, before the definition of the
1534 display_element_type enumeration.
1536 produce_glyphs also stores the result of glyph width, ascent
1537 etc. computations in *IT.
1539 IT->glyph_row may be null, in which case produce_glyphs does not
1540 actually fill in the glyphs. This is used in the move_* functions
1541 in xdisp.c for text width and height computations.
1543 Callers usually don't call produce_glyphs directly;
1544 instead they use the macro PRODUCE_GLYPHS. */
1547 produce_glyphs (struct it
*it
)
1549 /* If a hook is installed, let it do the work. */
1551 /* Nothing but characters are supported on terminal frames. */
1552 eassert (it
->what
== IT_CHARACTER
1553 || it
->what
== IT_COMPOSITION
1554 || it
->what
== IT_STRETCH
1555 || it
->what
== IT_GLYPHLESS
);
1557 if (it
->what
== IT_STRETCH
)
1559 produce_stretch_glyph (it
);
1563 if (it
->what
== IT_COMPOSITION
)
1565 produce_composite_glyph (it
);
1569 if (it
->what
== IT_GLYPHLESS
)
1571 produce_glyphless_glyph (it
, Qnil
);
1575 if (it
->char_to_display
>= 040 && it
->char_to_display
< 0177)
1577 it
->pixel_width
= it
->nglyphs
= 1;
1581 else if (it
->char_to_display
== '\n')
1582 it
->pixel_width
= it
->nglyphs
= 0;
1583 else if (it
->char_to_display
== '\t')
1585 int absolute_x
= (it
->current_x
1586 + it
->continuation_lines_width
);
1588 = (((1 + absolute_x
+ it
->tab_width
- 1)
1593 /* If part of the TAB has been displayed on the previous line
1594 which is continued now, continuation_lines_width will have
1595 been incremented already by the part that fitted on the
1596 continued line. So, we will get the right number of spaces
1598 nspaces
= next_tab_x
- absolute_x
;
1604 it
->char_to_display
= ' ';
1605 it
->pixel_width
= it
->len
= 1;
1611 it
->pixel_width
= nspaces
;
1612 it
->nglyphs
= nspaces
;
1614 else if (CHAR_BYTE8_P (it
->char_to_display
))
1616 /* Coming here means that we must send the raw 8-bit byte as is
1617 to the terminal. Although there's no way to know how many
1618 columns it occupies on a screen, it is a good assumption that
1619 a single byte code has 1-column width. */
1620 it
->pixel_width
= it
->nglyphs
= 1;
1626 Lisp_Object charset_list
= FRAME_TERMINAL (it
->f
)->charset_list
;
1628 if (char_charset (it
->char_to_display
, charset_list
, NULL
))
1630 it
->pixel_width
= CHAR_WIDTH (it
->char_to_display
);
1631 it
->nglyphs
= it
->pixel_width
;
1637 Lisp_Object acronym
= lookup_glyphless_char_display (-1, it
);
1639 eassert (it
->what
== IT_GLYPHLESS
);
1640 produce_glyphless_glyph (it
, acronym
);
1645 /* Advance current_x by the pixel width as a convenience for
1647 if (it
->area
== TEXT_AREA
)
1648 it
->current_x
+= it
->pixel_width
;
1649 it
->ascent
= it
->max_ascent
= it
->phys_ascent
= it
->max_phys_ascent
= 0;
1650 it
->descent
= it
->max_descent
= it
->phys_descent
= it
->max_phys_descent
= 1;
1653 /* Append glyphs to IT's glyph_row for the composition IT->cmp_id.
1654 Called from produce_composite_glyph for terminal frames if
1655 IT->glyph_row != NULL. IT->face_id contains the character's
1659 append_composite_glyph (struct it
*it
)
1661 struct glyph
*glyph
;
1663 eassert (it
->glyph_row
);
1664 glyph
= it
->glyph_row
->glyphs
[it
->area
] + it
->glyph_row
->used
[it
->area
];
1665 if (glyph
< it
->glyph_row
->glyphs
[1 + it
->area
])
1667 /* If the glyph row is reversed, we need to prepend the glyph
1668 rather than append it. */
1669 if (it
->glyph_row
->reversed_p
&& it
->area
== TEXT_AREA
)
1673 /* Make room for the new glyph. */
1674 for (g
= glyph
- 1; g
>= it
->glyph_row
->glyphs
[it
->area
]; g
--)
1676 glyph
= it
->glyph_row
->glyphs
[it
->area
];
1678 glyph
->type
= COMPOSITE_GLYPH
;
1679 eassert (it
->pixel_width
<= SHRT_MAX
);
1680 glyph
->pixel_width
= it
->pixel_width
;
1681 glyph
->u
.cmp
.id
= it
->cmp_it
.id
;
1682 if (it
->cmp_it
.ch
< 0)
1684 glyph
->u
.cmp
.automatic
= 0;
1685 glyph
->u
.cmp
.id
= it
->cmp_it
.id
;
1689 glyph
->u
.cmp
.automatic
= 1;
1690 glyph
->u
.cmp
.id
= it
->cmp_it
.id
;
1691 glyph
->slice
.cmp
.from
= it
->cmp_it
.from
;
1692 glyph
->slice
.cmp
.to
= it
->cmp_it
.to
- 1;
1695 glyph
->face_id
= it
->face_id
;
1696 glyph
->padding_p
= 0;
1697 glyph
->charpos
= CHARPOS (it
->position
);
1698 glyph
->object
= it
->object
;
1701 glyph
->resolved_level
= it
->bidi_it
.resolved_level
;
1702 eassert ((it
->bidi_it
.type
& 7) == it
->bidi_it
.type
);
1703 glyph
->bidi_type
= it
->bidi_it
.type
;
1707 glyph
->resolved_level
= 0;
1708 glyph
->bidi_type
= UNKNOWN_BT
;
1711 ++it
->glyph_row
->used
[it
->area
];
1717 /* Produce a composite glyph for iterator IT. IT->cmp_id is the ID of
1718 the composition. We simply produces components of the composition
1719 assuming that the terminal has a capability to layout/render it
1723 produce_composite_glyph (struct it
*it
)
1725 if (it
->cmp_it
.ch
< 0)
1727 struct composition
*cmp
= composition_table
[it
->cmp_it
.id
];
1729 it
->pixel_width
= cmp
->width
;
1733 Lisp_Object gstring
= composition_gstring_from_id (it
->cmp_it
.id
);
1735 it
->pixel_width
= composition_gstring_width (gstring
, it
->cmp_it
.from
,
1736 it
->cmp_it
.to
, NULL
);
1740 append_composite_glyph (it
);
1744 /* Append a glyph for a glyphless character to IT->glyph_row. FACE_ID
1745 is a face ID to be used for the glyph. What is actually appended
1746 are glyphs of type CHAR_GLYPH whose characters are in STR (which
1747 comes from it->nglyphs bytes). */
1750 append_glyphless_glyph (struct it
*it
, int face_id
, const char *str
)
1752 struct glyph
*glyph
, *end
;
1755 eassert (it
->glyph_row
);
1756 glyph
= it
->glyph_row
->glyphs
[it
->area
] + it
->glyph_row
->used
[it
->area
];
1757 end
= it
->glyph_row
->glyphs
[1 + it
->area
];
1759 /* If the glyph row is reversed, we need to prepend the glyph rather
1761 if (it
->glyph_row
->reversed_p
&& it
->area
== TEXT_AREA
)
1764 int move_by
= it
->pixel_width
;
1766 /* Make room for the new glyphs. */
1767 if (move_by
> end
- glyph
) /* don't overstep end of this area */
1768 move_by
= end
- glyph
;
1769 for (g
= glyph
- 1; g
>= it
->glyph_row
->glyphs
[it
->area
]; g
--)
1771 glyph
= it
->glyph_row
->glyphs
[it
->area
];
1772 end
= glyph
+ move_by
;
1777 glyph
->type
= CHAR_GLYPH
;
1778 glyph
->pixel_width
= 1;
1779 glyph
->face_id
= face_id
;
1780 glyph
->padding_p
= 0;
1781 glyph
->charpos
= CHARPOS (it
->position
);
1782 glyph
->object
= it
->object
;
1785 glyph
->resolved_level
= it
->bidi_it
.resolved_level
;
1786 eassert ((it
->bidi_it
.type
& 7) == it
->bidi_it
.type
);
1787 glyph
->bidi_type
= it
->bidi_it
.type
;
1791 glyph
->resolved_level
= 0;
1792 glyph
->bidi_type
= UNKNOWN_BT
;
1795 /* BIDI Note: we put the glyphs of characters left to right, even in
1796 the REVERSED_P case because we write to the terminal
1798 for (i
= 0; i
< it
->nglyphs
&& glyph
< end
; ++i
)
1801 glyph
[0] = glyph
[-1];
1802 glyph
->u
.ch
= str
[i
];
1803 ++it
->glyph_row
->used
[it
->area
];
1808 /* Produce glyphs for a glyphless character for iterator IT.
1809 IT->glyphless_method specifies which method to use for displaying
1810 the character. See the description of enum
1811 glyphless_display_method in dispextern.h for the details.
1813 ACRONYM, if non-nil, is an acronym string for the character.
1815 The glyphs actually produced are of type CHAR_GLYPH. */
1818 produce_glyphless_glyph (struct it
*it
, Lisp_Object acronym
)
1820 int len
, face_id
= merge_glyphless_glyph_face (it
);
1821 char buf
[sizeof "\\x" + max (6, (sizeof it
->c
* CHAR_BIT
+ 3) / 4)];
1822 char const *str
= " ";
1824 if (it
->glyphless_method
== GLYPHLESS_DISPLAY_THIN_SPACE
)
1826 /* As there's no way to produce a thin space, we produce a space
1827 of canonical width. */
1830 else if (it
->glyphless_method
== GLYPHLESS_DISPLAY_EMPTY_BOX
)
1832 len
= CHAR_WIDTH (it
->c
);
1837 len
= sprintf (buf
, "[%.*s]", len
, str
);
1842 if (it
->glyphless_method
== GLYPHLESS_DISPLAY_ACRONYM
)
1844 if (! STRINGP (acronym
) && CHAR_TABLE_P (Vglyphless_char_display
))
1845 acronym
= CHAR_TABLE_REF (Vglyphless_char_display
, it
->c
);
1846 if (CONSP (acronym
))
1847 acronym
= XCDR (acronym
);
1849 str
= STRINGP (acronym
) ? SSDATA (acronym
) : "";
1850 for (len
= 0; len
< 6 && str
[len
] && ASCII_CHAR_P (str
[len
]); len
++)
1851 buf
[1 + len
] = str
[len
];
1857 eassert (it
->glyphless_method
== GLYPHLESS_DISPLAY_HEX_CODE
);
1859 (it
->c
< 0x10000 ? "\\u%04X"
1860 : it
->c
<= MAX_UNICODE_CHAR
? "\\U%06X"
1867 it
->pixel_width
= len
;
1870 append_glyphless_glyph (it
, face_id
, str
);
1874 /***********************************************************************
1876 ***********************************************************************/
1878 /* Value is non-zero if attribute ATTR may be used. ATTR should be
1879 one of the enumerators from enum no_color_bit, or a bit set built
1880 from them. Some display attributes may not be used together with
1881 color; the termcap capability `NC' specifies which ones. */
1883 #define MAY_USE_WITH_COLORS_P(tty, ATTR) \
1884 (tty->TN_max_colors > 0 \
1885 ? (tty->TN_no_color_video & (ATTR)) == 0 \
1888 /* Turn appearances of face FACE_ID on tty frame F on.
1889 FACE_ID is a realized face ID number, in the face cache. */
1892 turn_on_face (struct frame
*f
, int face_id
)
1894 struct face
*face
= FACE_FROM_ID (f
, face_id
);
1895 unsigned long fg
= face
->foreground
;
1896 unsigned long bg
= face
->background
;
1897 struct tty_display_info
*tty
= FRAME_TTY (f
);
1899 /* Use reverse video if the face specifies that.
1900 Do this first because TS_end_standout_mode may be the same
1901 as TS_exit_attribute_mode, which turns all appearances off. */
1902 if (MAY_USE_WITH_COLORS_P (tty
, NC_REVERSE
)
1904 ? fg
== FACE_TTY_DEFAULT_FG_COLOR
|| bg
== FACE_TTY_DEFAULT_BG_COLOR
1905 : fg
== FACE_TTY_DEFAULT_BG_COLOR
|| bg
== FACE_TTY_DEFAULT_FG_COLOR
))
1906 tty_toggle_highlight (tty
);
1908 if (face
->tty_bold_p
&& MAY_USE_WITH_COLORS_P (tty
, NC_BOLD
))
1909 OUTPUT1_IF (tty
, tty
->TS_enter_bold_mode
);
1911 if (face
->tty_italic_p
&& MAY_USE_WITH_COLORS_P (tty
, NC_ITALIC
))
1913 if (tty
->TS_enter_italic_mode
)
1914 OUTPUT1 (tty
, tty
->TS_enter_italic_mode
);
1916 /* Italics mode is unavailable on many terminals. In that
1917 case, map slant to dimmed text; we want italic text to
1918 appear different and dimming is not otherwise used. */
1919 OUTPUT1 (tty
, tty
->TS_enter_dim_mode
);
1922 if (face
->tty_underline_p
&& MAY_USE_WITH_COLORS_P (tty
, NC_UNDERLINE
))
1923 OUTPUT1_IF (tty
, tty
->TS_enter_underline_mode
);
1925 if (tty
->TN_max_colors
> 0)
1930 ts
= tty
->standout_mode
? tty
->TS_set_background
: tty
->TS_set_foreground
;
1931 if (face_tty_specified_color (fg
) && ts
)
1933 p
= tparam (ts
, NULL
, 0, fg
, 0, 0, 0);
1938 ts
= tty
->standout_mode
? tty
->TS_set_foreground
: tty
->TS_set_background
;
1939 if (face_tty_specified_color (bg
) && ts
)
1941 p
= tparam (ts
, NULL
, 0, bg
, 0, 0, 0);
1949 /* Turn off appearances of face FACE_ID on tty frame F. */
1952 turn_off_face (struct frame
*f
, int face_id
)
1954 struct face
*face
= FACE_FROM_ID (f
, face_id
);
1955 struct tty_display_info
*tty
= FRAME_TTY (f
);
1957 if (tty
->TS_exit_attribute_mode
)
1959 /* Capability "me" will turn off appearance modes double-bright,
1960 half-bright, reverse-video, standout, underline. It may or
1961 may not turn off alt-char-mode. */
1962 if (face
->tty_bold_p
1963 || face
->tty_italic_p
1964 || face
->tty_reverse_p
1965 || face
->tty_underline_p
)
1967 OUTPUT1_IF (tty
, tty
->TS_exit_attribute_mode
);
1968 if (strcmp (tty
->TS_exit_attribute_mode
, tty
->TS_end_standout_mode
) == 0)
1969 tty
->standout_mode
= 0;
1974 /* If we don't have "me" we can only have those appearances
1975 that have exit sequences defined. */
1976 if (face
->tty_underline_p
)
1977 OUTPUT_IF (tty
, tty
->TS_exit_underline_mode
);
1980 /* Switch back to default colors. */
1981 if (tty
->TN_max_colors
> 0
1982 && ((face
->foreground
!= FACE_TTY_DEFAULT_COLOR
1983 && face
->foreground
!= FACE_TTY_DEFAULT_FG_COLOR
)
1984 || (face
->background
!= FACE_TTY_DEFAULT_COLOR
1985 && face
->background
!= FACE_TTY_DEFAULT_BG_COLOR
)))
1986 OUTPUT1_IF (tty
, tty
->TS_orig_pair
);
1990 /* Return true if the terminal on frame F supports all of the
1991 capabilities in CAPS simultaneously. */
1994 tty_capable_p (struct tty_display_info
*tty
, unsigned int caps
)
1996 #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
1997 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
2000 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_INVERSE
, tty
->TS_standout_mode
, NC_REVERSE
);
2001 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_UNDERLINE
, tty
->TS_enter_underline_mode
, NC_UNDERLINE
);
2002 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_BOLD
, tty
->TS_enter_bold_mode
, NC_BOLD
);
2003 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_DIM
, tty
->TS_enter_dim_mode
, NC_DIM
);
2004 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_ITALIC
, tty
->TS_enter_italic_mode
, NC_ITALIC
);
2010 /* Return non-zero if the terminal is capable to display colors. */
2012 DEFUN ("tty-display-color-p", Ftty_display_color_p
, Stty_display_color_p
,
2014 doc
: /* Return non-nil if the tty device TERMINAL can display colors.
2016 TERMINAL can be a terminal object, a frame, or nil (meaning the
2017 selected frame's terminal). This function always returns nil if
2018 TERMINAL does not refer to a text terminal. */)
2019 (Lisp_Object terminal
)
2021 struct terminal
*t
= decode_tty_terminal (terminal
);
2023 return (t
&& t
->display_info
.tty
->TN_max_colors
> 0) ? Qt
: Qnil
;
2026 /* Return the number of supported colors. */
2027 DEFUN ("tty-display-color-cells", Ftty_display_color_cells
,
2028 Stty_display_color_cells
, 0, 1, 0,
2029 doc
: /* Return the number of colors supported by the tty device TERMINAL.
2031 TERMINAL can be a terminal object, a frame, or nil (meaning the
2032 selected frame's terminal). This function always returns 0 if
2033 TERMINAL does not refer to a text terminal. */)
2034 (Lisp_Object terminal
)
2036 struct terminal
*t
= decode_tty_terminal (terminal
);
2038 return make_number (t
? t
->display_info
.tty
->TN_max_colors
: 0);
2043 /* Declare here rather than in the function, as in the rest of Emacs,
2044 to work around an HPUX compiler bug (?). See
2045 http://lists.gnu.org/archive/html/emacs-devel/2007-08/msg00410.html */
2046 static int default_max_colors
;
2047 static int default_max_pairs
;
2048 static int default_no_color_video
;
2049 static char *default_orig_pair
;
2050 static char *default_set_foreground
;
2051 static char *default_set_background
;
2053 /* Save or restore the default color-related capabilities of this
2056 tty_default_color_capabilities (struct tty_display_info
*tty
, bool save
)
2061 dupstring (&default_orig_pair
, tty
->TS_orig_pair
);
2062 dupstring (&default_set_foreground
, tty
->TS_set_foreground
);
2063 dupstring (&default_set_background
, tty
->TS_set_background
);
2064 default_max_colors
= tty
->TN_max_colors
;
2065 default_max_pairs
= tty
->TN_max_pairs
;
2066 default_no_color_video
= tty
->TN_no_color_video
;
2070 tty
->TS_orig_pair
= default_orig_pair
;
2071 tty
->TS_set_foreground
= default_set_foreground
;
2072 tty
->TS_set_background
= default_set_background
;
2073 tty
->TN_max_colors
= default_max_colors
;
2074 tty
->TN_max_pairs
= default_max_pairs
;
2075 tty
->TN_no_color_video
= default_no_color_video
;
2079 /* Setup one of the standard tty color schemes according to MODE.
2080 MODE's value is generally the number of colors which we want to
2081 support; zero means set up for the default capabilities, the ones
2082 we saw at init_tty time; -1 means turn off color support. */
2084 tty_setup_colors (struct tty_display_info
*tty
, int mode
)
2086 /* Canonicalize all negative values of MODE. */
2092 case -1: /* no colors at all */
2093 tty
->TN_max_colors
= 0;
2094 tty
->TN_max_pairs
= 0;
2095 tty
->TN_no_color_video
= 0;
2096 tty
->TS_set_foreground
= tty
->TS_set_background
= tty
->TS_orig_pair
= NULL
;
2098 case 0: /* default colors, if any */
2100 tty_default_color_capabilities (tty
, 0);
2102 case 8: /* 8 standard ANSI colors */
2103 tty
->TS_orig_pair
= "\033[0m";
2105 tty
->TS_set_foreground
= "\033[3%p1%dm";
2106 tty
->TS_set_background
= "\033[4%p1%dm";
2108 tty
->TS_set_foreground
= "\033[3%dm";
2109 tty
->TS_set_background
= "\033[4%dm";
2111 tty
->TN_max_colors
= 8;
2112 tty
->TN_max_pairs
= 64;
2113 tty
->TN_no_color_video
= 0;
2119 set_tty_color_mode (struct tty_display_info
*tty
, struct frame
*f
)
2121 Lisp_Object tem
, val
;
2122 Lisp_Object color_mode
;
2124 Lisp_Object tty_color_mode_alist
2125 = Fintern_soft (build_string ("tty-color-mode-alist"), Qnil
);
2127 tem
= assq_no_quit (Qtty_color_mode
, f
->param_alist
);
2128 val
= CONSP (tem
) ? XCDR (tem
) : Qnil
;
2132 else if (SYMBOLP (tty_color_mode_alist
))
2134 tem
= Fassq (val
, Fsymbol_value (tty_color_mode_alist
));
2135 color_mode
= CONSP (tem
) ? XCDR (tem
) : Qnil
;
2140 mode
= TYPE_RANGED_INTEGERP (int, color_mode
) ? XINT (color_mode
) : 0;
2142 if (mode
!= tty
->previous_color_mode
)
2144 tty
->previous_color_mode
= mode
;
2145 tty_setup_colors (tty
, mode
);
2146 /* This recomputes all the faces given the new color definitions. */
2147 safe_call (1, intern ("tty-set-up-initial-frame-faces"));
2151 #endif /* !DOS_NT */
2153 DEFUN ("tty-type", Ftty_type
, Stty_type
, 0, 1, 0,
2154 doc
: /* Return the type of the tty device that TERMINAL uses.
2155 Returns nil if TERMINAL is not on a tty device.
2157 TERMINAL can be a terminal object, a frame, or nil (meaning the
2158 selected frame's terminal). */)
2159 (Lisp_Object terminal
)
2161 struct terminal
*t
= decode_tty_terminal (terminal
);
2163 return (t
&& t
->display_info
.tty
->type
2164 ? build_string (t
->display_info
.tty
->type
) : Qnil
);
2167 DEFUN ("controlling-tty-p", Fcontrolling_tty_p
, Scontrolling_tty_p
, 0, 1, 0,
2168 doc
: /* Return non-nil if TERMINAL is the controlling tty of the Emacs process.
2170 TERMINAL can be a terminal object, a frame, or nil (meaning the
2171 selected frame's terminal). This function always returns nil if
2172 TERMINAL is not on a tty device. */)
2173 (Lisp_Object terminal
)
2175 struct terminal
*t
= decode_tty_terminal (terminal
);
2177 return (t
&& !strcmp (t
->display_info
.tty
->name
, DEV_TTY
) ? Qt
: Qnil
);
2180 DEFUN ("tty-no-underline", Ftty_no_underline
, Stty_no_underline
, 0, 1, 0,
2181 doc
: /* Declare that the tty used by TERMINAL does not handle underlining.
2182 This is used to override the terminfo data, for certain terminals that
2183 do not really do underlining, but say that they do. This function has
2184 no effect if used on a non-tty terminal.
2186 TERMINAL can be a terminal object, a frame or nil (meaning the
2187 selected frame's terminal). This function always returns nil if
2188 TERMINAL does not refer to a text terminal. */)
2189 (Lisp_Object terminal
)
2191 struct terminal
*t
= decode_live_terminal (terminal
);
2193 if (t
->type
== output_termcap
)
2194 t
->display_info
.tty
->TS_enter_underline_mode
= 0;
2198 DEFUN ("tty-top-frame", Ftty_top_frame
, Stty_top_frame
, 0, 1, 0,
2199 doc
: /* Return the topmost terminal frame on TERMINAL.
2200 TERMINAL can be a terminal object, a frame or nil (meaning the
2201 selected frame's terminal). This function returns nil if TERMINAL
2202 does not refer to a text terminal. Otherwise, it returns the
2203 top-most frame on the text terminal. */)
2204 (Lisp_Object terminal
)
2206 struct terminal
*t
= decode_live_terminal (terminal
);
2208 if (t
->type
== output_termcap
)
2209 return t
->display_info
.tty
->top_frame
;
2215 DEFUN ("suspend-tty", Fsuspend_tty
, Ssuspend_tty
, 0, 1, 0,
2216 doc
: /* Suspend the terminal device TTY.
2218 The device is restored to its default state, and Emacs ceases all
2219 access to the tty device. Frames that use the device are not deleted,
2220 but input is not read from them and if they change, their display is
2223 TTY may be a terminal object, a frame, or nil for the terminal device
2224 of the currently selected frame.
2226 This function runs `suspend-tty-functions' after suspending the
2227 device. The functions are run with one arg, the id of the suspended
2230 `suspend-tty' does nothing if it is called on a device that is already
2233 A suspended tty may be resumed by calling `resume-tty' on it. */)
2236 struct terminal
*t
= decode_tty_terminal (tty
);
2240 error ("Attempt to suspend a non-text terminal device");
2242 f
= t
->display_info
.tty
->input
;
2246 /* First run `suspend-tty-functions' and then clean up the tty
2247 state because `suspend-tty-functions' might need to change
2250 XSETTERMINAL (term
, t
);
2251 CALLN (Frun_hook_with_args
, intern ("suspend-tty-functions"), term
);
2253 reset_sys_modes (t
->display_info
.tty
);
2254 delete_keyboard_wait_descriptor (fileno (f
));
2258 if (f
!= t
->display_info
.tty
->output
)
2259 fclose (t
->display_info
.tty
->output
);
2262 t
->display_info
.tty
->input
= 0;
2263 t
->display_info
.tty
->output
= 0;
2265 if (FRAMEP (t
->display_info
.tty
->top_frame
))
2266 SET_FRAME_VISIBLE (XFRAME (t
->display_info
.tty
->top_frame
), 0);
2270 /* Clear display hooks to prevent further output. */
2271 clear_tty_hooks (t
);
2276 DEFUN ("resume-tty", Fresume_tty
, Sresume_tty
, 0, 1, 0,
2277 doc
: /* Resume the previously suspended terminal device TTY.
2278 The terminal is opened and reinitialized. Frames that are on the
2279 suspended terminal are revived.
2281 It is an error to resume a terminal while another terminal is active
2284 This function runs `resume-tty-functions' after resuming the terminal.
2285 The functions are run with one arg, the id of the resumed terminal
2288 `resume-tty' does nothing if it is called on a device that is not
2291 TTY may be a terminal object, a frame, or nil (meaning the selected
2292 frame's terminal). */)
2295 struct terminal
*t
= decode_tty_terminal (tty
);
2299 error ("Attempt to resume a non-text terminal device");
2301 if (!t
->display_info
.tty
->input
)
2303 if (get_named_terminal (t
->display_info
.tty
->name
))
2304 error ("Cannot resume display while another display is active on the same device");
2307 t
->display_info
.tty
->output
= stdout
;
2308 t
->display_info
.tty
->input
= stdin
;
2310 fd
= emacs_open (t
->display_info
.tty
->name
, O_RDWR
| O_NOCTTY
, 0);
2311 t
->display_info
.tty
->input
= t
->display_info
.tty
->output
2312 = fd
< 0 ? 0 : fdopen (fd
, "w+");
2314 if (! t
->display_info
.tty
->input
)
2316 int open_errno
= errno
;
2318 report_file_errno ("Cannot reopen tty device",
2319 build_string (t
->display_info
.tty
->name
),
2323 if (!O_IGNORE_CTTY
&& strcmp (t
->display_info
.tty
->name
, DEV_TTY
) != 0)
2324 dissociate_if_controlling_tty (fd
);
2327 add_keyboard_wait_descriptor (fd
);
2329 if (FRAMEP (t
->display_info
.tty
->top_frame
))
2331 struct frame
*f
= XFRAME (t
->display_info
.tty
->top_frame
);
2333 int old_height
= FRAME_COLS (f
);
2334 int old_width
= FRAME_TOTAL_LINES (f
);
2336 /* Check if terminal/window size has changed while the frame
2338 get_tty_size (fileno (t
->display_info
.tty
->input
), &width
, &height
);
2339 if (width
!= old_width
|| height
!= old_height
)
2340 change_frame_size (f
, width
, height
- FRAME_MENU_BAR_LINES (f
),
2342 SET_FRAME_VISIBLE (XFRAME (t
->display_info
.tty
->top_frame
), 1);
2346 init_sys_modes (t
->display_info
.tty
);
2348 /* Run `resume-tty-functions'. */
2350 XSETTERMINAL (term
, t
);
2351 CALLN (Frun_hook_with_args
, intern ("resume-tty-functions"), term
);
2360 /***********************************************************************
2362 ***********************************************************************/
2366 #ifndef HAVE_WINDOW_SYSTEM
2368 term_mouse_moveto (int x
, int y
)
2370 /* TODO: how to set mouse position?
2373 name = (const char *) ttyname (0);
2374 fd = emacs_open (name, O_WRONLY, 0);
2375 SOME_FUNCTION (x, y, fd);
2378 last_mouse_y = y; */
2380 #endif /* HAVE_WINDOW_SYSTEM */
2382 /* Implementation of draw_row_with_mouse_face for TTY/GPM. */
2384 tty_draw_row_with_mouse_face (struct window
*w
, struct glyph_row
*row
,
2385 int start_hpos
, int end_hpos
,
2386 enum draw_glyphs_face draw
)
2388 int nglyphs
= end_hpos
- start_hpos
;
2389 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2390 struct tty_display_info
*tty
= FRAME_TTY (f
);
2391 int face_id
= tty
->mouse_highlight
.mouse_face_face_id
;
2392 int save_x
, save_y
, pos_x
, pos_y
;
2394 if (end_hpos
>= row
->used
[TEXT_AREA
])
2395 nglyphs
= row
->used
[TEXT_AREA
] - start_hpos
;
2397 pos_y
= row
->y
+ WINDOW_TOP_EDGE_Y (w
);
2398 pos_x
= row
->used
[LEFT_MARGIN_AREA
] + start_hpos
+ WINDOW_LEFT_EDGE_X (w
);
2400 /* Save current cursor co-ordinates. */
2401 save_y
= curY (tty
);
2402 save_x
= curX (tty
);
2403 cursor_to (f
, pos_y
, pos_x
);
2405 if (draw
== DRAW_MOUSE_FACE
)
2406 tty_write_glyphs_with_face (f
, row
->glyphs
[TEXT_AREA
] + start_hpos
,
2408 else if (draw
== DRAW_NORMAL_TEXT
)
2409 write_glyphs (f
, row
->glyphs
[TEXT_AREA
] + start_hpos
, nglyphs
);
2411 cursor_to (f
, save_y
, save_x
);
2415 term_mouse_movement (struct frame
*frame
, Gpm_Event
*event
)
2417 /* Has the mouse moved off the glyph it was on at the last sighting? */
2418 if (event
->x
!= last_mouse_x
|| event
->y
!= last_mouse_y
)
2420 frame
->mouse_moved
= 1;
2421 note_mouse_highlight (frame
, event
->x
, event
->y
);
2422 /* Remember which glyph we're now on. */
2423 last_mouse_x
= event
->x
;
2424 last_mouse_y
= event
->y
;
2430 /* Return the Time that corresponds to T. Wrap around on overflow. */
2432 timeval_to_Time (struct timeval
const *t
)
2438 ms
= t
->tv_usec
/ 1000;
2442 /* Return the current position of the mouse.
2444 Set *f to the frame the mouse is in, or zero if the mouse is in no
2445 Emacs frame. If it is set to zero, all the other arguments are
2448 Set *bar_window to Qnil, and *x and *y to the column and
2449 row of the character cell the mouse is over.
2451 Set *timeptr to the time the mouse was at the returned position.
2453 This clears mouse_moved until the next motion
2456 term_mouse_position (struct frame
**fp
, int insist
, Lisp_Object
*bar_window
,
2457 enum scroll_bar_part
*part
, Lisp_Object
*x
,
2458 Lisp_Object
*y
, Time
*timeptr
)
2462 *fp
= SELECTED_FRAME ();
2463 (*fp
)->mouse_moved
= 0;
2466 *part
= scroll_bar_above_handle
;
2468 XSETINT (*x
, last_mouse_x
);
2469 XSETINT (*y
, last_mouse_y
);
2470 gettimeofday(&now
, 0);
2471 *timeptr
= timeval_to_Time (&now
);
2474 /* Prepare a mouse-event in *RESULT for placement in the input queue.
2476 If the event is a button press, then note that we have grabbed
2480 term_mouse_click (struct input_event
*result
, Gpm_Event
*event
,
2486 result
->kind
= GPM_CLICK_EVENT
;
2487 for (i
= 0, j
= GPM_B_LEFT
; i
< 3; i
++, j
>>= 1 )
2489 if (event
->buttons
& j
) {
2490 result
->code
= i
; /* button number */
2494 gettimeofday(&now
, 0);
2495 result
->timestamp
= timeval_to_Time (&now
);
2497 if (event
->type
& GPM_UP
)
2498 result
->modifiers
= up_modifier
;
2499 else if (event
->type
& GPM_DOWN
)
2500 result
->modifiers
= down_modifier
;
2502 result
->modifiers
= 0;
2504 if (event
->type
& GPM_SINGLE
)
2505 result
->modifiers
|= click_modifier
;
2507 if (event
->type
& GPM_DOUBLE
)
2508 result
->modifiers
|= double_modifier
;
2510 if (event
->type
& GPM_TRIPLE
)
2511 result
->modifiers
|= triple_modifier
;
2513 if (event
->type
& GPM_DRAG
)
2514 result
->modifiers
|= drag_modifier
;
2516 if (!(event
->type
& (GPM_MOVE
| GPM_DRAG
))) {
2519 if (event
->modifiers
& (1 << 0))
2520 result
->modifiers
|= shift_modifier
;
2523 if (event
->modifiers
& (1 << 2))
2524 result
->modifiers
|= ctrl_modifier
;
2526 /* 1 << KG_ALT || KG_ALTGR */
2527 if (event
->modifiers
& (1 << 3)
2528 || event
->modifiers
& (1 << 1))
2529 result
->modifiers
|= meta_modifier
;
2532 XSETINT (result
->x
, event
->x
);
2533 XSETINT (result
->y
, event
->y
);
2534 XSETFRAME (result
->frame_or_window
, f
);
2540 handle_one_term_event (struct tty_display_info
*tty
, Gpm_Event
*event
, struct input_event
* hold_quit
)
2542 struct frame
*f
= XFRAME (tty
->top_frame
);
2543 struct input_event ie
;
2551 if (event
->type
& (GPM_MOVE
| GPM_DRAG
)) {
2552 previous_help_echo_string
= help_echo_string
;
2553 help_echo_string
= Qnil
;
2555 Gpm_DrawPointer (event
->x
, event
->y
, fileno (tty
->output
));
2557 if (!term_mouse_movement (f
, event
))
2558 help_echo_string
= previous_help_echo_string
;
2560 /* If the contents of the global variable help_echo_string
2561 has changed, generate a HELP_EVENT. */
2562 if (!NILP (help_echo_string
)
2563 || !NILP (previous_help_echo_string
))
2570 term_mouse_click (&ie
, event
, f
);
2574 if (ie
.kind
!= NO_EVENT
)
2576 kbd_buffer_store_event_hold (&ie
, hold_quit
);
2581 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
2586 XSETFRAME (frame
, f
);
2590 gen_help_event (help_echo_string
, frame
, help_echo_window
,
2591 help_echo_object
, help_echo_pos
);
2598 DEFUN ("gpm-mouse-start", Fgpm_mouse_start
, Sgpm_mouse_start
,
2600 doc
: /* Open a connection to Gpm.
2601 Gpm-mouse can only be activated for one tty at a time. */)
2604 struct frame
*f
= SELECTED_FRAME ();
2605 struct tty_display_info
*tty
2606 = ((f
)->output_method
== output_termcap
2607 ? (f
)->terminal
->display_info
.tty
: NULL
);
2608 Gpm_Connect connection
;
2611 error ("Gpm-mouse only works in the GNU/Linux console");
2613 return Qnil
; /* Already activated, nothing to do. */
2615 error ("Gpm-mouse can only be activated for one tty at a time");
2617 connection
.eventMask
= ~0;
2618 connection
.defaultMask
= ~GPM_HARD
;
2619 connection
.maxMod
= ~0;
2620 connection
.minMod
= 0;
2623 if (Gpm_Open (&connection
, 0) < 0)
2624 error ("Gpm-mouse failed to connect to the gpm daemon");
2628 /* `init_sys_modes' arranges for mouse movements sent through gpm_fd
2629 to generate SIGIOs. Apparently we need to call reset_sys_modes
2630 before calling init_sys_modes. */
2631 reset_sys_modes (tty
);
2632 init_sys_modes (tty
);
2633 add_gpm_wait_descriptor (gpm_fd
);
2642 delete_gpm_wait_descriptor (fd
);
2643 while (Gpm_Close()); /* close all the stack */
2647 DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop
, Sgpm_mouse_stop
,
2649 doc
: /* Close a connection to Gpm. */)
2652 struct frame
*f
= SELECTED_FRAME ();
2653 struct tty_display_info
*tty
2654 = ((f
)->output_method
== output_termcap
2655 ? (f
)->terminal
->display_info
.tty
: NULL
);
2657 if (!tty
|| gpm_tty
!= tty
)
2658 return Qnil
; /* Not activated on this terminal, nothing to do. */
2663 #endif /* HAVE_GPM */
2666 /***********************************************************************
2668 ***********************************************************************/
2670 #if !defined (MSDOS)
2672 /* TTY menu implementation and main ideas are borrowed from msdos.c.
2674 However, unlike on MSDOS, where the menu text is drawn directly to
2675 the display video memory, on a TTY we use display_string (see
2676 display_tty_menu_item in xdisp.c) to put the glyphs produced from
2677 the menu items into the frame's 'desired_matrix' glyph matrix, and
2678 then call update_frame_with_menu to deliver the results to the
2679 glass. The previous contents of the screen, in the form of the
2680 current_matrix, is stashed away, and used to restore screen
2681 contents when the menu selection changes or when the final
2682 selection is made and the menu should be popped down.
2684 The idea of this implementation was suggested by Gerd Moellmann. */
2686 #define TTYM_FAILURE -1
2687 #define TTYM_SUCCESS 1
2688 #define TTYM_NO_SELECT 2
2689 #define TTYM_IA_SELECT 3
2693 /* These hold text of the current and the previous menu help messages. */
2694 static const char *menu_help_message
, *prev_menu_help_message
;
2695 /* Pane number and item number of the menu item which generated the
2696 last menu help message. */
2697 static int menu_help_paneno
, menu_help_itemno
;
2699 typedef struct tty_menu_struct
2703 struct tty_menu_struct
**submenu
;
2704 int *panenumber
; /* Also used as enabled flag. */
2705 ptrdiff_t allocated
;
2708 const char **help_text
;
2711 /* Create a brand new menu structure. */
2714 tty_menu_create (void)
2716 return xzalloc (sizeof *tty_menu_create ());
2719 /* Allocate some (more) memory for MENU ensuring that there is room for one
2723 tty_menu_make_room (tty_menu
*menu
)
2725 if (menu
->allocated
== menu
->count
)
2727 ptrdiff_t allocated
= menu
->allocated
;
2728 menu
->text
= xpalloc (menu
->text
, &allocated
, 1, -1, sizeof *menu
->text
);
2729 menu
->text
= xrealloc (menu
->text
, allocated
* sizeof *menu
->text
);
2730 menu
->submenu
= xrealloc (menu
->submenu
,
2731 allocated
* sizeof *menu
->submenu
);
2732 menu
->panenumber
= xrealloc (menu
->panenumber
,
2733 allocated
* sizeof *menu
->panenumber
);
2734 menu
->help_text
= xrealloc (menu
->help_text
,
2735 allocated
* sizeof *menu
->help_text
);
2736 menu
->allocated
= allocated
;
2740 /* Search the given menu structure for a given pane number. */
2743 tty_menu_search_pane (tty_menu
*menu
, int pane
)
2748 for (i
= 0; i
< menu
->count
; i
++)
2749 if (menu
->submenu
[i
])
2751 if (pane
== menu
->panenumber
[i
])
2752 return menu
->submenu
[i
];
2753 try = tty_menu_search_pane (menu
->submenu
[i
], pane
);
2757 return (tty_menu
*) 0;
2760 /* Determine how much screen space a given menu needs. */
2763 tty_menu_calc_size (tty_menu
*menu
, int *width
, int *height
)
2765 int i
, h2
, w2
, maxsubwidth
, maxheight
;
2767 maxsubwidth
= menu
->width
;
2768 maxheight
= menu
->count
;
2769 for (i
= 0; i
< menu
->count
; i
++)
2771 if (menu
->submenu
[i
])
2773 tty_menu_calc_size (menu
->submenu
[i
], &w2
, &h2
);
2774 if (w2
> maxsubwidth
) maxsubwidth
= w2
;
2775 if (i
+ h2
> maxheight
) maxheight
= i
+ h2
;
2778 *width
= maxsubwidth
;
2779 *height
= maxheight
;
2783 mouse_get_xy (int *x
, int *y
)
2785 struct frame
*sf
= SELECTED_FRAME ();
2786 Lisp_Object lmx
= Qnil
, lmy
= Qnil
, lisp_dummy
;
2787 enum scroll_bar_part part_dummy
;
2790 if (FRAME_TERMINAL (sf
)->mouse_position_hook
)
2791 (*FRAME_TERMINAL (sf
)->mouse_position_hook
) (&sf
, -1,
2792 &lisp_dummy
, &part_dummy
,
2802 /* Display MENU at (X,Y) using FACES, starting with FIRST_ITEM
2806 tty_menu_display (tty_menu
*menu
, int x
, int y
, int pn
, int *faces
,
2807 int mx
, int my
, int first_item
, bool disp_help
)
2809 int i
, face
, width
, enabled
, mousehere
, row
, col
;
2810 struct frame
*sf
= SELECTED_FRAME ();
2811 struct tty_display_info
*tty
= FRAME_TTY (sf
);
2812 /* Don't try to display more menu items than the console can display
2813 using the available screen lines. Exclude the echo area line, as
2814 it will be overwritten by the help-echo anyway. */
2815 int max_items
= min (menu
->count
- first_item
, FRAME_TOTAL_LINES (sf
) - 1 - y
);
2817 menu_help_message
= NULL
;
2819 width
= menu
->width
;
2820 col
= cursorX (tty
);
2821 row
= cursorY (tty
);
2822 for (i
= 0; i
< max_items
; i
++)
2824 int max_width
= width
+ 2; /* +2 for padding blanks on each side */
2825 int j
= i
+ first_item
;
2827 if (menu
->submenu
[j
])
2828 max_width
+= 2; /* for displaying " >" after the item */
2830 = (!menu
->submenu
[j
] && menu
->panenumber
[j
]) || (menu
->submenu
[j
]);
2831 mousehere
= (y
+ i
== my
&& x
<= mx
&& mx
< x
+ max_width
);
2832 face
= faces
[enabled
+ mousehere
* 2];
2833 /* Display the menu help string for the i-th menu item even if
2834 the menu item is currently disabled. That's what the GUI
2836 if (disp_help
&& enabled
+ mousehere
* 2 >= 2)
2838 menu_help_message
= menu
->help_text
[j
];
2839 menu_help_paneno
= pn
- 1;
2840 menu_help_itemno
= j
;
2842 /* Take note of the coordinates of the active menu item, to
2843 display the cursor there. */
2849 display_tty_menu_item (menu
->text
[j
], max_width
, face
, x
, y
+ i
,
2850 menu
->submenu
[j
] != NULL
);
2852 update_frame_with_menu (sf
, row
, col
);
2855 /* --------------------------- X Menu emulation ---------------------- */
2857 /* Create a new pane and place it on the outer-most level. */
2860 tty_menu_add_pane (tty_menu
*menu
, const char *txt
)
2864 tty_menu_make_room (menu
);
2865 menu
->submenu
[menu
->count
] = tty_menu_create ();
2866 menu
->text
[menu
->count
] = (char *)txt
;
2867 menu
->panenumber
[menu
->count
] = ++menu
->panecount
;
2868 menu
->help_text
[menu
->count
] = NULL
;
2871 /* Update the menu width, if necessary. */
2872 len
= menu_item_width ((const unsigned char *) txt
);
2873 if (len
> menu
->width
)
2876 return menu
->panecount
;
2879 /* Create a new item in a menu pane. */
2882 tty_menu_add_selection (tty_menu
*menu
, int pane
,
2883 char *txt
, bool enable
, char const *help_text
)
2889 menu
= tty_menu_search_pane (menu
, pane
);
2893 tty_menu_make_room (menu
);
2894 menu
->submenu
[menu
->count
] = (tty_menu
*) 0;
2895 menu
->text
[menu
->count
] = txt
;
2896 menu
->panenumber
[menu
->count
] = enable
;
2897 menu
->help_text
[menu
->count
] = help_text
;
2900 /* Update the menu width, if necessary. */
2901 len
= menu_item_width ((const unsigned char *) txt
);
2902 if (len
> menu
->width
)
2908 /* Decide where the menu would be placed if requested at (X,Y). */
2911 tty_menu_locate (tty_menu
*menu
, int x
, int y
,
2912 int *ulx
, int *uly
, int *width
, int *height
)
2914 tty_menu_calc_size (menu
, width
, height
);
2920 struct tty_menu_state
2922 struct glyph_matrix
*screen_behind
;
2928 /* Save away the contents of frame F's current frame matrix, and
2929 enable all its rows. Value is a glyph matrix holding the contents
2930 of F's current frame matrix with all its glyph rows enabled. */
2932 static struct glyph_matrix
*
2933 save_and_enable_current_matrix (struct frame
*f
)
2936 struct glyph_matrix
*saved
= xzalloc (sizeof *saved
);
2937 saved
->nrows
= f
->current_matrix
->nrows
;
2938 saved
->rows
= xzalloc (saved
->nrows
* sizeof *saved
->rows
);
2940 for (i
= 0; i
< saved
->nrows
; ++i
)
2942 struct glyph_row
*from
= f
->current_matrix
->rows
+ i
;
2943 struct glyph_row
*to
= saved
->rows
+ i
;
2944 ptrdiff_t nbytes
= from
->used
[TEXT_AREA
] * sizeof (struct glyph
);
2946 to
->glyphs
[TEXT_AREA
] = xmalloc (nbytes
);
2947 memcpy (to
->glyphs
[TEXT_AREA
], from
->glyphs
[TEXT_AREA
], nbytes
);
2948 to
->used
[TEXT_AREA
] = from
->used
[TEXT_AREA
];
2949 /* Make sure every row is enabled, or else update_frame will not
2950 redraw them. (Rows that are identical to what is already on
2951 screen will not be redrawn anyway.) */
2952 to
->enabled_p
= true;
2953 to
->hash
= from
->hash
;
2959 /* Restore the contents of frame F's desired frame matrix from SAVED,
2960 and free memory associated with SAVED. */
2963 restore_desired_matrix (struct frame
*f
, struct glyph_matrix
*saved
)
2967 for (i
= 0; i
< saved
->nrows
; ++i
)
2969 struct glyph_row
*from
= saved
->rows
+ i
;
2970 struct glyph_row
*to
= f
->desired_matrix
->rows
+ i
;
2971 ptrdiff_t nbytes
= from
->used
[TEXT_AREA
] * sizeof (struct glyph
);
2973 eassert (to
->glyphs
[TEXT_AREA
] != from
->glyphs
[TEXT_AREA
]);
2974 memcpy (to
->glyphs
[TEXT_AREA
], from
->glyphs
[TEXT_AREA
], nbytes
);
2975 to
->used
[TEXT_AREA
] = from
->used
[TEXT_AREA
];
2976 to
->enabled_p
= from
->enabled_p
;
2977 to
->hash
= from
->hash
;
2982 free_saved_screen (struct glyph_matrix
*saved
)
2987 return; /* Already freed! */
2989 for (i
= 0; i
< saved
->nrows
; ++i
)
2991 struct glyph_row
*from
= saved
->rows
+ i
;
2993 xfree (from
->glyphs
[TEXT_AREA
]);
2996 xfree (saved
->rows
);
3000 /* Update the display of frame F from its saved contents. */
3002 screen_update (struct frame
*f
, struct glyph_matrix
*mtx
)
3004 restore_desired_matrix (f
, mtx
);
3005 update_frame_with_menu (f
, -1, -1);
3011 MI_ITEM_SELECTED
= 1,
3014 MI_SCROLL_FORWARD
= 4,
3018 /* Read user input and return X and Y coordinates where that input
3019 puts us. We only consider mouse movement and click events, and
3020 keyboard movement commands; the rest are ignored. */
3022 read_menu_input (struct frame
*sf
, int *x
, int *y
, int min_y
, int max_y
,
3027 *first_time
= false;
3028 sf
->mouse_moved
= 1;
3033 bool usable_input
= 1;
3034 mi_result st
= MI_CONTINUE
;
3035 struct tty_display_info
*tty
= FRAME_TTY (sf
);
3036 Lisp_Object saved_mouse_tracking
= do_mouse_tracking
;
3038 /* Signal the keyboard reading routines we are displaying a menu
3039 on this terminal. */
3040 tty
->showing_menu
= 1;
3041 /* We want mouse movements be reported by read_menu_command. */
3042 do_mouse_tracking
= Qt
;
3044 cmd
= read_menu_command ();
3045 } while (NILP (cmd
));
3046 tty
->showing_menu
= 0;
3047 do_mouse_tracking
= saved_mouse_tracking
;
3049 if (EQ (cmd
, Qt
) || EQ (cmd
, Qtty_menu_exit
)
3050 /* If some input switched frames under our feet, exit the
3051 menu, since the menu faces are no longer valid, and the
3052 menu is no longer relevant anyway. */
3053 || sf
!= SELECTED_FRAME ())
3054 return MI_QUIT_MENU
;
3055 if (EQ (cmd
, Qtty_menu_mouse_movement
))
3056 mouse_get_xy (x
, y
);
3057 else if (EQ (cmd
, Qtty_menu_next_menu
))
3062 else if (EQ (cmd
, Qtty_menu_prev_menu
))
3067 else if (EQ (cmd
, Qtty_menu_next_item
))
3072 st
= MI_SCROLL_FORWARD
;
3074 else if (EQ (cmd
, Qtty_menu_prev_item
))
3079 st
= MI_SCROLL_BACK
;
3081 else if (EQ (cmd
, Qtty_menu_select
))
3082 st
= MI_ITEM_SELECTED
;
3083 else if (!EQ (cmd
, Qtty_menu_ignore
))
3086 sf
->mouse_moved
= 1;
3092 /* Display menu, wait for user's response, and return that response. */
3094 tty_menu_activate (tty_menu
*menu
, int *pane
, int *selidx
,
3095 int x0
, int y0
, char **txt
,
3096 void (*help_callback
)(char const *, int, int),
3097 bool kbd_navigation
)
3099 struct tty_menu_state
*state
;
3100 int statecount
, x
, y
, i
;
3101 bool leave
, onepane
;
3102 int result
IF_LINT (= 0);
3103 int title_faces
[4]; /* Face to display the menu title. */
3104 int faces
[4], buffers_num_deleted
= 0;
3105 struct frame
*sf
= SELECTED_FRAME ();
3106 struct tty_display_info
*tty
= FRAME_TTY (sf
);
3108 Lisp_Object selectface
;
3111 Lisp_Object prev_inhibit_redisplay
= Vinhibit_redisplay
;
3114 /* Don't allow non-positive x0 and y0, lest the menu will wrap
3115 around the display. */
3121 SAFE_NALLOCA (state
, 1, menu
->panecount
);
3122 memset (state
, 0, sizeof (*state
));
3124 = lookup_derived_face (sf
, intern ("tty-menu-disabled-face"),
3125 DEFAULT_FACE_ID
, 1);
3127 = lookup_derived_face (sf
, intern ("tty-menu-enabled-face"),
3128 DEFAULT_FACE_ID
, 1);
3129 selectface
= intern ("tty-menu-selected-face");
3130 faces
[2] = lookup_derived_face (sf
, selectface
,
3132 faces
[3] = lookup_derived_face (sf
, selectface
,
3135 /* Make sure the menu title is always displayed with
3136 `tty-menu-selected-face', no matter where the mouse pointer is. */
3137 for (i
= 0; i
< 4; i
++)
3138 title_faces
[i
] = faces
[3];
3142 /* Don't let the title for the "Buffers" popup menu include a
3143 digit (which is ugly).
3145 This is a terrible kludge, but I think the "Buffers" case is
3146 the only one where the title includes a number, so it doesn't
3147 seem to be necessary to make this more general. */
3148 if (strncmp (menu
->text
[0], "Buffers 1", 9) == 0)
3150 menu
->text
[0][7] = '\0';
3151 buffers_num_deleted
= 1;
3154 /* Inhibit redisplay for as long as the menu is active, to avoid
3155 messing the screen if some timer calls sit-for or a similar
3157 Vinhibit_redisplay
= Qt
;
3159 /* Force update of the current frame, so that the desired and the
3160 current matrices are identical. */
3161 update_frame_with_menu (sf
, -1, -1);
3162 state
[0].menu
= menu
;
3163 state
[0].screen_behind
= save_and_enable_current_matrix (sf
);
3165 /* Display the menu title. We subtract 1 from x0 and y0 because we
3166 want to interpret them as zero-based column and row coordinates,
3167 and also because we want the first item of the menu, not its
3168 title, to appear at x0,y0. */
3169 tty_menu_display (menu
, x0
- 1, y0
- 1, 1, title_faces
, x0
- 1, y0
- 1, 0, 0);
3171 /* Turn off the cursor. Otherwise it shows through the menu
3172 panes, which is ugly. */
3173 col
= cursorX (tty
);
3174 row
= cursorY (tty
);
3175 tty_hide_cursor (tty
);
3177 if (buffers_num_deleted
)
3178 menu
->text
[0][7] = ' ';
3179 onepane
= menu
->count
== 1 && menu
->submenu
[0];
3182 menu
->width
= menu
->submenu
[0]->width
;
3183 state
[0].menu
= menu
->submenu
[0];
3187 state
[0].menu
= menu
;
3189 state
[0].x
= x0
- 1;
3191 state
[0].pane
= onepane
;
3200 mi_result input_status
;
3201 int min_y
= state
[0].y
;
3202 int max_y
= min (min_y
+ state
[0].menu
->count
, FRAME_TOTAL_LINES (sf
) - 1) - 1;
3204 input_status
= read_menu_input (sf
, &x
, &y
, min_y
, max_y
, &first_time
);
3208 switch (input_status
)
3211 /* Remove the last help-echo, so that it doesn't
3212 re-appear after "Quit". */
3213 show_help_echo (Qnil
, Qnil
, Qnil
, Qnil
);
3214 result
= TTYM_NO_SELECT
;
3228 case MI_SCROLL_FORWARD
:
3229 if (y
- min_y
== state
[0].menu
->count
- 1 - first_item
)
3238 case MI_SCROLL_BACK
:
3239 if (first_item
== 0)
3242 first_item
= state
[0].menu
->count
- 1 - (y
- min_y
);
3249 /* MI_ITEM_SELECTED is handled below, so nothing to do. */
3253 if (sf
->mouse_moved
&& input_status
!= MI_QUIT_MENU
)
3255 sf
->mouse_moved
= 0;
3256 result
= TTYM_IA_SELECT
;
3257 for (i
= 0; i
< statecount
; i
++)
3258 if (state
[i
].x
<= x
&& x
< state
[i
].x
+ state
[i
].menu
->width
+ 2)
3260 int dy
= y
- state
[i
].y
+ first_item
;
3261 if (0 <= dy
&& dy
< state
[i
].menu
->count
)
3263 if (!state
[i
].menu
->submenu
[dy
])
3265 if (state
[i
].menu
->panenumber
[dy
])
3266 result
= TTYM_SUCCESS
;
3268 result
= TTYM_IA_SELECT
;
3270 *pane
= state
[i
].pane
- 1;
3272 /* We hit some part of a menu, so drop extra menus that
3273 have been opened. That does not include an open and
3275 if (i
!= statecount
- 2
3276 || state
[i
].menu
->submenu
[dy
] != state
[i
+ 1].menu
)
3277 while (i
!= statecount
- 1)
3280 screen_update (sf
, state
[statecount
].screen_behind
);
3281 state
[statecount
].screen_behind
= NULL
;
3283 if (i
== statecount
- 1 && state
[i
].menu
->submenu
[dy
])
3285 tty_menu_display (state
[i
].menu
,
3289 faces
, x
, y
, first_item
, 1);
3290 state
[statecount
].menu
= state
[i
].menu
->submenu
[dy
];
3291 state
[statecount
].pane
= state
[i
].menu
->panenumber
[dy
];
3292 state
[statecount
].screen_behind
3293 = save_and_enable_current_matrix (sf
);
3295 = state
[i
].x
+ state
[i
].menu
->width
+ 2;
3296 state
[statecount
].y
= y
;
3301 tty_menu_display (state
[statecount
- 1].menu
,
3302 state
[statecount
- 1].x
,
3303 state
[statecount
- 1].y
,
3304 state
[statecount
- 1].pane
,
3305 faces
, x
, y
, first_item
, 1);
3306 /* The call to display help-echo below will move the cursor,
3307 so remember its current position as computed by
3308 tty_menu_display. */
3309 col
= cursorX (tty
);
3310 row
= cursorY (tty
);
3313 /* Display the help-echo message for the currently-selected menu
3315 if ((menu_help_message
|| prev_menu_help_message
)
3316 && menu_help_message
!= prev_menu_help_message
)
3318 help_callback (menu_help_message
,
3319 menu_help_paneno
, menu_help_itemno
);
3320 /* Move the cursor to the beginning of the current menu
3321 item, so that screen readers and other accessibility aids
3322 know where the active region is. */
3323 cursor_to (sf
, row
, col
);
3324 prev_menu_help_message
= menu_help_message
;
3326 /* Both tty_menu_display and help_callback invoke update_end,
3327 which calls tty_show_cursor. Re-hide it, so it doesn't show
3328 through the menus. */
3329 tty_hide_cursor (tty
);
3330 fflush (tty
->output
);
3333 sf
->mouse_moved
= 0;
3334 screen_update (sf
, state
[0].screen_behind
);
3335 while (statecount
--)
3336 free_saved_screen (state
[statecount
].screen_behind
);
3337 tty_show_cursor (tty
); /* Turn cursor back on. */
3338 fflush (tty
->output
);
3340 /* Clean up any mouse events that are waiting inside Emacs event queue.
3341 These events are likely to be generated before the menu was even
3342 displayed, probably because the user pressed and released the button
3343 (which invoked the menu) too quickly. If we don't remove these events,
3344 Emacs will process them after we return and surprise the user. */
3345 discard_mouse_events ();
3346 if (!kbd_buffer_events_waiting ())
3347 clear_input_pending ();
3349 Vinhibit_redisplay
= prev_inhibit_redisplay
;
3353 /* Dispose of a menu. */
3356 tty_menu_destroy (tty_menu
*menu
)
3359 if (menu
->allocated
)
3361 for (i
= 0; i
< menu
->count
; i
++)
3362 if (menu
->submenu
[i
])
3363 tty_menu_destroy (menu
->submenu
[i
]);
3365 xfree (menu
->submenu
);
3366 xfree (menu
->panenumber
);
3367 xfree (menu
->help_text
);
3370 menu_help_message
= prev_menu_help_message
= NULL
;
3373 /* Show help HELP_STRING, or clear help if HELP_STRING is null.
3375 PANE is the pane number, and ITEM is the menu item number in
3376 the menu (currently not used). */
3379 tty_menu_help_callback (char const *help_string
, int pane
, int item
)
3381 Lisp_Object
*first_item
;
3382 Lisp_Object pane_name
;
3383 Lisp_Object menu_object
;
3385 first_item
= XVECTOR (menu_items
)->contents
;
3386 if (EQ (first_item
[0], Qt
))
3387 pane_name
= first_item
[MENU_ITEMS_PANE_NAME
];
3388 else if (EQ (first_item
[0], Qquote
))
3389 /* This shouldn't happen, see xmenu_show. */
3390 pane_name
= empty_unibyte_string
;
3392 pane_name
= first_item
[MENU_ITEMS_ITEM_NAME
];
3394 /* (menu-item MENU-NAME PANE-NUMBER) */
3395 menu_object
= list3 (Qmenu_item
, pane_name
, make_number (pane
));
3396 show_help_echo (help_string
? build_string (help_string
) : Qnil
,
3397 Qnil
, menu_object
, make_number (item
));
3401 tty_pop_down_menu (Lisp_Object arg
)
3403 tty_menu
*menu
= XSAVE_POINTER (arg
, 0);
3404 struct buffer
*orig_buffer
= XSAVE_POINTER (arg
, 1);
3407 tty_menu_destroy (menu
);
3408 set_buffer_internal (orig_buffer
);
3412 /* Return the zero-based index of the last menu-bar item on frame F. */
3414 tty_menu_last_menubar_item (struct frame
*f
)
3418 eassert (FRAME_TERMCAP_P (f
) && FRAME_LIVE_P (f
));
3419 if (FRAME_TERMCAP_P (f
) && FRAME_LIVE_P (f
))
3421 Lisp_Object items
= FRAME_MENU_BAR_ITEMS (f
);
3423 while (i
< ASIZE (items
))
3427 str
= AREF (items
, i
+ 1);
3432 i
-= 4; /* Went one too far! */
3437 /* Find in frame F's menu bar the menu item that is next or previous
3438 to the item at X/Y, and return that item's position in X/Y. WHICH
3439 says which one--next or previous--item to look for. X and Y are
3440 measured in character cells. This should only be called on TTY
3443 tty_menu_new_item_coords (struct frame
*f
, int which
, int *x
, int *y
)
3445 eassert (FRAME_TERMCAP_P (f
) && FRAME_LIVE_P (f
));
3446 if (FRAME_TERMCAP_P (f
) && FRAME_LIVE_P (f
))
3448 Lisp_Object items
= FRAME_MENU_BAR_ITEMS (f
);
3449 int last_i
= tty_menu_last_menubar_item (f
);
3452 /* This loop assumes a single menu-bar line, and will fail to
3453 find an item if it is not in the first line. Note that
3454 make_lispy_event in keyboard.c makes the same assumption. */
3455 for (i
= 0, prev_x
= -1; i
< ASIZE (items
); i
+= 4)
3457 Lisp_Object pos
, str
;
3460 str
= AREF (items
, i
+ 1);
3461 pos
= AREF (items
, i
+ 3);
3466 /* We use <= so the blank between 2 items on a TTY is
3467 considered part of the previous item. */
3468 && *x
<= ix
+ menu_item_width (SDATA (str
)))
3470 /* Found current item. Now compute the X coordinate of
3471 the previous or next item. */
3472 if (which
== TTYM_NEXT
)
3475 *x
= XINT (AREF (items
, i
+ 4 + 3));
3477 *x
= 0; /* Wrap around to the first item. */
3479 else if (prev_x
< 0)
3481 /* Wrap around to the last item. */
3482 *x
= XINT (AREF (items
, last_i
+ 3));
3493 /* WINDOWSNT uses this as menu_show_hook, see w32console.c. */
3495 tty_menu_show (struct frame
*f
, int x
, int y
, int menuflags
,
3496 Lisp_Object title
, const char **error_name
)
3499 int pane
, selidx
, lpane
, status
;
3500 Lisp_Object entry
, pane_prefix
;
3502 int ulx
, uly
, width
, height
;
3504 int dispwidth
, dispheight
;
3505 int i
, j
, lines
, maxlines
;
3507 ptrdiff_t specpdl_count
;
3509 eassert (FRAME_TERMCAP_P (f
));
3512 if (menu_items_n_panes
== 0)
3515 if (menu_items_used
<= MENU_ITEMS_PANE_LENGTH
)
3517 *error_name
= "Empty menu";
3521 /* Make the menu on that window. */
3522 menu
= tty_menu_create ();
3524 /* Don't GC while we prepare and show the menu, because we give the
3525 menu functions pointers to the contents of strings. */
3526 specpdl_count
= inhibit_garbage_collection ();
3528 /* Avoid crashes if, e.g., another client will connect while we
3530 temporarily_switch_to_single_kboard (f
);
3532 /* Adjust coordinates to be root-window-relative. */
3533 item_x
= x
+= f
->left_pos
;
3534 item_y
= y
+= f
->top_pos
;
3536 /* Create all the necessary panes and their items. */
3538 maxwidth
= maxlines
= lines
= i
= 0;
3539 lpane
= TTYM_FAILURE
;
3540 while (i
< menu_items_used
)
3542 if (EQ (AREF (menu_items
, i
), Qt
))
3544 /* Create a new pane. */
3545 Lisp_Object pane_name
, prefix
;
3546 const char *pane_string
;
3548 maxlines
= max (maxlines
, lines
);
3550 pane_name
= AREF (menu_items
, i
+ MENU_ITEMS_PANE_NAME
);
3551 prefix
= AREF (menu_items
, i
+ MENU_ITEMS_PANE_PREFIX
);
3552 pane_string
= (NILP (pane_name
)
3553 ? "" : SSDATA (pane_name
));
3554 if ((menuflags
& MENU_KEYMAPS
) && !NILP (prefix
))
3557 lpane
= tty_menu_add_pane (menu
, pane_string
);
3558 if (lpane
== TTYM_FAILURE
)
3560 tty_menu_destroy (menu
);
3561 *error_name
= "Can't create pane";
3565 i
+= MENU_ITEMS_PANE_LENGTH
;
3567 /* Find the width of the widest item in this pane. */
3569 while (j
< menu_items_used
)
3572 item
= AREF (menu_items
, j
);
3580 width
= SBYTES (item
);
3581 if (width
> maxwidth
)
3584 j
+= MENU_ITEMS_ITEM_LENGTH
;
3587 /* Ignore a nil in the item list.
3588 It's meaningful only for dialog boxes. */
3589 else if (EQ (AREF (menu_items
, i
), Qquote
))
3593 /* Create a new item within current pane. */
3594 Lisp_Object item_name
, enable
, descrip
, help
;
3596 char const *help_string
;
3598 item_name
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
);
3599 enable
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_ENABLE
);
3600 descrip
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
);
3601 help
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_HELP
);
3602 help_string
= STRINGP (help
) ? SSDATA (help
) : NULL
;
3604 if (!NILP (descrip
))
3606 item_data
= SAFE_ALLOCA (maxwidth
+ SBYTES (descrip
) + 1);
3607 memcpy (item_data
, SSDATA (item_name
), SBYTES (item_name
));
3608 for (j
= SCHARS (item_name
); j
< maxwidth
; j
++)
3610 memcpy (item_data
+ j
, SSDATA (descrip
), SBYTES (descrip
));
3611 item_data
[j
+ SBYTES (descrip
)] = 0;
3614 item_data
= SSDATA (item_name
);
3616 if (lpane
== TTYM_FAILURE
3617 || (! tty_menu_add_selection (menu
, lpane
, item_data
,
3618 !NILP (enable
), help_string
)))
3620 tty_menu_destroy (menu
);
3621 *error_name
= "Can't add selection to menu";
3625 i
+= MENU_ITEMS_ITEM_LENGTH
;
3630 maxlines
= max (maxlines
, lines
);
3632 /* All set and ready to fly. */
3633 dispwidth
= f
->text_cols
;
3634 dispheight
= f
->text_lines
;
3635 x
= min (x
, dispwidth
);
3636 y
= min (y
, dispheight
);
3639 tty_menu_locate (menu
, x
, y
, &ulx
, &uly
, &width
, &height
);
3640 if (ulx
+ width
> dispwidth
)
3642 x
-= (ulx
+ width
) - dispwidth
;
3643 ulx
= dispwidth
- width
;
3645 if (uly
+ height
> dispheight
)
3647 y
-= (uly
+ height
) - dispheight
;
3648 uly
= dispheight
- height
;
3651 if (FRAME_HAS_MINIBUF_P (f
) && uly
+ height
> dispheight
- 2)
3653 /* Move the menu away of the echo area, to avoid overwriting the
3654 menu with help echo messages or vice versa. */
3655 if (BUFFERP (echo_area_buffer
[0]) && WINDOWP (echo_area_window
))
3657 y
-= WINDOW_TOTAL_LINES (XWINDOW (echo_area_window
)) + 1;
3658 uly
-= WINDOW_TOTAL_LINES (XWINDOW (echo_area_window
)) + 1;
3667 if (ulx
< 0) x
-= ulx
;
3668 if (uly
< 0) y
-= uly
;
3671 /* This code doesn't make sense on a TTY, since it can easily annul
3672 the adjustments above that carefully avoid truncation of the menu
3673 items. I think it was written to fix some problem that only
3677 /* If position was not given by a mouse click, adjust so upper left
3678 corner of the menu as a whole ends up at given coordinates. This
3679 is what x-popup-menu says in its documentation. */
3681 y
+= 1.5 * height
/ (maxlines
+ 2);
3687 /* We save and restore the current buffer because tty_menu_activate
3688 triggers redisplay, which switches buffers at will. */
3689 record_unwind_protect (tty_pop_down_menu
,
3690 make_save_ptr_ptr (menu
, current_buffer
));
3692 specbind (Qoverriding_terminal_local_map
,
3693 Fsymbol_value (Qtty_menu_navigation_map
));
3694 status
= tty_menu_activate (menu
, &pane
, &selidx
, x
, y
, &datap
,
3695 tty_menu_help_callback
,
3696 menuflags
& MENU_KBD_NAVIGATION
);
3697 entry
= pane_prefix
= Qnil
;
3702 /* Find the item number SELIDX in pane number PANE. */
3704 while (i
< menu_items_used
)
3706 if (EQ (AREF (menu_items
, i
), Qt
))
3710 = AREF (menu_items
, i
+ MENU_ITEMS_PANE_PREFIX
);
3712 i
+= MENU_ITEMS_PANE_LENGTH
;
3721 = AREF (menu_items
, i
+ MENU_ITEMS_ITEM_VALUE
);
3722 if (menuflags
& MENU_KEYMAPS
)
3724 entry
= Fcons (entry
, Qnil
);
3725 if (!NILP (pane_prefix
))
3726 entry
= Fcons (pane_prefix
, entry
);
3732 i
+= MENU_ITEMS_ITEM_LENGTH
;
3739 tty_menu_new_item_coords (f
, status
, &item_x
, &item_y
);
3740 entry
= Fcons (make_number (item_x
), make_number (item_y
));
3744 *error_name
= "Can't activate menu";
3745 case TTYM_IA_SELECT
:
3747 case TTYM_NO_SELECT
:
3748 /* If the selected frame was changed while we displayed a menu,
3749 throw to top level in order to undo any temporary settings
3750 made by TTY menu code. */
3751 if (f
!= SELECTED_FRAME ())
3753 /* Make "Cancel" equivalent to C-g unless FOR_CLICK (which means
3754 the menu was invoked with a mouse event as POSITION). */
3755 if (!(menuflags
& MENU_FOR_CLICK
))
3756 Fsignal (Qquit
, Qnil
);
3763 unbind_to (specpdl_count
, Qnil
);
3771 /***********************************************************************
3773 ***********************************************************************/
3775 /* Initialize the tty-dependent part of frame F. The frame must
3776 already have its device initialized. */
3779 create_tty_output (struct frame
*f
)
3781 struct tty_output
*t
= xzalloc (sizeof *t
);
3783 eassert (FRAME_TERMCAP_P (f
));
3785 t
->display_info
= FRAME_TERMINAL (f
)->display_info
.tty
;
3787 f
->output_data
.tty
= t
;
3790 /* Delete frame F's face cache, and its tty-dependent part. */
3793 tty_free_frame_resources (struct frame
*f
)
3795 eassert (FRAME_TERMCAP_P (f
));
3796 free_frame_faces (f
);
3797 xfree (f
->output_data
.tty
);
3802 /* Delete frame F's face cache. */
3805 tty_free_frame_resources (struct frame
*f
)
3807 eassert (FRAME_TERMCAP_P (f
) || FRAME_MSDOS_P (f
));
3808 free_frame_faces (f
);
3812 /* Reset the hooks in TERMINAL. */
3815 clear_tty_hooks (struct terminal
*terminal
)
3818 terminal
->cursor_to_hook
= 0;
3819 terminal
->raw_cursor_to_hook
= 0;
3820 terminal
->clear_to_end_hook
= 0;
3821 terminal
->clear_frame_hook
= 0;
3822 terminal
->clear_end_of_line_hook
= 0;
3823 terminal
->ins_del_lines_hook
= 0;
3824 terminal
->insert_glyphs_hook
= 0;
3825 terminal
->write_glyphs_hook
= 0;
3826 terminal
->delete_glyphs_hook
= 0;
3827 terminal
->ring_bell_hook
= 0;
3828 terminal
->reset_terminal_modes_hook
= 0;
3829 terminal
->set_terminal_modes_hook
= 0;
3830 terminal
->update_begin_hook
= 0;
3831 terminal
->update_end_hook
= 0;
3832 terminal
->set_terminal_window_hook
= 0;
3833 terminal
->mouse_position_hook
= 0;
3834 terminal
->frame_rehighlight_hook
= 0;
3835 terminal
->frame_raise_lower_hook
= 0;
3836 terminal
->fullscreen_hook
= 0;
3837 terminal
->menu_show_hook
= 0;
3838 terminal
->set_vertical_scroll_bar_hook
= 0;
3839 terminal
->set_horizontal_scroll_bar_hook
= 0;
3840 terminal
->condemn_scroll_bars_hook
= 0;
3841 terminal
->redeem_scroll_bar_hook
= 0;
3842 terminal
->judge_scroll_bars_hook
= 0;
3843 terminal
->read_socket_hook
= 0;
3844 terminal
->frame_up_to_date_hook
= 0;
3846 /* Leave these two set, or suspended frames are not deleted
3848 terminal
->delete_frame_hook
= &tty_free_frame_resources
;
3849 terminal
->delete_terminal_hook
= &delete_tty
;
3852 /* Initialize hooks in TERMINAL with the values needed for a tty. */
3855 set_tty_hooks (struct terminal
*terminal
)
3857 terminal
->cursor_to_hook
= &tty_cursor_to
;
3858 terminal
->raw_cursor_to_hook
= &tty_raw_cursor_to
;
3859 terminal
->clear_to_end_hook
= &tty_clear_to_end
;
3860 terminal
->clear_frame_hook
= &tty_clear_frame
;
3861 terminal
->clear_end_of_line_hook
= &tty_clear_end_of_line
;
3862 terminal
->ins_del_lines_hook
= &tty_ins_del_lines
;
3863 terminal
->insert_glyphs_hook
= &tty_insert_glyphs
;
3864 terminal
->write_glyphs_hook
= &tty_write_glyphs
;
3865 terminal
->delete_glyphs_hook
= &tty_delete_glyphs
;
3866 terminal
->ring_bell_hook
= &tty_ring_bell
;
3867 terminal
->reset_terminal_modes_hook
= &tty_reset_terminal_modes
;
3868 terminal
->set_terminal_modes_hook
= &tty_set_terminal_modes
;
3869 terminal
->update_end_hook
= &tty_update_end
;
3871 terminal
->menu_show_hook
= &x_menu_show
;
3873 terminal
->menu_show_hook
= &tty_menu_show
;
3875 terminal
->set_terminal_window_hook
= &tty_set_terminal_window
;
3876 terminal
->read_socket_hook
= &tty_read_avail_input
; /* keyboard.c */
3877 terminal
->delete_frame_hook
= &tty_free_frame_resources
;
3878 terminal
->delete_terminal_hook
= &delete_tty
;
3879 /* Other hooks are NULL by default. */
3882 /* If FD is the controlling terminal, drop it. */
3884 dissociate_if_controlling_tty (int fd
)
3886 /* If tcgetpgrp succeeds, fd is the controlling terminal,
3887 so dissociate it by invoking setsid. */
3888 if (tcgetpgrp (fd
) >= 0 && setsid () < 0)
3891 /* setsid failed, presumably because Emacs is already a process
3892 group leader. Fall back on the obsolescent way to dissociate
3893 a controlling tty. */
3895 block_tty_out_signal (&oldset
);
3896 ioctl (fd
, TIOCNOTTY
, 0);
3897 unblock_tty_out_signal (&oldset
);
3902 /* Create a termcap display on the tty device with the given name and
3905 If NAME is NULL, then use the controlling tty, i.e., "/dev/tty".
3906 Otherwise NAME should be a path to the tty device file,
3909 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
3911 If MUST_SUCCEED is true, then all errors are fatal. */
3914 init_tty (const char *name
, const char *terminal_type
, bool must_succeed
)
3916 struct tty_display_info
*tty
= NULL
;
3917 struct terminal
*terminal
= NULL
;
3920 char **address
= &area
;
3923 bool ctty
= false; /* True if asked to open controlling tty. */
3927 maybe_fatal (must_succeed
, 0,
3928 "Unknown terminal type",
3929 "Unknown terminal type");
3934 if (!strcmp (name
, DEV_TTY
))
3938 /* If we already have a terminal on the given device, use that. If
3939 all such terminals are suspended, create a new one instead. */
3940 /* XXX Perhaps this should be made explicit by having init_tty
3941 always create a new terminal and separating terminal and frame
3942 creation on Lisp level. */
3943 terminal
= get_named_terminal (name
);
3947 terminal
= create_terminal (output_termcap
, NULL
);
3950 maybe_fatal (0, 0, "Attempt to create another terminal %s", "",
3953 tty
= &the_only_display_info
;
3955 tty
= xzalloc (sizeof *tty
);
3957 tty
->top_frame
= Qnil
;
3958 tty
->next
= tty_list
;
3961 terminal
->display_info
.tty
= tty
;
3962 tty
->terminal
= terminal
;
3964 tty
->Wcm
= xmalloc (sizeof *tty
->Wcm
);
3967 encode_terminal_src_size
= 0;
3968 encode_terminal_dst_size
= 0;
3972 set_tty_hooks (terminal
);
3975 /* Open the terminal device. */
3977 /* If !ctty, don't recognize it as our controlling terminal, and
3978 don't make it the controlling tty if we don't have one now.
3980 Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
3981 defined on Hurd. On other systems, we need to explicitly
3982 dissociate ourselves from the controlling tty when we want to
3983 open a frame on the same terminal. */
3984 int flags
= O_RDWR
| O_NOCTTY
| (ctty
? 0 : O_IGNORE_CTTY
);
3985 int fd
= emacs_open (name
, flags
, 0);
3986 tty
->input
= tty
->output
3987 = ((fd
< 0 || ! isatty (fd
))
3989 : fdopen (fd
, "w+"));
3993 char const *diagnostic
3994 = (fd
< 0) ? "Could not open file: %s" : "Not a tty device: %s";
3996 maybe_fatal (must_succeed
, terminal
, diagnostic
, diagnostic
, name
);
3999 tty
->name
= xstrdup (name
);
4000 terminal
->name
= xstrdup (name
);
4002 if (!O_IGNORE_CTTY
&& !ctty
)
4003 dissociate_if_controlling_tty (fd
);
4006 tty
->type
= xstrdup (terminal_type
);
4008 add_keyboard_wait_descriptor (fileno (tty
->input
));
4012 /* On some systems, tgetent tries to access the controlling
4014 block_tty_out_signal (&oldset
);
4015 status
= tgetent (tty
->termcap_term_buffer
, terminal_type
);
4016 if (tty
->termcap_term_buffer
[TERMCAP_BUFFER_SIZE
- 1])
4018 unblock_tty_out_signal (&oldset
);
4023 maybe_fatal (must_succeed
, terminal
,
4024 "Cannot open terminfo database file",
4025 "Cannot open terminfo database file");
4027 maybe_fatal (must_succeed
, terminal
,
4028 "Cannot open termcap database file",
4029 "Cannot open termcap database file");
4034 maybe_fatal (must_succeed
, terminal
,
4035 "Terminal type %s is not defined",
4036 "Terminal type %s is not defined.\n\
4037 If that is not the actual type of terminal you have,\n\
4038 use the Bourne shell command 'TERM=...; export TERM' (C-shell:\n\
4039 'setenv TERM ...') to specify the correct type. It may be necessary\n"
4041 "to do 'unset TERMINFO' (C-shell: 'unsetenv TERMINFO') as well.",
4043 "to do 'unset TERMCAP' (C-shell: 'unsetenv TERMCAP') as well.",
4048 area
= tty
->termcap_strings_buffer
;
4049 tty
->TS_ins_line
= tgetstr ("al", address
);
4050 tty
->TS_ins_multi_lines
= tgetstr ("AL", address
);
4051 tty
->TS_bell
= tgetstr ("bl", address
);
4052 BackTab (tty
) = tgetstr ("bt", address
);
4053 tty
->TS_clr_to_bottom
= tgetstr ("cd", address
);
4054 tty
->TS_clr_line
= tgetstr ("ce", address
);
4055 tty
->TS_clr_frame
= tgetstr ("cl", address
);
4056 ColPosition (tty
) = NULL
; /* tgetstr ("ch", address); */
4057 AbsPosition (tty
) = tgetstr ("cm", address
);
4058 CR (tty
) = tgetstr ("cr", address
);
4059 tty
->TS_set_scroll_region
= tgetstr ("cs", address
);
4060 tty
->TS_set_scroll_region_1
= tgetstr ("cS", address
);
4061 RowPosition (tty
) = tgetstr ("cv", address
);
4062 tty
->TS_del_char
= tgetstr ("dc", address
);
4063 tty
->TS_del_multi_chars
= tgetstr ("DC", address
);
4064 tty
->TS_del_line
= tgetstr ("dl", address
);
4065 tty
->TS_del_multi_lines
= tgetstr ("DL", address
);
4066 tty
->TS_delete_mode
= tgetstr ("dm", address
);
4067 tty
->TS_end_delete_mode
= tgetstr ("ed", address
);
4068 tty
->TS_end_insert_mode
= tgetstr ("ei", address
);
4069 Home (tty
) = tgetstr ("ho", address
);
4070 tty
->TS_ins_char
= tgetstr ("ic", address
);
4071 tty
->TS_ins_multi_chars
= tgetstr ("IC", address
);
4072 tty
->TS_insert_mode
= tgetstr ("im", address
);
4073 tty
->TS_pad_inserted_char
= tgetstr ("ip", address
);
4074 tty
->TS_end_keypad_mode
= tgetstr ("ke", address
);
4075 tty
->TS_keypad_mode
= tgetstr ("ks", address
);
4076 LastLine (tty
) = tgetstr ("ll", address
);
4077 Right (tty
) = tgetstr ("nd", address
);
4078 Down (tty
) = tgetstr ("do", address
);
4080 Down (tty
) = tgetstr ("nl", address
); /* Obsolete name for "do". */
4081 if (tgetflag ("bs"))
4082 Left (tty
) = "\b"; /* Can't possibly be longer! */
4083 else /* (Actually, "bs" is obsolete...) */
4084 Left (tty
) = tgetstr ("le", address
);
4086 Left (tty
) = tgetstr ("bc", address
); /* Obsolete name for "le". */
4087 tty
->TS_pad_char
= tgetstr ("pc", address
);
4088 tty
->TS_repeat
= tgetstr ("rp", address
);
4089 tty
->TS_end_standout_mode
= tgetstr ("se", address
);
4090 tty
->TS_fwd_scroll
= tgetstr ("sf", address
);
4091 tty
->TS_standout_mode
= tgetstr ("so", address
);
4092 tty
->TS_rev_scroll
= tgetstr ("sr", address
);
4093 tty
->Wcm
->cm_tab
= tgetstr ("ta", address
);
4094 tty
->TS_end_termcap_modes
= tgetstr ("te", address
);
4095 tty
->TS_termcap_modes
= tgetstr ("ti", address
);
4096 Up (tty
) = tgetstr ("up", address
);
4097 tty
->TS_visible_bell
= tgetstr ("vb", address
);
4098 tty
->TS_cursor_normal
= tgetstr ("ve", address
);
4099 tty
->TS_cursor_visible
= tgetstr ("vs", address
);
4100 tty
->TS_cursor_invisible
= tgetstr ("vi", address
);
4101 tty
->TS_set_window
= tgetstr ("wi", address
);
4103 tty
->TS_enter_underline_mode
= tgetstr ("us", address
);
4104 tty
->TS_exit_underline_mode
= tgetstr ("ue", address
);
4105 tty
->TS_enter_bold_mode
= tgetstr ("md", address
);
4106 tty
->TS_enter_italic_mode
= tgetstr ("ZH", address
);
4107 tty
->TS_enter_dim_mode
= tgetstr ("mh", address
);
4108 tty
->TS_enter_reverse_mode
= tgetstr ("mr", address
);
4109 tty
->TS_enter_alt_charset_mode
= tgetstr ("as", address
);
4110 tty
->TS_exit_alt_charset_mode
= tgetstr ("ae", address
);
4111 tty
->TS_exit_attribute_mode
= tgetstr ("me", address
);
4113 MultiUp (tty
) = tgetstr ("UP", address
);
4114 MultiDown (tty
) = tgetstr ("DO", address
);
4115 MultiLeft (tty
) = tgetstr ("LE", address
);
4116 MultiRight (tty
) = tgetstr ("RI", address
);
4118 /* SVr4/ANSI color support. If "op" isn't available, don't support
4119 color because we can't switch back to the default foreground and
4121 tty
->TS_orig_pair
= tgetstr ("op", address
);
4122 if (tty
->TS_orig_pair
)
4124 tty
->TS_set_foreground
= tgetstr ("AF", address
);
4125 tty
->TS_set_background
= tgetstr ("AB", address
);
4126 if (!tty
->TS_set_foreground
)
4129 tty
->TS_set_foreground
= tgetstr ("Sf", address
);
4130 tty
->TS_set_background
= tgetstr ("Sb", address
);
4133 tty
->TN_max_colors
= tgetnum ("Co");
4134 tty
->TN_max_pairs
= tgetnum ("pa");
4136 tty
->TN_no_color_video
= tgetnum ("NC");
4137 if (tty
->TN_no_color_video
== -1)
4138 tty
->TN_no_color_video
= 0;
4141 tty_default_color_capabilities (tty
, 1);
4143 MagicWrap (tty
) = tgetflag ("xn");
4144 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
4145 the former flag imply the latter. */
4146 AutoWrap (tty
) = MagicWrap (tty
) || tgetflag ("am");
4147 tty
->memory_below_frame
= tgetflag ("db");
4148 tty
->TF_hazeltine
= tgetflag ("hz");
4149 tty
->must_write_spaces
= tgetflag ("in");
4150 tty
->meta_key
= tgetflag ("km") || tgetflag ("MT");
4151 tty
->TF_insmode_motion
= tgetflag ("mi");
4152 tty
->TF_standout_motion
= tgetflag ("ms");
4153 tty
->TF_underscore
= tgetflag ("ul");
4154 tty
->TF_teleray
= tgetflag ("xt");
4159 struct frame
*f
= XFRAME (selected_frame
);
4162 initialize_w32_display (terminal
, &width
, &height
);
4164 FrameRows (tty
) = height
;
4165 FrameCols (tty
) = width
;
4166 tty
->specified_window
= height
;
4168 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_none
;
4169 FRAME_HAS_HORIZONTAL_SCROLL_BARS (f
) = 0;
4170 tty
->char_ins_del_ok
= 1;
4176 if (strcmp (terminal_type
, "internal") == 0)
4177 terminal
->type
= output_msdos_raw
;
4178 initialize_msdos_display (terminal
);
4180 get_tty_size (fileno (tty
->input
), &width
, &height
);
4181 FrameCols (tty
) = width
;
4182 FrameRows (tty
) = height
;
4183 tty
->char_ins_del_ok
= 0;
4184 init_baud_rate (fileno (tty
->input
));
4187 tty
->output
= stdout
;
4189 /* The following two are inaccessible from w32console.c. */
4190 terminal
->delete_frame_hook
= &tty_free_frame_resources
;
4191 terminal
->delete_terminal_hook
= &delete_tty
;
4193 tty
->name
= xstrdup (name
);
4194 terminal
->name
= xstrdup (name
);
4195 tty
->type
= xstrdup (terminal_type
);
4197 add_keyboard_wait_descriptor (0);
4199 tty
->delete_in_insert_mode
= 1;
4202 tty
->scroll_region_ok
= 0;
4204 /* Seems to insert lines when it's not supposed to, messing up the
4205 display. In doing a trace, it didn't seem to be called much, so I
4206 don't think we're losing anything by turning it off. */
4207 tty
->line_ins_del_ok
= 0;
4209 tty
->TN_max_colors
= 16; /* Must be non-zero for tty-display-color-p. */
4213 terminal
->mouse_position_hook
= term_mouse_position
;
4214 tty
->mouse_highlight
.mouse_face_window
= Qnil
;
4217 terminal
->kboard
= allocate_kboard (Qnil
);
4218 terminal
->kboard
->reference_count
++;
4219 /* Don't let the initial kboard remain current longer than necessary.
4220 That would cause problems if a file loaded on startup tries to
4221 prompt in the mini-buffer. */
4222 if (current_kboard
== initial_kboard
)
4223 current_kboard
= terminal
->kboard
;
4225 term_get_fkeys (address
, terminal
->kboard
);
4227 /* Get frame size from system, or else from termcap. */
4230 get_tty_size (fileno (tty
->input
), &width
, &height
);
4231 FrameCols (tty
) = width
;
4232 FrameRows (tty
) = height
;
4235 if (FrameCols (tty
) <= 0)
4236 FrameCols (tty
) = tgetnum ("co");
4237 if (FrameRows (tty
) <= 0)
4238 FrameRows (tty
) = tgetnum ("li");
4240 if (FrameRows (tty
) < 3 || FrameCols (tty
) < 3)
4241 maybe_fatal (must_succeed
, terminal
,
4242 "Screen size %dx%d is too small",
4243 "Screen size %dx%d is too small",
4244 FrameCols (tty
), FrameRows (tty
));
4246 TabWidth (tty
) = tgetnum ("tw");
4249 tty
->TS_bell
= "\07";
4251 if (!tty
->TS_fwd_scroll
)
4252 tty
->TS_fwd_scroll
= Down (tty
);
4254 PC
= tty
->TS_pad_char
? *tty
->TS_pad_char
: 0;
4256 if (TabWidth (tty
) < 0)
4259 /* Turned off since /etc/termcap seems to have :ta= for most terminals
4260 and newer termcap doc does not seem to say there is a default.
4261 if (!tty->Wcm->cm_tab)
4262 tty->Wcm->cm_tab = "\t";
4265 /* We don't support standout modes that use `magic cookies', so
4266 turn off any that do. */
4267 if (tty
->TS_standout_mode
&& tgetnum ("sg") >= 0)
4269 tty
->TS_standout_mode
= 0;
4270 tty
->TS_end_standout_mode
= 0;
4272 if (tty
->TS_enter_underline_mode
&& tgetnum ("ug") >= 0)
4274 tty
->TS_enter_underline_mode
= 0;
4275 tty
->TS_exit_underline_mode
= 0;
4278 /* If there's no standout mode, try to use underlining instead. */
4279 if (tty
->TS_standout_mode
== 0)
4281 tty
->TS_standout_mode
= tty
->TS_enter_underline_mode
;
4282 tty
->TS_end_standout_mode
= tty
->TS_exit_underline_mode
;
4285 /* If no `se' string, try using a `me' string instead.
4286 If that fails, we can't use standout mode at all. */
4287 if (tty
->TS_end_standout_mode
== 0)
4289 char *s
= tgetstr ("me", address
);
4291 tty
->TS_end_standout_mode
= s
;
4293 tty
->TS_standout_mode
= 0;
4296 if (tty
->TF_teleray
)
4298 tty
->Wcm
->cm_tab
= 0;
4299 /* We can't support standout mode, because it uses magic cookies. */
4300 tty
->TS_standout_mode
= 0;
4301 /* But that means we cannot rely on ^M to go to column zero! */
4303 /* LF can't be trusted either -- can alter hpos. */
4304 /* If move at column 0 thru a line with TS_standout_mode. */
4308 tty
->specified_window
= FrameRows (tty
);
4310 if (Wcm_init (tty
) == -1) /* Can't do cursor motion. */
4312 maybe_fatal (must_succeed
, terminal
,
4313 "Terminal type \"%s\" is not powerful enough to run Emacs",
4314 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
4315 It lacks the ability to position the cursor.\n\
4316 If that is not the actual type of terminal you have,\n\
4317 use the Bourne shell command 'TERM=...; export TERM' (C-shell:\n\
4318 'setenv TERM ...') to specify the correct type. It may be necessary\n"
4320 "to do 'unset TERMINFO' (C-shell: 'unsetenv TERMINFO') as well.",
4321 # else /* TERMCAP */
4322 "to do 'unset TERMCAP' (C-shell: 'unsetenv TERMCAP') as well.",
4323 # endif /* TERMINFO */
4327 if (FrameRows (tty
) <= 0 || FrameCols (tty
) <= 0)
4328 maybe_fatal (must_succeed
, terminal
,
4329 "Could not determine the frame size",
4330 "Could not determine the frame size");
4332 tty
->delete_in_insert_mode
4333 = tty
->TS_delete_mode
&& tty
->TS_insert_mode
4334 && !strcmp (tty
->TS_delete_mode
, tty
->TS_insert_mode
);
4336 UseTabs (tty
) = tabs_safe_p (fileno (tty
->input
)) && TabWidth (tty
) == 8;
4338 tty
->scroll_region_ok
4340 && (tty
->TS_set_window
|| tty
->TS_set_scroll_region
|| tty
->TS_set_scroll_region_1
));
4342 tty
->line_ins_del_ok
4343 = (((tty
->TS_ins_line
|| tty
->TS_ins_multi_lines
)
4344 && (tty
->TS_del_line
|| tty
->TS_del_multi_lines
))
4345 || (tty
->scroll_region_ok
4346 && tty
->TS_fwd_scroll
&& tty
->TS_rev_scroll
));
4348 tty
->char_ins_del_ok
4349 = ((tty
->TS_ins_char
|| tty
->TS_insert_mode
4350 || tty
->TS_pad_inserted_char
|| tty
->TS_ins_multi_chars
)
4351 && (tty
->TS_del_char
|| tty
->TS_del_multi_chars
));
4353 init_baud_rate (fileno (tty
->input
));
4355 #endif /* not DOS_NT */
4357 /* Init system terminal modes (RAW or CBREAK, etc.). */
4358 init_sys_modes (tty
);
4365 vfatal (const char *str
, va_list ap
)
4367 fprintf (stderr
, "emacs: ");
4368 vfprintf (stderr
, str
, ap
);
4369 if (!(strlen (str
) > 0 && str
[strlen (str
) - 1] == '\n'))
4370 fprintf (stderr
, "\n");
4376 /* Auxiliary error-handling function for init_tty.
4377 Delete TERMINAL, then call error or fatal with str1 or str2,
4378 respectively, according to whether MUST_SUCCEED is true. */
4381 maybe_fatal (bool must_succeed
, struct terminal
*terminal
,
4382 const char *str1
, const char *str2
, ...)
4385 va_start (ap
, str2
);
4387 delete_tty (terminal
);
4396 fatal (const char *str
, ...)
4405 /* Delete the given tty terminal, closing all frames on it. */
4408 delete_tty (struct terminal
*terminal
)
4410 struct tty_display_info
*tty
;
4412 /* Protect against recursive calls. delete_frame in
4413 delete_terminal calls us back when it deletes our last frame. */
4414 if (!terminal
->name
)
4417 eassert (terminal
->type
== output_termcap
);
4419 tty
= terminal
->display_info
.tty
;
4421 if (tty
== tty_list
)
4422 tty_list
= tty
->next
;
4425 struct tty_display_info
*p
;
4426 for (p
= tty_list
; p
&& p
->next
!= tty
; p
= p
->next
)
4430 /* This should not happen. */
4433 p
->next
= tty
->next
;
4437 /* reset_sys_modes needs a valid device, so this call needs to be
4438 before delete_terminal. */
4439 reset_sys_modes (tty
);
4441 delete_terminal (terminal
);
4448 delete_keyboard_wait_descriptor (fileno (tty
->input
));
4449 if (tty
->input
!= stdin
)
4450 fclose (tty
->input
);
4452 if (tty
->output
&& tty
->output
!= stdout
&& tty
->output
!= tty
->input
)
4453 fclose (tty
->output
);
4454 if (tty
->termscript
)
4455 fclose (tty
->termscript
);
4457 xfree (tty
->old_tty
);
4465 DEFVAR_BOOL ("system-uses-terminfo", system_uses_terminfo
,
4466 doc
: /* Non-nil means the system uses terminfo rather than termcap.
4467 This variable can be used by terminal emulator packages. */);
4469 system_uses_terminfo
= 1;
4471 system_uses_terminfo
= 0;
4474 DEFVAR_LISP ("suspend-tty-functions", Vsuspend_tty_functions
,
4475 doc
: /* Functions run after suspending a tty.
4476 The functions are run with one argument, the terminal object to be suspended.
4477 See `suspend-tty'. */);
4478 Vsuspend_tty_functions
= Qnil
;
4481 DEFVAR_LISP ("resume-tty-functions", Vresume_tty_functions
,
4482 doc
: /* Functions run after resuming a tty.
4483 The functions are run with one argument, the terminal object that was revived.
4484 See `resume-tty'. */);
4485 Vresume_tty_functions
= Qnil
;
4487 DEFVAR_BOOL ("visible-cursor", visible_cursor
,
4488 doc
: /* Non-nil means to make the cursor very visible.
4489 This only has an effect when running in a text terminal.
4490 What means \"very visible\" is up to your terminal. It may make the cursor
4491 bigger, or it may make it blink, or it may do nothing at all. */);
4494 defsubr (&Stty_display_color_p
);
4495 defsubr (&Stty_display_color_cells
);
4496 defsubr (&Stty_no_underline
);
4497 defsubr (&Stty_type
);
4498 defsubr (&Scontrolling_tty_p
);
4499 defsubr (&Stty_top_frame
);
4500 defsubr (&Ssuspend_tty
);
4501 defsubr (&Sresume_tty
);
4503 defsubr (&Sgpm_mouse_start
);
4504 defsubr (&Sgpm_mouse_stop
);
4505 #endif /* HAVE_GPM */
4508 default_orig_pair
= NULL
;
4509 default_set_foreground
= NULL
;
4510 default_set_background
= NULL
;
4511 #endif /* !DOS_NT */
4513 encode_terminal_src
= NULL
;
4514 encode_terminal_dst
= NULL
;
4516 DEFSYM (Qtty_mode_set_strings
, "tty-mode-set-strings");
4517 DEFSYM (Qtty_mode_reset_strings
, "tty-mode-reset-strings");
4520 DEFSYM (Qtty_menu_next_item
, "tty-menu-next-item");
4521 DEFSYM (Qtty_menu_prev_item
, "tty-menu-prev-item");
4522 DEFSYM (Qtty_menu_next_menu
, "tty-menu-next-menu");
4523 DEFSYM (Qtty_menu_prev_menu
, "tty-menu-prev-menu");
4524 DEFSYM (Qtty_menu_select
, "tty-menu-select");
4525 DEFSYM (Qtty_menu_ignore
, "tty-menu-ignore");
4526 DEFSYM (Qtty_menu_exit
, "tty-menu-exit");
4527 DEFSYM (Qtty_menu_mouse_movement
, "tty-menu-mouse-movement");
4528 DEFSYM (Qtty_menu_navigation_map
, "tty-menu-navigation-map");