1 /* Terminal control module for terminals described by TERMCAP
2 Copyright (C) 1985, 86, 87, 93, 94, 95, 98, 2000, 2001, 2002
3 Free Software Foundation, Inc.
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 2, or (at your option)
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; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* New redisplay, TTY faces by Gerd Moellmann <gerd@gnu.org>. */
31 #include <unistd.h> /* For isatty. */
32 #include <sys/ioctl.h> /* For TIOCNOTTY. */
42 #include "termhooks.h"
43 #include "dispextern.h"
47 /* For now, don't try to include termcap.h. On some systems,
48 configure finds a non-standard termcap.h that the main build
51 #if defined HAVE_TERMCAP_H && 0
54 extern void tputs
P_ ((const char *, int, int (*)(int)));
55 extern int tgetent
P_ ((char *, const char *));
56 extern int tgetflag
P_ ((char *id
));
57 extern int tgetnum
P_ ((char *id
));
76 static void turn_on_face
P_ ((struct frame
*, int face_id
));
77 static void turn_off_face
P_ ((struct frame
*, int face_id
));
78 static void tty_show_cursor
P_ ((struct tty_display_info
*));
79 static void tty_hide_cursor
P_ ((struct tty_display_info
*));
81 void delete_initial_display
P_ ((struct display
*));
82 void create_tty_output
P_ ((struct frame
*));
83 void delete_tty_output
P_ ((struct frame
*));
85 #define OUTPUT(tty, a) \
86 emacs_tputs ((tty), a, \
87 (int) (FRAME_LINES (XFRAME (selected_frame)) \
91 #define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
92 #define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
94 #define OUTPUT_IF(tty, a) \
97 emacs_tputs ((tty), a, \
98 (int) (FRAME_LINES (XFRAME (selected_frame)) \
103 #define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
105 /* Function to use to ring the bell. */
107 Lisp_Object Vring_bell_function
;
109 /* Functions to call after deleting a tty. */
110 Lisp_Object Vdelete_tty_after_functions
;
112 /* Functions to call after suspending a tty. */
113 Lisp_Object Vsuspend_tty_functions
;
115 /* Functions to call after resuming a tty. */
116 Lisp_Object Vresume_tty_functions
;
118 /* Chain of all displays currently in use. */
119 struct display
*display_list
;
121 /* The initial display device, created by initial_term_init. */
122 struct display
*initial_display
;
124 /* Chain of all tty device parameters. */
125 struct tty_display_info
*tty_list
;
127 /* Nonzero means no need to redraw the entire frame on resuming a
128 suspended Emacs. This is useful on terminals with multiple
129 pages, where one page is used for Emacs and another for all
131 int no_redraw_on_reenter
;
133 Lisp_Object Qframe_tty_name
, Qframe_tty_type
;
137 /* Meaning of bits in no_color_video. Each bit set means that the
138 corresponding attribute cannot be combined with colors. */
142 NC_STANDOUT
= 1 << 0,
143 NC_UNDERLINE
= 1 << 1,
150 NC_ALT_CHARSET
= 1 << 8
155 /* The largest frame width in any call to calculate_costs. */
159 /* The largest frame height in any call to calculate_costs. */
163 /* Frame currently being redisplayed; 0 if not currently redisplaying.
164 (Direct output does not count). */
166 FRAME_PTR updating_frame
;
168 /* Non-zero if we have dropped our controlling tty and therefore
169 should not open a frame on stdout. */
170 static int no_controlling_tty
;
172 /* Provided for lisp packages. */
174 static int system_uses_terminfo
;
178 extern char *tgetstr ();
182 /* We aren't X windows, but we aren't termcap either. This makes me
183 uncertain as to what value to use for frame.output_method. For
184 this file, we'll define FRAME_TERMCAP_P to be zero so that our
185 output hooks get called instead of the termcap functions. Probably
186 the best long-term solution is to define an output_windows_nt... */
188 #undef FRAME_TERMCAP_P
189 #define FRAME_TERMCAP_P(_f_) 0
190 #endif /* WINDOWSNT */
195 struct frame
*f
= XFRAME (selected_frame
);
197 if (!NILP (Vring_bell_function
))
199 Lisp_Object function
;
201 /* Temporarily set the global variable to nil
202 so that if we get an error, it stays nil
203 and we don't call it over and over.
205 We don't specbind it, because that would carefully
206 restore the bad value if there's an error
207 and make the loop of errors happen anyway. */
209 function
= Vring_bell_function
;
210 Vring_bell_function
= Qnil
;
214 Vring_bell_function
= function
;
216 else if (FRAME_DISPLAY (f
)->ring_bell_hook
)
217 (*FRAME_DISPLAY (f
)->ring_bell_hook
) ();
220 /* Ring the bell on a tty. */
225 struct frame
*f
= XFRAME (selected_frame
);
226 struct tty_display_info
*tty
= FRAME_TTY (f
);
228 OUTPUT (tty
, (tty
->TS_visible_bell
&& visible_bell
229 ? tty
->TS_visible_bell
233 /* Set up termcap modes for Emacs. */
236 tty_set_terminal_modes (struct display
*display
)
238 struct tty_display_info
*tty
= display
->display_info
.tty
;
242 OUTPUT_IF (tty
, tty
->TS_termcap_modes
);
243 OUTPUT_IF (tty
, tty
->TS_cursor_visible
);
244 OUTPUT_IF (tty
, tty
->TS_keypad_mode
);
249 /* Reset termcap modes before exiting Emacs. */
252 tty_reset_terminal_modes (struct display
*display
)
254 struct tty_display_info
*tty
= display
->display_info
.tty
;
258 turn_off_highlight (tty
);
259 turn_off_insert (tty
);
260 OUTPUT_IF (tty
, tty
->TS_end_keypad_mode
);
261 OUTPUT_IF (tty
, tty
->TS_cursor_normal
);
262 OUTPUT_IF (tty
, tty
->TS_end_termcap_modes
);
263 OUTPUT_IF (tty
, tty
->TS_orig_pair
);
264 /* Output raw CR so kernel can track the cursor hpos. */
275 if (FRAME_DISPLAY (f
)->update_begin_hook
)
276 (*FRAME_DISPLAY (f
)->update_begin_hook
) (f
);
283 if (FRAME_DISPLAY (f
)->update_end_hook
)
284 (*FRAME_DISPLAY (f
)->update_end_hook
) (f
);
285 updating_frame
= NULL
;
288 /* Flag the end of a display update on a termcap display. */
291 tty_update_end (struct frame
*f
)
293 struct tty_display_info
*tty
= FRAME_TTY (f
);
295 if (!XWINDOW (selected_window
)->cursor_off_p
)
296 tty_show_cursor (tty
);
297 turn_off_insert (tty
);
298 background_highlight (tty
);
301 /* Specify how many text lines, from the top of the window,
302 should be affected by insert-lines and delete-lines operations.
303 This, and those operations, are used only within an update
304 that is bounded by calls to update_begin and update_end. */
307 set_terminal_window (size
)
310 struct frame
*f
= (updating_frame
? updating_frame
: XFRAME (selected_frame
));
312 if (FRAME_DISPLAY (f
)->set_terminal_window_hook
)
313 (*FRAME_DISPLAY (f
)->set_terminal_window_hook
) (size
);
316 /* The implementation of set_terminal_window for termcap frames. */
319 tty_set_terminal_window (int size
)
321 struct frame
*f
= (updating_frame
? updating_frame
: XFRAME (selected_frame
));
323 struct tty_display_info
*tty
= FRAME_TTY (f
);
325 tty
->specified_window
= size
? size
: FRAME_LINES (f
);
326 if (FRAME_SCROLL_REGION_OK (f
))
327 set_scroll_region (0, tty
->specified_window
);
331 set_scroll_region (start
, stop
)
335 struct frame
*f
= (updating_frame
? updating_frame
: XFRAME (selected_frame
));
337 struct tty_display_info
*tty
= FRAME_TTY (f
);
339 if (tty
->TS_set_scroll_region
)
340 buf
= tparam (tty
->TS_set_scroll_region
, 0, 0, start
, stop
- 1);
341 else if (tty
->TS_set_scroll_region_1
)
342 buf
= tparam (tty
->TS_set_scroll_region_1
, 0, 0,
343 FRAME_LINES (f
), start
,
344 FRAME_LINES (f
) - stop
,
347 buf
= tparam (tty
->TS_set_window
, 0, 0, start
, 0, stop
, FRAME_COLS (f
));
356 turn_on_insert (struct tty_display_info
*tty
)
358 if (!tty
->insert_mode
)
359 OUTPUT (tty
, tty
->TS_insert_mode
);
360 tty
->insert_mode
= 1;
364 turn_off_insert (struct tty_display_info
*tty
)
366 if (tty
->insert_mode
)
367 OUTPUT (tty
, tty
->TS_end_insert_mode
);
368 tty
->insert_mode
= 0;
371 /* Handle highlighting. */
374 turn_off_highlight (struct tty_display_info
*tty
)
376 if (tty
->standout_mode
)
377 OUTPUT_IF (tty
, tty
->TS_end_standout_mode
);
378 tty
->standout_mode
= 0;
382 turn_on_highlight (struct tty_display_info
*tty
)
384 if (!tty
->standout_mode
)
385 OUTPUT_IF (tty
, tty
->TS_standout_mode
);
386 tty
->standout_mode
= 1;
390 toggle_highlight (struct tty_display_info
*tty
)
392 if (tty
->standout_mode
)
393 turn_off_highlight (tty
);
395 turn_on_highlight (tty
);
399 /* Make cursor invisible. */
402 tty_hide_cursor (struct tty_display_info
*tty
)
404 if (tty
->cursor_hidden
== 0)
406 tty
->cursor_hidden
= 1;
407 OUTPUT_IF (tty
, tty
->TS_cursor_invisible
);
412 /* Ensure that cursor is visible. */
415 tty_show_cursor (struct tty_display_info
*tty
)
417 if (tty
->cursor_hidden
)
419 tty
->cursor_hidden
= 0;
420 OUTPUT_IF (tty
, tty
->TS_cursor_normal
);
421 OUTPUT_IF (tty
, tty
->TS_cursor_visible
);
426 /* Set standout mode to the state it should be in for
427 empty space inside windows. What this is,
428 depends on the user option inverse-video. */
431 background_highlight (struct tty_display_info
*tty
)
434 turn_on_highlight (tty
);
436 turn_off_highlight (tty
);
439 /* Set standout mode to the mode specified for the text to be output. */
442 highlight_if_desired (struct tty_display_info
*tty
)
445 turn_on_highlight (tty
);
447 turn_off_highlight (tty
);
451 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
452 frame-relative coordinates. */
455 cursor_to (vpos
, hpos
)
458 struct frame
*f
= (updating_frame
? updating_frame
: XFRAME (selected_frame
));
460 if (FRAME_DISPLAY (f
)->cursor_to_hook
)
461 (*FRAME_DISPLAY (f
)->cursor_to_hook
) (vpos
, hpos
);
465 tty_cursor_to (int vpos
, int hpos
)
467 struct frame
*f
= (updating_frame
? updating_frame
: XFRAME (selected_frame
));
469 struct tty_display_info
*tty
= FRAME_TTY (f
);
471 /* Detect the case where we are called from reset_sys_modes
472 and the costs have never been calculated. Do nothing. */
473 if (! tty
->costs_set
)
476 if (curY (tty
) == vpos
477 && curX (tty
) == hpos
)
479 if (!tty
->TF_standout_motion
)
480 background_highlight (tty
);
481 if (!tty
->TF_insmode_motion
)
482 turn_off_insert (tty
);
483 cmgoto (tty
, vpos
, hpos
);
486 /* Similar but don't take any account of the wasted characters. */
489 raw_cursor_to (row
, col
)
492 struct frame
*f
= (updating_frame
? updating_frame
: XFRAME (selected_frame
));
494 if (FRAME_DISPLAY (f
)->raw_cursor_to_hook
)
495 (*FRAME_DISPLAY (f
)->raw_cursor_to_hook
) (row
, col
);
499 tty_raw_cursor_to (int row
, int col
)
501 struct frame
*f
= (updating_frame
? updating_frame
: XFRAME (selected_frame
));
503 struct tty_display_info
*tty
= FRAME_TTY (f
);
505 if (curY (tty
) == row
506 && curX (tty
) == col
)
508 if (!tty
->TF_standout_motion
)
509 background_highlight (tty
);
510 if (!tty
->TF_insmode_motion
)
511 turn_off_insert (tty
);
512 cmgoto (tty
, row
, col
);
515 /* Erase operations */
517 /* Clear from cursor to end of frame. */
521 struct frame
*f
= (updating_frame
? updating_frame
: XFRAME (selected_frame
));
523 if (FRAME_DISPLAY (f
)->clear_to_end_hook
)
524 (*FRAME_DISPLAY (f
)->clear_to_end_hook
) ();
527 /* Clear from cursor to end of frame on a termcap device. */
530 tty_clear_to_end (void)
533 struct frame
*f
= (updating_frame
? updating_frame
: XFRAME (selected_frame
));
534 struct tty_display_info
*tty
= FRAME_TTY (f
);
536 if (tty
->TS_clr_to_bottom
)
538 background_highlight (tty
);
539 OUTPUT (tty
, tty
->TS_clr_to_bottom
);
543 for (i
= curY (tty
); i
< FRAME_LINES (f
); i
++)
546 clear_end_of_line (FRAME_COLS (f
));
551 /* Clear entire frame */
556 struct frame
*f
= (updating_frame
? updating_frame
: XFRAME (selected_frame
));
558 if (FRAME_DISPLAY (f
)->clear_frame_hook
)
559 (*FRAME_DISPLAY (f
)->clear_frame_hook
) ();
562 /* Clear an entire termcap frame. */
567 struct frame
*f
= (updating_frame
? updating_frame
: XFRAME (selected_frame
));
569 struct tty_display_info
*tty
= FRAME_TTY (f
);
571 if (tty
->TS_clr_frame
)
573 background_highlight (tty
);
574 OUTPUT (tty
, tty
->TS_clr_frame
);
584 /* Clear from cursor to end of line.
585 Assume that the line is already clear starting at column first_unused_hpos.
587 Note that the cursor may be moved, on terminals lacking a `ce' string. */
590 clear_end_of_line (first_unused_hpos
)
591 int first_unused_hpos
;
593 struct frame
*f
= (updating_frame
? updating_frame
: XFRAME (selected_frame
));
595 if (FRAME_DISPLAY (f
)->clear_end_of_line_hook
)
596 (*FRAME_DISPLAY (f
)->clear_end_of_line_hook
) (first_unused_hpos
);
599 /* An implementation of clear_end_of_line for termcap frames.
601 Note that the cursor may be moved, on terminals lacking a `ce' string. */
604 tty_clear_end_of_line (int first_unused_hpos
)
607 struct frame
*f
= (updating_frame
? updating_frame
: XFRAME (selected_frame
));
608 struct tty_display_info
*tty
= FRAME_TTY (f
);
610 /* Detect the case where we are called from reset_sys_modes
611 and the costs have never been calculated. Do nothing. */
612 if (! tty
->costs_set
)
615 if (curX (tty
) >= first_unused_hpos
)
617 background_highlight (tty
);
618 if (tty
->TS_clr_line
)
620 OUTPUT1 (tty
, tty
->TS_clr_line
);
623 { /* have to do it the hard way */
624 turn_off_insert (tty
);
626 /* Do not write in last row last col with Auto-wrap on. */
628 && curY (tty
) == FrameRows (tty
) - 1
629 && first_unused_hpos
== FrameCols (tty
))
632 for (i
= curX (tty
); i
< first_unused_hpos
; i
++)
635 fputc (' ', tty
->termscript
);
636 fputc (' ', tty
->output
);
638 cmplus (tty
, first_unused_hpos
- curX (tty
));
642 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes and
643 store them at DST. Do not write more than DST_LEN bytes. That may
644 require stopping before all SRC_LEN input glyphs have been
647 We store the number of glyphs actually converted in *CONSUMED. The
648 return value is the number of bytes store in DST. */
651 encode_terminal_code (src
, dst
, src_len
, dst_len
, consumed
)
655 int dst_len
, *consumed
;
657 struct glyph
*src_start
= src
, *src_end
= src
+ src_len
;
658 unsigned char *dst_start
= dst
, *dst_end
= dst
+ dst_len
;
660 unsigned char workbuf
[MAX_MULTIBYTE_LENGTH
];
661 const unsigned char *buf
;
663 register int tlen
= GLYPH_TABLE_LENGTH
;
664 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
666 struct coding_system
*coding
;
668 /* If terminal_coding does any conversion, use it, otherwise use
669 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
670 because it always return 1 if the member src_multibyte is 1. */
671 coding
= (terminal_coding
.common_flags
& CODING_REQUIRE_ENCODING_MASK
673 : &safe_terminal_coding
);
675 while (src
< src_end
)
677 /* We must skip glyphs to be padded for a wide character. */
678 if (! CHAR_GLYPH_PADDING_P (*src
))
680 g
= GLYPH_FROM_CHAR_GLYPH (src
[0]);
682 if (g
< 0 || g
>= tlen
)
684 /* This glyph doesn't has an entry in Vglyph_table. */
685 if (! CHAR_VALID_P (src
->u
.ch
, 0))
689 coding
->src_multibyte
= 0;
693 len
= CHAR_STRING (src
->u
.ch
, workbuf
);
695 coding
->src_multibyte
= 1;
700 /* This glyph has an entry in Vglyph_table,
701 so process any alias before testing for simpleness. */
702 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
704 if (GLYPH_SIMPLE_P (tbase
, tlen
, g
))
706 /* We set the multi-byte form of a character in G
707 (that should be an ASCII character) at
709 workbuf
[0] = FAST_GLYPH_CHAR (g
);
712 coding
->src_multibyte
= 0;
716 /* We have a string in Vglyph_table. */
717 len
= GLYPH_LENGTH (tbase
, g
);
718 buf
= GLYPH_STRING (tbase
, g
);
719 coding
->src_multibyte
= STRING_MULTIBYTE (tbase
[g
]);
723 result
= encode_coding (coding
, buf
, dst
, len
, dst_end
- dst
);
724 len
-= coding
->consumed
;
725 dst
+= coding
->produced
;
726 if (result
== CODING_FINISH_INSUFFICIENT_DST
727 || (result
== CODING_FINISH_INSUFFICIENT_SRC
728 && len
> dst_end
- dst
))
729 /* The remaining output buffer is too short. We must
730 break the loop here without increasing SRC so that the
731 next call of this function starts from the same glyph. */
736 /* This is the case that a code of the range 0200..0237
737 exists in buf. We must just write out such a code. */
738 buf
+= coding
->consumed
;
746 *consumed
= src
- src_start
;
747 return (dst
- dst_start
);
751 /* Output LEN glyphs starting at STRING at the nominal cursor position.
752 Advance the nominal cursor over the text. */
755 write_glyphs (string
, len
)
756 register struct glyph
*string
;
759 struct frame
*f
= (updating_frame
? updating_frame
: XFRAME (selected_frame
));
761 if (FRAME_DISPLAY (f
)->write_glyphs_hook
)
762 (*FRAME_DISPLAY (f
)->write_glyphs_hook
) (string
, len
);
765 /* An implementation of write_glyphs for termcap frames. */
768 tty_write_glyphs (struct glyph
*string
, int len
)
770 int produced
, consumed
;
771 unsigned char conversion_buffer
[1024];
772 int conversion_buffer_size
= sizeof conversion_buffer
;
774 struct frame
*f
= (updating_frame
? updating_frame
: XFRAME (selected_frame
));
776 struct tty_display_info
*tty
= FRAME_TTY (f
);
778 turn_off_insert (tty
);
779 tty_hide_cursor (tty
);
781 /* Don't dare write in last column of bottom line, if Auto-Wrap,
782 since that would scroll the whole frame on some terminals. */
785 && curY (tty
) + 1 == FRAME_LINES (f
)
786 && (curX (tty
) + len
) == FRAME_COLS (f
))
793 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
795 terminal_coding
.mode
&= ~CODING_MODE_LAST_BLOCK
;
799 /* Identify a run of glyphs with the same face. */
800 int face_id
= string
->face_id
;
803 for (n
= 1; n
< len
; ++n
)
804 if (string
[n
].face_id
!= face_id
)
807 /* Turn appearance modes of the face of the run on. */
808 highlight_if_desired (tty
);
809 turn_on_face (f
, face_id
);
813 /* We use a fixed size (1024 bytes) of conversion buffer.
814 Usually it is sufficient, but if not, we just repeat the
816 produced
= encode_terminal_code (string
, conversion_buffer
,
817 n
, conversion_buffer_size
,
821 fwrite (conversion_buffer
, 1, produced
,
823 if (ferror (tty
->output
))
824 clearerr (tty
->output
);
826 fwrite (conversion_buffer
, 1, produced
,
834 /* Turn appearance modes off. */
835 turn_off_face (f
, face_id
);
836 turn_off_highlight (tty
);
839 /* We may have to output some codes to terminate the writing. */
840 if (CODING_REQUIRE_FLUSHING (&terminal_coding
))
842 terminal_coding
.mode
|= CODING_MODE_LAST_BLOCK
;
843 encode_coding (&terminal_coding
, "", conversion_buffer
,
844 0, conversion_buffer_size
);
845 if (terminal_coding
.produced
> 0)
847 fwrite (conversion_buffer
, 1, terminal_coding
.produced
,
849 if (ferror (tty
->output
))
850 clearerr (tty
->output
);
852 fwrite (conversion_buffer
, 1, terminal_coding
.produced
,
860 /* Insert LEN glyphs from START at the nominal cursor position.
862 If start is zero, insert blanks instead of a string at start */
865 insert_glyphs (start
, len
)
866 register struct glyph
*start
;
869 struct frame
*f
= (updating_frame
? updating_frame
: XFRAME (selected_frame
));
874 if (FRAME_DISPLAY (f
)->insert_glyphs_hook
)
875 (*FRAME_DISPLAY (f
)->insert_glyphs_hook
) (start
, len
);
878 /* An implementation of insert_glyphs for termcap frames. */
881 tty_insert_glyphs (struct glyph
*start
, int len
)
884 struct glyph
*glyph
= NULL
;
885 struct frame
*f
= (updating_frame
? updating_frame
: XFRAME (selected_frame
));
887 struct tty_display_info
*tty
= FRAME_TTY (f
);
889 if (tty
->TS_ins_multi_chars
)
891 buf
= tparam (tty
->TS_ins_multi_chars
, 0, 0, len
);
895 write_glyphs (start
, len
);
899 turn_on_insert (tty
);
901 /* The bit CODING_MODE_LAST_BLOCK should be set to 1 only at the tail. */
902 terminal_coding
.mode
&= ~CODING_MODE_LAST_BLOCK
;
905 int produced
, consumed
;
906 unsigned char conversion_buffer
[1024];
907 int conversion_buffer_size
= sizeof conversion_buffer
;
909 OUTPUT1_IF (tty
, tty
->TS_ins_char
);
912 conversion_buffer
[0] = SPACEGLYPH
;
917 highlight_if_desired (tty
);
918 turn_on_face (f
, start
->face_id
);
921 /* We must open sufficient space for a character which
922 occupies more than one column. */
923 while (len
&& CHAR_GLYPH_PADDING_P (*start
))
925 OUTPUT1_IF (tty
, tty
->TS_ins_char
);
930 /* This is the last glyph. */
931 terminal_coding
.mode
|= CODING_MODE_LAST_BLOCK
;
933 /* The size of conversion buffer (1024 bytes) is surely
934 sufficient for just one glyph. */
935 produced
= encode_terminal_code (glyph
, conversion_buffer
, 1,
936 conversion_buffer_size
, &consumed
);
941 fwrite (conversion_buffer
, 1, produced
,
943 if (ferror (tty
->output
))
944 clearerr (tty
->output
);
946 fwrite (conversion_buffer
, 1, produced
,
950 OUTPUT1_IF (tty
, tty
->TS_pad_inserted_char
);
953 turn_off_face (f
, glyph
->face_id
);
954 turn_off_highlight (tty
);
961 /* Delete N glyphs at the nominal cursor position. */
967 struct frame
*f
= (updating_frame
? updating_frame
: XFRAME (selected_frame
));
969 if (FRAME_DISPLAY (f
)->delete_glyphs_hook
)
970 (*FRAME_DISPLAY (f
)->delete_glyphs_hook
) (n
);
973 /* An implementation of delete_glyphs for termcap frames. */
976 tty_delete_glyphs (int n
)
980 struct frame
*f
= (updating_frame
? updating_frame
: XFRAME (selected_frame
));
982 struct tty_display_info
*tty
= FRAME_TTY (f
);
984 if (tty
->delete_in_insert_mode
)
986 turn_on_insert (tty
);
990 turn_off_insert (tty
);
991 OUTPUT_IF (tty
, tty
->TS_delete_mode
);
994 if (tty
->TS_del_multi_chars
)
996 buf
= tparam (tty
->TS_del_multi_chars
, 0, 0, n
);
1001 for (i
= 0; i
< n
; i
++)
1002 OUTPUT1 (tty
, tty
->TS_del_char
);
1003 if (!tty
->delete_in_insert_mode
)
1004 OUTPUT_IF (tty
, tty
->TS_end_delete_mode
);
1007 /* Insert N lines at vpos VPOS. If N is negative, delete -N lines. */
1010 ins_del_lines (vpos
, n
)
1013 struct frame
*f
= (updating_frame
? updating_frame
: XFRAME (selected_frame
));
1015 if (FRAME_DISPLAY (f
)->ins_del_lines_hook
)
1016 (*FRAME_DISPLAY (f
)->ins_del_lines_hook
) (vpos
, n
);
1019 /* An implementation of ins_del_lines for termcap frames. */
1022 tty_ins_del_lines (int vpos
, int n
)
1024 struct frame
*f
= (updating_frame
? updating_frame
: XFRAME (selected_frame
));
1026 struct tty_display_info
*tty
= FRAME_TTY (f
);
1027 char *multi
= n
> 0 ? tty
->TS_ins_multi_lines
: tty
->TS_del_multi_lines
;
1028 char *single
= n
> 0 ? tty
->TS_ins_line
: tty
->TS_del_line
;
1029 char *scroll
= n
> 0 ? tty
->TS_rev_scroll
: tty
->TS_fwd_scroll
;
1031 register int i
= n
> 0 ? n
: -n
;
1034 /* If the lines below the insertion are being pushed
1035 into the end of the window, this is the same as clearing;
1036 and we know the lines are already clear, since the matching
1037 deletion has already been done. So can ignore this. */
1038 /* If the lines below the deletion are blank lines coming
1039 out of the end of the window, don't bother,
1040 as there will be a matching inslines later that will flush them. */
1041 if (FRAME_SCROLL_REGION_OK (f
)
1042 && vpos
+ i
>= tty
->specified_window
)
1044 if (!FRAME_MEMORY_BELOW_FRAME (f
)
1045 && vpos
+ i
>= FRAME_LINES (f
))
1050 raw_cursor_to (vpos
, 0);
1051 background_highlight (tty
);
1052 buf
= tparam (multi
, 0, 0, i
);
1058 raw_cursor_to (vpos
, 0);
1059 background_highlight (tty
);
1061 OUTPUT (tty
, single
);
1062 if (tty
->TF_teleray
)
1067 set_scroll_region (vpos
, tty
->specified_window
);
1069 raw_cursor_to (tty
->specified_window
- 1, 0);
1071 raw_cursor_to (vpos
, 0);
1072 background_highlight (tty
);
1074 OUTPUTL (tty
, scroll
, tty
->specified_window
- vpos
);
1075 set_scroll_region (0, tty
->specified_window
);
1078 if (!FRAME_SCROLL_REGION_OK (f
)
1079 && FRAME_MEMORY_BELOW_FRAME (f
)
1082 cursor_to (FRAME_LINES (f
) + n
, 0);
1087 /* Compute cost of sending "str", in characters,
1088 not counting any line-dependent padding. */
1096 tputs (str
, 0, evalcost
);
1100 /* Compute cost of sending "str", in characters,
1101 counting any line-dependent padding at one line. */
1104 string_cost_one_line (str
)
1109 tputs (str
, 1, evalcost
);
1113 /* Compute per line amount of line-dependent padding,
1114 in tenths of characters. */
1122 tputs (str
, 0, evalcost
);
1125 tputs (str
, 10, evalcost
);
1130 /* char_ins_del_cost[n] is cost of inserting N characters.
1131 char_ins_del_cost[-n] is cost of deleting N characters.
1132 The length of this vector is based on max_frame_cols. */
1134 int *char_ins_del_vector
;
1136 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
1141 calculate_ins_del_char_costs (f
)
1144 struct tty_display_info
*tty
= FRAME_TTY (f
);
1145 int ins_startup_cost
, del_startup_cost
;
1146 int ins_cost_per_char
, del_cost_per_char
;
1150 if (tty
->TS_ins_multi_chars
)
1152 ins_cost_per_char
= 0;
1153 ins_startup_cost
= string_cost_one_line (tty
->TS_ins_multi_chars
);
1155 else if (tty
->TS_ins_char
|| tty
->TS_pad_inserted_char
1156 || (tty
->TS_insert_mode
&& tty
->TS_end_insert_mode
))
1158 ins_startup_cost
= (30 * (string_cost (tty
->TS_insert_mode
)
1159 + string_cost (tty
->TS_end_insert_mode
))) / 100;
1160 ins_cost_per_char
= (string_cost_one_line (tty
->TS_ins_char
)
1161 + string_cost_one_line (tty
->TS_pad_inserted_char
));
1165 ins_startup_cost
= 9999;
1166 ins_cost_per_char
= 0;
1169 if (tty
->TS_del_multi_chars
)
1171 del_cost_per_char
= 0;
1172 del_startup_cost
= string_cost_one_line (tty
->TS_del_multi_chars
);
1174 else if (tty
->TS_del_char
)
1176 del_startup_cost
= (string_cost (tty
->TS_delete_mode
)
1177 + string_cost (tty
->TS_end_delete_mode
));
1178 if (tty
->delete_in_insert_mode
)
1179 del_startup_cost
/= 2;
1180 del_cost_per_char
= string_cost_one_line (tty
->TS_del_char
);
1184 del_startup_cost
= 9999;
1185 del_cost_per_char
= 0;
1188 /* Delete costs are at negative offsets */
1189 p
= &char_ins_del_cost (f
)[0];
1190 for (i
= FRAME_COLS (f
); --i
>= 0;)
1191 *--p
= (del_startup_cost
+= del_cost_per_char
);
1193 /* Doing nothing is free */
1194 p
= &char_ins_del_cost (f
)[0];
1197 /* Insert costs are at positive offsets */
1198 for (i
= FRAME_COLS (f
); --i
>= 0;)
1199 *p
++ = (ins_startup_cost
+= ins_cost_per_char
);
1203 calculate_costs (frame
)
1206 FRAME_COST_BAUD_RATE (frame
) = baud_rate
;
1208 if (FRAME_TERMCAP_P (frame
))
1210 struct tty_display_info
*tty
= FRAME_TTY (frame
);
1211 register char *f
= (tty
->TS_set_scroll_region
1212 ? tty
->TS_set_scroll_region
1213 : tty
->TS_set_scroll_region_1
);
1215 FRAME_SCROLL_REGION_COST (frame
) = string_cost (f
);
1219 /* These variables are only used for terminal stuff. They are
1220 allocated once for the terminal frame of X-windows emacs, but not
1223 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1224 X turns off char_ins_del_ok. */
1226 max_frame_lines
= max (max_frame_lines
, FRAME_LINES (frame
));
1227 max_frame_cols
= max (max_frame_cols
, FRAME_COLS (frame
));
1229 if (char_ins_del_vector
!= 0)
1231 = (int *) xrealloc (char_ins_del_vector
,
1233 + 2 * max_frame_cols
* sizeof (int)));
1236 = (int *) xmalloc (sizeof (int)
1237 + 2 * max_frame_cols
* sizeof (int));
1239 bzero (char_ins_del_vector
, (sizeof (int)
1240 + 2 * max_frame_cols
* sizeof (int)));
1243 if (f
&& (!tty
->TS_ins_line
&& !tty
->TS_del_line
))
1244 do_line_insertion_deletion_costs (frame
,
1245 tty
->TS_rev_scroll
, tty
->TS_ins_multi_lines
,
1246 tty
->TS_fwd_scroll
, tty
->TS_del_multi_lines
,
1249 do_line_insertion_deletion_costs (frame
,
1250 tty
->TS_ins_line
, tty
->TS_ins_multi_lines
,
1251 tty
->TS_del_line
, tty
->TS_del_multi_lines
,
1254 calculate_ins_del_char_costs (frame
);
1256 /* Don't use TS_repeat if its padding is worse than sending the chars */
1257 if (tty
->TS_repeat
&& per_line_cost (tty
->TS_repeat
) * baud_rate
< 9000)
1258 tty
->RPov
= string_cost (tty
->TS_repeat
);
1260 tty
->RPov
= FRAME_COLS (frame
) * 2;
1262 cmcostinit (FRAME_TTY (frame
)); /* set up cursor motion costs */
1270 /* Termcap capability names that correspond directly to X keysyms.
1271 Some of these (marked "terminfo") aren't supplied by old-style
1272 (Berkeley) termcap entries. They're listed in X keysym order;
1273 except we put the keypad keys first, so that if they clash with
1274 other keys (as on the IBM PC keyboard) they get overridden.
1277 static struct fkey_table keys
[] =
1279 {"kh", "home"}, /* termcap */
1280 {"kl", "left"}, /* termcap */
1281 {"ku", "up"}, /* termcap */
1282 {"kr", "right"}, /* termcap */
1283 {"kd", "down"}, /* termcap */
1284 {"%8", "prior"}, /* terminfo */
1285 {"%5", "next"}, /* terminfo */
1286 {"@7", "end"}, /* terminfo */
1287 {"@1", "begin"}, /* terminfo */
1288 {"*6", "select"}, /* terminfo */
1289 {"%9", "print"}, /* terminfo */
1290 {"@4", "execute"}, /* terminfo --- actually the `command' key */
1292 * "insert" --- see below
1294 {"&8", "undo"}, /* terminfo */
1295 {"%0", "redo"}, /* terminfo */
1296 {"%7", "menu"}, /* terminfo --- actually the `options' key */
1297 {"@0", "find"}, /* terminfo */
1298 {"@2", "cancel"}, /* terminfo */
1299 {"%1", "help"}, /* terminfo */
1301 * "break" goes here, but can't be reliably intercepted with termcap
1303 {"&4", "reset"}, /* terminfo --- actually `restart' */
1305 * "system" and "user" --- no termcaps
1307 {"kE", "clearline"}, /* terminfo */
1308 {"kA", "insertline"}, /* terminfo */
1309 {"kL", "deleteline"}, /* terminfo */
1310 {"kI", "insertchar"}, /* terminfo */
1311 {"kD", "deletechar"}, /* terminfo */
1312 {"kB", "backtab"}, /* terminfo */
1314 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1316 {"@8", "kp-enter"}, /* terminfo */
1318 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1319 * "kp-multiply", "kp-add", "kp-separator",
1320 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1321 * --- no termcaps for any of these.
1323 {"K4", "kp-1"}, /* terminfo */
1325 * "kp-2" --- no termcap
1327 {"K5", "kp-3"}, /* terminfo */
1329 * "kp-4" --- no termcap
1331 {"K2", "kp-5"}, /* terminfo */
1333 * "kp-6" --- no termcap
1335 {"K1", "kp-7"}, /* terminfo */
1337 * "kp-8" --- no termcap
1339 {"K3", "kp-9"}, /* terminfo */
1341 * "kp-equal" --- no termcap
1354 static char **term_get_fkeys_arg
;
1355 static Lisp_Object
term_get_fkeys_1 ();
1357 /* Find the escape codes sent by the function keys for Vfunction_key_map.
1358 This function scans the termcap function key sequence entries, and
1359 adds entries to Vfunction_key_map for each function key it finds. */
1362 term_get_fkeys (address
)
1365 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1366 errors during the call. The only errors should be from Fdefine_key
1367 when given a key sequence containing an invalid prefix key. If the
1368 termcap defines function keys which use a prefix that is already bound
1369 to a command by the default bindings, we should silently ignore that
1370 function key specification, rather than giving the user an error and
1371 refusing to run at all on such a terminal. */
1373 extern Lisp_Object
Fidentity ();
1374 term_get_fkeys_arg
= address
;
1375 internal_condition_case (term_get_fkeys_1
, Qerror
, Fidentity
);
1383 char **address
= term_get_fkeys_arg
;
1385 /* This can happen if CANNOT_DUMP or with strange options. */
1387 Vfunction_key_map
= Fmake_sparse_keymap (Qnil
);
1389 for (i
= 0; i
< (sizeof (keys
)/sizeof (keys
[0])); i
++)
1391 char *sequence
= tgetstr (keys
[i
].cap
, address
);
1393 Fdefine_key (Vfunction_key_map
, build_string (sequence
),
1394 Fmake_vector (make_number (1),
1395 intern (keys
[i
].name
)));
1398 /* The uses of the "k0" capability are inconsistent; sometimes it
1399 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1400 We will attempt to politely accommodate both systems by testing for
1401 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1404 char *k_semi
= tgetstr ("k;", address
);
1405 char *k0
= tgetstr ("k0", address
);
1406 char *k0_name
= "f10";
1411 /* Define f0 first, so that f10 takes precedence in case the
1412 key sequences happens to be the same. */
1413 Fdefine_key (Vfunction_key_map
, build_string (k0
),
1414 Fmake_vector (make_number (1), intern ("f0")));
1415 Fdefine_key (Vfunction_key_map
, build_string (k_semi
),
1416 Fmake_vector (make_number (1), intern ("f10")));
1419 Fdefine_key (Vfunction_key_map
, build_string (k0
),
1420 Fmake_vector (make_number (1), intern (k0_name
)));
1423 /* Set up cookies for numbered function keys above f10. */
1425 char fcap
[3], fkey
[4];
1427 fcap
[0] = 'F'; fcap
[2] = '\0';
1428 for (i
= 11; i
< 64; i
++)
1431 fcap
[1] = '1' + i
- 11;
1433 fcap
[1] = 'A' + i
- 20;
1435 fcap
[1] = 'a' + i
- 46;
1438 char *sequence
= tgetstr (fcap
, address
);
1441 sprintf (fkey
, "f%d", i
);
1442 Fdefine_key (Vfunction_key_map
, build_string (sequence
),
1443 Fmake_vector (make_number (1),
1451 * Various mappings to try and get a better fit.
1454 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1455 if (!tgetstr (cap1, address)) \
1457 char *sequence = tgetstr (cap2, address); \
1459 Fdefine_key (Vfunction_key_map, build_string (sequence), \
1460 Fmake_vector (make_number (1), \
1464 /* if there's no key_next keycap, map key_npage to `next' keysym */
1465 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1466 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1467 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1468 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1469 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1470 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1471 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1473 /* IBM has their own non-standard dialect of terminfo.
1474 If the standard name isn't found, try the IBM name. */
1475 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1476 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1477 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1478 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1479 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1480 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1481 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1482 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1483 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1484 #undef CONDITIONAL_REASSIGN
1491 /***********************************************************************
1492 Character Display Information
1493 ***********************************************************************/
1495 static void append_glyph
P_ ((struct it
*));
1498 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1499 terminal frames if IT->glyph_row != NULL. IT->c is the character
1500 for which to produce glyphs; IT->face_id contains the character's
1501 face. Padding glyphs are appended if IT->c has a IT->pixel_width >
1508 struct glyph
*glyph
, *end
;
1511 xassert (it
->glyph_row
);
1512 glyph
= (it
->glyph_row
->glyphs
[it
->area
]
1513 + it
->glyph_row
->used
[it
->area
]);
1514 end
= it
->glyph_row
->glyphs
[1 + it
->area
];
1517 i
< it
->pixel_width
&& glyph
< end
;
1520 glyph
->type
= CHAR_GLYPH
;
1521 glyph
->pixel_width
= 1;
1522 glyph
->u
.ch
= it
->c
;
1523 glyph
->face_id
= it
->face_id
;
1524 glyph
->padding_p
= i
> 0;
1525 glyph
->charpos
= CHARPOS (it
->position
);
1526 glyph
->object
= it
->object
;
1528 ++it
->glyph_row
->used
[it
->area
];
1534 /* Produce glyphs for the display element described by IT. *IT
1535 specifies what we want to produce a glyph for (character, image, ...),
1536 and where in the glyph matrix we currently are (glyph row and hpos).
1537 produce_glyphs fills in output fields of *IT with information such as the
1538 pixel width and height of a character, and maybe output actual glyphs at
1539 the same time if IT->glyph_row is non-null. See the explanation of
1540 struct display_iterator in dispextern.h for an overview.
1542 produce_glyphs also stores the result of glyph width, ascent
1543 etc. computations in *IT.
1545 IT->glyph_row may be null, in which case produce_glyphs does not
1546 actually fill in the glyphs. This is used in the move_* functions
1547 in xdisp.c for text width and height computations.
1549 Callers usually don't call produce_glyphs directly;
1550 instead they use the macro PRODUCE_GLYPHS. */
1556 /* If a hook is installed, let it do the work. */
1557 xassert (it
->what
== IT_CHARACTER
1558 || it
->what
== IT_COMPOSITION
1559 || it
->what
== IT_IMAGE
1560 || it
->what
== IT_STRETCH
);
1562 /* Nothing but characters are supported on terminal frames. For a
1563 composition sequence, it->c is the first character of the
1565 xassert (it
->what
== IT_CHARACTER
1566 || it
->what
== IT_COMPOSITION
);
1568 if (it
->c
>= 040 && it
->c
< 0177)
1570 it
->pixel_width
= it
->nglyphs
= 1;
1574 else if (it
->c
== '\n')
1575 it
->pixel_width
= it
->nglyphs
= 0;
1576 else if (it
->c
== '\t')
1578 int absolute_x
= (it
->current_x
1579 + it
->continuation_lines_width
);
1581 = (((1 + absolute_x
+ it
->tab_width
- 1)
1586 /* If part of the TAB has been displayed on the previous line
1587 which is continued now, continuation_lines_width will have
1588 been incremented already by the part that fitted on the
1589 continued line. So, we will get the right number of spaces
1591 nspaces
= next_tab_x
- absolute_x
;
1598 it
->pixel_width
= it
->len
= 1;
1606 it
->pixel_width
= nspaces
;
1607 it
->nglyphs
= nspaces
;
1609 else if (SINGLE_BYTE_CHAR_P (it
->c
))
1611 /* Coming here means that it->c is from display table, thus we
1612 must send the code as is to the terminal. Although there's
1613 no way to know how many columns it occupies on a screen, it
1614 is a good assumption that a single byte code has 1-column
1616 it
->pixel_width
= it
->nglyphs
= 1;
1622 /* A multi-byte character. The display width is fixed for all
1623 characters of the set. Some of the glyphs may have to be
1624 ignored because they are already displayed in a continued
1626 int charset
= CHAR_CHARSET (it
->c
);
1628 it
->pixel_width
= CHARSET_WIDTH (charset
);
1629 it
->nglyphs
= it
->pixel_width
;
1635 /* Advance current_x by the pixel width as a convenience for
1637 if (it
->area
== TEXT_AREA
)
1638 it
->current_x
+= it
->pixel_width
;
1639 it
->ascent
= it
->max_ascent
= it
->phys_ascent
= it
->max_phys_ascent
= 0;
1640 it
->descent
= it
->max_descent
= it
->phys_descent
= it
->max_phys_descent
= 1;
1644 /* Get information about special display element WHAT in an
1645 environment described by IT. WHAT is one of IT_TRUNCATION or
1646 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1647 non-null glyph_row member. This function ensures that fields like
1648 face_id, c, len of IT are left untouched. */
1651 produce_special_glyphs (it
, what
)
1653 enum display_element_type what
;
1659 temp_it
.what
= IT_CHARACTER
;
1661 temp_it
.object
= make_number (0);
1662 bzero (&temp_it
.current
, sizeof temp_it
.current
);
1664 if (what
== IT_CONTINUATION
)
1666 /* Continuation glyph. */
1668 && INTEGERP (DISP_CONTINUE_GLYPH (it
->dp
))
1669 && GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (it
->dp
))))
1671 temp_it
.c
= FAST_GLYPH_CHAR (XINT (DISP_CONTINUE_GLYPH (it
->dp
)));
1672 temp_it
.len
= CHAR_BYTES (temp_it
.c
);
1677 produce_glyphs (&temp_it
);
1678 it
->pixel_width
= temp_it
.pixel_width
;
1679 it
->nglyphs
= temp_it
.pixel_width
;
1681 else if (what
== IT_TRUNCATION
)
1683 /* Truncation glyph. */
1685 && INTEGERP (DISP_TRUNC_GLYPH (it
->dp
))
1686 && GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (it
->dp
))))
1688 temp_it
.c
= FAST_GLYPH_CHAR (XINT (DISP_TRUNC_GLYPH (it
->dp
)));
1689 temp_it
.len
= CHAR_BYTES (temp_it
.c
);
1694 produce_glyphs (&temp_it
);
1695 it
->pixel_width
= temp_it
.pixel_width
;
1696 it
->nglyphs
= temp_it
.pixel_width
;
1704 /***********************************************************************
1706 ***********************************************************************/
1708 /* Value is non-zero if attribute ATTR may be used. ATTR should be
1709 one of the enumerators from enum no_color_bit, or a bit set built
1710 from them. Some display attributes may not be used together with
1711 color; the termcap capability `NC' specifies which ones. */
1713 #define MAY_USE_WITH_COLORS_P(tty, ATTR) \
1714 (tty->TN_max_colors > 0 \
1715 ? (tty->TN_no_color_video & (ATTR)) == 0 \
1718 /* Turn appearances of face FACE_ID on tty frame F on. */
1721 turn_on_face (f
, face_id
)
1725 struct face
*face
= FACE_FROM_ID (f
, face_id
);
1726 long fg
= face
->foreground
;
1727 long bg
= face
->background
;
1728 struct tty_display_info
*tty
= FRAME_TTY (f
);
1730 /* Do this first because TS_end_standout_mode may be the same
1731 as TS_exit_attribute_mode, which turns all appearances off. */
1732 if (MAY_USE_WITH_COLORS_P (tty
, NC_REVERSE
))
1734 if (tty
->TN_max_colors
> 0)
1736 if (fg
>= 0 && bg
>= 0)
1738 /* If the terminal supports colors, we can set them
1739 below without using reverse video. The face's fg
1740 and bg colors are set as they should appear on
1741 the screen, i.e. they take the inverse-video'ness
1742 of the face already into account. */
1744 else if (inverse_video
)
1746 if (fg
== FACE_TTY_DEFAULT_FG_COLOR
1747 || bg
== FACE_TTY_DEFAULT_BG_COLOR
)
1748 toggle_highlight (tty
);
1752 if (fg
== FACE_TTY_DEFAULT_BG_COLOR
1753 || bg
== FACE_TTY_DEFAULT_FG_COLOR
)
1754 toggle_highlight (tty
);
1759 /* If we can't display colors, use reverse video
1760 if the face specifies that. */
1763 if (fg
== FACE_TTY_DEFAULT_FG_COLOR
1764 || bg
== FACE_TTY_DEFAULT_BG_COLOR
)
1765 toggle_highlight (tty
);
1769 if (fg
== FACE_TTY_DEFAULT_BG_COLOR
1770 || bg
== FACE_TTY_DEFAULT_FG_COLOR
)
1771 toggle_highlight (tty
);
1776 if (face
->tty_bold_p
)
1778 if (MAY_USE_WITH_COLORS_P (tty
, NC_BOLD
))
1779 OUTPUT1_IF (tty
, tty
->TS_enter_bold_mode
);
1781 else if (face
->tty_dim_p
)
1782 if (MAY_USE_WITH_COLORS_P (tty
, NC_DIM
))
1783 OUTPUT1_IF (tty
, tty
->TS_enter_dim_mode
);
1785 /* Alternate charset and blinking not yet used. */
1786 if (face
->tty_alt_charset_p
1787 && MAY_USE_WITH_COLORS_P (tty
, NC_ALT_CHARSET
))
1788 OUTPUT1_IF (tty
, tty
->TS_enter_alt_charset_mode
);
1790 if (face
->tty_blinking_p
1791 && MAY_USE_WITH_COLORS_P (tty
, NC_BLINK
))
1792 OUTPUT1_IF (tty
, tty
->TS_enter_blink_mode
);
1794 if (face
->tty_underline_p
&& MAY_USE_WITH_COLORS_P (tty
, NC_UNDERLINE
))
1795 OUTPUT1_IF (tty
, tty
->TS_enter_underline_mode
);
1797 if (tty
->TN_max_colors
> 0)
1801 if (fg
>= 0 && tty
->TS_set_foreground
)
1803 p
= tparam (tty
->TS_set_foreground
, NULL
, 0, (int) fg
);
1808 if (bg
>= 0 && tty
->TS_set_background
)
1810 p
= tparam (tty
->TS_set_background
, NULL
, 0, (int) bg
);
1818 /* Turn off appearances of face FACE_ID on tty frame F. */
1821 turn_off_face (f
, face_id
)
1825 struct face
*face
= FACE_FROM_ID (f
, face_id
);
1826 struct tty_display_info
*tty
= FRAME_TTY (f
);
1828 xassert (face
!= NULL
);
1830 if (tty
->TS_exit_attribute_mode
)
1832 /* Capability "me" will turn off appearance modes double-bright,
1833 half-bright, reverse-video, standout, underline. It may or
1834 may not turn off alt-char-mode. */
1835 if (face
->tty_bold_p
1837 || face
->tty_reverse_p
1838 || face
->tty_alt_charset_p
1839 || face
->tty_blinking_p
1840 || face
->tty_underline_p
)
1842 OUTPUT1_IF (tty
, tty
->TS_exit_attribute_mode
);
1843 if (strcmp (tty
->TS_exit_attribute_mode
, tty
->TS_end_standout_mode
) == 0)
1844 tty
->standout_mode
= 0;
1847 if (face
->tty_alt_charset_p
)
1848 OUTPUT_IF (tty
, tty
->TS_exit_alt_charset_mode
);
1852 /* If we don't have "me" we can only have those appearances
1853 that have exit sequences defined. */
1854 if (face
->tty_alt_charset_p
)
1855 OUTPUT_IF (tty
, tty
->TS_exit_alt_charset_mode
);
1857 if (face
->tty_underline_p
)
1858 OUTPUT_IF (tty
, tty
->TS_exit_underline_mode
);
1861 /* Switch back to default colors. */
1862 if (tty
->TN_max_colors
> 0
1863 && ((face
->foreground
!= FACE_TTY_DEFAULT_COLOR
1864 && face
->foreground
!= FACE_TTY_DEFAULT_FG_COLOR
)
1865 || (face
->background
!= FACE_TTY_DEFAULT_COLOR
1866 && face
->background
!= FACE_TTY_DEFAULT_BG_COLOR
)))
1867 OUTPUT1_IF (tty
, tty
->TS_orig_pair
);
1871 /* Return non-zero if the terminal on frame F supports all of the
1872 capabilities in CAPS simultaneously, with foreground and background
1873 colors FG and BG. */
1876 tty_capable_p (tty
, caps
, fg
, bg
)
1877 struct tty_display_info
*tty
;
1879 unsigned long fg
, bg
;
1881 #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
1882 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
1885 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_INVERSE
, tty
->TS_standout_mode
, NC_REVERSE
);
1886 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_UNDERLINE
, tty
->TS_enter_underline_mode
, NC_UNDERLINE
);
1887 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_BOLD
, tty
->TS_enter_bold_mode
, NC_BOLD
);
1888 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_DIM
, tty
->TS_enter_dim_mode
, NC_DIM
);
1889 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_BLINK
, tty
->TS_enter_blink_mode
, NC_BLINK
);
1890 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_ALT_CHARSET
, tty
->TS_enter_alt_charset_mode
, NC_ALT_CHARSET
);
1896 /* Return the tty display object specified by DISPLAY. DISPLAY may be
1897 a frame, a string, or nil for the display device of the current
1900 static struct display
*
1901 get_tty_display (Lisp_Object display
)
1906 display
= selected_frame
;
1908 if (! FRAMEP (display
) && ! STRINGP (display
))
1911 /* The initial frame does not support colors. */
1912 if (FRAMEP (display
) && FRAME_INITIAL_P (XFRAME (display
)))
1915 if (FRAMEP (display
))
1917 if (! FRAME_TERMCAP_P (XFRAME (display
)))
1918 #if 0 /* XXX We need a predicate as the first argument; find one. */
1919 wrong_type_argument ("Not a termcap frame", display
);
1920 #else /* Until we fix the wrong_type_argument call above, simply throw
1922 error ("DISPLAY is not a termcap frame");
1925 d
= FRAME_DISPLAY (XFRAME (display
));
1927 else if (STRINGP (display
))
1929 char *name
= (char *) alloca (SBYTES (display
) + 1);
1930 strncpy (name
, SDATA (display
), SBYTES (display
));
1931 name
[SBYTES (display
)] = 0;
1933 d
= get_named_tty_display (name
);
1936 error ("There is no tty display on %s", name
);
1943 /* Return non-zero if the terminal is capable to display colors. */
1945 DEFUN ("tty-display-color-p", Ftty_display_color_p
, Stty_display_color_p
,
1947 doc
: /* Return non-nil if TTY can display colors on DISPLAY. */)
1949 Lisp_Object display
;
1951 struct display
*d
= get_tty_display (display
);
1955 return d
->display_info
.tty
->TN_max_colors
> 0 ? Qt
: Qnil
;
1958 /* Return the number of supported colors. */
1959 DEFUN ("tty-display-color-cells", Ftty_display_color_cells
,
1960 Stty_display_color_cells
, 0, 1, 0,
1961 doc
: /* Return the number of colors supported by TTY on DISPLAY. */)
1963 Lisp_Object display
;
1965 struct display
*d
= get_tty_display (display
);
1969 return make_number (d
->display_info
.tty
->TN_max_colors
);
1974 /* Save or restore the default color-related capabilities of this
1977 tty_default_color_capabilities (struct tty_display_info
*tty
, int save
)
1980 *default_orig_pair
, *default_set_foreground
, *default_set_background
;
1981 static int default_max_colors
, default_max_pairs
, default_no_color_video
;
1985 if (default_orig_pair
)
1986 xfree (default_orig_pair
);
1987 default_orig_pair
= tty
->TS_orig_pair
? xstrdup (tty
->TS_orig_pair
) : NULL
;
1989 if (default_set_foreground
)
1990 xfree (default_set_foreground
);
1991 default_set_foreground
= tty
->TS_set_foreground
? xstrdup (tty
->TS_set_foreground
)
1994 if (default_set_background
)
1995 xfree (default_set_background
);
1996 default_set_background
= tty
->TS_set_background
? xstrdup (tty
->TS_set_background
)
1999 default_max_colors
= tty
->TN_max_colors
;
2000 default_max_pairs
= tty
->TN_max_pairs
;
2001 default_no_color_video
= tty
->TN_no_color_video
;
2005 tty
->TS_orig_pair
= default_orig_pair
;
2006 tty
->TS_set_foreground
= default_set_foreground
;
2007 tty
->TS_set_background
= default_set_background
;
2008 tty
->TN_max_colors
= default_max_colors
;
2009 tty
->TN_max_pairs
= default_max_pairs
;
2010 tty
->TN_no_color_video
= default_no_color_video
;
2014 /* Setup one of the standard tty color schemes according to MODE.
2015 MODE's value is generally the number of colors which we want to
2016 support; zero means set up for the default capabilities, the ones
2017 we saw at term_init time; -1 means turn off color support. */
2019 tty_setup_colors (struct tty_display_info
*tty
, int mode
)
2021 /* Canonicalize all negative values of MODE. */
2027 case -1: /* no colors at all */
2028 tty
->TN_max_colors
= 0;
2029 tty
->TN_max_pairs
= 0;
2030 tty
->TN_no_color_video
= 0;
2031 tty
->TS_set_foreground
= tty
->TS_set_background
= tty
->TS_orig_pair
= NULL
;
2033 case 0: /* default colors, if any */
2035 tty_default_color_capabilities (tty
, 0);
2037 case 8: /* 8 standard ANSI colors */
2038 tty
->TS_orig_pair
= "\033[0m";
2040 tty
->TS_set_foreground
= "\033[3%p1%dm";
2041 tty
->TS_set_background
= "\033[4%p1%dm";
2043 tty
->TS_set_foreground
= "\033[3%dm";
2044 tty
->TS_set_background
= "\033[4%dm";
2046 tty
->TN_max_colors
= 8;
2047 tty
->TN_max_pairs
= 64;
2048 tty
->TN_no_color_video
= 0;
2054 set_tty_color_mode (f
, val
)
2058 Lisp_Object color_mode_spec
, current_mode_spec
;
2059 Lisp_Object color_mode
, current_mode
;
2061 extern Lisp_Object Qtty_color_mode
;
2062 Lisp_Object tty_color_mode_alist
;
2064 tty_color_mode_alist
= Fintern_soft (build_string ("tty-color-mode-alist"),
2071 if (NILP (tty_color_mode_alist
))
2072 color_mode_spec
= Qnil
;
2074 color_mode_spec
= Fassq (val
, XSYMBOL (tty_color_mode_alist
)->value
);
2076 if (CONSP (color_mode_spec
))
2077 color_mode
= XCDR (color_mode_spec
);
2082 current_mode_spec
= assq_no_quit (Qtty_color_mode
, f
->param_alist
);
2084 if (CONSP (current_mode_spec
))
2085 current_mode
= XCDR (current_mode_spec
);
2087 current_mode
= Qnil
;
2088 if (INTEGERP (color_mode
))
2089 mode
= XINT (color_mode
);
2091 mode
= 0; /* meaning default */
2092 if (INTEGERP (current_mode
))
2093 old_mode
= XINT (current_mode
);
2097 if (mode
!= old_mode
)
2099 tty_setup_colors (FRAME_TTY (f
), mode
);
2100 /* This recomputes all the faces given the new color
2102 call0 (intern ("tty-set-up-initial-frame-faces"));
2107 #endif /* !WINDOWSNT */
2111 /* Return the termcap display with the given name. If NAME is null,
2112 return the display corresponding to our controlling terminal.
2114 Returns NULL if the named terminal device is not opened. */
2117 get_named_tty_display (name
)
2122 for (d
= display_list
; d
; d
= d
->next_display
) {
2123 if (d
->type
== output_termcap
2124 && ((d
->display_info
.tty
->name
== 0 && name
== 0)
2125 || (name
&& d
->display_info
.tty
->name
2126 && !strcmp (d
->display_info
.tty
->name
, name
))))
2135 DEFUN ("frame-tty-name", Fframe_tty_name
, Sframe_tty_name
, 0, 1, 0,
2136 doc
: /* Return the name of the TTY device that FRAME is displayed on. */)
2144 f
= XFRAME (selected_frame
);
2148 CHECK_LIVE_FRAME (frame
);
2152 if (f
->output_method
!= output_termcap
)
2153 wrong_type_argument (Qframe_tty_name
, frame
);
2155 if (FRAME_TTY (f
)->name
)
2156 return build_string (FRAME_TTY (f
)->name
);
2161 DEFUN ("frame-tty-type", Fframe_tty_type
, Sframe_tty_type
, 0, 1, 0,
2162 doc
: /* Return the type of the TTY device that FRAME is displayed on. */)
2170 f
= XFRAME (selected_frame
);
2174 CHECK_LIVE_FRAME (frame
);
2178 if (f
->output_method
!= output_termcap
)
2179 wrong_type_argument (Qframe_tty_type
, frame
);
2181 if (FRAME_TTY (f
)->type
)
2182 return build_string (FRAME_TTY (f
)->type
);
2188 /***********************************************************************
2190 ***********************************************************************/
2192 /* Create the bootstrap display device for the initial frame.
2193 Returns a display of type output_initial. */
2196 init_initial_display (void)
2198 if (initialized
|| display_list
|| tty_list
)
2201 initial_display
= create_display ();
2202 initial_display
->type
= output_initial
;
2204 initial_display
->delete_display_hook
= &delete_initial_display
;
2205 /* All other hooks are NULL. */
2207 return initial_display
;
2210 /* Deletes the bootstrap display device.
2211 Called through delete_display_hook. */
2214 delete_initial_display (struct display
*display
)
2216 if (display
!= initial_display
)
2219 delete_display (display
);
2220 initial_display
= NULL
;
2223 /* Create a termcap display on the tty device with the given name and
2226 If NAME is NULL, then use the controlling tty, i.e., stdin/stdout.
2227 Otherwise NAME should be a path to the tty device file,
2230 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
2232 If MUST_SUCCEED is true, then all errors are fatal. */
2235 term_init (char *name
, char *terminal_type
, int must_succeed
)
2238 char **address
= &area
;
2239 char *buffer
= NULL
;
2240 int buffer_size
= 4096;
2243 struct tty_display_info
*tty
;
2244 struct display
*display
;
2246 static void maybe_fatal();
2249 maybe_fatal (must_succeed
, 0, 0,
2250 "Unknown terminal type",
2251 "Unknown terminal type");
2253 display
= get_named_tty_display (name
);
2256 if (! display
->display_info
.tty
->input
)
2257 error ("%s already has a suspended frame on it, can't open it twice", name
);
2261 display
= create_display ();
2262 tty
= (struct tty_display_info
*) xmalloc (sizeof (struct tty_display_info
));
2263 bzero (tty
, sizeof (struct tty_display_info
));
2264 tty
->next
= tty_list
;
2267 display
->type
= output_termcap
;
2268 display
->display_info
.tty
= tty
;
2269 tty
->display
= display
;
2271 tty
->Wcm
= (struct cm
*) xmalloc (sizeof (struct cm
));
2274 display
->rif
= 0; /* ttys don't support window-based redisplay. */
2276 display
->cursor_to_hook
= &tty_cursor_to
;
2277 display
->raw_cursor_to_hook
= &tty_raw_cursor_to
;
2279 display
->clear_to_end_hook
= &tty_clear_to_end
;
2280 display
->clear_frame_hook
= &tty_clear_frame
;
2281 display
->clear_end_of_line_hook
= &tty_clear_end_of_line
;
2283 display
->ins_del_lines_hook
= &tty_ins_del_lines
;
2285 display
->insert_glyphs_hook
= &tty_insert_glyphs
;
2286 display
->write_glyphs_hook
= &tty_write_glyphs
;
2287 display
->delete_glyphs_hook
= &tty_delete_glyphs
;
2289 display
->ring_bell_hook
= &tty_ring_bell
;
2291 display
->reset_terminal_modes_hook
= &tty_reset_terminal_modes
;
2292 display
->set_terminal_modes_hook
= &tty_set_terminal_modes
;
2293 display
->update_begin_hook
= 0; /* Not needed. */
2294 display
->update_end_hook
= &tty_update_end
;
2295 display
->set_terminal_window_hook
= &tty_set_terminal_window
;
2297 display
->mouse_position_hook
= 0; /* Not needed. */
2298 display
->frame_rehighlight_hook
= 0; /* Not needed. */
2299 display
->frame_raise_lower_hook
= 0; /* Not needed. */
2301 display
->set_vertical_scroll_bar_hook
= 0; /* Not needed. */
2302 display
->condemn_scroll_bars_hook
= 0; /* Not needed. */
2303 display
->redeem_scroll_bar_hook
= 0; /* Not needed. */
2304 display
->judge_scroll_bars_hook
= 0; /* Not needed. */
2306 display
->read_socket_hook
= &tty_read_avail_input
; /* keyboard.c */
2307 display
->frame_up_to_date_hook
= 0; /* Not needed. */
2309 display
->delete_frame_hook
= &delete_tty_output
;
2310 display
->delete_display_hook
= &delete_tty
;
2317 #ifdef O_IGNORE_CTTY
2318 /* Open the terminal device. Don't recognize it as our
2319 controlling terminal, and don't make it the controlling tty
2320 if we don't have one at the moment. */
2321 fd
= emacs_open (name
, O_RDWR
| O_IGNORE_CTTY
| O_NOCTTY
, 0);
2323 /* Alas, O_IGNORE_CTTY is a GNU extension that is only defined
2324 on Hurd. On other systems, we need to dissociate ourselves
2325 from the controlling tty when we want to open a frame on the
2326 same terminal. The function setsid should be used for this,
2327 but it didn't work for me. */
2329 fd
= emacs_open (name
, O_RDWR
| O_NOCTTY
, 0);
2332 /* Drop our controlling tty if it is the same device. */
2333 if (ioctl (fd
, TIOCNOTTY
, 0) != -1)
2335 no_controlling_tty
= 1;
2338 #endif /* O_IGNORE_CTTY */
2342 delete_tty (display
);
2343 error ("Could not open file: %s", name
);
2348 error ("Not a tty device: %s", name
);
2351 file
= fdopen (fd
, "w+");
2352 tty
->name
= xstrdup (name
);
2358 if (no_controlling_tty
)
2360 /* Opening a frame on stdout is unsafe if we have
2361 disconnected our controlling terminal. */
2362 error ("There is no controlling terminal any more");
2366 tty
->output
= stdout
;
2369 tty
->type
= xstrdup (terminal_type
);
2371 add_keyboard_wait_descriptor (fileno (tty
->input
));
2374 initialize_w32_display ();
2378 area
= (char *) xmalloc (2044);
2380 FrameRows (tty
) = FRAME_LINES (f
); /* XXX */
2381 FrameCols (tty
) = FRAME_COLS (f
); /* XXX */
2382 tty
->specified_window
= FRAME_LINES (f
); /* XXX */
2384 tty
->display
->delete_in_insert_mode
= 1;
2387 display
->scroll_region_ok
= 0;
2389 /* Seems to insert lines when it's not supposed to, messing
2390 up the display. In doing a trace, it didn't seem to be
2391 called much, so I don't think we're losing anything by
2393 display
->line_ins_del_ok
= 0;
2394 display
->char_ins_del_ok
= 1;
2398 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 0; /* XXX */
2399 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_none
; /* XXX */
2400 TN_max_colors
= 16; /* Required to be non-zero for tty-display-color-p */
2403 #else /* not WINDOWSNT */
2407 buffer
= (char *) xmalloc (buffer_size
);
2408 status
= tgetent (buffer
, terminal_type
);
2412 maybe_fatal (must_succeed
, buffer
, display
,
2413 "Cannot open terminfo database file",
2414 "Cannot open terminfo database file");
2416 maybe_fatal (must_succeed
, buffer
, display
,
2417 "Cannot open termcap database file",
2418 "Cannot open termcap database file");
2424 maybe_fatal (must_succeed
, buffer
, display
,
2425 "Terminal type %s is not defined",
2426 "Terminal type %s is not defined.\n\
2427 If that is not the actual type of terminal you have,\n\
2428 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2429 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2430 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
2433 maybe_fatal (must_succeed
, buffer
, display
,
2434 "Terminal type %s is not defined",
2435 "Terminal type %s is not defined.\n\
2436 If that is not the actual type of terminal you have,\n\
2437 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2438 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2439 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
2445 if (strlen (buffer
) >= buffer_size
)
2447 buffer_size
= strlen (buffer
);
2449 area
= (char *) xmalloc (buffer_size
);
2451 tty
->TS_ins_line
= tgetstr ("al", address
);
2452 tty
->TS_ins_multi_lines
= tgetstr ("AL", address
);
2453 tty
->TS_bell
= tgetstr ("bl", address
);
2454 BackTab (tty
) = tgetstr ("bt", address
);
2455 tty
->TS_clr_to_bottom
= tgetstr ("cd", address
);
2456 tty
->TS_clr_line
= tgetstr ("ce", address
);
2457 tty
->TS_clr_frame
= tgetstr ("cl", address
);
2458 ColPosition (tty
) = NULL
; /* tgetstr ("ch", address); */
2459 AbsPosition (tty
) = tgetstr ("cm", address
);
2460 CR (tty
) = tgetstr ("cr", address
);
2461 tty
->TS_set_scroll_region
= tgetstr ("cs", address
);
2462 tty
->TS_set_scroll_region_1
= tgetstr ("cS", address
);
2463 RowPosition (tty
) = tgetstr ("cv", address
);
2464 tty
->TS_del_char
= tgetstr ("dc", address
);
2465 tty
->TS_del_multi_chars
= tgetstr ("DC", address
);
2466 tty
->TS_del_line
= tgetstr ("dl", address
);
2467 tty
->TS_del_multi_lines
= tgetstr ("DL", address
);
2468 tty
->TS_delete_mode
= tgetstr ("dm", address
);
2469 tty
->TS_end_delete_mode
= tgetstr ("ed", address
);
2470 tty
->TS_end_insert_mode
= tgetstr ("ei", address
);
2471 Home (tty
) = tgetstr ("ho", address
);
2472 tty
->TS_ins_char
= tgetstr ("ic", address
);
2473 tty
->TS_ins_multi_chars
= tgetstr ("IC", address
);
2474 tty
->TS_insert_mode
= tgetstr ("im", address
);
2475 tty
->TS_pad_inserted_char
= tgetstr ("ip", address
);
2476 tty
->TS_end_keypad_mode
= tgetstr ("ke", address
);
2477 tty
->TS_keypad_mode
= tgetstr ("ks", address
);
2478 LastLine (tty
) = tgetstr ("ll", address
);
2479 Right (tty
) = tgetstr ("nd", address
);
2480 Down (tty
) = tgetstr ("do", address
);
2482 Down (tty
) = tgetstr ("nl", address
); /* Obsolete name for "do" */
2484 /* VMS puts a carriage return before each linefeed,
2485 so it is not safe to use linefeeds. */
2486 if (Down (tty
) && Down (tty
)[0] == '\n' && Down (tty
)[1] == '\0')
2489 if (tgetflag ("bs"))
2490 Left (tty
) = "\b"; /* can't possibly be longer! */
2491 else /* (Actually, "bs" is obsolete...) */
2492 Left (tty
) = tgetstr ("le", address
);
2494 Left (tty
) = tgetstr ("bc", address
); /* Obsolete name for "le" */
2495 tty
->TS_pad_char
= tgetstr ("pc", address
);
2496 tty
->TS_repeat
= tgetstr ("rp", address
);
2497 tty
->TS_end_standout_mode
= tgetstr ("se", address
);
2498 tty
->TS_fwd_scroll
= tgetstr ("sf", address
);
2499 tty
->TS_standout_mode
= tgetstr ("so", address
);
2500 tty
->TS_rev_scroll
= tgetstr ("sr", address
);
2501 tty
->Wcm
->cm_tab
= tgetstr ("ta", address
);
2502 tty
->TS_end_termcap_modes
= tgetstr ("te", address
);
2503 tty
->TS_termcap_modes
= tgetstr ("ti", address
);
2504 Up (tty
) = tgetstr ("up", address
);
2505 tty
->TS_visible_bell
= tgetstr ("vb", address
);
2506 tty
->TS_cursor_normal
= tgetstr ("ve", address
);
2507 tty
->TS_cursor_visible
= tgetstr ("vs", address
);
2508 tty
->TS_cursor_invisible
= tgetstr ("vi", address
);
2509 tty
->TS_set_window
= tgetstr ("wi", address
);
2511 tty
->TS_enter_underline_mode
= tgetstr ("us", address
);
2512 tty
->TS_exit_underline_mode
= tgetstr ("ue", address
);
2513 tty
->TS_enter_bold_mode
= tgetstr ("md", address
);
2514 tty
->TS_enter_dim_mode
= tgetstr ("mh", address
);
2515 tty
->TS_enter_blink_mode
= tgetstr ("mb", address
);
2516 tty
->TS_enter_reverse_mode
= tgetstr ("mr", address
);
2517 tty
->TS_enter_alt_charset_mode
= tgetstr ("as", address
);
2518 tty
->TS_exit_alt_charset_mode
= tgetstr ("ae", address
);
2519 tty
->TS_exit_attribute_mode
= tgetstr ("me", address
);
2521 MultiUp (tty
) = tgetstr ("UP", address
);
2522 MultiDown (tty
) = tgetstr ("DO", address
);
2523 MultiLeft (tty
) = tgetstr ("LE", address
);
2524 MultiRight (tty
) = tgetstr ("RI", address
);
2526 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
2527 color because we can't switch back to the default foreground and
2529 tty
->TS_orig_pair
= tgetstr ("op", address
);
2530 if (tty
->TS_orig_pair
)
2532 tty
->TS_set_foreground
= tgetstr ("AF", address
);
2533 tty
->TS_set_background
= tgetstr ("AB", address
);
2534 if (!tty
->TS_set_foreground
)
2537 tty
->TS_set_foreground
= tgetstr ("Sf", address
);
2538 tty
->TS_set_background
= tgetstr ("Sb", address
);
2541 tty
->TN_max_colors
= tgetnum ("Co");
2542 tty
->TN_max_pairs
= tgetnum ("pa");
2544 tty
->TN_no_color_video
= tgetnum ("NC");
2545 if (tty
->TN_no_color_video
== -1)
2546 tty
->TN_no_color_video
= 0;
2549 tty_default_color_capabilities (tty
, 1);
2551 MagicWrap (tty
) = tgetflag ("xn");
2552 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
2553 the former flag imply the latter. */
2554 AutoWrap (tty
) = MagicWrap (tty
) || tgetflag ("am");
2555 display
->memory_below_frame
= tgetflag ("db");
2556 tty
->TF_hazeltine
= tgetflag ("hz");
2557 display
->must_write_spaces
= tgetflag ("in");
2558 tty
->meta_key
= tgetflag ("km") || tgetflag ("MT");
2559 tty
->TF_insmode_motion
= tgetflag ("mi");
2560 tty
->TF_standout_motion
= tgetflag ("ms");
2561 tty
->TF_underscore
= tgetflag ("ul");
2562 tty
->TF_teleray
= tgetflag ("xt");
2564 term_get_fkeys (address
);
2566 /* Get frame size from system, or else from termcap. */
2569 get_tty_size (fileno (tty
->input
), &width
, &height
);
2570 FrameCols (tty
) = width
;
2571 FrameRows (tty
) = height
;
2574 if (FrameCols (tty
) <= 0)
2575 FrameCols (tty
) = tgetnum ("co");
2576 if (FrameRows (tty
) <= 0)
2577 FrameRows (tty
) = tgetnum ("li");
2579 if (FrameRows (tty
) < 3 || FrameCols (tty
) < 3)
2580 maybe_fatal (must_succeed
, NULL
, display
,
2581 "Screen size %dx%d is too small"
2582 "Screen size %dx%d is too small",
2583 FrameCols (tty
), FrameRows (tty
));
2585 #if 0 /* This is not used anywhere. */
2586 tty
->display
->min_padding_speed
= tgetnum ("pb");
2589 TabWidth (tty
) = tgetnum ("tw");
2592 /* These capabilities commonly use ^J.
2593 I don't know why, but sending them on VMS does not work;
2594 it causes following spaces to be lost, sometimes.
2595 For now, the simplest fix is to avoid using these capabilities ever. */
2596 if (Down (tty
) && Down (tty
)[0] == '\n')
2601 tty
->TS_bell
= "\07";
2603 if (!tty
->TS_fwd_scroll
)
2604 tty
->TS_fwd_scroll
= Down (tty
);
2606 PC
= tty
->TS_pad_char
? *tty
->TS_pad_char
: 0;
2608 if (TabWidth (tty
) < 0)
2611 /* Turned off since /etc/termcap seems to have :ta= for most terminals
2612 and newer termcap doc does not seem to say there is a default.
2613 if (!tty->Wcm->cm_tab)
2614 tty->Wcm->cm_tab = "\t";
2617 /* We don't support standout modes that use `magic cookies', so
2618 turn off any that do. */
2619 if (tty
->TS_standout_mode
&& tgetnum ("sg") >= 0)
2621 tty
->TS_standout_mode
= 0;
2622 tty
->TS_end_standout_mode
= 0;
2624 if (tty
->TS_enter_underline_mode
&& tgetnum ("ug") >= 0)
2626 tty
->TS_enter_underline_mode
= 0;
2627 tty
->TS_exit_underline_mode
= 0;
2630 /* If there's no standout mode, try to use underlining instead. */
2631 if (tty
->TS_standout_mode
== 0)
2633 tty
->TS_standout_mode
= tty
->TS_enter_underline_mode
;
2634 tty
->TS_end_standout_mode
= tty
->TS_exit_underline_mode
;
2637 /* If no `se' string, try using a `me' string instead.
2638 If that fails, we can't use standout mode at all. */
2639 if (tty
->TS_end_standout_mode
== 0)
2641 char *s
= tgetstr ("me", address
);
2643 tty
->TS_end_standout_mode
= s
;
2645 tty
->TS_standout_mode
= 0;
2648 if (tty
->TF_teleray
)
2650 tty
->Wcm
->cm_tab
= 0;
2651 /* We can't support standout mode, because it uses magic cookies. */
2652 tty
->TS_standout_mode
= 0;
2653 /* But that means we cannot rely on ^M to go to column zero! */
2655 /* LF can't be trusted either -- can alter hpos */
2656 /* if move at column 0 thru a line with TS_standout_mode */
2660 /* Special handling for certain terminal types known to need it */
2662 if (!strcmp (terminal_type
, "supdup"))
2664 display
->memory_below_frame
= 1;
2665 tty
->Wcm
->cm_losewrap
= 1;
2667 if (!strncmp (terminal_type
, "c10", 3)
2668 || !strcmp (terminal_type
, "perq"))
2670 /* Supply a makeshift :wi string.
2671 This string is not valid in general since it works only
2672 for windows starting at the upper left corner;
2673 but that is all Emacs uses.
2675 This string works only if the frame is using
2676 the top of the video memory, because addressing is memory-relative.
2677 So first check the :ti string to see if that is true.
2679 It would be simpler if the :wi string could go in the termcap
2680 entry, but it can't because it is not fully valid.
2681 If it were in the termcap entry, it would confuse other programs. */
2682 if (!tty
->TS_set_window
)
2684 p
= tty
->TS_termcap_modes
;
2685 while (*p
&& strcmp (p
, "\033v "))
2688 tty
->TS_set_window
= "\033v%C %C %C %C ";
2690 /* Termcap entry often fails to have :in: flag */
2691 display
->must_write_spaces
= 1;
2692 /* :ti string typically fails to have \E^G! in it */
2693 /* This limits scope of insert-char to one line. */
2694 strcpy (area
, tty
->TS_termcap_modes
);
2695 strcat (area
, "\033\007!");
2696 tty
->TS_termcap_modes
= area
;
2697 area
+= strlen (area
) + 1;
2698 p
= AbsPosition (tty
);
2699 /* Change all %+ parameters to %C, to handle
2700 values above 96 correctly for the C100. */
2703 if (p
[0] == '%' && p
[1] == '+')
2709 tty
->specified_window
= FrameRows (tty
);
2711 if (Wcm_init (tty
) == -1) /* can't do cursor motion */
2713 maybe_fatal (must_succeed
, NULL
, display
,
2714 "Terminal type \"%s\" is not powerful enough to run Emacs",
2716 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2717 It lacks the ability to position the cursor.\n\
2718 If that is not the actual type of terminal you have, use either the\n\
2719 DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
2720 or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
2723 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2724 It lacks the ability to position the cursor.\n\
2725 If that is not the actual type of terminal you have,\n\
2726 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2727 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2728 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
2729 # else /* TERMCAP */
2730 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2731 It lacks the ability to position the cursor.\n\
2732 If that is not the actual type of terminal you have,\n\
2733 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2734 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2735 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
2736 # endif /* TERMINFO */
2741 if (FrameRows (tty
) <= 0 || FrameCols (tty
) <= 0)
2742 maybe_fatal (must_succeed
, NULL
, display
,
2743 "Could not determine the frame size",
2744 "Could not determine the frame size");
2746 tty
->delete_in_insert_mode
2747 = tty
->TS_delete_mode
&& tty
->TS_insert_mode
2748 && !strcmp (tty
->TS_delete_mode
, tty
->TS_insert_mode
);
2750 tty
->se_is_so
= (tty
->TS_standout_mode
2751 && tty
->TS_end_standout_mode
2752 && !strcmp (tty
->TS_standout_mode
, tty
->TS_end_standout_mode
));
2754 UseTabs (tty
) = tabs_safe_p (fileno (tty
->input
)) && TabWidth (tty
) == 8;
2756 display
->scroll_region_ok
2758 && (tty
->TS_set_window
|| tty
->TS_set_scroll_region
|| tty
->TS_set_scroll_region_1
));
2760 display
->line_ins_del_ok
2761 = (((tty
->TS_ins_line
|| tty
->TS_ins_multi_lines
)
2762 && (tty
->TS_del_line
|| tty
->TS_del_multi_lines
))
2763 || (display
->scroll_region_ok
2764 && tty
->TS_fwd_scroll
&& tty
->TS_rev_scroll
));
2766 display
->char_ins_del_ok
2767 = ((tty
->TS_ins_char
|| tty
->TS_insert_mode
2768 || tty
->TS_pad_inserted_char
|| tty
->TS_ins_multi_chars
)
2769 && (tty
->TS_del_char
|| tty
->TS_del_multi_chars
));
2771 display
->fast_clear_end_of_line
= tty
->TS_clr_line
!= 0;
2773 init_baud_rate (fileno (tty
->input
));
2776 /* The HFT system on AIX doesn't optimize for scrolling, so it's
2777 really ugly at times. */
2778 display
->line_ins_del_ok
= 0;
2779 display
->char_ins_del_ok
= 0;
2783 tty
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
2784 init_kboard (tty
->kboard
);
2785 tty
->kboard
->next_kboard
= all_kboards
;
2786 all_kboards
= tty
->kboard
;
2787 /* Don't let the initial kboard remain current longer than necessary.
2788 That would cause problems if a file loaded on startup tries to
2789 prompt in the mini-buffer. */
2790 if (current_kboard
== initial_kboard
)
2791 current_kboard
= tty
->kboard
;
2792 tty
->kboard
->reference_count
++;
2795 /* Don't do this. I think termcap may still need the buffer. */
2796 /* xfree (buffer); */
2798 /* Init system terminal modes (RAW or CBREAK, etc.). */
2799 init_sys_modes (tty
);
2802 #endif /* not WINDOWSNT */
2805 /* Auxiliary error-handling function for term_init.
2806 Free BUFFER and delete DISPLAY, then call error or fatal
2807 with str1 or str2, respectively, according to MUST_SUCCEED. */
2810 maybe_fatal (must_succeed
, buffer
, display
, str1
, str2
, arg1
, arg2
)
2813 struct display
*display
;
2814 char *str1
, *str2
, *arg1
, *arg2
;
2820 delete_tty (display
);
2823 fatal (str2
, arg1
, arg2
);
2825 error (str1
, arg1
, arg2
);
2832 fatal (str
, arg1
, arg2
)
2833 char *str
, *arg1
, *arg2
;
2835 fprintf (stderr
, "emacs: ");
2836 fprintf (stderr
, str
, arg1
, arg2
);
2837 fprintf (stderr
, "\n");
2844 DEFUN ("delete-tty", Fdelete_tty
, Sdelete_tty
, 0, 1, 0,
2845 doc
: /* Delete all frames on the terminal named TTY, and close the device.
2846 If omitted, TTY defaults to the controlling terminal.
2848 This function runs `delete-tty-after-functions' after closing the
2849 tty. The functions are run with one arg, the frame to be deleted. */)
2858 if (SBYTES (tty
) > 0)
2860 name
= (char *) alloca (SBYTES (tty
) + 1);
2861 strncpy (name
, SDATA (tty
), SBYTES (tty
));
2862 name
[SBYTES (tty
)] = 0;
2865 d
= get_named_tty_display (name
);
2868 error ("No such terminal device: %s", name
);
2875 static int deleting_tty
= 0;
2878 /* Delete the given terminal device, closing all frames on it. */
2881 delete_tty (struct display
*display
)
2883 struct tty_display_info
*tty
;
2884 Lisp_Object tail
, frame
;
2889 /* We get a recursive call when we delete the last frame on this
2893 if (display
->type
!= output_termcap
)
2896 tty
= display
->display_info
.tty
;
2899 FOR_EACH_FRAME (tail
, frame
)
2901 struct frame
*f
= XFRAME (frame
);
2902 if (FRAME_LIVE_P (f
) && (!FRAME_TERMCAP_P (f
) || FRAME_TTY (f
) != tty
))
2909 error ("Attempt to delete the sole display with live frames");
2911 if (tty
== tty_list
)
2912 tty_list
= tty
->next
;
2915 struct tty_display_info
*p
;
2916 for (p
= tty_list
; p
&& p
->next
!= tty
; p
= p
->next
)
2920 /* This should not happen. */
2923 p
->next
= tty
->next
;
2929 FOR_EACH_FRAME (tail
, frame
)
2931 struct frame
*f
= XFRAME (frame
);
2932 if (FRAME_TERMCAP_P (f
) && FRAME_LIVE_P (f
) && FRAME_TTY (f
) == tty
)
2934 Fdelete_frame (frame
, Qt
);
2938 /* reset_sys_modes needs a valid display, so this call needs to be
2939 before delete_display. */
2940 reset_sys_modes (tty
);
2942 delete_display (display
);
2944 tty_name
= tty
->name
;
2950 delete_keyboard_wait_descriptor (fileno (tty
->input
));
2951 if (tty
->input
!= stdin
)
2952 fclose (tty
->input
);
2954 if (tty
->output
&& tty
->output
!= stdout
&& tty
->output
!= tty
->input
)
2955 fclose (tty
->output
);
2956 if (tty
->termscript
)
2957 fclose (tty
->termscript
);
2960 xfree (tty
->old_tty
);
2966 if (tty
->kboard
&& --tty
->kboard
->reference_count
> 0)
2969 delete_kboard (tty
->kboard
);
2972 bzero (tty
, sizeof (struct tty_display_info
));
2976 /* Run `delete-tty-after-functions'. */
2977 if (!NILP (Vrun_hooks
))
2979 Lisp_Object args
[2];
2980 args
[0] = intern ("delete-tty-after-functions");
2983 args
[1] = build_string (tty_name
);
2988 Frun_hook_with_args (2, args
);
2994 /* Initialize the tty-dependent part of frame F. The frame must
2995 already have its display initialized. */
2998 create_tty_output (struct frame
*f
)
3000 struct tty_output
*t
;
3002 if (! FRAME_TERMCAP_P (f
))
3005 t
= xmalloc (sizeof (struct tty_output
));
3006 bzero (t
, sizeof (struct tty_output
));
3008 t
->display_info
= FRAME_DISPLAY (f
)->display_info
.tty
;
3010 f
->output_data
.tty
= t
;
3013 /* Delete the tty-dependent part of frame F. */
3016 delete_tty_output (struct frame
*f
)
3018 if (! FRAME_TERMCAP_P (f
))
3021 xfree (f
->output_data
.tty
);
3027 /* Mark the pointers in the tty_display_info objects.
3028 Called by the Fgarbage_collector. */
3033 struct tty_display_info
*tty
;
3035 for (tty
= tty_list
; tty
; tty
= tty
->next
)
3038 mark_object (tty
->top_frame
);
3044 /* Create a new display object and add it to the display list. */
3047 create_display (void)
3049 struct display
*dev
= (struct display
*) xmalloc (sizeof (struct display
));
3051 bzero (dev
, sizeof (struct display
));
3052 dev
->next_display
= display_list
;
3058 /* Remove a display from the display list and free its memory. */
3061 delete_display (struct display
*dev
)
3063 struct display
**dp
;
3064 Lisp_Object tail
, frame
;
3066 /* Check for and close live frames that are still on this
3068 FOR_EACH_FRAME (tail
, frame
)
3070 struct frame
*f
= XFRAME (frame
);
3071 if (FRAME_LIVE_P (f
) && f
->display
== dev
)
3073 Fdelete_frame (frame
, Qt
);
3077 for (dp
= &display_list
; *dp
!= dev
; dp
= &(*dp
)->next_display
)
3080 *dp
= dev
->next_display
;
3082 bzero (dev
, sizeof (struct display
));
3088 DEFUN ("suspend-tty", Fsuspend_tty
, Ssuspend_tty
, 0, 1, 0,
3089 doc
: /* Suspend the terminal device TTY.
3090 The terminal is restored to its default state, and Emacs closes all
3091 access to the terminal device. Frames that use the device are not
3092 deleted, but input is not read from them and if they change, their
3093 display is not updated.
3095 TTY may a string (a device name), a frame, or nil for the display
3096 device of the currently selected frame.
3098 This function runs `suspend-tty-functions' after suspending the
3099 device. The functions are run with one arg, the name of the terminal
3102 `suspend-tty' does nothing if it is called on an already suspended
3105 A suspended terminal device may be resumed by calling `resume-tty' on
3110 struct display
*d
= get_tty_display (tty
);
3114 error ("Unknown tty device");
3116 f
= d
->display_info
.tty
->input
;
3120 reset_sys_modes (d
->display_info
.tty
);
3122 delete_keyboard_wait_descriptor (fileno (f
));
3125 if (f
!= d
->display_info
.tty
->output
)
3126 fclose (d
->display_info
.tty
->output
);
3128 d
->display_info
.tty
->input
= 0;
3129 d
->display_info
.tty
->output
= 0;
3131 if (FRAMEP (d
->display_info
.tty
->top_frame
))
3132 FRAME_SET_VISIBLE (XFRAME (d
->display_info
.tty
->top_frame
), 0);
3134 /* Run `suspend-tty-functions'. */
3135 if (!NILP (Vrun_hooks
))
3137 Lisp_Object args
[2];
3138 args
[0] = intern ("suspend-tty-functions");
3139 if (d
->display_info
.tty
->name
)
3141 args
[1] = build_string (d
->display_info
.tty
->name
);
3145 Frun_hook_with_args (2, args
);
3153 DEFUN ("resume-tty", Fresume_tty
, Sresume_tty
, 0, 1, 0,
3154 doc
: /* Resume the previously suspended terminal device TTY.
3155 The terminal is opened and reinitialized. Frames that used the
3156 suspended device are revived.
3158 This function runs `resume-tty-functions' after resuming the device.
3159 The functions are run with one arg, the name of the terminal device.
3161 `resume-tty' does nothing if it is called on a device that is not
3164 TTY may a string (a device name), a frame, or nil for the display
3165 device of the currently selected frame. */)
3169 struct display
*d
= get_tty_display (tty
);
3173 error ("Unknown tty device");
3175 if (!d
->display_info
.tty
->input
)
3177 fd
= emacs_open (d
->display_info
.tty
->name
, O_RDWR
| O_NOCTTY
, 0);
3180 /* Drop our controlling tty if it is the same device. */
3181 if (ioctl (fd
, TIOCNOTTY
, 0) != -1)
3183 no_controlling_tty
= 1;
3187 d
->display_info
.tty
->output
= fdopen (fd
, "w+");
3188 d
->display_info
.tty
->input
= d
->display_info
.tty
->output
;
3190 add_keyboard_wait_descriptor (fd
);
3192 if (FRAMEP (d
->display_info
.tty
->top_frame
))
3193 FRAME_SET_VISIBLE (XFRAME (d
->display_info
.tty
->top_frame
), 1);
3195 init_sys_modes (d
->display_info
.tty
);
3197 /* Run `suspend-tty-functions'. */
3198 if (!NILP (Vrun_hooks
))
3200 Lisp_Object args
[2];
3201 args
[0] = intern ("resume-tty-functions");
3202 if (d
->display_info
.tty
->name
)
3204 args
[1] = build_string (d
->display_info
.tty
->name
);
3208 Frun_hook_with_args (2, args
);
3219 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo
,
3220 doc
: /* Non-nil means the system uses terminfo rather than termcap.
3221 This variable can be used by terminal emulator packages. */);
3223 system_uses_terminfo
= 1;
3225 system_uses_terminfo
= 0;
3228 DEFVAR_LISP ("ring-bell-function", &Vring_bell_function
,
3229 doc
: /* Non-nil means call this function to ring the bell.
3230 The function should accept no arguments. */);
3231 Vring_bell_function
= Qnil
;
3233 DEFVAR_LISP ("delete-tty-after-functions", &Vdelete_tty_after_functions
,
3234 doc
: /* Functions to be run after deleting a tty.
3235 The functions are run with one argument, the name of the tty to be deleted.
3236 See `delete-tty'. */);
3237 Vdelete_tty_after_functions
= Qnil
;
3240 DEFVAR_LISP ("suspend-tty-functions", &Vsuspend_tty_functions
,
3241 doc
: /* Functions to be run after suspending a tty.
3242 The functions are run with one argument, the name of the tty to be suspended.
3243 See `suspend-tty'. */);
3244 Vsuspend_tty_functions
= Qnil
;
3247 DEFVAR_LISP ("resume-tty-functions", &Vresume_tty_functions
,
3248 doc
: /* Functions to be run after resuming a tty.
3249 The functions are run with one argument, the name of the tty that was revived.
3250 See `resume-tty'. */);
3251 Vresume_tty_functions
= Qnil
;
3253 Qframe_tty_name
= intern ("frame-tty-name");
3254 staticpro (&Qframe_tty_name
);
3256 Qframe_tty_type
= intern ("frame-tty-type");
3257 staticpro (&Qframe_tty_type
);
3259 defsubr (&Stty_display_color_p
);
3260 defsubr (&Stty_display_color_cells
);
3261 defsubr (&Sframe_tty_name
);
3262 defsubr (&Sframe_tty_type
);
3263 defsubr (&Sdelete_tty
);
3264 defsubr (&Ssuspend_tty
);
3265 defsubr (&Sresume_tty
);
3267 Fprovide (intern ("multi-tty"), Qnil
);
3273 /* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193
3274 (do not change this comment) */