1 /* Terminal control module for terminals described by TERMCAP
2 Copyright (C) 1985-1987, 1993-1995, 1998, 2000-2013 Free Software
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20 /* New redisplay, TTY faces by Gerd Moellmann <gerd@gnu.org>. */
33 #include "character.h"
37 #include "composite.h"
41 #include "termhooks.h"
42 #include "dispextern.h"
45 #include "blockinput.h"
46 #include "syssignal.h"
48 #include "intervals.h"
51 static int been_here
= -1;
55 #include "../lwlib/lwlib.h"
65 /* The name of the default console device. */
67 #define DEV_TTY "CONOUT$"
70 #define DEV_TTY "/dev/tty"
73 static void tty_set_scroll_region (struct frame
*f
, int start
, int stop
);
74 static void turn_on_face (struct frame
*, int face_id
);
75 static void turn_off_face (struct frame
*, int face_id
);
76 static void tty_turn_off_highlight (struct tty_display_info
*);
77 static void tty_show_cursor (struct tty_display_info
*);
78 static void tty_hide_cursor (struct tty_display_info
*);
79 static void tty_background_highlight (struct tty_display_info
*tty
);
80 static struct terminal
*get_tty_terminal (Lisp_Object
, bool);
81 static void clear_tty_hooks (struct terminal
*terminal
);
82 static void set_tty_hooks (struct terminal
*terminal
);
83 static void dissociate_if_controlling_tty (int fd
);
84 static void delete_tty (struct terminal
*);
85 static _Noreturn
void maybe_fatal (bool, struct terminal
*,
86 const char *, const char *, ...)
87 ATTRIBUTE_FORMAT_PRINTF (3, 5) ATTRIBUTE_FORMAT_PRINTF (4, 5);
88 static _Noreturn
void vfatal (const char *str
, va_list ap
)
89 ATTRIBUTE_FORMAT_PRINTF (1, 0);
92 #define OUTPUT(tty, a) \
93 emacs_tputs ((tty), a, \
94 FRAME_LINES (XFRAME (selected_frame)) - curY (tty), \
97 #define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
98 #define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
100 #define OUTPUT_IF(tty, a) \
106 #define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
108 /* Display space properties */
110 /* Chain of all tty device parameters. */
111 struct tty_display_info
*tty_list
;
113 /* Meaning of bits in no_color_video. Each bit set means that the
114 corresponding attribute cannot be combined with colors. */
118 NC_STANDOUT
= 1 << 0,
119 NC_UNDERLINE
= 1 << 1,
130 /* The largest frame width in any call to calculate_costs. */
132 static int max_frame_cols
;
137 #include <sys/fcntl.h>
139 /* The device for which we have enabled gpm support (or NULL). */
140 struct tty_display_info
*gpm_tty
= NULL
;
142 /* Last recorded mouse coordinates. */
143 static int last_mouse_x
, last_mouse_y
;
144 #endif /* HAVE_GPM */
146 /* Ring the bell on a tty. */
149 tty_ring_bell (struct frame
*f
)
151 struct tty_display_info
*tty
= FRAME_TTY (f
);
155 OUTPUT (tty
, (tty
->TS_visible_bell
&& visible_bell
156 ? tty
->TS_visible_bell
158 fflush (tty
->output
);
162 /* Set up termcap modes for Emacs. */
165 tty_set_terminal_modes (struct terminal
*terminal
)
167 struct tty_display_info
*tty
= terminal
->display_info
.tty
;
171 if (tty
->TS_termcap_modes
)
172 OUTPUT (tty
, tty
->TS_termcap_modes
);
175 /* Output enough newlines to scroll all the old screen contents
176 off the screen, so it won't be overwritten and lost. */
179 for (i
= 0; i
< FRAME_LINES (XFRAME (selected_frame
)); i
++)
183 OUTPUT_IF (tty
, visible_cursor
? tty
->TS_cursor_visible
: tty
->TS_cursor_normal
);
184 OUTPUT_IF (tty
, tty
->TS_keypad_mode
);
186 fflush (tty
->output
);
190 /* Reset termcap modes before exiting Emacs. */
193 tty_reset_terminal_modes (struct terminal
*terminal
)
195 struct tty_display_info
*tty
= terminal
->display_info
.tty
;
199 tty_turn_off_highlight (tty
);
200 tty_turn_off_insert (tty
);
201 OUTPUT_IF (tty
, tty
->TS_end_keypad_mode
);
202 OUTPUT_IF (tty
, tty
->TS_cursor_normal
);
203 OUTPUT_IF (tty
, tty
->TS_end_termcap_modes
);
204 OUTPUT_IF (tty
, tty
->TS_orig_pair
);
205 /* Output raw CR so kernel can track the cursor hpos. */
208 fflush (tty
->output
);
212 /* Flag the end of a display update on a termcap terminal. */
215 tty_update_end (struct frame
*f
)
217 struct tty_display_info
*tty
= FRAME_TTY (f
);
219 if (!XWINDOW (selected_window
)->cursor_off_p
)
220 tty_show_cursor (tty
);
221 tty_turn_off_insert (tty
);
222 tty_background_highlight (tty
);
223 fflush (tty
->output
);
226 /* The implementation of set_terminal_window for termcap frames. */
229 tty_set_terminal_window (struct frame
*f
, int size
)
231 struct tty_display_info
*tty
= FRAME_TTY (f
);
233 tty
->specified_window
= size
? size
: FRAME_LINES (f
);
234 if (FRAME_SCROLL_REGION_OK (f
))
235 tty_set_scroll_region (f
, 0, tty
->specified_window
);
239 tty_set_scroll_region (struct frame
*f
, int start
, int stop
)
242 struct tty_display_info
*tty
= FRAME_TTY (f
);
244 if (tty
->TS_set_scroll_region
)
245 buf
= tparam (tty
->TS_set_scroll_region
, 0, 0, start
, stop
- 1, 0, 0);
246 else if (tty
->TS_set_scroll_region_1
)
247 buf
= tparam (tty
->TS_set_scroll_region_1
, 0, 0,
248 FRAME_LINES (f
), start
,
249 FRAME_LINES (f
) - stop
,
252 buf
= tparam (tty
->TS_set_window
, 0, 0, start
, 0, stop
, FRAME_COLS (f
));
261 tty_turn_on_insert (struct tty_display_info
*tty
)
263 if (!tty
->insert_mode
)
264 OUTPUT (tty
, tty
->TS_insert_mode
);
265 tty
->insert_mode
= 1;
269 tty_turn_off_insert (struct tty_display_info
*tty
)
271 if (tty
->insert_mode
)
272 OUTPUT (tty
, tty
->TS_end_insert_mode
);
273 tty
->insert_mode
= 0;
276 /* Handle highlighting. */
279 tty_turn_off_highlight (struct tty_display_info
*tty
)
281 if (tty
->standout_mode
)
282 OUTPUT_IF (tty
, tty
->TS_end_standout_mode
);
283 tty
->standout_mode
= 0;
287 tty_turn_on_highlight (struct tty_display_info
*tty
)
289 if (!tty
->standout_mode
)
290 OUTPUT_IF (tty
, tty
->TS_standout_mode
);
291 tty
->standout_mode
= 1;
295 tty_toggle_highlight (struct tty_display_info
*tty
)
297 if (tty
->standout_mode
)
298 tty_turn_off_highlight (tty
);
300 tty_turn_on_highlight (tty
);
304 /* Make cursor invisible. */
307 tty_hide_cursor (struct tty_display_info
*tty
)
309 if (tty
->cursor_hidden
== 0)
311 tty
->cursor_hidden
= 1;
313 w32con_hide_cursor ();
315 OUTPUT_IF (tty
, tty
->TS_cursor_invisible
);
321 /* Ensure that cursor is visible. */
324 tty_show_cursor (struct tty_display_info
*tty
)
326 if (tty
->cursor_hidden
)
328 tty
->cursor_hidden
= 0;
330 w32con_show_cursor ();
332 OUTPUT_IF (tty
, tty
->TS_cursor_normal
);
334 OUTPUT_IF (tty
, tty
->TS_cursor_visible
);
340 /* Set standout mode to the state it should be in for
341 empty space inside windows. What this is,
342 depends on the user option inverse-video. */
345 tty_background_highlight (struct tty_display_info
*tty
)
348 tty_turn_on_highlight (tty
);
350 tty_turn_off_highlight (tty
);
353 /* Set standout mode to the mode specified for the text to be output. */
356 tty_highlight_if_desired (struct tty_display_info
*tty
)
359 tty_turn_on_highlight (tty
);
361 tty_turn_off_highlight (tty
);
365 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
366 frame-relative coordinates. */
369 tty_cursor_to (struct frame
*f
, int vpos
, int hpos
)
371 struct tty_display_info
*tty
= FRAME_TTY (f
);
373 /* Detect the case where we are called from reset_sys_modes
374 and the costs have never been calculated. Do nothing. */
375 if (! tty
->costs_set
)
378 if (curY (tty
) == vpos
379 && curX (tty
) == hpos
)
381 if (!tty
->TF_standout_motion
)
382 tty_background_highlight (tty
);
383 if (!tty
->TF_insmode_motion
)
384 tty_turn_off_insert (tty
);
385 cmgoto (tty
, vpos
, hpos
);
388 /* Similar but don't take any account of the wasted characters. */
391 tty_raw_cursor_to (struct frame
*f
, int row
, int col
)
393 struct tty_display_info
*tty
= FRAME_TTY (f
);
395 if (curY (tty
) == row
396 && curX (tty
) == col
)
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
, row
, col
);
405 /* Erase operations */
407 /* Clear from cursor to end of frame on a termcap device. */
410 tty_clear_to_end (struct frame
*f
)
413 struct tty_display_info
*tty
= FRAME_TTY (f
);
415 if (tty
->TS_clr_to_bottom
)
417 tty_background_highlight (tty
);
418 OUTPUT (tty
, tty
->TS_clr_to_bottom
);
422 for (i
= curY (tty
); i
< FRAME_LINES (f
); i
++)
425 clear_end_of_line (f
, FRAME_COLS (f
));
430 /* Clear an entire termcap frame. */
433 tty_clear_frame (struct frame
*f
)
435 struct tty_display_info
*tty
= FRAME_TTY (f
);
437 if (tty
->TS_clr_frame
)
439 tty_background_highlight (tty
);
440 OUTPUT (tty
, tty
->TS_clr_frame
);
450 /* An implementation of clear_end_of_line for termcap frames.
452 Note that the cursor may be moved, on terminals lacking a `ce' string. */
455 tty_clear_end_of_line (struct frame
*f
, int first_unused_hpos
)
458 struct tty_display_info
*tty
= FRAME_TTY (f
);
460 /* Detect the case where we are called from reset_sys_modes
461 and the costs have never been calculated. Do nothing. */
462 if (! tty
->costs_set
)
465 if (curX (tty
) >= first_unused_hpos
)
467 tty_background_highlight (tty
);
468 if (tty
->TS_clr_line
)
470 OUTPUT1 (tty
, tty
->TS_clr_line
);
473 { /* have to do it the hard way */
474 tty_turn_off_insert (tty
);
476 /* Do not write in last row last col with Auto-wrap on. */
478 && curY (tty
) == FrameRows (tty
) - 1
479 && first_unused_hpos
== FrameCols (tty
))
482 for (i
= curX (tty
); i
< first_unused_hpos
; i
++)
485 fputc (' ', tty
->termscript
);
486 fputc (' ', tty
->output
);
488 cmplus (tty
, first_unused_hpos
- curX (tty
));
492 /* Buffers to store the source and result of code conversion for terminal. */
493 static unsigned char *encode_terminal_src
;
494 static unsigned char *encode_terminal_dst
;
495 /* Allocated sizes of the above buffers. */
496 static ptrdiff_t encode_terminal_src_size
;
497 static ptrdiff_t encode_terminal_dst_size
;
499 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes.
500 Set CODING->produced to the byte-length of the resulting byte
501 sequence, and return a pointer to that byte sequence. */
504 encode_terminal_code (struct glyph
*src
, int src_len
, struct coding_system
*coding
)
506 struct glyph
*src_end
= src
+ src_len
;
508 ptrdiff_t nchars
, nbytes
, required
;
509 ptrdiff_t tlen
= GLYPH_TABLE_LENGTH
;
510 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
511 Lisp_Object charset_list
;
513 /* Allocate sufficient size of buffer to store all characters in
514 multibyte-form. But, it may be enlarged on demand if
515 Vglyph_table contains a string or a composite glyph is
517 if (min (PTRDIFF_MAX
, SIZE_MAX
) / MAX_MULTIBYTE_LENGTH
< src_len
)
518 memory_full (SIZE_MAX
);
520 required
*= MAX_MULTIBYTE_LENGTH
;
521 if (encode_terminal_src_size
< required
)
523 encode_terminal_src
= xrealloc (encode_terminal_src
, required
);
524 encode_terminal_src_size
= required
;
527 charset_list
= coding_charset_list (coding
);
529 buf
= encode_terminal_src
;
531 while (src
< src_end
)
533 if (src
->type
== COMPOSITE_GLYPH
)
535 struct composition
*cmp
IF_LINT (= NULL
);
536 Lisp_Object gstring
IF_LINT (= Qnil
);
539 nbytes
= buf
- encode_terminal_src
;
540 if (src
->u
.cmp
.automatic
)
542 gstring
= composition_gstring_from_id (src
->u
.cmp
.id
);
543 required
= src
->slice
.cmp
.to
- src
->slice
.cmp
.from
+ 1;
547 cmp
= composition_table
[src
->u
.cmp
.id
];
548 required
= cmp
->glyph_len
;
549 required
*= MAX_MULTIBYTE_LENGTH
;
552 if (encode_terminal_src_size
- nbytes
< required
)
554 encode_terminal_src
=
555 xpalloc (encode_terminal_src
, &encode_terminal_src_size
,
556 required
- (encode_terminal_src_size
- nbytes
),
558 buf
= encode_terminal_src
+ nbytes
;
561 if (src
->u
.cmp
.automatic
)
562 for (i
= src
->slice
.cmp
.from
; i
<= src
->slice
.cmp
.to
; i
++)
564 Lisp_Object g
= LGSTRING_GLYPH (gstring
, i
);
565 int c
= LGLYPH_CHAR (g
);
567 if (! char_charset (c
, charset_list
, NULL
))
569 buf
+= CHAR_STRING (c
, buf
);
573 for (i
= 0; i
< cmp
->glyph_len
; i
++)
575 int c
= COMPOSITION_GLYPH (cmp
, i
);
577 /* TAB in a composition means display glyphs with
578 padding space on the left or right. */
581 if (char_charset (c
, charset_list
, NULL
))
583 if (CHAR_WIDTH (c
) == 0
584 && i
> 0 && COMPOSITION_GLYPH (cmp
, i
- 1) == '\t')
585 /* Should be left-padded */
587 buf
+= CHAR_STRING (' ', buf
);
593 buf
+= CHAR_STRING (c
, buf
);
597 /* We must skip glyphs to be padded for a wide character. */
598 else if (! CHAR_GLYPH_PADDING_P (*src
))
605 SET_GLYPH_FROM_CHAR_GLYPH (g
, src
[0]);
607 if (GLYPH_INVALID_P (g
) || GLYPH_SIMPLE_P (tbase
, tlen
, g
))
609 /* This glyph doesn't have an entry in Vglyph_table. */
614 /* This glyph has an entry in Vglyph_table,
615 so process any alias before testing for simpleness. */
616 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
618 if (GLYPH_SIMPLE_P (tbase
, tlen
, g
))
619 /* We set the multi-byte form of a character in G
620 (that should be an ASCII character) at WORKBUF. */
623 /* We have a string in Vglyph_table. */
624 string
= tbase
[GLYPH_CHAR (g
)];
629 nbytes
= buf
- encode_terminal_src
;
630 if (encode_terminal_src_size
- nbytes
< MAX_MULTIBYTE_LENGTH
)
632 encode_terminal_src
=
633 xpalloc (encode_terminal_src
, &encode_terminal_src_size
,
634 MAX_MULTIBYTE_LENGTH
, -1, 1);
635 buf
= encode_terminal_src
+ nbytes
;
638 || char_charset (c
, charset_list
, NULL
))
640 /* Store the multibyte form of C at BUF. */
641 buf
+= CHAR_STRING (c
, buf
);
646 /* C is not encodable. */
649 while (src
+ 1 < src_end
&& CHAR_GLYPH_PADDING_P (src
[1]))
659 if (! STRING_MULTIBYTE (string
))
660 string
= string_to_multibyte (string
);
661 nbytes
= buf
- encode_terminal_src
;
662 if (encode_terminal_src_size
- nbytes
< SBYTES (string
))
664 encode_terminal_src
=
665 xpalloc (encode_terminal_src
, &encode_terminal_src_size
,
667 - (encode_terminal_src_size
- nbytes
)),
669 buf
= encode_terminal_src
+ nbytes
;
671 memcpy (buf
, SDATA (string
), SBYTES (string
));
672 buf
+= SBYTES (string
);
673 nchars
+= SCHARS (string
);
681 coding
->produced
= 0;
685 nbytes
= buf
- encode_terminal_src
;
686 coding
->source
= encode_terminal_src
;
687 if (encode_terminal_dst_size
== 0)
689 encode_terminal_dst
= xrealloc (encode_terminal_dst
,
690 encode_terminal_src_size
);
691 encode_terminal_dst_size
= encode_terminal_src_size
;
693 coding
->destination
= encode_terminal_dst
;
694 coding
->dst_bytes
= encode_terminal_dst_size
;
695 encode_coding_object (coding
, Qnil
, 0, 0, nchars
, nbytes
, Qnil
);
696 /* coding->destination may have been reallocated. */
697 encode_terminal_dst
= coding
->destination
;
698 encode_terminal_dst_size
= coding
->dst_bytes
;
700 return (encode_terminal_dst
);
705 /* An implementation of write_glyphs for termcap frames. */
708 tty_write_glyphs (struct frame
*f
, struct glyph
*string
, int len
)
710 unsigned char *conversion_buffer
;
711 struct coding_system
*coding
;
714 struct tty_display_info
*tty
= FRAME_TTY (f
);
716 tty_turn_off_insert (tty
);
717 tty_hide_cursor (tty
);
719 /* Don't dare write in last column of bottom line, if Auto-Wrap,
720 since that would scroll the whole frame on some terminals. */
723 && curY (tty
) + 1 == FRAME_LINES (f
)
724 && (curX (tty
) + len
) == FRAME_COLS (f
))
731 /* If terminal_coding does any conversion, use it, otherwise use
732 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
733 because it always return 1 if the member src_multibyte is 1. */
734 coding
= (FRAME_TERMINAL_CODING (f
)->common_flags
& CODING_REQUIRE_ENCODING_MASK
735 ? FRAME_TERMINAL_CODING (f
) : &safe_terminal_coding
);
736 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
738 coding
->mode
&= ~CODING_MODE_LAST_BLOCK
;
740 for (stringlen
= len
; stringlen
!= 0; stringlen
-= n
)
742 /* Identify a run of glyphs with the same face. */
743 int face_id
= string
->face_id
;
745 for (n
= 1; n
< stringlen
; ++n
)
746 if (string
[n
].face_id
!= face_id
)
749 /* Turn appearance modes of the face of the run on. */
750 tty_highlight_if_desired (tty
);
751 turn_on_face (f
, face_id
);
754 /* This is the last run. */
755 coding
->mode
|= CODING_MODE_LAST_BLOCK
;
756 conversion_buffer
= encode_terminal_code (string
, n
, coding
);
757 if (coding
->produced
> 0)
760 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->output
);
761 if (ferror (tty
->output
))
762 clearerr (tty
->output
);
764 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->termscript
);
769 /* Turn appearance modes off. */
770 turn_off_face (f
, face_id
);
771 tty_turn_off_highlight (tty
);
777 #ifdef HAVE_GPM /* Only used by GPM code. */
780 tty_write_glyphs_with_face (register struct frame
*f
, register struct glyph
*string
,
781 register int len
, register int face_id
)
783 unsigned char *conversion_buffer
;
784 struct coding_system
*coding
;
786 struct tty_display_info
*tty
= FRAME_TTY (f
);
788 tty_turn_off_insert (tty
);
789 tty_hide_cursor (tty
);
791 /* Don't dare write in last column of bottom line, if Auto-Wrap,
792 since that would scroll the whole frame on some terminals. */
795 && curY (tty
) + 1 == FRAME_LINES (f
)
796 && (curX (tty
) + len
) == FRAME_COLS (f
))
803 /* If terminal_coding does any conversion, use it, otherwise use
804 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
805 because it always return 1 if the member src_multibyte is 1. */
806 coding
= (FRAME_TERMINAL_CODING (f
)->common_flags
& CODING_REQUIRE_ENCODING_MASK
807 ? FRAME_TERMINAL_CODING (f
) : &safe_terminal_coding
);
808 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
810 coding
->mode
&= ~CODING_MODE_LAST_BLOCK
;
812 /* Turn appearance modes of the face. */
813 tty_highlight_if_desired (tty
);
814 turn_on_face (f
, face_id
);
816 coding
->mode
|= CODING_MODE_LAST_BLOCK
;
817 conversion_buffer
= encode_terminal_code (string
, len
, coding
);
818 if (coding
->produced
> 0)
821 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->output
);
822 if (ferror (tty
->output
))
823 clearerr (tty
->output
);
825 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->termscript
);
829 /* Turn appearance modes off. */
830 turn_off_face (f
, face_id
);
831 tty_turn_off_highlight (tty
);
837 /* An implementation of insert_glyphs for termcap frames. */
840 tty_insert_glyphs (struct frame
*f
, struct glyph
*start
, int len
)
843 struct glyph
*glyph
= NULL
;
844 unsigned char *conversion_buffer
;
845 unsigned char space
[1];
846 struct coding_system
*coding
;
848 struct tty_display_info
*tty
= FRAME_TTY (f
);
850 if (tty
->TS_ins_multi_chars
)
852 buf
= tparam (tty
->TS_ins_multi_chars
, 0, 0, len
, 0, 0, 0);
856 write_glyphs (f
, start
, len
);
860 tty_turn_on_insert (tty
);
864 space
[0] = SPACEGLYPH
;
866 /* If terminal_coding does any conversion, use it, otherwise use
867 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
868 because it always return 1 if the member src_multibyte is 1. */
869 coding
= (FRAME_TERMINAL_CODING (f
)->common_flags
& CODING_REQUIRE_ENCODING_MASK
870 ? FRAME_TERMINAL_CODING (f
) : &safe_terminal_coding
);
871 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
873 coding
->mode
&= ~CODING_MODE_LAST_BLOCK
;
877 OUTPUT1_IF (tty
, tty
->TS_ins_char
);
880 conversion_buffer
= space
;
881 coding
->produced
= 1;
885 tty_highlight_if_desired (tty
);
886 turn_on_face (f
, start
->face_id
);
889 /* We must open sufficient space for a character which
890 occupies more than one column. */
891 while (len
&& CHAR_GLYPH_PADDING_P (*start
))
893 OUTPUT1_IF (tty
, tty
->TS_ins_char
);
898 /* This is the last glyph. */
899 coding
->mode
|= CODING_MODE_LAST_BLOCK
;
901 conversion_buffer
= encode_terminal_code (glyph
, 1, coding
);
904 if (coding
->produced
> 0)
907 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->output
);
908 if (ferror (tty
->output
))
909 clearerr (tty
->output
);
911 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->termscript
);
915 OUTPUT1_IF (tty
, tty
->TS_pad_inserted_char
);
918 turn_off_face (f
, glyph
->face_id
);
919 tty_turn_off_highlight (tty
);
926 /* An implementation of delete_glyphs for termcap frames. */
929 tty_delete_glyphs (struct frame
*f
, int n
)
934 struct tty_display_info
*tty
= FRAME_TTY (f
);
936 if (tty
->delete_in_insert_mode
)
938 tty_turn_on_insert (tty
);
942 tty_turn_off_insert (tty
);
943 OUTPUT_IF (tty
, tty
->TS_delete_mode
);
946 if (tty
->TS_del_multi_chars
)
948 buf
= tparam (tty
->TS_del_multi_chars
, 0, 0, n
, 0, 0, 0);
953 for (i
= 0; i
< n
; i
++)
954 OUTPUT1 (tty
, tty
->TS_del_char
);
955 if (!tty
->delete_in_insert_mode
)
956 OUTPUT_IF (tty
, tty
->TS_end_delete_mode
);
959 /* An implementation of ins_del_lines for termcap frames. */
962 tty_ins_del_lines (struct frame
*f
, int vpos
, int n
)
964 struct tty_display_info
*tty
= FRAME_TTY (f
);
966 n
> 0 ? tty
->TS_ins_multi_lines
: tty
->TS_del_multi_lines
;
967 const char *single
= n
> 0 ? tty
->TS_ins_line
: tty
->TS_del_line
;
968 const char *scroll
= n
> 0 ? tty
->TS_rev_scroll
: tty
->TS_fwd_scroll
;
973 /* If the lines below the insertion are being pushed
974 into the end of the window, this is the same as clearing;
975 and we know the lines are already clear, since the matching
976 deletion has already been done. So can ignore this. */
977 /* If the lines below the deletion are blank lines coming
978 out of the end of the window, don't bother,
979 as there will be a matching inslines later that will flush them. */
980 if (FRAME_SCROLL_REGION_OK (f
)
981 && vpos
+ i
>= tty
->specified_window
)
983 if (!FRAME_MEMORY_BELOW_FRAME (f
)
984 && vpos
+ i
>= FRAME_LINES (f
))
989 raw_cursor_to (f
, vpos
, 0);
990 tty_background_highlight (tty
);
991 buf
= tparam (multi
, 0, 0, i
, 0, 0, 0);
997 raw_cursor_to (f
, vpos
, 0);
998 tty_background_highlight (tty
);
1000 OUTPUT (tty
, single
);
1001 if (tty
->TF_teleray
)
1006 tty_set_scroll_region (f
, vpos
, tty
->specified_window
);
1008 raw_cursor_to (f
, tty
->specified_window
- 1, 0);
1010 raw_cursor_to (f
, vpos
, 0);
1011 tty_background_highlight (tty
);
1013 OUTPUTL (tty
, scroll
, tty
->specified_window
- vpos
);
1014 tty_set_scroll_region (f
, 0, tty
->specified_window
);
1017 if (!FRAME_SCROLL_REGION_OK (f
)
1018 && FRAME_MEMORY_BELOW_FRAME (f
)
1021 cursor_to (f
, FRAME_LINES (f
) + n
, 0);
1026 /* Compute cost of sending "str", in characters,
1027 not counting any line-dependent padding. */
1030 string_cost (const char *str
)
1034 tputs (str
, 0, evalcost
);
1038 /* Compute cost of sending "str", in characters,
1039 counting any line-dependent padding at one line. */
1042 string_cost_one_line (const char *str
)
1046 tputs (str
, 1, evalcost
);
1050 /* Compute per line amount of line-dependent padding,
1051 in tenths of characters. */
1054 per_line_cost (const char *str
)
1058 tputs (str
, 0, evalcost
);
1061 tputs (str
, 10, evalcost
);
1065 /* char_ins_del_cost[n] is cost of inserting N characters.
1066 char_ins_del_cost[-n] is cost of deleting N characters.
1067 The length of this vector is based on max_frame_cols. */
1069 int *char_ins_del_vector
;
1071 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
1075 calculate_ins_del_char_costs (struct frame
*f
)
1077 struct tty_display_info
*tty
= FRAME_TTY (f
);
1078 int ins_startup_cost
, del_startup_cost
;
1079 int ins_cost_per_char
, del_cost_per_char
;
1083 if (tty
->TS_ins_multi_chars
)
1085 ins_cost_per_char
= 0;
1086 ins_startup_cost
= string_cost_one_line (tty
->TS_ins_multi_chars
);
1088 else if (tty
->TS_ins_char
|| tty
->TS_pad_inserted_char
1089 || (tty
->TS_insert_mode
&& tty
->TS_end_insert_mode
))
1091 ins_startup_cost
= (30 * (string_cost (tty
->TS_insert_mode
)
1092 + string_cost (tty
->TS_end_insert_mode
))) / 100;
1093 ins_cost_per_char
= (string_cost_one_line (tty
->TS_ins_char
)
1094 + string_cost_one_line (tty
->TS_pad_inserted_char
));
1098 ins_startup_cost
= 9999;
1099 ins_cost_per_char
= 0;
1102 if (tty
->TS_del_multi_chars
)
1104 del_cost_per_char
= 0;
1105 del_startup_cost
= string_cost_one_line (tty
->TS_del_multi_chars
);
1107 else if (tty
->TS_del_char
)
1109 del_startup_cost
= (string_cost (tty
->TS_delete_mode
)
1110 + string_cost (tty
->TS_end_delete_mode
));
1111 if (tty
->delete_in_insert_mode
)
1112 del_startup_cost
/= 2;
1113 del_cost_per_char
= string_cost_one_line (tty
->TS_del_char
);
1117 del_startup_cost
= 9999;
1118 del_cost_per_char
= 0;
1121 /* Delete costs are at negative offsets */
1122 p
= &char_ins_del_cost (f
)[0];
1123 for (i
= FRAME_COLS (f
); --i
>= 0;)
1124 *--p
= (del_startup_cost
+= del_cost_per_char
);
1126 /* Doing nothing is free */
1127 p
= &char_ins_del_cost (f
)[0];
1130 /* Insert costs are at positive offsets */
1131 for (i
= FRAME_COLS (f
); --i
>= 0;)
1132 *p
++ = (ins_startup_cost
+= ins_cost_per_char
);
1136 calculate_costs (struct frame
*frame
)
1138 FRAME_COST_BAUD_RATE (frame
) = baud_rate
;
1140 if (FRAME_TERMCAP_P (frame
))
1142 struct tty_display_info
*tty
= FRAME_TTY (frame
);
1143 register const char *f
= (tty
->TS_set_scroll_region
1144 ? tty
->TS_set_scroll_region
1145 : tty
->TS_set_scroll_region_1
);
1147 FRAME_SCROLL_REGION_COST (frame
) = string_cost (f
);
1151 /* These variables are only used for terminal stuff. They are
1152 allocated once for the terminal frame of X-windows emacs, but not
1155 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1156 X turns off char_ins_del_ok. */
1158 max_frame_cols
= max (max_frame_cols
, FRAME_COLS (frame
));
1159 if ((min (PTRDIFF_MAX
, SIZE_MAX
) / sizeof (int) - 1) / 2
1161 memory_full (SIZE_MAX
);
1163 char_ins_del_vector
=
1164 xrealloc (char_ins_del_vector
,
1165 (sizeof (int) + 2 * sizeof (int) * max_frame_cols
));
1167 memset (char_ins_del_vector
, 0,
1168 (sizeof (int) + 2 * sizeof (int) * max_frame_cols
));
1171 if (f
&& (!tty
->TS_ins_line
&& !tty
->TS_del_line
))
1172 do_line_insertion_deletion_costs (frame
,
1173 tty
->TS_rev_scroll
, tty
->TS_ins_multi_lines
,
1174 tty
->TS_fwd_scroll
, tty
->TS_del_multi_lines
,
1177 do_line_insertion_deletion_costs (frame
,
1178 tty
->TS_ins_line
, tty
->TS_ins_multi_lines
,
1179 tty
->TS_del_line
, tty
->TS_del_multi_lines
,
1182 calculate_ins_del_char_costs (frame
);
1184 /* Don't use TS_repeat if its padding is worse than sending the chars */
1185 if (tty
->TS_repeat
&& per_line_cost (tty
->TS_repeat
) * baud_rate
< 9000)
1186 tty
->RPov
= string_cost (tty
->TS_repeat
);
1188 tty
->RPov
= FRAME_COLS (frame
) * 2;
1190 cmcostinit (FRAME_TTY (frame
)); /* set up cursor motion costs */
1195 const char *cap
, *name
;
1198 /* Termcap capability names that correspond directly to X keysyms.
1199 Some of these (marked "terminfo") aren't supplied by old-style
1200 (Berkeley) termcap entries. They're listed in X keysym order;
1201 except we put the keypad keys first, so that if they clash with
1202 other keys (as on the IBM PC keyboard) they get overridden.
1205 static const struct fkey_table keys
[] =
1207 {"kh", "home"}, /* termcap */
1208 {"kl", "left"}, /* termcap */
1209 {"ku", "up"}, /* termcap */
1210 {"kr", "right"}, /* termcap */
1211 {"kd", "down"}, /* termcap */
1212 {"%8", "prior"}, /* terminfo */
1213 {"%5", "next"}, /* terminfo */
1214 {"@7", "end"}, /* terminfo */
1215 {"@1", "begin"}, /* terminfo */
1216 {"*6", "select"}, /* terminfo */
1217 {"%9", "print"}, /* terminfo */
1218 {"@4", "execute"}, /* terminfo --- actually the `command' key */
1220 * "insert" --- see below
1222 {"&8", "undo"}, /* terminfo */
1223 {"%0", "redo"}, /* terminfo */
1224 {"%7", "menu"}, /* terminfo --- actually the `options' key */
1225 {"@0", "find"}, /* terminfo */
1226 {"@2", "cancel"}, /* terminfo */
1227 {"%1", "help"}, /* terminfo */
1229 * "break" goes here, but can't be reliably intercepted with termcap
1231 {"&4", "reset"}, /* terminfo --- actually `restart' */
1233 * "system" and "user" --- no termcaps
1235 {"kE", "clearline"}, /* terminfo */
1236 {"kA", "insertline"}, /* terminfo */
1237 {"kL", "deleteline"}, /* terminfo */
1238 {"kI", "insertchar"}, /* terminfo */
1239 {"kD", "deletechar"}, /* terminfo */
1240 {"kB", "backtab"}, /* terminfo */
1242 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1244 {"@8", "kp-enter"}, /* terminfo */
1246 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1247 * "kp-multiply", "kp-add", "kp-separator",
1248 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1249 * --- no termcaps for any of these.
1251 {"K4", "kp-1"}, /* terminfo */
1253 * "kp-2" --- no termcap
1255 {"K5", "kp-3"}, /* terminfo */
1257 * "kp-4" --- no termcap
1259 {"K2", "kp-5"}, /* terminfo */
1261 * "kp-6" --- no termcap
1263 {"K1", "kp-7"}, /* terminfo */
1265 * "kp-8" --- no termcap
1267 {"K3", "kp-9"}, /* terminfo */
1269 * "kp-equal" --- no termcap
1281 {"&0", "S-cancel"}, /*shifted cancel key*/
1282 {"&9", "S-begin"}, /*shifted begin key*/
1283 {"*0", "S-find"}, /*shifted find key*/
1284 {"*1", "S-execute"}, /*shifted execute? actually shifted command key*/
1285 {"*4", "S-delete"}, /*shifted delete-character key*/
1286 {"*7", "S-end"}, /*shifted end key*/
1287 {"*8", "S-clearline"}, /*shifted clear-to end-of-line key*/
1288 {"#1", "S-help"}, /*shifted help key*/
1289 {"#2", "S-home"}, /*shifted home key*/
1290 {"#3", "S-insert"}, /*shifted insert-character key*/
1291 {"#4", "S-left"}, /*shifted left-arrow key*/
1292 {"%d", "S-menu"}, /*shifted menu? actually shifted options key*/
1293 {"%c", "S-next"}, /*shifted next key*/
1294 {"%e", "S-prior"}, /*shifted previous key*/
1295 {"%f", "S-print"}, /*shifted print key*/
1296 {"%g", "S-redo"}, /*shifted redo key*/
1297 {"%i", "S-right"}, /*shifted right-arrow key*/
1298 {"!3", "S-undo"} /*shifted undo key*/
1302 static char **term_get_fkeys_address
;
1303 static KBOARD
*term_get_fkeys_kboard
;
1304 static Lisp_Object
term_get_fkeys_1 (void);
1306 /* Find the escape codes sent by the function keys for Vinput_decode_map.
1307 This function scans the termcap function key sequence entries, and
1308 adds entries to Vinput_decode_map for each function key it finds. */
1311 term_get_fkeys (char **address
, KBOARD
*kboard
)
1313 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1314 errors during the call. The only errors should be from Fdefine_key
1315 when given a key sequence containing an invalid prefix key. If the
1316 termcap defines function keys which use a prefix that is already bound
1317 to a command by the default bindings, we should silently ignore that
1318 function key specification, rather than giving the user an error and
1319 refusing to run at all on such a terminal. */
1321 term_get_fkeys_address
= address
;
1322 term_get_fkeys_kboard
= kboard
;
1323 internal_condition_case (term_get_fkeys_1
, Qerror
, Fidentity
);
1327 term_get_fkeys_1 (void)
1331 char **address
= term_get_fkeys_address
;
1332 KBOARD
*kboard
= term_get_fkeys_kboard
;
1334 /* This can happen if CANNOT_DUMP or with strange options. */
1335 if (!KEYMAPP (KVAR (kboard
, Vinput_decode_map
)))
1336 kset_input_decode_map (kboard
, Fmake_sparse_keymap (Qnil
));
1338 for (i
= 0; i
< (sizeof (keys
) / sizeof (keys
[0])); i
++)
1340 char *sequence
= tgetstr (keys
[i
].cap
, address
);
1342 Fdefine_key (KVAR (kboard
, Vinput_decode_map
), build_string (sequence
),
1343 Fmake_vector (make_number (1),
1344 intern (keys
[i
].name
)));
1347 /* The uses of the "k0" capability are inconsistent; sometimes it
1348 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1349 We will attempt to politely accommodate both systems by testing for
1350 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1353 const char *k_semi
= tgetstr ("k;", address
);
1354 const char *k0
= tgetstr ("k0", address
);
1355 const char *k0_name
= "f10";
1360 /* Define f0 first, so that f10 takes precedence in case the
1361 key sequences happens to be the same. */
1362 Fdefine_key (KVAR (kboard
, Vinput_decode_map
), build_string (k0
),
1363 Fmake_vector (make_number (1), intern ("f0")));
1364 Fdefine_key (KVAR (kboard
, Vinput_decode_map
), build_string (k_semi
),
1365 Fmake_vector (make_number (1), intern ("f10")));
1368 Fdefine_key (KVAR (kboard
, Vinput_decode_map
), build_string (k0
),
1369 Fmake_vector (make_number (1), intern (k0_name
)));
1372 /* Set up cookies for numbered function keys above f10. */
1374 char fcap
[3], fkey
[4];
1376 fcap
[0] = 'F'; fcap
[2] = '\0';
1377 for (i
= 11; i
< 64; i
++)
1380 fcap
[1] = '1' + i
- 11;
1382 fcap
[1] = 'A' + i
- 20;
1384 fcap
[1] = 'a' + i
- 46;
1387 char *sequence
= tgetstr (fcap
, address
);
1390 sprintf (fkey
, "f%d", i
);
1391 Fdefine_key (KVAR (kboard
, Vinput_decode_map
), build_string (sequence
),
1392 Fmake_vector (make_number (1),
1400 * Various mappings to try and get a better fit.
1403 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1404 if (!tgetstr (cap1, address)) \
1406 char *sequence = tgetstr (cap2, address); \
1408 Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (sequence), \
1409 Fmake_vector (make_number (1), \
1413 /* if there's no key_next keycap, map key_npage to `next' keysym */
1414 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1415 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1416 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1417 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1418 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1419 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1420 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1422 /* IBM has their own non-standard dialect of terminfo.
1423 If the standard name isn't found, try the IBM name. */
1424 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1425 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1426 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1427 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1428 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1429 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1430 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1431 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1432 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1433 #undef CONDITIONAL_REASSIGN
1438 #endif /* not DOS_NT */
1441 /***********************************************************************
1442 Character Display Information
1443 ***********************************************************************/
1444 static void append_glyph (struct it
*);
1445 static void append_composite_glyph (struct it
*);
1446 static void produce_composite_glyph (struct it
*);
1447 static void append_glyphless_glyph (struct it
*, int, const char *);
1448 static void produce_glyphless_glyph (struct it
*, Lisp_Object
);
1450 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1451 terminal frames if IT->glyph_row != NULL. IT->char_to_display is
1452 the character for which to produce glyphs; IT->face_id contains the
1453 character's face. Padding glyphs are appended if IT->c has a
1454 IT->pixel_width > 1. */
1457 append_glyph (struct it
*it
)
1459 struct glyph
*glyph
, *end
;
1462 eassert (it
->glyph_row
);
1463 glyph
= (it
->glyph_row
->glyphs
[it
->area
]
1464 + it
->glyph_row
->used
[it
->area
]);
1465 end
= it
->glyph_row
->glyphs
[1 + it
->area
];
1467 /* If the glyph row is reversed, we need to prepend the glyph rather
1469 if (it
->glyph_row
->reversed_p
&& it
->area
== TEXT_AREA
)
1472 int move_by
= it
->pixel_width
;
1474 /* Make room for the new glyphs. */
1475 if (move_by
> end
- glyph
) /* don't overstep end of this area */
1476 move_by
= end
- glyph
;
1477 for (g
= glyph
- 1; g
>= it
->glyph_row
->glyphs
[it
->area
]; g
--)
1479 glyph
= it
->glyph_row
->glyphs
[it
->area
];
1480 end
= glyph
+ move_by
;
1483 /* BIDI Note: we put the glyphs of a "multi-pixel" character left to
1484 right, even in the REVERSED_P case, since (a) all of its u.ch are
1485 identical, and (b) the PADDING_P flag needs to be set for the
1486 leftmost one, because we write to the terminal left-to-right. */
1488 i
< it
->pixel_width
&& glyph
< end
;
1491 glyph
->type
= CHAR_GLYPH
;
1492 glyph
->pixel_width
= 1;
1493 glyph
->u
.ch
= it
->char_to_display
;
1494 glyph
->face_id
= it
->face_id
;
1495 glyph
->padding_p
= i
> 0;
1496 glyph
->charpos
= CHARPOS (it
->position
);
1497 glyph
->object
= it
->object
;
1500 glyph
->resolved_level
= it
->bidi_it
.resolved_level
;
1501 if ((it
->bidi_it
.type
& 7) != it
->bidi_it
.type
)
1503 glyph
->bidi_type
= it
->bidi_it
.type
;
1507 glyph
->resolved_level
= 0;
1508 glyph
->bidi_type
= UNKNOWN_BT
;
1511 ++it
->glyph_row
->used
[it
->area
];
1516 /* For external use. */
1518 tty_append_glyph (struct it
*it
)
1524 /* Produce glyphs for the display element described by IT. *IT
1525 specifies what we want to produce a glyph for (character, image, ...),
1526 and where in the glyph matrix we currently are (glyph row and hpos).
1527 produce_glyphs fills in output fields of *IT with information such as the
1528 pixel width and height of a character, and maybe output actual glyphs at
1529 the same time if IT->glyph_row is non-null. For an overview, see
1530 the explanation in dispextern.h, before the definition of the
1531 display_element_type enumeration.
1533 produce_glyphs also stores the result of glyph width, ascent
1534 etc. computations in *IT.
1536 IT->glyph_row may be null, in which case produce_glyphs does not
1537 actually fill in the glyphs. This is used in the move_* functions
1538 in xdisp.c for text width and height computations.
1540 Callers usually don't call produce_glyphs directly;
1541 instead they use the macro PRODUCE_GLYPHS. */
1544 produce_glyphs (struct it
*it
)
1546 /* If a hook is installed, let it do the work. */
1548 /* Nothing but characters are supported on terminal frames. */
1549 eassert (it
->what
== IT_CHARACTER
1550 || it
->what
== IT_COMPOSITION
1551 || it
->what
== IT_STRETCH
1552 || it
->what
== IT_GLYPHLESS
);
1554 if (it
->what
== IT_STRETCH
)
1556 produce_stretch_glyph (it
);
1560 if (it
->what
== IT_COMPOSITION
)
1562 produce_composite_glyph (it
);
1566 if (it
->what
== IT_GLYPHLESS
)
1568 produce_glyphless_glyph (it
, Qnil
);
1572 if (it
->char_to_display
>= 040 && it
->char_to_display
< 0177)
1574 it
->pixel_width
= it
->nglyphs
= 1;
1578 else if (it
->char_to_display
== '\n')
1579 it
->pixel_width
= it
->nglyphs
= 0;
1580 else if (it
->char_to_display
== '\t')
1582 int absolute_x
= (it
->current_x
1583 + it
->continuation_lines_width
);
1585 = (((1 + absolute_x
+ it
->tab_width
- 1)
1590 /* If part of the TAB has been displayed on the previous line
1591 which is continued now, continuation_lines_width will have
1592 been incremented already by the part that fitted on the
1593 continued line. So, we will get the right number of spaces
1595 nspaces
= next_tab_x
- absolute_x
;
1601 it
->char_to_display
= ' ';
1602 it
->pixel_width
= it
->len
= 1;
1608 it
->pixel_width
= nspaces
;
1609 it
->nglyphs
= nspaces
;
1611 else if (CHAR_BYTE8_P (it
->char_to_display
))
1613 /* Coming here means that we must send the raw 8-bit byte as is
1614 to the terminal. Although there's no way to know how many
1615 columns it occupies on a screen, it is a good assumption that
1616 a single byte code has 1-column width. */
1617 it
->pixel_width
= it
->nglyphs
= 1;
1623 Lisp_Object charset_list
= FRAME_TERMINAL (it
->f
)->charset_list
;
1625 if (char_charset (it
->char_to_display
, charset_list
, NULL
))
1627 it
->pixel_width
= CHAR_WIDTH (it
->char_to_display
);
1628 it
->nglyphs
= it
->pixel_width
;
1634 Lisp_Object acronym
= lookup_glyphless_char_display (-1, it
);
1636 eassert (it
->what
== IT_GLYPHLESS
);
1637 produce_glyphless_glyph (it
, acronym
);
1642 /* Advance current_x by the pixel width as a convenience for
1644 if (it
->area
== TEXT_AREA
)
1645 it
->current_x
+= it
->pixel_width
;
1646 it
->ascent
= it
->max_ascent
= it
->phys_ascent
= it
->max_phys_ascent
= 0;
1647 it
->descent
= it
->max_descent
= it
->phys_descent
= it
->max_phys_descent
= 1;
1650 /* Append glyphs to IT's glyph_row for the composition IT->cmp_id.
1651 Called from produce_composite_glyph for terminal frames if
1652 IT->glyph_row != NULL. IT->face_id contains the character's
1656 append_composite_glyph (struct it
*it
)
1658 struct glyph
*glyph
;
1660 eassert (it
->glyph_row
);
1661 glyph
= it
->glyph_row
->glyphs
[it
->area
] + it
->glyph_row
->used
[it
->area
];
1662 if (glyph
< it
->glyph_row
->glyphs
[1 + it
->area
])
1664 /* If the glyph row is reversed, we need to prepend the glyph
1665 rather than append it. */
1666 if (it
->glyph_row
->reversed_p
&& it
->area
== TEXT_AREA
)
1670 /* Make room for the new glyph. */
1671 for (g
= glyph
- 1; g
>= it
->glyph_row
->glyphs
[it
->area
]; g
--)
1673 glyph
= it
->glyph_row
->glyphs
[it
->area
];
1675 glyph
->type
= COMPOSITE_GLYPH
;
1676 glyph
->pixel_width
= it
->pixel_width
;
1677 glyph
->u
.cmp
.id
= it
->cmp_it
.id
;
1678 if (it
->cmp_it
.ch
< 0)
1680 glyph
->u
.cmp
.automatic
= 0;
1681 glyph
->u
.cmp
.id
= it
->cmp_it
.id
;
1685 glyph
->u
.cmp
.automatic
= 1;
1686 glyph
->u
.cmp
.id
= it
->cmp_it
.id
;
1687 glyph
->slice
.cmp
.from
= it
->cmp_it
.from
;
1688 glyph
->slice
.cmp
.to
= it
->cmp_it
.to
- 1;
1691 glyph
->face_id
= it
->face_id
;
1692 glyph
->padding_p
= 0;
1693 glyph
->charpos
= CHARPOS (it
->position
);
1694 glyph
->object
= it
->object
;
1697 glyph
->resolved_level
= it
->bidi_it
.resolved_level
;
1698 if ((it
->bidi_it
.type
& 7) != it
->bidi_it
.type
)
1700 glyph
->bidi_type
= it
->bidi_it
.type
;
1704 glyph
->resolved_level
= 0;
1705 glyph
->bidi_type
= UNKNOWN_BT
;
1708 ++it
->glyph_row
->used
[it
->area
];
1714 /* Produce a composite glyph for iterator IT. IT->cmp_id is the ID of
1715 the composition. We simply produces components of the composition
1716 assuming that the terminal has a capability to layout/render it
1720 produce_composite_glyph (struct it
*it
)
1722 if (it
->cmp_it
.ch
< 0)
1724 struct composition
*cmp
= composition_table
[it
->cmp_it
.id
];
1726 it
->pixel_width
= cmp
->width
;
1730 Lisp_Object gstring
= composition_gstring_from_id (it
->cmp_it
.id
);
1732 it
->pixel_width
= composition_gstring_width (gstring
, it
->cmp_it
.from
,
1733 it
->cmp_it
.to
, NULL
);
1737 append_composite_glyph (it
);
1741 /* Append a glyph for a glyphless character to IT->glyph_row. FACE_ID
1742 is a face ID to be used for the glyph. What is actually appended
1743 are glyphs of type CHAR_GLYPH whose characters are in STR (which
1744 comes from it->nglyphs bytes). */
1747 append_glyphless_glyph (struct it
*it
, int face_id
, const char *str
)
1749 struct glyph
*glyph
, *end
;
1752 eassert (it
->glyph_row
);
1753 glyph
= it
->glyph_row
->glyphs
[it
->area
] + it
->glyph_row
->used
[it
->area
];
1754 end
= it
->glyph_row
->glyphs
[1 + it
->area
];
1756 /* If the glyph row is reversed, we need to prepend the glyph rather
1758 if (it
->glyph_row
->reversed_p
&& it
->area
== TEXT_AREA
)
1761 int move_by
= it
->pixel_width
;
1763 /* Make room for the new glyphs. */
1764 if (move_by
> end
- glyph
) /* don't overstep end of this area */
1765 move_by
= end
- glyph
;
1766 for (g
= glyph
- 1; g
>= it
->glyph_row
->glyphs
[it
->area
]; g
--)
1768 glyph
= it
->glyph_row
->glyphs
[it
->area
];
1769 end
= glyph
+ move_by
;
1774 glyph
->type
= CHAR_GLYPH
;
1775 glyph
->pixel_width
= 1;
1776 glyph
->face_id
= face_id
;
1777 glyph
->padding_p
= 0;
1778 glyph
->charpos
= CHARPOS (it
->position
);
1779 glyph
->object
= it
->object
;
1782 glyph
->resolved_level
= it
->bidi_it
.resolved_level
;
1783 if ((it
->bidi_it
.type
& 7) != it
->bidi_it
.type
)
1785 glyph
->bidi_type
= it
->bidi_it
.type
;
1789 glyph
->resolved_level
= 0;
1790 glyph
->bidi_type
= UNKNOWN_BT
;
1793 /* BIDI Note: we put the glyphs of characters left to right, even in
1794 the REVERSED_P case because we write to the terminal
1796 for (i
= 0; i
< it
->nglyphs
&& glyph
< end
; ++i
)
1799 glyph
[0] = glyph
[-1];
1800 glyph
->u
.ch
= str
[i
];
1801 ++it
->glyph_row
->used
[it
->area
];
1806 /* Produce glyphs for a glyphless character for iterator IT.
1807 IT->glyphless_method specifies which method to use for displaying
1808 the character. See the description of enum
1809 glyphless_display_method in dispextern.h for the details.
1811 ACRONYM, if non-nil, is an acronym string for the character.
1813 The glyphs actually produced are of type CHAR_GLYPH. */
1816 produce_glyphless_glyph (struct it
*it
, Lisp_Object acronym
)
1818 int len
, face_id
= merge_glyphless_glyph_face (it
);
1819 char buf
[sizeof "\\x" + max (6, (sizeof it
->c
* CHAR_BIT
+ 3) / 4)];
1820 char const *str
= " ";
1822 if (it
->glyphless_method
== GLYPHLESS_DISPLAY_THIN_SPACE
)
1824 /* As there's no way to produce a thin space, we produce a space
1825 of canonical width. */
1828 else if (it
->glyphless_method
== GLYPHLESS_DISPLAY_EMPTY_BOX
)
1830 len
= CHAR_WIDTH (it
->c
);
1835 len
= sprintf (buf
, "[%.*s]", len
, str
);
1840 if (it
->glyphless_method
== GLYPHLESS_DISPLAY_ACRONYM
)
1842 if (! STRINGP (acronym
) && CHAR_TABLE_P (Vglyphless_char_display
))
1843 acronym
= CHAR_TABLE_REF (Vglyphless_char_display
, it
->c
);
1844 if (CONSP (acronym
))
1845 acronym
= XCDR (acronym
);
1847 str
= STRINGP (acronym
) ? SSDATA (acronym
) : "";
1848 for (len
= 0; len
< 6 && str
[len
] && ASCII_BYTE_P (str
[len
]); len
++)
1849 buf
[1 + len
] = str
[len
];
1855 eassert (it
->glyphless_method
== GLYPHLESS_DISPLAY_HEX_CODE
);
1856 len
= (it
->c
< 0x10000 ? sprintf (buf
, "\\u%04X", it
->c
)
1857 : it
->c
<= MAX_UNICODE_CHAR
? sprintf (buf
, "\\U%06X", it
->c
)
1858 : sprintf (buf
, "\\x%06X", it
->c
));
1863 it
->pixel_width
= len
;
1866 append_glyphless_glyph (it
, face_id
, str
);
1870 /***********************************************************************
1872 ***********************************************************************/
1874 /* Value is non-zero if attribute ATTR may be used. ATTR should be
1875 one of the enumerators from enum no_color_bit, or a bit set built
1876 from them. Some display attributes may not be used together with
1877 color; the termcap capability `NC' specifies which ones. */
1879 #define MAY_USE_WITH_COLORS_P(tty, ATTR) \
1880 (tty->TN_max_colors > 0 \
1881 ? (tty->TN_no_color_video & (ATTR)) == 0 \
1884 /* Turn appearances of face FACE_ID on tty frame F on.
1885 FACE_ID is a realized face ID number, in the face cache. */
1888 turn_on_face (struct frame
*f
, int face_id
)
1890 struct face
*face
= FACE_FROM_ID (f
, face_id
);
1891 long fg
= face
->foreground
;
1892 long bg
= face
->background
;
1893 struct tty_display_info
*tty
= FRAME_TTY (f
);
1895 /* Do this first because TS_end_standout_mode may be the same
1896 as TS_exit_attribute_mode, which turns all appearances off. */
1897 if (MAY_USE_WITH_COLORS_P (tty
, NC_REVERSE
))
1899 if (tty
->TN_max_colors
> 0)
1901 if (fg
>= 0 && bg
>= 0)
1903 /* If the terminal supports colors, we can set them
1904 below without using reverse video. The face's fg
1905 and bg colors are set as they should appear on
1906 the screen, i.e. they take the inverse-video'ness
1907 of the face already into account. */
1909 else if (inverse_video
)
1911 if (fg
== FACE_TTY_DEFAULT_FG_COLOR
1912 || bg
== FACE_TTY_DEFAULT_BG_COLOR
)
1913 tty_toggle_highlight (tty
);
1917 if (fg
== FACE_TTY_DEFAULT_BG_COLOR
1918 || bg
== FACE_TTY_DEFAULT_FG_COLOR
)
1919 tty_toggle_highlight (tty
);
1924 /* If we can't display colors, use reverse video
1925 if the face specifies that. */
1928 if (fg
== FACE_TTY_DEFAULT_FG_COLOR
1929 || bg
== FACE_TTY_DEFAULT_BG_COLOR
)
1930 tty_toggle_highlight (tty
);
1934 if (fg
== FACE_TTY_DEFAULT_BG_COLOR
1935 || bg
== FACE_TTY_DEFAULT_FG_COLOR
)
1936 tty_toggle_highlight (tty
);
1941 if (face
->tty_bold_p
&& MAY_USE_WITH_COLORS_P (tty
, NC_BOLD
))
1942 OUTPUT1_IF (tty
, tty
->TS_enter_bold_mode
);
1944 if (face
->tty_italic_p
&& MAY_USE_WITH_COLORS_P (tty
, NC_ITALIC
))
1946 if (tty
->TS_enter_italic_mode
)
1947 OUTPUT1 (tty
, tty
->TS_enter_italic_mode
);
1949 /* Italics mode is unavailable on many terminals. In that
1950 case, map slant to dimmed text; we want italic text to
1951 appear different and dimming is not otherwise used. */
1952 OUTPUT1 (tty
, tty
->TS_enter_dim_mode
);
1955 if (face
->tty_underline_p
&& MAY_USE_WITH_COLORS_P (tty
, NC_UNDERLINE
))
1956 OUTPUT1_IF (tty
, tty
->TS_enter_underline_mode
);
1958 if (tty
->TN_max_colors
> 0)
1963 ts
= tty
->standout_mode
? tty
->TS_set_background
: tty
->TS_set_foreground
;
1966 p
= tparam (ts
, NULL
, 0, fg
, 0, 0, 0);
1971 ts
= tty
->standout_mode
? tty
->TS_set_foreground
: tty
->TS_set_background
;
1974 p
= tparam (ts
, NULL
, 0, bg
, 0, 0, 0);
1982 /* Turn off appearances of face FACE_ID on tty frame F. */
1985 turn_off_face (struct frame
*f
, int face_id
)
1987 struct face
*face
= FACE_FROM_ID (f
, face_id
);
1988 struct tty_display_info
*tty
= FRAME_TTY (f
);
1990 eassert (face
!= NULL
);
1992 if (tty
->TS_exit_attribute_mode
)
1994 /* Capability "me" will turn off appearance modes double-bright,
1995 half-bright, reverse-video, standout, underline. It may or
1996 may not turn off alt-char-mode. */
1997 if (face
->tty_bold_p
1998 || face
->tty_italic_p
1999 || face
->tty_reverse_p
2000 || face
->tty_underline_p
)
2002 OUTPUT1_IF (tty
, tty
->TS_exit_attribute_mode
);
2003 if (strcmp (tty
->TS_exit_attribute_mode
, tty
->TS_end_standout_mode
) == 0)
2004 tty
->standout_mode
= 0;
2009 /* If we don't have "me" we can only have those appearances
2010 that have exit sequences defined. */
2011 if (face
->tty_underline_p
)
2012 OUTPUT_IF (tty
, tty
->TS_exit_underline_mode
);
2015 /* Switch back to default colors. */
2016 if (tty
->TN_max_colors
> 0
2017 && ((face
->foreground
!= FACE_TTY_DEFAULT_COLOR
2018 && face
->foreground
!= FACE_TTY_DEFAULT_FG_COLOR
)
2019 || (face
->background
!= FACE_TTY_DEFAULT_COLOR
2020 && face
->background
!= FACE_TTY_DEFAULT_BG_COLOR
)))
2021 OUTPUT1_IF (tty
, tty
->TS_orig_pair
);
2025 /* Return true if the terminal on frame F supports all of the
2026 capabilities in CAPS simultaneously, with foreground and background
2027 colors FG and BG. */
2030 tty_capable_p (struct tty_display_info
*tty
, unsigned int caps
,
2031 unsigned long fg
, unsigned long bg
)
2033 #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
2034 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
2037 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_INVERSE
, tty
->TS_standout_mode
, NC_REVERSE
);
2038 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_UNDERLINE
, tty
->TS_enter_underline_mode
, NC_UNDERLINE
);
2039 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_BOLD
, tty
->TS_enter_bold_mode
, NC_BOLD
);
2040 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_DIM
, tty
->TS_enter_dim_mode
, NC_DIM
);
2041 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_ITALIC
, tty
->TS_enter_italic_mode
, NC_ITALIC
);
2047 /* Return non-zero if the terminal is capable to display colors. */
2049 DEFUN ("tty-display-color-p", Ftty_display_color_p
, Stty_display_color_p
,
2051 doc
: /* Return non-nil if the tty device TERMINAL can display colors.
2053 TERMINAL can be a terminal object, a frame, or nil (meaning the
2054 selected frame's terminal). This function always returns nil if
2055 TERMINAL does not refer to a text terminal. */)
2056 (Lisp_Object terminal
)
2058 struct terminal
*t
= get_tty_terminal (terminal
, 0);
2062 return t
->display_info
.tty
->TN_max_colors
> 0 ? Qt
: Qnil
;
2065 /* Return the number of supported colors. */
2066 DEFUN ("tty-display-color-cells", Ftty_display_color_cells
,
2067 Stty_display_color_cells
, 0, 1, 0,
2068 doc
: /* Return the number of colors supported by the tty device TERMINAL.
2070 TERMINAL can be a terminal object, a frame, or nil (meaning the
2071 selected frame's terminal). This function always returns 0 if
2072 TERMINAL does not refer to a text terminal. */)
2073 (Lisp_Object terminal
)
2075 struct terminal
*t
= get_tty_terminal (terminal
, 0);
2077 return make_number (0);
2079 return make_number (t
->display_info
.tty
->TN_max_colors
);
2084 /* Declare here rather than in the function, as in the rest of Emacs,
2085 to work around an HPUX compiler bug (?). See
2086 http://lists.gnu.org/archive/html/emacs-devel/2007-08/msg00410.html */
2087 static int default_max_colors
;
2088 static int default_max_pairs
;
2089 static int default_no_color_video
;
2090 static char *default_orig_pair
;
2091 static char *default_set_foreground
;
2092 static char *default_set_background
;
2094 /* Save or restore the default color-related capabilities of this
2097 tty_default_color_capabilities (struct tty_display_info
*tty
, bool save
)
2102 xfree (default_orig_pair
);
2103 default_orig_pair
= tty
->TS_orig_pair
? xstrdup (tty
->TS_orig_pair
) : NULL
;
2105 xfree (default_set_foreground
);
2106 default_set_foreground
= tty
->TS_set_foreground
? xstrdup (tty
->TS_set_foreground
)
2109 xfree (default_set_background
);
2110 default_set_background
= tty
->TS_set_background
? xstrdup (tty
->TS_set_background
)
2113 default_max_colors
= tty
->TN_max_colors
;
2114 default_max_pairs
= tty
->TN_max_pairs
;
2115 default_no_color_video
= tty
->TN_no_color_video
;
2119 tty
->TS_orig_pair
= default_orig_pair
;
2120 tty
->TS_set_foreground
= default_set_foreground
;
2121 tty
->TS_set_background
= default_set_background
;
2122 tty
->TN_max_colors
= default_max_colors
;
2123 tty
->TN_max_pairs
= default_max_pairs
;
2124 tty
->TN_no_color_video
= default_no_color_video
;
2128 /* Setup one of the standard tty color schemes according to MODE.
2129 MODE's value is generally the number of colors which we want to
2130 support; zero means set up for the default capabilities, the ones
2131 we saw at init_tty time; -1 means turn off color support. */
2133 tty_setup_colors (struct tty_display_info
*tty
, int mode
)
2135 /* Canonicalize all negative values of MODE. */
2141 case -1: /* no colors at all */
2142 tty
->TN_max_colors
= 0;
2143 tty
->TN_max_pairs
= 0;
2144 tty
->TN_no_color_video
= 0;
2145 tty
->TS_set_foreground
= tty
->TS_set_background
= tty
->TS_orig_pair
= NULL
;
2147 case 0: /* default colors, if any */
2149 tty_default_color_capabilities (tty
, 0);
2151 case 8: /* 8 standard ANSI colors */
2152 tty
->TS_orig_pair
= "\033[0m";
2154 tty
->TS_set_foreground
= "\033[3%p1%dm";
2155 tty
->TS_set_background
= "\033[4%p1%dm";
2157 tty
->TS_set_foreground
= "\033[3%dm";
2158 tty
->TS_set_background
= "\033[4%dm";
2160 tty
->TN_max_colors
= 8;
2161 tty
->TN_max_pairs
= 64;
2162 tty
->TN_no_color_video
= 0;
2168 set_tty_color_mode (struct tty_display_info
*tty
, struct frame
*f
)
2170 Lisp_Object tem
, val
;
2171 Lisp_Object color_mode
;
2173 Lisp_Object tty_color_mode_alist
2174 = Fintern_soft (build_string ("tty-color-mode-alist"), Qnil
);
2176 tem
= assq_no_quit (Qtty_color_mode
, f
->param_alist
);
2177 val
= CONSP (tem
) ? XCDR (tem
) : Qnil
;
2181 else if (SYMBOLP (tty_color_mode_alist
))
2183 tem
= Fassq (val
, Fsymbol_value (tty_color_mode_alist
));
2184 color_mode
= CONSP (tem
) ? XCDR (tem
) : Qnil
;
2189 mode
= TYPE_RANGED_INTEGERP (int, color_mode
) ? XINT (color_mode
) : 0;
2191 if (mode
!= tty
->previous_color_mode
)
2193 tty
->previous_color_mode
= mode
;
2194 tty_setup_colors (tty
, mode
);
2195 /* This recomputes all the faces given the new color definitions. */
2196 safe_call (1, intern ("tty-set-up-initial-frame-faces"));
2200 #endif /* !DOS_NT */
2204 /* Return the tty display object specified by TERMINAL. */
2206 static struct terminal
*
2207 get_tty_terminal (Lisp_Object terminal
, bool throw)
2209 struct terminal
*t
= get_terminal (terminal
, throw);
2211 if (t
&& t
->type
!= output_termcap
&& t
->type
!= output_msdos_raw
)
2214 error ("Device %d is not a termcap terminal device", t
->id
);
2222 /* Return an active termcap device that uses the tty device with the
2225 This function ignores suspended devices.
2227 Returns NULL if the named terminal device is not opened. */
2230 get_named_tty (const char *name
)
2236 for (t
= terminal_list
; t
; t
= t
->next_terminal
)
2238 if ((t
->type
== output_termcap
|| t
->type
== output_msdos_raw
)
2239 && !strcmp (t
->display_info
.tty
->name
, name
)
2240 && TERMINAL_ACTIVE_P (t
))
2248 DEFUN ("tty-type", Ftty_type
, Stty_type
, 0, 1, 0,
2249 doc
: /* Return the type of the tty device that TERMINAL uses.
2250 Returns nil if TERMINAL is not on a tty device.
2252 TERMINAL can be a terminal object, a frame, or nil (meaning the
2253 selected frame's terminal). */)
2254 (Lisp_Object terminal
)
2256 struct terminal
*t
= get_terminal (terminal
, 1);
2258 if (t
->type
!= output_termcap
&& t
->type
!= output_msdos_raw
)
2261 if (t
->display_info
.tty
->type
)
2262 return build_string (t
->display_info
.tty
->type
);
2267 DEFUN ("controlling-tty-p", Fcontrolling_tty_p
, Scontrolling_tty_p
, 0, 1, 0,
2268 doc
: /* Return non-nil if TERMINAL is the controlling tty of the Emacs process.
2270 TERMINAL can be a terminal object, a frame, or nil (meaning the
2271 selected frame's terminal). This function always returns nil if
2272 TERMINAL is not on a tty device. */)
2273 (Lisp_Object terminal
)
2275 struct terminal
*t
= get_terminal (terminal
, 1);
2277 if ((t
->type
!= output_termcap
&& t
->type
!= output_msdos_raw
)
2278 || strcmp (t
->display_info
.tty
->name
, DEV_TTY
) != 0)
2284 DEFUN ("tty-no-underline", Ftty_no_underline
, Stty_no_underline
, 0, 1, 0,
2285 doc
: /* Declare that the tty used by TERMINAL does not handle underlining.
2286 This is used to override the terminfo data, for certain terminals that
2287 do not really do underlining, but say that they do. This function has
2288 no effect if used on a non-tty terminal.
2290 TERMINAL can be a terminal object, a frame or nil (meaning the
2291 selected frame's terminal). This function always returns nil if
2292 TERMINAL does not refer to a text terminal. */)
2293 (Lisp_Object terminal
)
2295 struct terminal
*t
= get_terminal (terminal
, 1);
2297 if (t
->type
== output_termcap
)
2298 t
->display_info
.tty
->TS_enter_underline_mode
= 0;
2302 DEFUN ("tty-top-frame", Ftty_top_frame
, Stty_top_frame
, 0, 1, 0,
2303 doc
: /* Return the topmost terminal frame on TERMINAL.
2304 TERMINAL can be a terminal object, a frame or nil (meaning the
2305 selected frame's terminal). This function returns nil if TERMINAL
2306 does not refer to a text terminal. Otherwise, it returns the
2307 top-most frame on the text terminal. */)
2308 (Lisp_Object terminal
)
2310 struct terminal
*t
= get_terminal (terminal
, 1);
2312 if (t
->type
== output_termcap
)
2313 return t
->display_info
.tty
->top_frame
;
2319 DEFUN ("suspend-tty", Fsuspend_tty
, Ssuspend_tty
, 0, 1, 0,
2320 doc
: /* Suspend the terminal device TTY.
2322 The device is restored to its default state, and Emacs ceases all
2323 access to the tty device. Frames that use the device are not deleted,
2324 but input is not read from them and if they change, their display is
2327 TTY may be a terminal object, a frame, or nil for the terminal device
2328 of the currently selected frame.
2330 This function runs `suspend-tty-functions' after suspending the
2331 device. The functions are run with one arg, the id of the suspended
2334 `suspend-tty' does nothing if it is called on a device that is already
2337 A suspended tty may be resumed by calling `resume-tty' on it. */)
2340 struct terminal
*t
= get_tty_terminal (tty
, 1);
2344 error ("Unknown tty device");
2346 f
= t
->display_info
.tty
->input
;
2350 /* First run `suspend-tty-functions' and then clean up the tty
2351 state because `suspend-tty-functions' might need to change
2353 Lisp_Object args
[2];
2354 args
[0] = intern ("suspend-tty-functions");
2355 XSETTERMINAL (args
[1], t
);
2356 Frun_hook_with_args (2, args
);
2358 reset_sys_modes (t
->display_info
.tty
);
2359 delete_keyboard_wait_descriptor (fileno (f
));
2363 if (f
!= t
->display_info
.tty
->output
)
2364 fclose (t
->display_info
.tty
->output
);
2367 t
->display_info
.tty
->input
= 0;
2368 t
->display_info
.tty
->output
= 0;
2370 if (FRAMEP (t
->display_info
.tty
->top_frame
))
2371 SET_FRAME_VISIBLE (XFRAME (t
->display_info
.tty
->top_frame
), 0);
2375 /* Clear display hooks to prevent further output. */
2376 clear_tty_hooks (t
);
2381 DEFUN ("resume-tty", Fresume_tty
, Sresume_tty
, 0, 1, 0,
2382 doc
: /* Resume the previously suspended terminal device TTY.
2383 The terminal is opened and reinitialized. Frames that are on the
2384 suspended terminal are revived.
2386 It is an error to resume a terminal while another terminal is active
2389 This function runs `resume-tty-functions' after resuming the terminal.
2390 The functions are run with one arg, the id of the resumed terminal
2393 `resume-tty' does nothing if it is called on a device that is not
2396 TTY may be a terminal object, a frame, or nil (meaning the selected
2397 frame's terminal). */)
2400 struct terminal
*t
= get_tty_terminal (tty
, 1);
2404 error ("Unknown tty device");
2406 if (!t
->display_info
.tty
->input
)
2408 if (get_named_tty (t
->display_info
.tty
->name
))
2409 error ("Cannot resume display while another display is active on the same device");
2412 t
->display_info
.tty
->output
= stdout
;
2413 t
->display_info
.tty
->input
= stdin
;
2415 fd
= emacs_open (t
->display_info
.tty
->name
, O_RDWR
| O_NOCTTY
, 0);
2416 t
->display_info
.tty
->input
= t
->display_info
.tty
->output
2417 = fd
< 0 ? 0 : fdopen (fd
, "w+");
2419 if (! t
->display_info
.tty
->input
)
2421 int open_errno
= errno
;
2423 report_file_errno ("Cannot reopen tty device",
2424 build_string (t
->display_info
.tty
->name
),
2428 if (!O_IGNORE_CTTY
&& strcmp (t
->display_info
.tty
->name
, DEV_TTY
) != 0)
2429 dissociate_if_controlling_tty (fd
);
2432 add_keyboard_wait_descriptor (fd
);
2434 if (FRAMEP (t
->display_info
.tty
->top_frame
))
2436 struct frame
*f
= XFRAME (t
->display_info
.tty
->top_frame
);
2438 int old_height
= FRAME_COLS (f
);
2439 int old_width
= FRAME_LINES (f
);
2441 /* Check if terminal/window size has changed while the frame
2443 get_tty_size (fileno (t
->display_info
.tty
->input
), &width
, &height
);
2444 if (width
!= old_width
|| height
!= old_height
)
2445 change_frame_size (f
, height
, width
, 0, 0, 0);
2446 SET_FRAME_VISIBLE (XFRAME (t
->display_info
.tty
->top_frame
), 1);
2450 init_sys_modes (t
->display_info
.tty
);
2453 /* Run `resume-tty-functions'. */
2454 Lisp_Object args
[2];
2455 args
[0] = intern ("resume-tty-functions");
2456 XSETTERMINAL (args
[1], t
);
2457 Frun_hook_with_args (2, args
);
2467 /***********************************************************************
2469 ***********************************************************************/
2473 #ifndef HAVE_WINDOW_SYSTEM
2475 term_mouse_moveto (int x
, int y
)
2477 /* TODO: how to set mouse position?
2480 name = (const char *) ttyname (0);
2481 fd = emacs_open (name, O_WRONLY, 0);
2482 SOME_FUNCTION (x, y, fd);
2485 last_mouse_y = y; */
2487 #endif /* HAVE_WINDOW_SYSTEM */
2489 /* Implementation of draw_row_with_mouse_face for TTY/GPM. */
2491 tty_draw_row_with_mouse_face (struct window
*w
, struct glyph_row
*row
,
2492 int start_hpos
, int end_hpos
,
2493 enum draw_glyphs_face draw
)
2495 int nglyphs
= end_hpos
- start_hpos
;
2496 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2497 struct tty_display_info
*tty
= FRAME_TTY (f
);
2498 int face_id
= tty
->mouse_highlight
.mouse_face_face_id
;
2499 int save_x
, save_y
, pos_x
, pos_y
;
2501 if (end_hpos
>= row
->used
[TEXT_AREA
])
2502 nglyphs
= row
->used
[TEXT_AREA
] - start_hpos
;
2504 pos_y
= row
->y
+ WINDOW_TOP_EDGE_Y (w
);
2505 pos_x
= row
->used
[LEFT_MARGIN_AREA
] + start_hpos
+ WINDOW_LEFT_EDGE_X (w
);
2507 /* Save current cursor co-ordinates. */
2508 save_y
= curY (tty
);
2509 save_x
= curX (tty
);
2510 cursor_to (f
, pos_y
, pos_x
);
2512 if (draw
== DRAW_MOUSE_FACE
)
2513 tty_write_glyphs_with_face (f
, row
->glyphs
[TEXT_AREA
] + start_hpos
,
2515 else if (draw
== DRAW_NORMAL_TEXT
)
2516 write_glyphs (f
, row
->glyphs
[TEXT_AREA
] + start_hpos
, nglyphs
);
2518 cursor_to (f
, save_y
, save_x
);
2522 term_mouse_movement (struct frame
*frame
, Gpm_Event
*event
)
2524 /* Has the mouse moved off the glyph it was on at the last sighting? */
2525 if (event
->x
!= last_mouse_x
|| event
->y
!= last_mouse_y
)
2527 frame
->mouse_moved
= 1;
2528 note_mouse_highlight (frame
, event
->x
, event
->y
);
2529 /* Remember which glyph we're now on. */
2530 last_mouse_x
= event
->x
;
2531 last_mouse_y
= event
->y
;
2537 /* Return the Time that corresponds to T. Wrap around on overflow. */
2539 timeval_to_Time (struct timeval
const *t
)
2545 ms
= t
->tv_usec
/ 1000;
2549 /* Return the current position of the mouse.
2551 Set *f to the frame the mouse is in, or zero if the mouse is in no
2552 Emacs frame. If it is set to zero, all the other arguments are
2555 Set *bar_window to Qnil, and *x and *y to the column and
2556 row of the character cell the mouse is over.
2558 Set *timeptr to the time the mouse was at the returned position.
2560 This clears mouse_moved until the next motion
2563 term_mouse_position (struct frame
**fp
, int insist
, Lisp_Object
*bar_window
,
2564 enum scroll_bar_part
*part
, Lisp_Object
*x
,
2565 Lisp_Object
*y
, Time
*timeptr
)
2569 *fp
= SELECTED_FRAME ();
2570 (*fp
)->mouse_moved
= 0;
2575 XSETINT (*x
, last_mouse_x
);
2576 XSETINT (*y
, last_mouse_y
);
2577 gettimeofday(&now
, 0);
2578 *timeptr
= timeval_to_Time (&now
);
2581 /* Prepare a mouse-event in *RESULT for placement in the input queue.
2583 If the event is a button press, then note that we have grabbed
2587 term_mouse_click (struct input_event
*result
, Gpm_Event
*event
,
2593 result
->kind
= GPM_CLICK_EVENT
;
2594 for (i
= 0, j
= GPM_B_LEFT
; i
< 3; i
++, j
>>= 1 )
2596 if (event
->buttons
& j
) {
2597 result
->code
= i
; /* button number */
2601 gettimeofday(&now
, 0);
2602 result
->timestamp
= timeval_to_Time (&now
);
2604 if (event
->type
& GPM_UP
)
2605 result
->modifiers
= up_modifier
;
2606 else if (event
->type
& GPM_DOWN
)
2607 result
->modifiers
= down_modifier
;
2609 result
->modifiers
= 0;
2611 if (event
->type
& GPM_SINGLE
)
2612 result
->modifiers
|= click_modifier
;
2614 if (event
->type
& GPM_DOUBLE
)
2615 result
->modifiers
|= double_modifier
;
2617 if (event
->type
& GPM_TRIPLE
)
2618 result
->modifiers
|= triple_modifier
;
2620 if (event
->type
& GPM_DRAG
)
2621 result
->modifiers
|= drag_modifier
;
2623 if (!(event
->type
& (GPM_MOVE
| GPM_DRAG
))) {
2626 if (event
->modifiers
& (1 << 0))
2627 result
->modifiers
|= shift_modifier
;
2630 if (event
->modifiers
& (1 << 2))
2631 result
->modifiers
|= ctrl_modifier
;
2633 /* 1 << KG_ALT || KG_ALTGR */
2634 if (event
->modifiers
& (1 << 3)
2635 || event
->modifiers
& (1 << 1))
2636 result
->modifiers
|= meta_modifier
;
2639 XSETINT (result
->x
, event
->x
);
2640 XSETINT (result
->y
, event
->y
);
2641 XSETFRAME (result
->frame_or_window
, f
);
2647 handle_one_term_event (struct tty_display_info
*tty
, Gpm_Event
*event
, struct input_event
* hold_quit
)
2649 struct frame
*f
= XFRAME (tty
->top_frame
);
2650 struct input_event ie
;
2658 if (event
->type
& (GPM_MOVE
| GPM_DRAG
)) {
2659 previous_help_echo_string
= help_echo_string
;
2660 help_echo_string
= Qnil
;
2662 Gpm_DrawPointer (event
->x
, event
->y
, fileno (tty
->output
));
2664 if (!term_mouse_movement (f
, event
))
2665 help_echo_string
= previous_help_echo_string
;
2667 /* If the contents of the global variable help_echo_string
2668 has changed, generate a HELP_EVENT. */
2669 if (!NILP (help_echo_string
)
2670 || !NILP (previous_help_echo_string
))
2677 term_mouse_click (&ie
, event
, f
);
2681 if (ie
.kind
!= NO_EVENT
)
2683 kbd_buffer_store_event_hold (&ie
, hold_quit
);
2688 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
2693 XSETFRAME (frame
, f
);
2697 gen_help_event (help_echo_string
, frame
, help_echo_window
,
2698 help_echo_object
, help_echo_pos
);
2705 DEFUN ("gpm-mouse-start", Fgpm_mouse_start
, Sgpm_mouse_start
,
2707 doc
: /* Open a connection to Gpm.
2708 Gpm-mouse can only be activated for one tty at a time. */)
2711 struct frame
*f
= SELECTED_FRAME ();
2712 struct tty_display_info
*tty
2713 = ((f
)->output_method
== output_termcap
2714 ? (f
)->terminal
->display_info
.tty
: NULL
);
2715 Gpm_Connect connection
;
2718 error ("Gpm-mouse only works in the GNU/Linux console");
2720 return Qnil
; /* Already activated, nothing to do. */
2722 error ("Gpm-mouse can only be activated for one tty at a time");
2724 connection
.eventMask
= ~0;
2725 connection
.defaultMask
= ~GPM_HARD
;
2726 connection
.maxMod
= ~0;
2727 connection
.minMod
= 0;
2730 if (Gpm_Open (&connection
, 0) < 0)
2731 error ("Gpm-mouse failed to connect to the gpm daemon");
2735 /* `init_sys_modes' arranges for mouse movements sent through gpm_fd
2736 to generate SIGIOs. Apparently we need to call reset_sys_modes
2737 before calling init_sys_modes. */
2738 reset_sys_modes (tty
);
2739 init_sys_modes (tty
);
2740 add_gpm_wait_descriptor (gpm_fd
);
2749 delete_gpm_wait_descriptor (fd
);
2750 while (Gpm_Close()); /* close all the stack */
2754 DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop
, Sgpm_mouse_stop
,
2756 doc
: /* Close a connection to Gpm. */)
2759 struct frame
*f
= SELECTED_FRAME ();
2760 struct tty_display_info
*tty
2761 = ((f
)->output_method
== output_termcap
2762 ? (f
)->terminal
->display_info
.tty
: NULL
);
2764 if (!tty
|| gpm_tty
!= tty
)
2765 return Qnil
; /* Not activated on this terminal, nothing to do. */
2770 #endif /* HAVE_GPM */
2773 /***********************************************************************
2775 ***********************************************************************/
2777 #if defined (HAVE_MENUS) && !defined (MSDOS)
2779 /* TTY menu implementation and main ideas are borrowed from msdos.c.
2781 However, unlike on MSDOS, where the menu text is drawn directly to
2782 the display video memory, on a TTY we use display_string (see
2783 display_tty_menu_item in xdisp.c) to put the glyphs produced from
2784 the menu items directly into the frame's 'desired_matrix' glyph
2785 matrix, and then call update_frame_with_menu to deliver the results
2786 to the glass. The previous contents of the screen, in the form of
2787 the current_matrix, is stashed away, and used to restore screen
2788 contents when the menu selection changes or when the final
2789 selection is made and the menu should be popped down.
2791 The idea of this implementation was suggested by Gerd Moellmann. */
2793 #define TTYM_FAILURE -1
2794 #define TTYM_SUCCESS 1
2795 #define TTYM_NO_SELECT 2
2796 #define TTYM_IA_SELECT 3
2800 /* These hold text of the current and the previous menu help messages. */
2801 static const char *menu_help_message
, *prev_menu_help_message
;
2802 /* Pane number and item number of the menu item which generated the
2803 last menu help message. */
2804 static int menu_help_paneno
, menu_help_itemno
;
2806 static Lisp_Object Qtty_menu_navigation_map
, Qtty_menu_exit
;
2807 static Lisp_Object Qtty_menu_prev_item
, Qtty_menu_next_item
;
2808 static Lisp_Object Qtty_menu_next_menu
, Qtty_menu_prev_menu
;
2809 static Lisp_Object Qtty_menu_select
, Qtty_menu_ignore
;
2810 static Lisp_Object Qtty_menu_mouse_movement
;
2812 typedef struct tty_menu_struct
2816 struct tty_menu_struct
**submenu
;
2817 int *panenumber
; /* Also used as enabled flag. */
2818 ptrdiff_t allocated
;
2821 const char **help_text
;
2824 /* Create a brand new menu structure. */
2827 tty_menu_create (void)
2829 return xzalloc (sizeof *tty_menu_create ());
2832 /* Allocate some (more) memory for MENU ensuring that there is room for one
2836 tty_menu_make_room (tty_menu
*menu
)
2838 if (menu
->allocated
== menu
->count
)
2840 ptrdiff_t allocated
= menu
->allocated
;
2841 menu
->text
= xpalloc (menu
->text
, &allocated
, 1, -1, sizeof *menu
->text
);
2842 menu
->text
= xrealloc (menu
->text
, allocated
* sizeof *menu
->text
);
2843 menu
->submenu
= xrealloc (menu
->submenu
,
2844 allocated
* sizeof *menu
->submenu
);
2845 menu
->panenumber
= xrealloc (menu
->panenumber
,
2846 allocated
* sizeof *menu
->panenumber
);
2847 menu
->help_text
= xrealloc (menu
->help_text
,
2848 allocated
* sizeof *menu
->help_text
);
2849 menu
->allocated
= allocated
;
2853 /* Search the given menu structure for a given pane number. */
2856 tty_menu_search_pane (tty_menu
*menu
, int pane
)
2861 for (i
= 0; i
< menu
->count
; i
++)
2862 if (menu
->submenu
[i
])
2864 if (pane
== menu
->panenumber
[i
])
2865 return menu
->submenu
[i
];
2866 if ((try = tty_menu_search_pane (menu
->submenu
[i
], pane
)))
2869 return (tty_menu
*) 0;
2872 /* Determine how much screen space a given menu needs. */
2875 tty_menu_calc_size (tty_menu
*menu
, int *width
, int *height
)
2877 int i
, h2
, w2
, maxsubwidth
, maxheight
;
2879 maxsubwidth
= menu
->width
;
2880 maxheight
= menu
->count
;
2881 for (i
= 0; i
< menu
->count
; i
++)
2883 if (menu
->submenu
[i
])
2885 tty_menu_calc_size (menu
->submenu
[i
], &w2
, &h2
);
2886 if (w2
> maxsubwidth
) maxsubwidth
= w2
;
2887 if (i
+ h2
> maxheight
) maxheight
= i
+ h2
;
2890 *width
= maxsubwidth
;
2891 *height
= maxheight
;
2895 mouse_get_xy (int *x
, int *y
)
2897 struct frame
*sf
= SELECTED_FRAME ();
2898 Lisp_Object lmx
= Qnil
, lmy
= Qnil
, lisp_dummy
;
2899 enum scroll_bar_part part_dummy
;
2902 if (FRAME_TERMINAL (sf
)->mouse_position_hook
)
2903 (*FRAME_TERMINAL (sf
)->mouse_position_hook
) (&sf
, -1,
2904 &lisp_dummy
, &part_dummy
,
2914 /* Display MENU at (X,Y) using FACES. */
2917 tty_menu_display (tty_menu
*menu
, int x
, int y
, int pn
, int *faces
,
2918 int mx
, int my
, int disp_help
)
2920 int i
, face
, width
, enabled
, mousehere
, row
, col
;
2921 struct frame
*sf
= SELECTED_FRAME ();
2922 struct tty_display_info
*tty
= FRAME_TTY (sf
);
2923 /* Don't try to display more menu items than the console can display
2924 using the available screen lines. Exclude the echo area line, as
2925 it will be overwritten by the help-echo anyway. */
2926 int max_items
= min (menu
->count
, FRAME_LINES (sf
) - 1);
2928 menu_help_message
= NULL
;
2930 width
= menu
->width
;
2931 col
= cursorX (tty
);
2932 row
= cursorY (tty
);
2933 for (i
= 0; i
< max_items
; i
++)
2935 int max_width
= width
+ 2; /* +2 for padding blanks on each side */
2937 if (menu
->submenu
[i
])
2938 max_width
+= 2; /* for displaying " >" after the item */
2940 = (!menu
->submenu
[i
] && menu
->panenumber
[i
]) || (menu
->submenu
[i
]);
2941 mousehere
= (y
+ i
== my
&& x
<= mx
&& mx
< x
+ max_width
);
2942 face
= faces
[enabled
+ mousehere
* 2];
2943 /* Display the menu help string for the i-th menu item even if
2944 the menu item is currently disabled. That's what the GUI
2946 if (disp_help
&& enabled
+ mousehere
* 2 >= 2)
2948 menu_help_message
= menu
->help_text
[i
];
2949 menu_help_paneno
= pn
- 1;
2950 menu_help_itemno
= i
;
2952 display_tty_menu_item (menu
->text
[i
], max_width
, face
, x
, y
+ i
,
2953 menu
->submenu
[i
] != NULL
);
2955 update_frame_with_menu (sf
);
2956 cursor_to (sf
, row
, col
);
2959 /* --------------------------- X Menu emulation ---------------------- */
2961 /* Create a new pane and place it on the outer-most level. */
2964 tty_menu_add_pane (tty_menu
*menu
, const char *txt
)
2967 const unsigned char *p
;
2969 tty_menu_make_room (menu
);
2970 menu
->submenu
[menu
->count
] = tty_menu_create ();
2971 menu
->text
[menu
->count
] = (char *)txt
;
2972 menu
->panenumber
[menu
->count
] = ++menu
->panecount
;
2973 menu
->help_text
[menu
->count
] = NULL
;
2976 /* Update the menu width, if necessary. */
2977 for (len
= 0, p
= (unsigned char *) txt
; *p
; )
2980 int ch
= STRING_CHAR_AND_LENGTH (p
, ch_len
);
2982 len
+= CHAR_WIDTH (ch
);
2986 if (len
> menu
->width
)
2989 return menu
->panecount
;
2992 /* Create a new item in a menu pane. */
2995 tty_menu_add_selection (tty_menu
*menu
, int pane
,
2996 char *txt
, int enable
, char const *help_text
)
3002 if (!(menu
= tty_menu_search_pane (menu
, pane
)))
3003 return TTYM_FAILURE
;
3004 tty_menu_make_room (menu
);
3005 menu
->submenu
[menu
->count
] = (tty_menu
*) 0;
3006 menu
->text
[menu
->count
] = txt
;
3007 menu
->panenumber
[menu
->count
] = enable
;
3008 menu
->help_text
[menu
->count
] = help_text
;
3011 /* Update the menu width, if necessary. */
3012 for (len
= 0, p
= (unsigned char *) txt
; *p
; )
3015 int ch
= STRING_CHAR_AND_LENGTH (p
, ch_len
);
3017 len
+= CHAR_WIDTH (ch
);
3021 if (len
> menu
->width
)
3024 return TTYM_SUCCESS
;
3027 /* Decide where the menu would be placed if requested at (X,Y). */
3030 tty_menu_locate (tty_menu
*menu
, int x
, int y
,
3031 int *ulx
, int *uly
, int *width
, int *height
)
3033 tty_menu_calc_size (menu
, width
, height
);
3039 struct tty_menu_state
3041 struct glyph_matrix
*screen_behind
;
3047 /* Save away the contents of frame F's current frame matrix, and
3048 enable all its rows. Value is a glyph matrix holding the contents
3049 of F's current frame matrix with all its glyph rows enabled. */
3051 static struct glyph_matrix
*
3052 save_and_enable_current_matrix (struct frame
*f
)
3055 struct glyph_matrix
*saved
= xzalloc (sizeof *saved
);
3056 saved
->nrows
= f
->current_matrix
->nrows
;
3057 saved
->rows
= xzalloc (saved
->nrows
* sizeof *saved
->rows
);
3059 for (i
= 0; i
< saved
->nrows
; ++i
)
3061 struct glyph_row
*from
= f
->current_matrix
->rows
+ i
;
3062 struct glyph_row
*to
= saved
->rows
+ i
;
3063 ptrdiff_t nbytes
= from
->used
[TEXT_AREA
] * sizeof (struct glyph
);
3065 to
->glyphs
[TEXT_AREA
] = xmalloc (nbytes
);
3066 memcpy (to
->glyphs
[TEXT_AREA
], from
->glyphs
[TEXT_AREA
], nbytes
);
3067 to
->used
[TEXT_AREA
] = from
->used
[TEXT_AREA
];
3068 /* Make sure every row is enabled, or else update_frame will not
3069 redraw them. (Rows that are identical to what is already on
3070 screen will not be redrawn anyway.) */
3072 to
->hash
= from
->hash
;
3078 /* Restore the contents of frame F's desired frame matrix from SAVED,
3079 and free memory associated with SAVED. */
3082 restore_desired_matrix (struct frame
*f
, struct glyph_matrix
*saved
)
3086 for (i
= 0; i
< saved
->nrows
; ++i
)
3088 struct glyph_row
*from
= saved
->rows
+ i
;
3089 struct glyph_row
*to
= f
->desired_matrix
->rows
+ i
;
3090 ptrdiff_t nbytes
= from
->used
[TEXT_AREA
] * sizeof (struct glyph
);
3092 eassert (to
->glyphs
[TEXT_AREA
] != from
->glyphs
[TEXT_AREA
]);
3093 memcpy (to
->glyphs
[TEXT_AREA
], from
->glyphs
[TEXT_AREA
], nbytes
);
3094 to
->used
[TEXT_AREA
] = from
->used
[TEXT_AREA
];
3095 to
->enabled_p
= from
->enabled_p
;
3096 to
->hash
= from
->hash
;
3101 free_saved_screen (struct glyph_matrix
*saved
)
3106 return; /* already freed */
3108 for (i
= 0; i
< saved
->nrows
; ++i
)
3110 struct glyph_row
*from
= saved
->rows
+ i
;
3112 xfree (from
->glyphs
[TEXT_AREA
]);
3115 xfree (saved
->rows
);
3119 /* Update the display of frame F from its saved contents. */
3121 screen_update (struct frame
*f
, struct glyph_matrix
*mtx
)
3123 restore_desired_matrix (f
, mtx
);
3124 update_frame_with_menu (f
);
3127 /* Read user input and return X and Y coordinates where that input
3128 puts us. We only consider mouse movement and click events and
3129 keyboard movement commands; the rest are ignored.
3131 Value is -1 if C-g was pressed, 1 if an item was selected, 2 or 3
3132 if we need to move to the next or previous menu-bar menu, zero
3135 read_menu_input (struct frame
*sf
, int *x
, int *y
, int min_y
, int max_y
,
3140 *first_time
= false;
3141 sf
->mouse_moved
= 1;
3146 int usable_input
= 1;
3148 struct tty_display_info
*tty
= FRAME_TTY (sf
);
3149 Lisp_Object saved_mouse_tracking
= do_mouse_tracking
;
3151 /* Signal the keyboard reading routines we are displaying a menu
3152 on this terminal. */
3153 tty
->showing_menu
= 1;
3154 /* We want mouse movements be reported by read_menu_command. */
3155 do_mouse_tracking
= Qt
;
3157 cmd
= read_menu_command ();
3158 } while (NILP (cmd
));
3159 tty
->showing_menu
= 0;
3160 do_mouse_tracking
= saved_mouse_tracking
;
3162 if (EQ (cmd
, Qt
) || EQ (cmd
, Qtty_menu_exit
))
3164 if (EQ (cmd
, Qtty_menu_mouse_movement
))
3165 mouse_get_xy (x
, y
);
3166 else if (EQ (cmd
, Qtty_menu_next_menu
))
3171 else if (EQ (cmd
, Qtty_menu_prev_menu
))
3176 else if (EQ (cmd
, Qtty_menu_next_item
))
3183 else if (EQ (cmd
, Qtty_menu_prev_item
))
3190 else if (EQ (cmd
, Qtty_menu_select
))
3192 else if (!EQ (cmd
, Qtty_menu_ignore
))
3195 sf
->mouse_moved
= 1;
3201 /* Display menu, wait for user's response, and return that response. */
3203 tty_menu_activate (tty_menu
*menu
, int *pane
, int *selidx
,
3204 int x0
, int y0
, char **txt
,
3205 void (*help_callback
)(char const *, int, int),
3208 struct tty_menu_state
*state
;
3209 int statecount
, x
, y
, i
, leave
, onepane
;
3210 int result
IF_LINT (= 0);
3211 int title_faces
[4]; /* face to display the menu title */
3212 int faces
[4], buffers_num_deleted
= 0;
3213 struct frame
*sf
= SELECTED_FRAME ();
3214 struct tty_display_info
*tty
= FRAME_TTY (sf
);
3216 Lisp_Object selectface
;
3218 /* Don't allow non-positive x0 and y0, lest the menu will wrap
3219 around the display. */
3225 state
= alloca (menu
->panecount
* sizeof (struct tty_menu_state
));
3226 memset (state
, 0, sizeof (*state
));
3228 = lookup_derived_face (sf
, intern ("tty-menu-disabled-face"),
3229 DEFAULT_FACE_ID
, 1);
3231 = lookup_derived_face (sf
, intern ("tty-menu-enabled-face"),
3232 DEFAULT_FACE_ID
, 1);
3233 selectface
= intern ("tty-menu-selected-face");
3234 faces
[2] = lookup_derived_face (sf
, selectface
,
3236 faces
[3] = lookup_derived_face (sf
, selectface
,
3239 /* Make sure the menu title is always displayed with
3240 `tty-menu-selected-face', no matter where the mouse pointer is. */
3241 for (i
= 0; i
< 4; i
++)
3242 title_faces
[i
] = faces
[3];
3246 /* Don't let the title for the "Buffers" popup menu include a
3247 digit (which is ugly).
3249 This is a terrible kludge, but I think the "Buffers" case is
3250 the only one where the title includes a number, so it doesn't
3251 seem to be necessary to make this more general. */
3252 if (strncmp (menu
->text
[0], "Buffers 1", 9) == 0)
3254 menu
->text
[0][7] = '\0';
3255 buffers_num_deleted
= 1;
3258 /* Force update of the current frame, so that the desired and the
3259 current matrices are identical. */
3260 update_frame_with_menu (sf
);
3261 state
[0].menu
= menu
;
3262 state
[0].screen_behind
= save_and_enable_current_matrix (sf
);
3264 /* Display the menu title. We subtract 1 from x0 and y0 because we
3265 want to interpret them as zero-based column and row coordinates,
3266 and also because we want the first item of the menu, not its
3267 title, to appear at x0,y0. */
3268 tty_menu_display (menu
, x0
- 1, y0
- 1, 1, title_faces
, x0
- 1, y0
- 1, 0);
3270 /* Turn off the cursor. Otherwise it shows through the menu
3271 panes, which is ugly. */
3272 tty_hide_cursor (tty
);
3273 if (buffers_num_deleted
)
3274 menu
->text
[0][7] = ' ';
3275 if ((onepane
= menu
->count
== 1 && menu
->submenu
[0]))
3277 menu
->width
= menu
->submenu
[0]->width
;
3278 state
[0].menu
= menu
->submenu
[0];
3282 state
[0].menu
= menu
;
3284 state
[0].x
= x0
- 1;
3286 state
[0].pane
= onepane
;
3296 int min_y
= state
[0].y
;
3297 int max_y
= min (min_y
+ state
[0].menu
->count
, FRAME_LINES (sf
) - 1) - 1;
3299 input_status
= read_menu_input (sf
, &x
, &y
, min_y
, max_y
, &first_time
);
3303 if (input_status
== -1)
3305 /* Remove the last help-echo, so that it doesn't
3306 re-appear after "Quit". */
3307 show_help_echo (Qnil
, Qnil
, Qnil
, Qnil
);
3308 result
= TTYM_NO_SELECT
;
3310 else if (input_status
== 2)
3317 else if (input_status
== 3)
3325 if (sf
->mouse_moved
&& input_status
!= -1)
3327 sf
->mouse_moved
= 0;
3328 result
= TTYM_IA_SELECT
;
3329 for (i
= 0; i
< statecount
; i
++)
3330 if (state
[i
].x
<= x
&& x
< state
[i
].x
+ state
[i
].menu
->width
+ 2)
3332 int dy
= y
- state
[i
].y
;
3333 if (0 <= dy
&& dy
< state
[i
].menu
->count
)
3335 if (!state
[i
].menu
->submenu
[dy
])
3337 if (state
[i
].menu
->panenumber
[dy
])
3338 result
= TTYM_SUCCESS
;
3340 result
= TTYM_IA_SELECT
;
3342 *pane
= state
[i
].pane
- 1;
3344 /* We hit some part of a menu, so drop extra menus that
3345 have been opened. That does not include an open and
3347 if (i
!= statecount
- 2
3348 || state
[i
].menu
->submenu
[dy
] != state
[i
+1].menu
)
3349 while (i
!= statecount
- 1)
3352 screen_update (sf
, state
[statecount
].screen_behind
);
3353 state
[statecount
].screen_behind
= NULL
;
3355 if (i
== statecount
- 1 && state
[i
].menu
->submenu
[dy
])
3357 tty_menu_display (state
[i
].menu
,
3362 state
[statecount
].menu
= state
[i
].menu
->submenu
[dy
];
3363 state
[statecount
].pane
= state
[i
].menu
->panenumber
[dy
];
3364 state
[statecount
].screen_behind
3365 = save_and_enable_current_matrix (sf
);
3367 = state
[i
].x
+ state
[i
].menu
->width
+ 2;
3368 state
[statecount
].y
= y
;
3373 tty_menu_display (state
[statecount
- 1].menu
,
3374 state
[statecount
- 1].x
,
3375 state
[statecount
- 1].y
,
3376 state
[statecount
- 1].pane
,
3378 tty_hide_cursor (tty
);
3379 fflush (tty
->output
);
3382 /* Display the help-echo message for the currently-selected menu
3384 if ((menu_help_message
|| prev_menu_help_message
)
3385 && menu_help_message
!= prev_menu_help_message
)
3387 help_callback (menu_help_message
,
3388 menu_help_paneno
, menu_help_itemno
);
3389 tty_hide_cursor (tty
);
3390 fflush (tty
->output
);
3391 prev_menu_help_message
= menu_help_message
;
3395 sf
->mouse_moved
= 0;
3396 screen_update (sf
, state
[0].screen_behind
);
3397 while (statecount
--)
3398 free_saved_screen (state
[statecount
].screen_behind
);
3399 tty_show_cursor (tty
); /* turn cursor back on */
3400 fflush (tty
->output
);
3402 /* Clean up any mouse events that are waiting inside Emacs event queue.
3403 These events are likely to be generated before the menu was even
3404 displayed, probably because the user pressed and released the button
3405 (which invoked the menu) too quickly. If we don't remove these events,
3406 Emacs will process them after we return and surprise the user. */
3407 discard_mouse_events ();
3408 if (!kbd_buffer_events_waiting ())
3409 clear_input_pending ();
3413 /* Dispose of a menu. */
3416 tty_menu_destroy (tty_menu
*menu
)
3419 if (menu
->allocated
)
3421 for (i
= 0; i
< menu
->count
; i
++)
3422 if (menu
->submenu
[i
])
3423 tty_menu_destroy (menu
->submenu
[i
]);
3425 xfree (menu
->submenu
);
3426 xfree (menu
->panenumber
);
3427 xfree (menu
->help_text
);
3430 menu_help_message
= prev_menu_help_message
= NULL
;
3433 /* Show help HELP_STRING, or clear help if HELP_STRING is null.
3435 PANE is the pane number, and ITEM is the menu item number in
3436 the menu (currently not used). */
3439 tty_menu_help_callback (char const *help_string
, int pane
, int item
)
3441 Lisp_Object
*first_item
;
3442 Lisp_Object pane_name
;
3443 Lisp_Object menu_object
;
3445 first_item
= XVECTOR (menu_items
)->u
.contents
;
3446 if (EQ (first_item
[0], Qt
))
3447 pane_name
= first_item
[MENU_ITEMS_PANE_NAME
];
3448 else if (EQ (first_item
[0], Qquote
))
3449 /* This shouldn't happen, see xmenu_show. */
3450 pane_name
= empty_unibyte_string
;
3452 pane_name
= first_item
[MENU_ITEMS_ITEM_NAME
];
3454 /* (menu-item MENU-NAME PANE-NUMBER) */
3455 menu_object
= list3 (Qmenu_item
, pane_name
, make_number (pane
));
3456 show_help_echo (help_string
? build_string (help_string
) : Qnil
,
3457 Qnil
, menu_object
, make_number (item
));
3461 tty_pop_down_menu (Lisp_Object arg
)
3463 tty_menu
*menu
= XSAVE_POINTER (arg
, 0);
3466 tty_menu_destroy (menu
);
3470 /* Return the zero-based index of the last menu-bar item on frame F. */
3472 tty_menu_last_menubar_item (struct frame
*f
)
3476 eassert (FRAME_TERMCAP_P (f
) && FRAME_LIVE_P (f
));
3477 if (FRAME_TERMCAP_P (f
) && FRAME_LIVE_P (f
))
3479 Lisp_Object items
= FRAME_MENU_BAR_ITEMS (f
);
3481 while (i
< ASIZE (items
))
3485 str
= AREF (items
, i
+ 1);
3490 i
-= 4; /* went one too far */
3495 /* Find in frame F's menu bar the menu item that is next or previous
3496 to the item at X/Y, and return that item's position in X/Y. WHICH
3497 says which one--next or previous--item to look for. X and Y are
3498 measured in character cells. This should only be called on TTY
3501 tty_menu_new_item_coords (struct frame
*f
, int which
, int *x
, int *y
)
3503 eassert (FRAME_TERMCAP_P (f
) && FRAME_LIVE_P (f
));
3504 if (FRAME_TERMCAP_P (f
) && FRAME_LIVE_P (f
))
3506 Lisp_Object items
= FRAME_MENU_BAR_ITEMS (f
);
3507 int last_i
= tty_menu_last_menubar_item (f
);
3510 /* This loop assumes a single menu-bar line, and will fail to
3511 find an item if it is not in the first line. Note that
3512 make_lispy_event in keyboard.c makes the same assumption. */
3513 for (i
= 0, prev_x
= -1; i
< ASIZE (items
); i
+= 4)
3515 Lisp_Object pos
, str
;
3518 str
= AREF (items
, i
+ 1);
3519 pos
= AREF (items
, i
+ 3);
3524 /* We use <= so the blank between 2 items on a TTY is
3525 considered part of the previous item. */
3526 && *x
<= ix
+ menu_item_width (SDATA (str
)))
3528 /* Found current item. Now compute the X coordinate of
3529 the previous or next item. */
3530 if (which
== TTYM_NEXT
)
3533 *x
= XINT (AREF (items
, i
+ 4 + 3));
3535 *x
= 0; /* wrap around to the first item */
3537 else if (prev_x
< 0)
3539 /* Wrap around to the last item. */
3540 *x
= XINT (AREF (items
, last_i
+ 3));
3552 tty_menu_show (struct frame
*f
, int x
, int y
, int for_click
, int keymaps
,
3553 Lisp_Object title
, int kbd_navigation
, const char **error_name
)
3556 int pane
, selidx
, lpane
, status
;
3557 Lisp_Object entry
, pane_prefix
;
3559 int ulx
, uly
, width
, height
;
3561 int dispwidth
, dispheight
;
3562 int i
, j
, lines
, maxlines
;
3564 ptrdiff_t specpdl_count
;
3566 eassert (FRAME_TERMCAP_P (f
));
3569 if (menu_items_n_panes
== 0)
3572 if (menu_items_used
<= MENU_ITEMS_PANE_LENGTH
)
3574 *error_name
= "Empty menu";
3578 /* Make the menu on that window. */
3579 menu
= tty_menu_create ();
3582 *error_name
= "Can't create menu";
3586 /* Don't GC while we prepare and show the menu, because we give the
3587 menu functions pointers to the contents of strings. */
3588 specpdl_count
= inhibit_garbage_collection ();
3590 /* Adjust coordinates to be root-window-relative. */
3591 item_x
= x
+= f
->left_pos
;
3592 item_y
= y
+= f
->top_pos
;
3594 /* Create all the necessary panes and their items. */
3595 maxwidth
= maxlines
= lines
= i
= 0;
3596 lpane
= TTYM_FAILURE
;
3597 while (i
< menu_items_used
)
3599 if (EQ (AREF (menu_items
, i
), Qt
))
3601 /* Create a new pane. */
3602 Lisp_Object pane_name
, prefix
;
3603 const char *pane_string
;
3605 maxlines
= max (maxlines
, lines
);
3607 pane_name
= AREF (menu_items
, i
+ MENU_ITEMS_PANE_NAME
);
3608 prefix
= AREF (menu_items
, i
+ MENU_ITEMS_PANE_PREFIX
);
3609 pane_string
= (NILP (pane_name
)
3610 ? "" : SSDATA (pane_name
));
3611 if (keymaps
&& !NILP (prefix
))
3614 lpane
= tty_menu_add_pane (menu
, pane_string
);
3615 if (lpane
== TTYM_FAILURE
)
3617 tty_menu_destroy (menu
);
3618 *error_name
= "Can't create pane";
3622 i
+= MENU_ITEMS_PANE_LENGTH
;
3624 /* Find the width of the widest item in this pane. */
3626 while (j
< menu_items_used
)
3629 item
= AREF (menu_items
, j
);
3637 width
= SBYTES (item
);
3638 if (width
> maxwidth
)
3641 j
+= MENU_ITEMS_ITEM_LENGTH
;
3644 /* Ignore a nil in the item list.
3645 It's meaningful only for dialog boxes. */
3646 else if (EQ (AREF (menu_items
, i
), Qquote
))
3650 /* Create a new item within current pane. */
3651 Lisp_Object item_name
, enable
, descrip
, help
;
3653 char const *help_string
;
3655 item_name
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
);
3656 enable
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_ENABLE
);
3657 descrip
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
);
3658 help
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_HELP
);
3659 help_string
= STRINGP (help
) ? SSDATA (help
) : NULL
;
3661 if (!NILP (descrip
))
3663 /* if alloca is fast, use that to make the space,
3664 to reduce gc needs. */
3665 item_data
= (char *) alloca (maxwidth
+ SBYTES (descrip
) + 1);
3666 memcpy (item_data
, SSDATA (item_name
), SBYTES (item_name
));
3667 for (j
= SCHARS (item_name
); j
< maxwidth
; j
++)
3669 memcpy (item_data
+ j
, SSDATA (descrip
), SBYTES (descrip
));
3670 item_data
[j
+ SBYTES (descrip
)] = 0;
3673 item_data
= SSDATA (item_name
);
3675 if (lpane
== TTYM_FAILURE
3676 || (tty_menu_add_selection (menu
, lpane
, item_data
,
3677 !NILP (enable
), help_string
)
3680 tty_menu_destroy (menu
);
3681 *error_name
= "Can't add selection to menu";
3685 i
+= MENU_ITEMS_ITEM_LENGTH
;
3690 maxlines
= max (maxlines
, lines
);
3692 /* All set and ready to fly. */
3693 dispwidth
= f
->text_cols
;
3694 dispheight
= f
->text_lines
;
3695 x
= min (x
, dispwidth
);
3696 y
= min (y
, dispheight
);
3699 tty_menu_locate (menu
, x
, y
, &ulx
, &uly
, &width
, &height
);
3700 if (ulx
+ width
> dispwidth
)
3702 x
-= (ulx
+ width
) - dispwidth
;
3703 ulx
= dispwidth
- width
;
3705 if (uly
+ height
> dispheight
)
3707 y
-= (uly
+ height
) - dispheight
;
3708 uly
= dispheight
- height
;
3711 if (FRAME_HAS_MINIBUF_P (f
) && uly
+height
> dispheight
- 2)
3713 /* Move the menu away of the echo area, to avoid overwriting the
3714 menu with help echo messages or vice versa. */
3715 if (BUFFERP (echo_area_buffer
[0]) && WINDOWP (echo_area_window
))
3717 y
-= WINDOW_TOTAL_LINES (XWINDOW (echo_area_window
)) + 1;
3718 uly
-= WINDOW_TOTAL_LINES (XWINDOW (echo_area_window
)) + 1;
3727 if (ulx
< 0) x
-= ulx
;
3728 if (uly
< 0) y
-= uly
;
3731 /* This code doesn't make sense on a TTY, since it can easily annul
3732 the adjustments above that carefully avoid truncation of the menu
3733 items. I think it was written to fix some problem that only
3737 /* If position was not given by a mouse click, adjust so upper left
3738 corner of the menu as a whole ends up at given coordinates. This
3739 is what x-popup-menu says in its documentation. */
3741 y
+= 1.5*height
/(maxlines
+2);
3747 record_unwind_protect (tty_pop_down_menu
, make_save_ptr (menu
));
3749 specbind (Qoverriding_terminal_local_map
,
3750 Fsymbol_value (Qtty_menu_navigation_map
));
3751 status
= tty_menu_activate (menu
, &pane
, &selidx
, x
, y
, &datap
,
3752 tty_menu_help_callback
, kbd_navigation
);
3753 entry
= pane_prefix
= Qnil
;
3758 /* Find the item number SELIDX in pane number PANE. */
3760 while (i
< menu_items_used
)
3762 if (EQ (AREF (menu_items
, i
), Qt
))
3766 = AREF (menu_items
, i
+ MENU_ITEMS_PANE_PREFIX
);
3768 i
+= MENU_ITEMS_PANE_LENGTH
;
3777 = AREF (menu_items
, i
+ MENU_ITEMS_ITEM_VALUE
);
3780 entry
= Fcons (entry
, Qnil
);
3781 if (!NILP (pane_prefix
))
3782 entry
= Fcons (pane_prefix
, entry
);
3788 i
+= MENU_ITEMS_ITEM_LENGTH
;
3795 tty_menu_new_item_coords (f
, status
, &item_x
, &item_y
);
3796 entry
= Fcons (make_number (item_x
), make_number (item_y
));
3800 *error_name
= "Can't activate menu";
3801 case TTYM_IA_SELECT
:
3803 case TTYM_NO_SELECT
:
3804 /* Make "Cancel" equivalent to C-g unless FOR_CLICK (which means
3805 the menu was invoked with a mouse event as POSITION). */
3807 Fsignal (Qquit
, Qnil
);
3813 unbind_to (specpdl_count
, Qnil
);
3817 #endif /* HAVE_MENUS && !MSDOS */
3821 /***********************************************************************
3823 ***********************************************************************/
3825 /* Initialize the tty-dependent part of frame F. The frame must
3826 already have its device initialized. */
3829 create_tty_output (struct frame
*f
)
3831 struct tty_output
*t
= xzalloc (sizeof *t
);
3833 eassert (FRAME_TERMCAP_P (f
));
3835 t
->display_info
= FRAME_TERMINAL (f
)->display_info
.tty
;
3837 f
->output_data
.tty
= t
;
3840 /* Delete frame F's face cache, and its tty-dependent part. */
3843 tty_free_frame_resources (struct frame
*f
)
3845 eassert (FRAME_TERMCAP_P (f
));
3847 if (FRAME_FACE_CACHE (f
))
3848 free_frame_faces (f
);
3850 xfree (f
->output_data
.tty
);
3855 /* Delete frame F's face cache. */
3858 tty_free_frame_resources (struct frame
*f
)
3860 eassert (FRAME_TERMCAP_P (f
) || FRAME_MSDOS_P (f
));
3862 if (FRAME_FACE_CACHE (f
))
3863 free_frame_faces (f
);
3867 /* Reset the hooks in TERMINAL. */
3870 clear_tty_hooks (struct terminal
*terminal
)
3873 terminal
->cursor_to_hook
= 0;
3874 terminal
->raw_cursor_to_hook
= 0;
3875 terminal
->clear_to_end_hook
= 0;
3876 terminal
->clear_frame_hook
= 0;
3877 terminal
->clear_end_of_line_hook
= 0;
3878 terminal
->ins_del_lines_hook
= 0;
3879 terminal
->insert_glyphs_hook
= 0;
3880 terminal
->write_glyphs_hook
= 0;
3881 terminal
->delete_glyphs_hook
= 0;
3882 terminal
->ring_bell_hook
= 0;
3883 terminal
->reset_terminal_modes_hook
= 0;
3884 terminal
->set_terminal_modes_hook
= 0;
3885 terminal
->update_begin_hook
= 0;
3886 terminal
->update_end_hook
= 0;
3887 terminal
->set_terminal_window_hook
= 0;
3888 terminal
->mouse_position_hook
= 0;
3889 terminal
->frame_rehighlight_hook
= 0;
3890 terminal
->frame_raise_lower_hook
= 0;
3891 terminal
->fullscreen_hook
= 0;
3892 terminal
->set_vertical_scroll_bar_hook
= 0;
3893 terminal
->condemn_scroll_bars_hook
= 0;
3894 terminal
->redeem_scroll_bar_hook
= 0;
3895 terminal
->judge_scroll_bars_hook
= 0;
3896 terminal
->read_socket_hook
= 0;
3897 terminal
->frame_up_to_date_hook
= 0;
3899 /* Leave these two set, or suspended frames are not deleted
3901 terminal
->delete_frame_hook
= &tty_free_frame_resources
;
3902 terminal
->delete_terminal_hook
= &delete_tty
;
3905 /* Initialize hooks in TERMINAL with the values needed for a tty. */
3908 set_tty_hooks (struct terminal
*terminal
)
3910 terminal
->rif
= 0; /* ttys don't support window-based redisplay. */
3912 terminal
->cursor_to_hook
= &tty_cursor_to
;
3913 terminal
->raw_cursor_to_hook
= &tty_raw_cursor_to
;
3915 terminal
->clear_to_end_hook
= &tty_clear_to_end
;
3916 terminal
->clear_frame_hook
= &tty_clear_frame
;
3917 terminal
->clear_end_of_line_hook
= &tty_clear_end_of_line
;
3919 terminal
->ins_del_lines_hook
= &tty_ins_del_lines
;
3921 terminal
->insert_glyphs_hook
= &tty_insert_glyphs
;
3922 terminal
->write_glyphs_hook
= &tty_write_glyphs
;
3923 terminal
->delete_glyphs_hook
= &tty_delete_glyphs
;
3925 terminal
->ring_bell_hook
= &tty_ring_bell
;
3927 terminal
->reset_terminal_modes_hook
= &tty_reset_terminal_modes
;
3928 terminal
->set_terminal_modes_hook
= &tty_set_terminal_modes
;
3929 terminal
->update_begin_hook
= 0; /* Not needed. */
3930 terminal
->update_end_hook
= &tty_update_end
;
3931 terminal
->set_terminal_window_hook
= &tty_set_terminal_window
;
3933 terminal
->mouse_position_hook
= 0; /* Not needed. */
3934 terminal
->frame_rehighlight_hook
= 0; /* Not needed. */
3935 terminal
->frame_raise_lower_hook
= 0; /* Not needed. */
3937 terminal
->set_vertical_scroll_bar_hook
= 0; /* Not needed. */
3938 terminal
->condemn_scroll_bars_hook
= 0; /* Not needed. */
3939 terminal
->redeem_scroll_bar_hook
= 0; /* Not needed. */
3940 terminal
->judge_scroll_bars_hook
= 0; /* Not needed. */
3942 terminal
->read_socket_hook
= &tty_read_avail_input
; /* keyboard.c */
3943 terminal
->frame_up_to_date_hook
= 0; /* Not needed. */
3945 terminal
->delete_frame_hook
= &tty_free_frame_resources
;
3946 terminal
->delete_terminal_hook
= &delete_tty
;
3949 /* If FD is the controlling terminal, drop it. */
3951 dissociate_if_controlling_tty (int fd
)
3953 /* If tcgetpgrp succeeds, fd is the controlling terminal,
3954 so dissociate it by invoking setsid. */
3955 if (tcgetpgrp (fd
) >= 0 && setsid () < 0)
3958 /* setsid failed, presumably because Emacs is already a process
3959 group leader. Fall back on the obsolescent way to dissociate
3960 a controlling tty. */
3961 block_tty_out_signal ();
3962 ioctl (fd
, TIOCNOTTY
, 0);
3963 unblock_tty_out_signal ();
3968 /* Create a termcap display on the tty device with the given name and
3971 If NAME is NULL, then use the controlling tty, i.e., "/dev/tty".
3972 Otherwise NAME should be a path to the tty device file,
3975 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
3977 If MUST_SUCCEED is true, then all errors are fatal. */
3980 init_tty (const char *name
, const char *terminal_type
, bool must_succeed
)
3983 char **address
= &area
;
3985 struct tty_display_info
*tty
= NULL
;
3986 struct terminal
*terminal
= NULL
;
3987 bool ctty
= false; /* True if asked to open controlling tty. */
3990 maybe_fatal (must_succeed
, 0,
3991 "Unknown terminal type",
3992 "Unknown terminal type");
3996 if (!strcmp (name
, DEV_TTY
))
3999 /* If we already have a terminal on the given device, use that. If
4000 all such terminals are suspended, create a new one instead. */
4001 /* XXX Perhaps this should be made explicit by having init_tty
4002 always create a new terminal and separating terminal and frame
4003 creation on Lisp level. */
4004 terminal
= get_named_tty (name
);
4008 terminal
= create_terminal ();
4011 maybe_fatal (0, 0, "Attempt to create another terminal %s", "",
4014 tty
= &the_only_display_info
;
4016 tty
= xzalloc (sizeof *tty
);
4018 tty
->top_frame
= Qnil
;
4019 tty
->next
= tty_list
;
4022 terminal
->type
= output_termcap
;
4023 terminal
->display_info
.tty
= tty
;
4024 tty
->terminal
= terminal
;
4026 tty
->Wcm
= xmalloc (sizeof *tty
->Wcm
);
4029 encode_terminal_src_size
= 0;
4030 encode_terminal_dst_size
= 0;
4034 set_tty_hooks (terminal
);
4037 /* Open the terminal device. */
4039 /* If !ctty, don't recognize it as our controlling terminal, and
4040 don't make it the controlling tty if we don't have one now.
4042 Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
4043 defined on Hurd. On other systems, we need to explicitly
4044 dissociate ourselves from the controlling tty when we want to
4045 open a frame on the same terminal. */
4046 int flags
= O_RDWR
| O_NOCTTY
| (ctty
? 0 : O_IGNORE_CTTY
);
4047 int fd
= emacs_open (name
, flags
, 0);
4048 tty
->input
= tty
->output
= fd
< 0 || ! isatty (fd
) ? 0 : fdopen (fd
, "w+");
4052 char const *diagnostic
4053 = tty
->input
? "Not a tty device: %s" : "Could not open file: %s";
4055 maybe_fatal (must_succeed
, terminal
, diagnostic
, diagnostic
, name
);
4058 tty
->name
= xstrdup (name
);
4059 terminal
->name
= xstrdup (name
);
4061 if (!O_IGNORE_CTTY
&& !ctty
)
4062 dissociate_if_controlling_tty (fd
);
4065 tty
->type
= xstrdup (terminal_type
);
4067 add_keyboard_wait_descriptor (fileno (tty
->input
));
4071 /* On some systems, tgetent tries to access the controlling
4073 block_tty_out_signal ();
4074 status
= tgetent (tty
->termcap_term_buffer
, terminal_type
);
4075 if (tty
->termcap_term_buffer
[TERMCAP_BUFFER_SIZE
- 1])
4077 unblock_tty_out_signal ();
4082 maybe_fatal (must_succeed
, terminal
,
4083 "Cannot open terminfo database file",
4084 "Cannot open terminfo database file");
4086 maybe_fatal (must_succeed
, terminal
,
4087 "Cannot open termcap database file",
4088 "Cannot open termcap database file");
4093 maybe_fatal (must_succeed
, terminal
,
4094 "Terminal type %s is not defined",
4095 "Terminal type %s is not defined.\n\
4096 If that is not the actual type of terminal you have,\n\
4097 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
4098 `setenv TERM ...') to specify the correct type. It may be necessary\n"
4100 "to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
4102 "to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
4107 area
= tty
->termcap_strings_buffer
;
4108 tty
->TS_ins_line
= tgetstr ("al", address
);
4109 tty
->TS_ins_multi_lines
= tgetstr ("AL", address
);
4110 tty
->TS_bell
= tgetstr ("bl", address
);
4111 BackTab (tty
) = tgetstr ("bt", address
);
4112 tty
->TS_clr_to_bottom
= tgetstr ("cd", address
);
4113 tty
->TS_clr_line
= tgetstr ("ce", address
);
4114 tty
->TS_clr_frame
= tgetstr ("cl", address
);
4115 ColPosition (tty
) = NULL
; /* tgetstr ("ch", address); */
4116 AbsPosition (tty
) = tgetstr ("cm", address
);
4117 CR (tty
) = tgetstr ("cr", address
);
4118 tty
->TS_set_scroll_region
= tgetstr ("cs", address
);
4119 tty
->TS_set_scroll_region_1
= tgetstr ("cS", address
);
4120 RowPosition (tty
) = tgetstr ("cv", address
);
4121 tty
->TS_del_char
= tgetstr ("dc", address
);
4122 tty
->TS_del_multi_chars
= tgetstr ("DC", address
);
4123 tty
->TS_del_line
= tgetstr ("dl", address
);
4124 tty
->TS_del_multi_lines
= tgetstr ("DL", address
);
4125 tty
->TS_delete_mode
= tgetstr ("dm", address
);
4126 tty
->TS_end_delete_mode
= tgetstr ("ed", address
);
4127 tty
->TS_end_insert_mode
= tgetstr ("ei", address
);
4128 Home (tty
) = tgetstr ("ho", address
);
4129 tty
->TS_ins_char
= tgetstr ("ic", address
);
4130 tty
->TS_ins_multi_chars
= tgetstr ("IC", address
);
4131 tty
->TS_insert_mode
= tgetstr ("im", address
);
4132 tty
->TS_pad_inserted_char
= tgetstr ("ip", address
);
4133 tty
->TS_end_keypad_mode
= tgetstr ("ke", address
);
4134 tty
->TS_keypad_mode
= tgetstr ("ks", address
);
4135 LastLine (tty
) = tgetstr ("ll", address
);
4136 Right (tty
) = tgetstr ("nd", address
);
4137 Down (tty
) = tgetstr ("do", address
);
4139 Down (tty
) = tgetstr ("nl", address
); /* Obsolete name for "do". */
4140 if (tgetflag ("bs"))
4141 Left (tty
) = "\b"; /* Can't possibly be longer! */
4142 else /* (Actually, "bs" is obsolete...) */
4143 Left (tty
) = tgetstr ("le", address
);
4145 Left (tty
) = tgetstr ("bc", address
); /* Obsolete name for "le". */
4146 tty
->TS_pad_char
= tgetstr ("pc", address
);
4147 tty
->TS_repeat
= tgetstr ("rp", address
);
4148 tty
->TS_end_standout_mode
= tgetstr ("se", address
);
4149 tty
->TS_fwd_scroll
= tgetstr ("sf", address
);
4150 tty
->TS_standout_mode
= tgetstr ("so", address
);
4151 tty
->TS_rev_scroll
= tgetstr ("sr", address
);
4152 tty
->Wcm
->cm_tab
= tgetstr ("ta", address
);
4153 tty
->TS_end_termcap_modes
= tgetstr ("te", address
);
4154 tty
->TS_termcap_modes
= tgetstr ("ti", address
);
4155 Up (tty
) = tgetstr ("up", address
);
4156 tty
->TS_visible_bell
= tgetstr ("vb", address
);
4157 tty
->TS_cursor_normal
= tgetstr ("ve", address
);
4158 tty
->TS_cursor_visible
= tgetstr ("vs", address
);
4159 tty
->TS_cursor_invisible
= tgetstr ("vi", address
);
4160 tty
->TS_set_window
= tgetstr ("wi", address
);
4162 tty
->TS_enter_underline_mode
= tgetstr ("us", address
);
4163 tty
->TS_exit_underline_mode
= tgetstr ("ue", address
);
4164 tty
->TS_enter_bold_mode
= tgetstr ("md", address
);
4165 tty
->TS_enter_italic_mode
= tgetstr ("ZH", address
);
4166 tty
->TS_enter_dim_mode
= tgetstr ("mh", address
);
4167 tty
->TS_enter_reverse_mode
= tgetstr ("mr", address
);
4168 tty
->TS_enter_alt_charset_mode
= tgetstr ("as", address
);
4169 tty
->TS_exit_alt_charset_mode
= tgetstr ("ae", address
);
4170 tty
->TS_exit_attribute_mode
= tgetstr ("me", address
);
4172 MultiUp (tty
) = tgetstr ("UP", address
);
4173 MultiDown (tty
) = tgetstr ("DO", address
);
4174 MultiLeft (tty
) = tgetstr ("LE", address
);
4175 MultiRight (tty
) = tgetstr ("RI", address
);
4177 /* SVr4/ANSI color support. If "op" isn't available, don't support
4178 color because we can't switch back to the default foreground and
4180 tty
->TS_orig_pair
= tgetstr ("op", address
);
4181 if (tty
->TS_orig_pair
)
4183 tty
->TS_set_foreground
= tgetstr ("AF", address
);
4184 tty
->TS_set_background
= tgetstr ("AB", address
);
4185 if (!tty
->TS_set_foreground
)
4188 tty
->TS_set_foreground
= tgetstr ("Sf", address
);
4189 tty
->TS_set_background
= tgetstr ("Sb", address
);
4192 tty
->TN_max_colors
= tgetnum ("Co");
4193 tty
->TN_max_pairs
= tgetnum ("pa");
4195 tty
->TN_no_color_video
= tgetnum ("NC");
4196 if (tty
->TN_no_color_video
== -1)
4197 tty
->TN_no_color_video
= 0;
4200 tty_default_color_capabilities (tty
, 1);
4202 MagicWrap (tty
) = tgetflag ("xn");
4203 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
4204 the former flag imply the latter. */
4205 AutoWrap (tty
) = MagicWrap (tty
) || tgetflag ("am");
4206 terminal
->memory_below_frame
= tgetflag ("db");
4207 tty
->TF_hazeltine
= tgetflag ("hz");
4208 terminal
->must_write_spaces
= tgetflag ("in");
4209 tty
->meta_key
= tgetflag ("km") || tgetflag ("MT");
4210 tty
->TF_insmode_motion
= tgetflag ("mi");
4211 tty
->TF_standout_motion
= tgetflag ("ms");
4212 tty
->TF_underscore
= tgetflag ("ul");
4213 tty
->TF_teleray
= tgetflag ("xt");
4218 struct frame
*f
= XFRAME (selected_frame
);
4221 initialize_w32_display (terminal
, &width
, &height
);
4223 FrameRows (tty
) = height
;
4224 FrameCols (tty
) = width
;
4225 tty
->specified_window
= height
;
4227 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_none
;
4228 terminal
->char_ins_del_ok
= 1;
4234 if (strcmp (terminal_type
, "internal") == 0)
4235 terminal
->type
= output_msdos_raw
;
4236 initialize_msdos_display (terminal
);
4238 get_tty_size (fileno (tty
->input
), &width
, &height
);
4239 FrameCols (tty
) = width
;
4240 FrameRows (tty
) = height
;
4241 terminal
->char_ins_del_ok
= 0;
4242 init_baud_rate (fileno (tty
->input
));
4245 tty
->output
= stdout
;
4247 /* The following two are inaccessible from w32console.c. */
4248 terminal
->delete_frame_hook
= &tty_free_frame_resources
;
4249 terminal
->delete_terminal_hook
= &delete_tty
;
4251 tty
->name
= xstrdup (name
);
4252 terminal
->name
= xstrdup (name
);
4253 tty
->type
= xstrdup (terminal_type
);
4255 add_keyboard_wait_descriptor (0);
4257 tty
->delete_in_insert_mode
= 1;
4260 terminal
->scroll_region_ok
= 0;
4262 /* Seems to insert lines when it's not supposed to, messing up the
4263 display. In doing a trace, it didn't seem to be called much, so I
4264 don't think we're losing anything by turning it off. */
4265 terminal
->line_ins_del_ok
= 0;
4267 tty
->TN_max_colors
= 16; /* Must be non-zero for tty-display-color-p. */
4271 terminal
->mouse_position_hook
= term_mouse_position
;
4272 tty
->mouse_highlight
.mouse_face_window
= Qnil
;
4275 terminal
->kboard
= allocate_kboard (Qnil
);
4276 terminal
->kboard
->reference_count
++;
4277 /* Don't let the initial kboard remain current longer than necessary.
4278 That would cause problems if a file loaded on startup tries to
4279 prompt in the mini-buffer. */
4280 if (current_kboard
== initial_kboard
)
4281 current_kboard
= terminal
->kboard
;
4283 term_get_fkeys (address
, terminal
->kboard
);
4285 /* Get frame size from system, or else from termcap. */
4288 get_tty_size (fileno (tty
->input
), &width
, &height
);
4289 FrameCols (tty
) = width
;
4290 FrameRows (tty
) = height
;
4293 if (FrameCols (tty
) <= 0)
4294 FrameCols (tty
) = tgetnum ("co");
4295 if (FrameRows (tty
) <= 0)
4296 FrameRows (tty
) = tgetnum ("li");
4298 if (FrameRows (tty
) < 3 || FrameCols (tty
) < 3)
4299 maybe_fatal (must_succeed
, terminal
,
4300 "Screen size %dx%d is too small",
4301 "Screen size %dx%d is too small",
4302 FrameCols (tty
), FrameRows (tty
));
4304 TabWidth (tty
) = tgetnum ("tw");
4307 tty
->TS_bell
= "\07";
4309 if (!tty
->TS_fwd_scroll
)
4310 tty
->TS_fwd_scroll
= Down (tty
);
4312 PC
= tty
->TS_pad_char
? *tty
->TS_pad_char
: 0;
4314 if (TabWidth (tty
) < 0)
4317 /* Turned off since /etc/termcap seems to have :ta= for most terminals
4318 and newer termcap doc does not seem to say there is a default.
4319 if (!tty->Wcm->cm_tab)
4320 tty->Wcm->cm_tab = "\t";
4323 /* We don't support standout modes that use `magic cookies', so
4324 turn off any that do. */
4325 if (tty
->TS_standout_mode
&& tgetnum ("sg") >= 0)
4327 tty
->TS_standout_mode
= 0;
4328 tty
->TS_end_standout_mode
= 0;
4330 if (tty
->TS_enter_underline_mode
&& tgetnum ("ug") >= 0)
4332 tty
->TS_enter_underline_mode
= 0;
4333 tty
->TS_exit_underline_mode
= 0;
4336 /* If there's no standout mode, try to use underlining instead. */
4337 if (tty
->TS_standout_mode
== 0)
4339 tty
->TS_standout_mode
= tty
->TS_enter_underline_mode
;
4340 tty
->TS_end_standout_mode
= tty
->TS_exit_underline_mode
;
4343 /* If no `se' string, try using a `me' string instead.
4344 If that fails, we can't use standout mode at all. */
4345 if (tty
->TS_end_standout_mode
== 0)
4347 char *s
= tgetstr ("me", address
);
4349 tty
->TS_end_standout_mode
= s
;
4351 tty
->TS_standout_mode
= 0;
4354 if (tty
->TF_teleray
)
4356 tty
->Wcm
->cm_tab
= 0;
4357 /* We can't support standout mode, because it uses magic cookies. */
4358 tty
->TS_standout_mode
= 0;
4359 /* But that means we cannot rely on ^M to go to column zero! */
4361 /* LF can't be trusted either -- can alter hpos. */
4362 /* If move at column 0 thru a line with TS_standout_mode. */
4366 tty
->specified_window
= FrameRows (tty
);
4368 if (Wcm_init (tty
) == -1) /* Can't do cursor motion. */
4370 maybe_fatal (must_succeed
, terminal
,
4371 "Terminal type \"%s\" is not powerful enough to run Emacs",
4372 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
4373 It lacks the ability to position the cursor.\n\
4374 If that is not the actual type of terminal you have,\n\
4375 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
4376 `setenv TERM ...') to specify the correct type. It may be necessary\n"
4378 "to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
4379 # else /* TERMCAP */
4380 "to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
4381 # endif /* TERMINFO */
4385 if (FrameRows (tty
) <= 0 || FrameCols (tty
) <= 0)
4386 maybe_fatal (must_succeed
, terminal
,
4387 "Could not determine the frame size",
4388 "Could not determine the frame size");
4390 tty
->delete_in_insert_mode
4391 = tty
->TS_delete_mode
&& tty
->TS_insert_mode
4392 && !strcmp (tty
->TS_delete_mode
, tty
->TS_insert_mode
);
4394 UseTabs (tty
) = tabs_safe_p (fileno (tty
->input
)) && TabWidth (tty
) == 8;
4396 terminal
->scroll_region_ok
4398 && (tty
->TS_set_window
|| tty
->TS_set_scroll_region
|| tty
->TS_set_scroll_region_1
));
4400 terminal
->line_ins_del_ok
4401 = (((tty
->TS_ins_line
|| tty
->TS_ins_multi_lines
)
4402 && (tty
->TS_del_line
|| tty
->TS_del_multi_lines
))
4403 || (terminal
->scroll_region_ok
4404 && tty
->TS_fwd_scroll
&& tty
->TS_rev_scroll
));
4406 terminal
->char_ins_del_ok
4407 = ((tty
->TS_ins_char
|| tty
->TS_insert_mode
4408 || tty
->TS_pad_inserted_char
|| tty
->TS_ins_multi_chars
)
4409 && (tty
->TS_del_char
|| tty
->TS_del_multi_chars
));
4411 terminal
->fast_clear_end_of_line
= tty
->TS_clr_line
!= 0;
4413 init_baud_rate (fileno (tty
->input
));
4415 #endif /* not DOS_NT */
4417 /* Init system terminal modes (RAW or CBREAK, etc.). */
4418 init_sys_modes (tty
);
4425 vfatal (const char *str
, va_list ap
)
4427 fprintf (stderr
, "emacs: ");
4428 vfprintf (stderr
, str
, ap
);
4429 if (!(strlen (str
) > 0 && str
[strlen (str
) - 1] == '\n'))
4430 fprintf (stderr
, "\n");
4436 /* Auxiliary error-handling function for init_tty.
4437 Delete TERMINAL, then call error or fatal with str1 or str2,
4438 respectively, according to whether MUST_SUCCEED is true. */
4441 maybe_fatal (bool must_succeed
, struct terminal
*terminal
,
4442 const char *str1
, const char *str2
, ...)
4445 va_start (ap
, str2
);
4447 delete_tty (terminal
);
4456 fatal (const char *str
, ...)
4465 /* Delete the given tty terminal, closing all frames on it. */
4468 delete_tty (struct terminal
*terminal
)
4470 struct tty_display_info
*tty
;
4472 /* Protect against recursive calls. delete_frame in
4473 delete_terminal calls us back when it deletes our last frame. */
4474 if (!terminal
->name
)
4477 eassert (terminal
->type
== output_termcap
);
4479 tty
= terminal
->display_info
.tty
;
4481 if (tty
== tty_list
)
4482 tty_list
= tty
->next
;
4485 struct tty_display_info
*p
;
4486 for (p
= tty_list
; p
&& p
->next
!= tty
; p
= p
->next
)
4490 /* This should not happen. */
4493 p
->next
= tty
->next
;
4497 /* reset_sys_modes needs a valid device, so this call needs to be
4498 before delete_terminal. */
4499 reset_sys_modes (tty
);
4501 delete_terminal (terminal
);
4508 delete_keyboard_wait_descriptor (fileno (tty
->input
));
4509 if (tty
->input
!= stdin
)
4510 fclose (tty
->input
);
4512 if (tty
->output
&& tty
->output
!= stdout
&& tty
->output
!= tty
->input
)
4513 fclose (tty
->output
);
4514 if (tty
->termscript
)
4515 fclose (tty
->termscript
);
4517 xfree (tty
->old_tty
);
4525 DEFVAR_BOOL ("system-uses-terminfo", system_uses_terminfo
,
4526 doc
: /* Non-nil means the system uses terminfo rather than termcap.
4527 This variable can be used by terminal emulator packages. */);
4529 system_uses_terminfo
= 1;
4531 system_uses_terminfo
= 0;
4534 DEFVAR_LISP ("suspend-tty-functions", Vsuspend_tty_functions
,
4535 doc
: /* Functions run after suspending a tty.
4536 The functions are run with one argument, the terminal object to be suspended.
4537 See `suspend-tty'. */);
4538 Vsuspend_tty_functions
= Qnil
;
4541 DEFVAR_LISP ("resume-tty-functions", Vresume_tty_functions
,
4542 doc
: /* Functions run after resuming a tty.
4543 The functions are run with one argument, the terminal object that was revived.
4544 See `resume-tty'. */);
4545 Vresume_tty_functions
= Qnil
;
4547 DEFVAR_BOOL ("visible-cursor", visible_cursor
,
4548 doc
: /* Non-nil means to make the cursor very visible.
4549 This only has an effect when running in a text terminal.
4550 What means \"very visible\" is up to your terminal. It may make the cursor
4551 bigger, or it may make it blink, or it may do nothing at all. */);
4554 defsubr (&Stty_display_color_p
);
4555 defsubr (&Stty_display_color_cells
);
4556 defsubr (&Stty_no_underline
);
4557 defsubr (&Stty_type
);
4558 defsubr (&Scontrolling_tty_p
);
4559 defsubr (&Stty_top_frame
);
4560 defsubr (&Ssuspend_tty
);
4561 defsubr (&Sresume_tty
);
4563 defsubr (&Sgpm_mouse_start
);
4564 defsubr (&Sgpm_mouse_stop
);
4565 #endif /* HAVE_GPM */
4568 default_orig_pair
= NULL
;
4569 default_set_foreground
= NULL
;
4570 default_set_background
= NULL
;
4571 #endif /* !DOS_NT */
4573 encode_terminal_src
= NULL
;
4574 encode_terminal_dst
= NULL
;
4576 DEFSYM (Qtty_menu_next_item
, "tty-menu-next-item");
4577 DEFSYM (Qtty_menu_prev_item
, "tty-menu-prev-item");
4578 DEFSYM (Qtty_menu_next_menu
, "tty-menu-next-menu");
4579 DEFSYM (Qtty_menu_prev_menu
, "tty-menu-prev-menu");
4580 DEFSYM (Qtty_menu_select
, "tty-menu-select");
4581 DEFSYM (Qtty_menu_ignore
, "tty-menu-ignore");
4582 DEFSYM (Qtty_menu_exit
, "tty-menu-exit");
4583 DEFSYM (Qtty_menu_mouse_movement
, "tty-menu-mouse-movement");
4584 DEFSYM (Qtty_menu_navigation_map
, "tty-menu-navigation-map");