1 /* Terminal control module for terminals described by TERMCAP
2 Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1998, 2000, 2001,
3 2002, 2003, 2004, 2005, 2006, 2007 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 3, 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., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 /* New redisplay, TTY faces by Gerd Moellmann <gerd@gnu.org>. */
36 #include <termios.h> /* For TIOCNOTTY. */
49 #include "termhooks.h"
50 #include "dispextern.h"
53 #include "blockinput.h"
54 #include "syssignal.h"
56 #include "intervals.h"
58 /* For now, don't try to include termcap.h. On some systems,
59 configure finds a non-standard termcap.h that the main build
62 #if defined HAVE_TERMCAP_H && 0
65 extern void tputs
P_ ((const char *, int, int (*)(int)));
66 extern int tgetent
P_ ((char *, const char *));
67 extern int tgetflag
P_ ((char *id
));
68 extern int tgetnum
P_ ((char *id
));
87 /* The name of the default console device. */
89 #define DEV_TTY "CONOUT$"
91 #define DEV_TTY "/dev/tty"
94 static void tty_set_scroll_region
P_ ((struct frame
*f
, int start
, int stop
));
95 static void turn_on_face
P_ ((struct frame
*, int face_id
));
96 static void turn_off_face
P_ ((struct frame
*, int face_id
));
97 static void tty_show_cursor
P_ ((struct tty_display_info
*));
98 static void tty_hide_cursor
P_ ((struct tty_display_info
*));
99 static void tty_background_highlight
P_ ((struct tty_display_info
*tty
));
100 static void clear_tty_hooks
P_ ((struct terminal
*terminal
));
101 static void set_tty_hooks
P_ ((struct terminal
*terminal
));
102 static void dissociate_if_controlling_tty
P_ ((int fd
));
103 static void delete_tty
P_ ((struct terminal
*));
105 #define OUTPUT(tty, a) \
106 emacs_tputs ((tty), a, \
107 (int) (FRAME_LINES (XFRAME (selected_frame)) \
111 #define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
112 #define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
114 #define OUTPUT_IF(tty, a) \
117 emacs_tputs ((tty), a, \
118 (int) (FRAME_LINES (XFRAME (selected_frame)) \
123 #define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
125 /* If true, use "vs", otherwise use "ve" to make the cursor visible. */
127 static int visible_cursor
;
129 /* Display space properties */
131 extern Lisp_Object Qspace
, QCalign_to
, QCwidth
;
133 /* Functions to call after suspending a tty. */
134 Lisp_Object Vsuspend_tty_functions
;
136 /* Functions to call after resuming a tty. */
137 Lisp_Object Vresume_tty_functions
;
139 /* Chain of all tty device parameters. */
140 struct tty_display_info
*tty_list
;
142 /* Nonzero means no need to redraw the entire frame on resuming a
143 suspended Emacs. This is useful on terminals with multiple
144 pages, where one page is used for Emacs and another for all
146 int no_redraw_on_reenter
;
148 /* Meaning of bits in no_color_video. Each bit set means that the
149 corresponding attribute cannot be combined with colors. */
153 NC_STANDOUT
= 1 << 0,
154 NC_UNDERLINE
= 1 << 1,
161 NC_ALT_CHARSET
= 1 << 8
166 /* The largest frame width in any call to calculate_costs. */
170 /* The largest frame height in any call to calculate_costs. */
174 /* Non-zero if we have dropped our controlling tty and therefore
175 should not open a frame on stdout. */
176 static int no_controlling_tty
;
178 /* Provided for lisp packages. */
180 static int system_uses_terminfo
;
184 extern char *tgetstr ();
188 #include <sys/fcntl.h>
191 static void term_clear_mouse_face ();
192 static void term_mouse_highlight (struct frame
*f
, int x
, int y
);
194 /* The device for which we have enabled gpm support (or NULL). */
195 struct tty_display_info
*gpm_tty
= NULL
;
197 /* These variables describe the range of text currently shown in its
198 mouse-face, together with the window they apply to. As long as
199 the mouse stays within this range, we need not redraw anything on
200 its account. Rows and columns are glyph matrix positions in
201 MOUSE_FACE_WINDOW. */
202 static int mouse_face_beg_row
, mouse_face_beg_col
;
203 static int mouse_face_end_row
, mouse_face_end_col
;
204 static int mouse_face_past_end
;
205 static Lisp_Object mouse_face_window
;
206 static int mouse_face_face_id
;
208 static int pos_x
, pos_y
;
209 static int last_mouse_x
, last_mouse_y
;
210 #endif /* HAVE_GPM */
212 /* Ring the bell on a tty. */
215 tty_ring_bell (struct frame
*f
)
217 struct tty_display_info
*tty
= FRAME_TTY (f
);
221 OUTPUT (tty
, (tty
->TS_visible_bell
&& visible_bell
222 ? tty
->TS_visible_bell
224 fflush (tty
->output
);
228 /* Set up termcap modes for Emacs. */
231 tty_set_terminal_modes (struct terminal
*terminal
)
233 struct tty_display_info
*tty
= terminal
->display_info
.tty
;
237 if (tty
->TS_termcap_modes
)
238 OUTPUT (tty
, tty
->TS_termcap_modes
);
241 /* Output enough newlines to scroll all the old screen contents
242 off the screen, so it won't be overwritten and lost. */
245 for (i
= 0; i
< FRAME_LINES (XFRAME (selected_frame
)); i
++)
249 OUTPUT_IF (tty
, tty
->TS_termcap_modes
);
250 OUTPUT_IF (tty
, visible_cursor
? tty
->TS_cursor_visible
: tty
->TS_cursor_normal
);
251 OUTPUT_IF (tty
, tty
->TS_keypad_mode
);
253 fflush (tty
->output
);
257 /* Reset termcap modes before exiting Emacs. */
260 tty_reset_terminal_modes (struct terminal
*terminal
)
262 struct tty_display_info
*tty
= terminal
->display_info
.tty
;
266 tty_turn_off_highlight (tty
);
267 tty_turn_off_insert (tty
);
268 OUTPUT_IF (tty
, tty
->TS_end_keypad_mode
);
269 OUTPUT_IF (tty
, tty
->TS_cursor_normal
);
270 OUTPUT_IF (tty
, tty
->TS_end_termcap_modes
);
271 OUTPUT_IF (tty
, tty
->TS_orig_pair
);
272 /* Output raw CR so kernel can track the cursor hpos. */
275 fflush (tty
->output
);
279 /* Flag the end of a display update on a termcap terminal. */
282 tty_update_end (struct frame
*f
)
284 struct tty_display_info
*tty
= FRAME_TTY (f
);
286 if (!XWINDOW (selected_window
)->cursor_off_p
)
287 tty_show_cursor (tty
);
288 tty_turn_off_insert (tty
);
289 tty_background_highlight (tty
);
292 /* The implementation of set_terminal_window for termcap frames. */
295 tty_set_terminal_window (struct frame
*f
, int size
)
297 struct tty_display_info
*tty
= FRAME_TTY (f
);
299 tty
->specified_window
= size
? size
: FRAME_LINES (f
);
300 if (FRAME_SCROLL_REGION_OK (f
))
301 tty_set_scroll_region (f
, 0, tty
->specified_window
);
305 tty_set_scroll_region (struct frame
*f
, int start
, int stop
)
308 struct tty_display_info
*tty
= FRAME_TTY (f
);
310 if (tty
->TS_set_scroll_region
)
311 buf
= tparam (tty
->TS_set_scroll_region
, 0, 0, start
, stop
- 1);
312 else if (tty
->TS_set_scroll_region_1
)
313 buf
= tparam (tty
->TS_set_scroll_region_1
, 0, 0,
314 FRAME_LINES (f
), start
,
315 FRAME_LINES (f
) - stop
,
318 buf
= tparam (tty
->TS_set_window
, 0, 0, start
, 0, stop
, FRAME_COLS (f
));
327 tty_turn_on_insert (struct tty_display_info
*tty
)
329 if (!tty
->insert_mode
)
330 OUTPUT (tty
, tty
->TS_insert_mode
);
331 tty
->insert_mode
= 1;
335 tty_turn_off_insert (struct tty_display_info
*tty
)
337 if (tty
->insert_mode
)
338 OUTPUT (tty
, tty
->TS_end_insert_mode
);
339 tty
->insert_mode
= 0;
342 /* Handle highlighting. */
345 tty_turn_off_highlight (struct tty_display_info
*tty
)
347 if (tty
->standout_mode
)
348 OUTPUT_IF (tty
, tty
->TS_end_standout_mode
);
349 tty
->standout_mode
= 0;
353 tty_turn_on_highlight (struct tty_display_info
*tty
)
355 if (!tty
->standout_mode
)
356 OUTPUT_IF (tty
, tty
->TS_standout_mode
);
357 tty
->standout_mode
= 1;
361 tty_toggle_highlight (struct tty_display_info
*tty
)
363 if (tty
->standout_mode
)
364 tty_turn_off_highlight (tty
);
366 tty_turn_on_highlight (tty
);
370 /* Make cursor invisible. */
373 tty_hide_cursor (struct tty_display_info
*tty
)
375 if (tty
->cursor_hidden
== 0)
377 tty
->cursor_hidden
= 1;
378 OUTPUT_IF (tty
, tty
->TS_cursor_invisible
);
383 /* Ensure that cursor is visible. */
386 tty_show_cursor (struct tty_display_info
*tty
)
388 if (tty
->cursor_hidden
)
390 tty
->cursor_hidden
= 0;
391 OUTPUT_IF (tty
, tty
->TS_cursor_normal
);
393 OUTPUT_IF (tty
, tty
->TS_cursor_visible
);
398 /* Set standout mode to the state it should be in for
399 empty space inside windows. What this is,
400 depends on the user option inverse-video. */
403 tty_background_highlight (struct tty_display_info
*tty
)
406 tty_turn_on_highlight (tty
);
408 tty_turn_off_highlight (tty
);
411 /* Set standout mode to the mode specified for the text to be output. */
414 tty_highlight_if_desired (struct tty_display_info
*tty
)
417 tty_turn_on_highlight (tty
);
419 tty_turn_off_highlight (tty
);
423 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
424 frame-relative coordinates. */
427 tty_cursor_to (struct frame
*f
, int vpos
, int hpos
)
429 struct tty_display_info
*tty
= FRAME_TTY (f
);
431 /* Detect the case where we are called from reset_sys_modes
432 and the costs have never been calculated. Do nothing. */
433 if (! tty
->costs_set
)
436 if (curY (tty
) == vpos
437 && curX (tty
) == hpos
)
439 if (!tty
->TF_standout_motion
)
440 tty_background_highlight (tty
);
441 if (!tty
->TF_insmode_motion
)
442 tty_turn_off_insert (tty
);
443 cmgoto (tty
, vpos
, hpos
);
446 /* Similar but don't take any account of the wasted characters. */
449 tty_raw_cursor_to (struct frame
*f
, int row
, int col
)
451 struct tty_display_info
*tty
= FRAME_TTY (f
);
453 if (curY (tty
) == row
454 && curX (tty
) == col
)
456 if (!tty
->TF_standout_motion
)
457 tty_background_highlight (tty
);
458 if (!tty
->TF_insmode_motion
)
459 tty_turn_off_insert (tty
);
460 cmgoto (tty
, row
, col
);
463 /* Erase operations */
465 /* Clear from cursor to end of frame on a termcap device. */
468 tty_clear_to_end (struct frame
*f
)
471 struct tty_display_info
*tty
= FRAME_TTY (f
);
473 if (tty
->TS_clr_to_bottom
)
475 tty_background_highlight (tty
);
476 OUTPUT (tty
, tty
->TS_clr_to_bottom
);
480 for (i
= curY (tty
); i
< FRAME_LINES (f
); i
++)
483 clear_end_of_line (f
, FRAME_COLS (f
));
488 /* Clear an entire termcap frame. */
491 tty_clear_frame (struct frame
*f
)
493 struct tty_display_info
*tty
= FRAME_TTY (f
);
495 if (tty
->TS_clr_frame
)
497 tty_background_highlight (tty
);
498 OUTPUT (tty
, tty
->TS_clr_frame
);
508 /* An implementation of clear_end_of_line for termcap frames.
510 Note that the cursor may be moved, on terminals lacking a `ce' string. */
513 tty_clear_end_of_line (struct frame
*f
, int first_unused_hpos
)
516 struct tty_display_info
*tty
= FRAME_TTY (f
);
518 /* Detect the case where we are called from reset_sys_modes
519 and the costs have never been calculated. Do nothing. */
520 if (! tty
->costs_set
)
523 if (curX (tty
) >= first_unused_hpos
)
525 tty_background_highlight (tty
);
526 if (tty
->TS_clr_line
)
528 OUTPUT1 (tty
, tty
->TS_clr_line
);
531 { /* have to do it the hard way */
532 tty_turn_off_insert (tty
);
534 /* Do not write in last row last col with Auto-wrap on. */
536 && curY (tty
) == FrameRows (tty
) - 1
537 && first_unused_hpos
== FrameCols (tty
))
540 for (i
= curX (tty
); i
< first_unused_hpos
; i
++)
543 fputc (' ', tty
->termscript
);
544 fputc (' ', tty
->output
);
546 cmplus (tty
, first_unused_hpos
- curX (tty
));
550 /* Buffer to store the source and result of code conversion for terminal. */
551 static unsigned char *encode_terminal_buf
;
552 /* Allocated size of the above buffer. */
553 static int encode_terminal_bufsize
;
555 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes.
556 Set CODING->produced to the byte-length of the resulting byte
557 sequence, and return a pointer to that byte sequence. */
560 encode_terminal_code (src
, src_len
, coding
)
563 struct coding_system
*coding
;
565 struct glyph
*src_end
= src
+ src_len
;
568 int nchars
, nbytes
, required
;
569 register int tlen
= GLYPH_TABLE_LENGTH
;
570 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
572 /* Allocate sufficient size of buffer to store all characters in
573 multibyte-form. But, it may be enlarged on demand if
574 Vglyph_table contains a string. */
575 required
= MAX_MULTIBYTE_LENGTH
* src_len
;
576 if (encode_terminal_bufsize
< required
)
578 if (encode_terminal_bufsize
== 0)
579 encode_terminal_buf
= xmalloc (required
);
581 encode_terminal_buf
= xrealloc (encode_terminal_buf
, required
);
582 encode_terminal_bufsize
= required
;
585 buf
= encode_terminal_buf
;
587 while (src
< src_end
)
589 /* We must skip glyphs to be padded for a wide character. */
590 if (! CHAR_GLYPH_PADDING_P (*src
))
592 g
= GLYPH_FROM_CHAR_GLYPH (src
[0]);
594 if (g
< 0 || g
>= tlen
)
596 /* This glyph doesn't has an entry in Vglyph_table. */
597 if (CHAR_VALID_P (src
->u
.ch
, 0))
598 buf
+= CHAR_STRING (src
->u
.ch
, buf
);
605 /* This glyph has an entry in Vglyph_table,
606 so process any alias before testing for simpleness. */
607 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
609 if (GLYPH_SIMPLE_P (tbase
, tlen
, g
))
611 int c
= FAST_GLYPH_CHAR (g
);
613 if (CHAR_VALID_P (c
, 0))
614 buf
+= CHAR_STRING (c
, buf
);
621 /* We have a string in Vglyph_table. */
625 if (! STRING_MULTIBYTE (string
))
626 string
= string_to_multibyte (string
);
627 nbytes
= buf
- encode_terminal_buf
;
628 if (encode_terminal_bufsize
< nbytes
+ SBYTES (string
))
630 encode_terminal_bufsize
= nbytes
+ SBYTES (string
);
631 encode_terminal_buf
= xrealloc (encode_terminal_buf
,
632 encode_terminal_bufsize
);
633 buf
= encode_terminal_buf
+ nbytes
;
635 bcopy (SDATA (string
), buf
, SBYTES (string
));
636 buf
+= SBYTES (string
);
637 nchars
+= SCHARS (string
);
644 nbytes
= buf
- encode_terminal_buf
;
645 coding
->src_multibyte
= 1;
646 coding
->dst_multibyte
= 0;
647 if (SYMBOLP (coding
->pre_write_conversion
)
648 && ! NILP (Ffboundp (coding
->pre_write_conversion
)))
650 run_pre_write_conversin_on_c_str (&encode_terminal_buf
,
651 &encode_terminal_bufsize
,
652 nchars
, nbytes
, coding
);
653 nchars
= coding
->produced_char
;
654 nbytes
= coding
->produced
;
656 required
= nbytes
+ encoding_buffer_size (coding
, nbytes
);
657 if (encode_terminal_bufsize
< required
)
659 encode_terminal_bufsize
= required
;
660 encode_terminal_buf
= xrealloc (encode_terminal_buf
, required
);
663 encode_coding (coding
, encode_terminal_buf
, encode_terminal_buf
+ nbytes
,
664 nbytes
, encode_terminal_bufsize
- nbytes
);
665 return encode_terminal_buf
+ nbytes
;
669 /* An implementation of write_glyphs for termcap frames. */
672 tty_write_glyphs (struct frame
*f
, struct glyph
*string
, int len
)
674 unsigned char *conversion_buffer
;
675 struct coding_system
*coding
;
677 struct tty_display_info
*tty
= FRAME_TTY (f
);
679 tty_turn_off_insert (tty
);
680 tty_hide_cursor (tty
);
682 /* Don't dare write in last column of bottom line, if Auto-Wrap,
683 since that would scroll the whole frame on some terminals. */
686 && curY (tty
) + 1 == FRAME_LINES (f
)
687 && (curX (tty
) + len
) == FRAME_COLS (f
))
694 /* If terminal_coding does any conversion, use it, otherwise use
695 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
696 because it always return 1 if the member src_multibyte is 1. */
697 coding
= (FRAME_TERMINAL_CODING (f
)->common_flags
& CODING_REQUIRE_ENCODING_MASK
698 ? FRAME_TERMINAL_CODING (f
) : &safe_terminal_coding
);
699 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
701 coding
->mode
&= ~CODING_MODE_LAST_BLOCK
;
705 /* Identify a run of glyphs with the same face. */
706 int face_id
= string
->face_id
;
709 for (n
= 1; n
< len
; ++n
)
710 if (string
[n
].face_id
!= face_id
)
713 /* Turn appearance modes of the face of the run on. */
714 tty_highlight_if_desired (tty
);
715 turn_on_face (f
, face_id
);
718 /* This is the last run. */
719 coding
->mode
|= CODING_MODE_LAST_BLOCK
;
720 conversion_buffer
= encode_terminal_code (string
, n
, coding
);
721 if (coding
->produced
> 0)
724 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->output
);
725 if (ferror (tty
->output
))
726 clearerr (tty
->output
);
728 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->termscript
);
734 /* Turn appearance modes off. */
735 turn_off_face (f
, face_id
);
736 tty_turn_off_highlight (tty
);
742 #ifdef HAVE_GPM /* Only used by GPM code. */
745 tty_write_glyphs_with_face (f
, string
, len
, face_id
)
746 register struct frame
*f
;
747 register struct glyph
*string
;
748 register int len
, face_id
;
750 unsigned char *conversion_buffer
;
751 struct coding_system
*coding
;
753 struct tty_display_info
*tty
= FRAME_TTY (f
);
755 tty_turn_off_insert (tty
);
756 tty_hide_cursor (tty
);
758 /* Don't dare write in last column of bottom line, if Auto-Wrap,
759 since that would scroll the whole frame on some terminals. */
762 && curY (tty
) + 1 == FRAME_LINES (f
)
763 && (curX (tty
) + len
) == FRAME_COLS (f
))
770 /* If terminal_coding does any conversion, use it, otherwise use
771 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
772 because it always return 1 if the member src_multibyte is 1. */
773 coding
= (FRAME_TERMINAL_CODING (f
)->common_flags
& CODING_REQUIRE_ENCODING_MASK
774 ? FRAME_TERMINAL_CODING (f
) : &safe_terminal_coding
);
775 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
777 coding
->mode
&= ~CODING_MODE_LAST_BLOCK
;
779 /* Turn appearance modes of the face. */
780 tty_highlight_if_desired (tty
);
781 turn_on_face (f
, face_id
);
783 coding
->mode
|= CODING_MODE_LAST_BLOCK
;
784 conversion_buffer
= encode_terminal_code (string
, len
, coding
);
785 if (coding
->produced
> 0)
788 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->output
);
789 if (ferror (tty
->output
))
790 clearerr (tty
->output
);
792 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->termscript
);
796 /* Turn appearance modes off. */
797 turn_off_face (f
, face_id
);
798 tty_turn_off_highlight (tty
);
804 /* An implementation of insert_glyphs for termcap frames. */
807 tty_insert_glyphs (struct frame
*f
, struct glyph
*start
, int len
)
810 struct glyph
*glyph
= NULL
;
811 unsigned char *conversion_buffer
;
812 unsigned char space
[1];
813 struct coding_system
*coding
;
815 struct tty_display_info
*tty
= FRAME_TTY (f
);
817 if (tty
->TS_ins_multi_chars
)
819 buf
= tparam (tty
->TS_ins_multi_chars
, 0, 0, len
);
823 write_glyphs (f
, start
, len
);
827 tty_turn_on_insert (tty
);
831 space
[0] = SPACEGLYPH
;
833 /* If terminal_coding does any conversion, use it, otherwise use
834 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
835 because it always return 1 if the member src_multibyte is 1. */
836 coding
= (FRAME_TERMINAL_CODING (f
)->common_flags
& CODING_REQUIRE_ENCODING_MASK
837 ? FRAME_TERMINAL_CODING (f
) : &safe_terminal_coding
);
838 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
840 coding
->mode
&= ~CODING_MODE_LAST_BLOCK
;
844 OUTPUT1_IF (tty
, tty
->TS_ins_char
);
847 conversion_buffer
= space
;
848 coding
->produced
= 1;
852 tty_highlight_if_desired (tty
);
853 turn_on_face (f
, start
->face_id
);
856 /* We must open sufficient space for a character which
857 occupies more than one column. */
858 while (len
&& CHAR_GLYPH_PADDING_P (*start
))
860 OUTPUT1_IF (tty
, tty
->TS_ins_char
);
865 /* This is the last glyph. */
866 coding
->mode
|= CODING_MODE_LAST_BLOCK
;
868 conversion_buffer
= encode_terminal_code (glyph
, 1, coding
);
871 if (coding
->produced
> 0)
874 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->output
);
875 if (ferror (tty
->output
))
876 clearerr (tty
->output
);
878 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->termscript
);
882 OUTPUT1_IF (tty
, tty
->TS_pad_inserted_char
);
885 turn_off_face (f
, glyph
->face_id
);
886 tty_turn_off_highlight (tty
);
893 /* An implementation of delete_glyphs for termcap frames. */
896 tty_delete_glyphs (struct frame
*f
, int n
)
901 struct tty_display_info
*tty
= FRAME_TTY (f
);
903 if (tty
->delete_in_insert_mode
)
905 tty_turn_on_insert (tty
);
909 tty_turn_off_insert (tty
);
910 OUTPUT_IF (tty
, tty
->TS_delete_mode
);
913 if (tty
->TS_del_multi_chars
)
915 buf
= tparam (tty
->TS_del_multi_chars
, 0, 0, n
);
920 for (i
= 0; i
< n
; i
++)
921 OUTPUT1 (tty
, tty
->TS_del_char
);
922 if (!tty
->delete_in_insert_mode
)
923 OUTPUT_IF (tty
, tty
->TS_end_delete_mode
);
926 /* An implementation of ins_del_lines for termcap frames. */
929 tty_ins_del_lines (struct frame
*f
, int vpos
, int n
)
931 struct tty_display_info
*tty
= FRAME_TTY (f
);
932 char *multi
= n
> 0 ? tty
->TS_ins_multi_lines
: tty
->TS_del_multi_lines
;
933 char *single
= n
> 0 ? tty
->TS_ins_line
: tty
->TS_del_line
;
934 char *scroll
= n
> 0 ? tty
->TS_rev_scroll
: tty
->TS_fwd_scroll
;
936 register int i
= n
> 0 ? n
: -n
;
939 /* If the lines below the insertion are being pushed
940 into the end of the window, this is the same as clearing;
941 and we know the lines are already clear, since the matching
942 deletion has already been done. So can ignore this. */
943 /* If the lines below the deletion are blank lines coming
944 out of the end of the window, don't bother,
945 as there will be a matching inslines later that will flush them. */
946 if (FRAME_SCROLL_REGION_OK (f
)
947 && vpos
+ i
>= tty
->specified_window
)
949 if (!FRAME_MEMORY_BELOW_FRAME (f
)
950 && vpos
+ i
>= FRAME_LINES (f
))
955 raw_cursor_to (f
, vpos
, 0);
956 tty_background_highlight (tty
);
957 buf
= tparam (multi
, 0, 0, i
);
963 raw_cursor_to (f
, vpos
, 0);
964 tty_background_highlight (tty
);
966 OUTPUT (tty
, single
);
972 tty_set_scroll_region (f
, vpos
, tty
->specified_window
);
974 raw_cursor_to (f
, tty
->specified_window
- 1, 0);
976 raw_cursor_to (f
, vpos
, 0);
977 tty_background_highlight (tty
);
979 OUTPUTL (tty
, scroll
, tty
->specified_window
- vpos
);
980 tty_set_scroll_region (f
, 0, tty
->specified_window
);
983 if (!FRAME_SCROLL_REGION_OK (f
)
984 && FRAME_MEMORY_BELOW_FRAME (f
)
987 cursor_to (f
, FRAME_LINES (f
) + n
, 0);
992 /* Compute cost of sending "str", in characters,
993 not counting any line-dependent padding. */
996 string_cost (char *str
)
1000 tputs (str
, 0, evalcost
);
1004 /* Compute cost of sending "str", in characters,
1005 counting any line-dependent padding at one line. */
1008 string_cost_one_line (char *str
)
1012 tputs (str
, 1, evalcost
);
1016 /* Compute per line amount of line-dependent padding,
1017 in tenths of characters. */
1020 per_line_cost (char *str
)
1024 tputs (str
, 0, evalcost
);
1027 tputs (str
, 10, evalcost
);
1032 /* char_ins_del_cost[n] is cost of inserting N characters.
1033 char_ins_del_cost[-n] is cost of deleting N characters.
1034 The length of this vector is based on max_frame_cols. */
1036 int *char_ins_del_vector
;
1038 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
1043 calculate_ins_del_char_costs (struct frame
*f
)
1045 struct tty_display_info
*tty
= FRAME_TTY (f
);
1046 int ins_startup_cost
, del_startup_cost
;
1047 int ins_cost_per_char
, del_cost_per_char
;
1051 if (tty
->TS_ins_multi_chars
)
1053 ins_cost_per_char
= 0;
1054 ins_startup_cost
= string_cost_one_line (tty
->TS_ins_multi_chars
);
1056 else if (tty
->TS_ins_char
|| tty
->TS_pad_inserted_char
1057 || (tty
->TS_insert_mode
&& tty
->TS_end_insert_mode
))
1059 ins_startup_cost
= (30 * (string_cost (tty
->TS_insert_mode
)
1060 + string_cost (tty
->TS_end_insert_mode
))) / 100;
1061 ins_cost_per_char
= (string_cost_one_line (tty
->TS_ins_char
)
1062 + string_cost_one_line (tty
->TS_pad_inserted_char
));
1066 ins_startup_cost
= 9999;
1067 ins_cost_per_char
= 0;
1070 if (tty
->TS_del_multi_chars
)
1072 del_cost_per_char
= 0;
1073 del_startup_cost
= string_cost_one_line (tty
->TS_del_multi_chars
);
1075 else if (tty
->TS_del_char
)
1077 del_startup_cost
= (string_cost (tty
->TS_delete_mode
)
1078 + string_cost (tty
->TS_end_delete_mode
));
1079 if (tty
->delete_in_insert_mode
)
1080 del_startup_cost
/= 2;
1081 del_cost_per_char
= string_cost_one_line (tty
->TS_del_char
);
1085 del_startup_cost
= 9999;
1086 del_cost_per_char
= 0;
1089 /* Delete costs are at negative offsets */
1090 p
= &char_ins_del_cost (f
)[0];
1091 for (i
= FRAME_COLS (f
); --i
>= 0;)
1092 *--p
= (del_startup_cost
+= del_cost_per_char
);
1094 /* Doing nothing is free */
1095 p
= &char_ins_del_cost (f
)[0];
1098 /* Insert costs are at positive offsets */
1099 for (i
= FRAME_COLS (f
); --i
>= 0;)
1100 *p
++ = (ins_startup_cost
+= ins_cost_per_char
);
1104 calculate_costs (struct frame
*frame
)
1106 FRAME_COST_BAUD_RATE (frame
) = baud_rate
;
1108 if (FRAME_TERMCAP_P (frame
))
1110 struct tty_display_info
*tty
= FRAME_TTY (frame
);
1111 register char *f
= (tty
->TS_set_scroll_region
1112 ? tty
->TS_set_scroll_region
1113 : tty
->TS_set_scroll_region_1
);
1115 FRAME_SCROLL_REGION_COST (frame
) = string_cost (f
);
1119 /* These variables are only used for terminal stuff. They are
1120 allocated once for the terminal frame of X-windows emacs, but not
1123 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1124 X turns off char_ins_del_ok. */
1126 max_frame_lines
= max (max_frame_lines
, FRAME_LINES (frame
));
1127 max_frame_cols
= max (max_frame_cols
, FRAME_COLS (frame
));
1129 if (char_ins_del_vector
!= 0)
1131 = (int *) xrealloc (char_ins_del_vector
,
1133 + 2 * max_frame_cols
* sizeof (int)));
1136 = (int *) xmalloc (sizeof (int)
1137 + 2 * max_frame_cols
* sizeof (int));
1139 bzero (char_ins_del_vector
, (sizeof (int)
1140 + 2 * max_frame_cols
* sizeof (int)));
1143 if (f
&& (!tty
->TS_ins_line
&& !tty
->TS_del_line
))
1144 do_line_insertion_deletion_costs (frame
,
1145 tty
->TS_rev_scroll
, tty
->TS_ins_multi_lines
,
1146 tty
->TS_fwd_scroll
, tty
->TS_del_multi_lines
,
1149 do_line_insertion_deletion_costs (frame
,
1150 tty
->TS_ins_line
, tty
->TS_ins_multi_lines
,
1151 tty
->TS_del_line
, tty
->TS_del_multi_lines
,
1154 calculate_ins_del_char_costs (frame
);
1156 /* Don't use TS_repeat if its padding is worse than sending the chars */
1157 if (tty
->TS_repeat
&& per_line_cost (tty
->TS_repeat
) * baud_rate
< 9000)
1158 tty
->RPov
= string_cost (tty
->TS_repeat
);
1160 tty
->RPov
= FRAME_COLS (frame
) * 2;
1162 cmcostinit (FRAME_TTY (frame
)); /* set up cursor motion costs */
1170 /* Termcap capability names that correspond directly to X keysyms.
1171 Some of these (marked "terminfo") aren't supplied by old-style
1172 (Berkeley) termcap entries. They're listed in X keysym order;
1173 except we put the keypad keys first, so that if they clash with
1174 other keys (as on the IBM PC keyboard) they get overridden.
1177 static struct fkey_table keys
[] =
1179 {"kh", "home"}, /* termcap */
1180 {"kl", "left"}, /* termcap */
1181 {"ku", "up"}, /* termcap */
1182 {"kr", "right"}, /* termcap */
1183 {"kd", "down"}, /* termcap */
1184 {"%8", "prior"}, /* terminfo */
1185 {"%5", "next"}, /* terminfo */
1186 {"@7", "end"}, /* terminfo */
1187 {"@1", "begin"}, /* terminfo */
1188 {"*6", "select"}, /* terminfo */
1189 {"%9", "print"}, /* terminfo */
1190 {"@4", "execute"}, /* terminfo --- actually the `command' key */
1192 * "insert" --- see below
1194 {"&8", "undo"}, /* terminfo */
1195 {"%0", "redo"}, /* terminfo */
1196 {"%7", "menu"}, /* terminfo --- actually the `options' key */
1197 {"@0", "find"}, /* terminfo */
1198 {"@2", "cancel"}, /* terminfo */
1199 {"%1", "help"}, /* terminfo */
1201 * "break" goes here, but can't be reliably intercepted with termcap
1203 {"&4", "reset"}, /* terminfo --- actually `restart' */
1205 * "system" and "user" --- no termcaps
1207 {"kE", "clearline"}, /* terminfo */
1208 {"kA", "insertline"}, /* terminfo */
1209 {"kL", "deleteline"}, /* terminfo */
1210 {"kI", "insertchar"}, /* terminfo */
1211 {"kD", "deletechar"}, /* terminfo */
1212 {"kB", "backtab"}, /* terminfo */
1214 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1216 {"@8", "kp-enter"}, /* terminfo */
1218 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1219 * "kp-multiply", "kp-add", "kp-separator",
1220 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1221 * --- no termcaps for any of these.
1223 {"K4", "kp-1"}, /* terminfo */
1225 * "kp-2" --- no termcap
1227 {"K5", "kp-3"}, /* terminfo */
1229 * "kp-4" --- no termcap
1231 {"K2", "kp-5"}, /* terminfo */
1233 * "kp-6" --- no termcap
1235 {"K1", "kp-7"}, /* terminfo */
1237 * "kp-8" --- no termcap
1239 {"K3", "kp-9"}, /* terminfo */
1241 * "kp-equal" --- no termcap
1253 {"&0", "S-cancel"}, /*shifted cancel key*/
1254 {"&9", "S-begin"}, /*shifted begin key*/
1255 {"*0", "S-find"}, /*shifted find key*/
1256 {"*1", "S-execute"}, /*shifted execute? actually shifted command key*/
1257 {"*4", "S-delete"}, /*shifted delete-character key*/
1258 {"*7", "S-end"}, /*shifted end key*/
1259 {"*8", "S-clearline"}, /*shifted clear-to end-of-line key*/
1260 {"#1", "S-help"}, /*shifted help key*/
1261 {"#2", "S-home"}, /*shifted home key*/
1262 {"#3", "S-insert"}, /*shifted insert-character key*/
1263 {"#4", "S-left"}, /*shifted left-arrow key*/
1264 {"%d", "S-menu"}, /*shifted menu? actually shifted options key*/
1265 {"%c", "S-next"}, /*shifted next key*/
1266 {"%e", "S-prior"}, /*shifted previous key*/
1267 {"%f", "S-print"}, /*shifted print key*/
1268 {"%g", "S-redo"}, /*shifted redo key*/
1269 {"%i", "S-right"}, /*shifted right-arrow key*/
1270 {"!3", "S-undo"} /*shifted undo key*/
1273 static char **term_get_fkeys_address
;
1274 static KBOARD
*term_get_fkeys_kboard
;
1275 static Lisp_Object
term_get_fkeys_1 ();
1277 /* Find the escape codes sent by the function keys for Vfunction_key_map.
1278 This function scans the termcap function key sequence entries, and
1279 adds entries to Vfunction_key_map for each function key it finds. */
1282 term_get_fkeys (address
, kboard
)
1286 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1287 errors during the call. The only errors should be from Fdefine_key
1288 when given a key sequence containing an invalid prefix key. If the
1289 termcap defines function keys which use a prefix that is already bound
1290 to a command by the default bindings, we should silently ignore that
1291 function key specification, rather than giving the user an error and
1292 refusing to run at all on such a terminal. */
1294 extern Lisp_Object
Fidentity ();
1295 term_get_fkeys_address
= address
;
1296 term_get_fkeys_kboard
= kboard
;
1297 internal_condition_case (term_get_fkeys_1
, Qerror
, Fidentity
);
1305 char **address
= term_get_fkeys_address
;
1306 KBOARD
*kboard
= term_get_fkeys_kboard
;
1308 /* This can happen if CANNOT_DUMP or with strange options. */
1310 kboard
->Vlocal_function_key_map
= Fmake_sparse_keymap (Qnil
);
1312 for (i
= 0; i
< (sizeof (keys
)/sizeof (keys
[0])); i
++)
1314 char *sequence
= tgetstr (keys
[i
].cap
, address
);
1316 Fdefine_key (kboard
->Vlocal_function_key_map
, build_string (sequence
),
1317 Fmake_vector (make_number (1),
1318 intern (keys
[i
].name
)));
1321 /* The uses of the "k0" capability are inconsistent; sometimes it
1322 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1323 We will attempt to politely accommodate both systems by testing for
1324 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1327 char *k_semi
= tgetstr ("k;", address
);
1328 char *k0
= tgetstr ("k0", address
);
1329 char *k0_name
= "f10";
1334 /* Define f0 first, so that f10 takes precedence in case the
1335 key sequences happens to be the same. */
1336 Fdefine_key (kboard
->Vlocal_function_key_map
, build_string (k0
),
1337 Fmake_vector (make_number (1), intern ("f0")));
1338 Fdefine_key (kboard
->Vlocal_function_key_map
, build_string (k_semi
),
1339 Fmake_vector (make_number (1), intern ("f10")));
1342 Fdefine_key (kboard
->Vlocal_function_key_map
, build_string (k0
),
1343 Fmake_vector (make_number (1), intern (k0_name
)));
1346 /* Set up cookies for numbered function keys above f10. */
1348 char fcap
[3], fkey
[4];
1350 fcap
[0] = 'F'; fcap
[2] = '\0';
1351 for (i
= 11; i
< 64; i
++)
1354 fcap
[1] = '1' + i
- 11;
1356 fcap
[1] = 'A' + i
- 20;
1358 fcap
[1] = 'a' + i
- 46;
1361 char *sequence
= tgetstr (fcap
, address
);
1364 sprintf (fkey
, "f%d", i
);
1365 Fdefine_key (kboard
->Vlocal_function_key_map
, build_string (sequence
),
1366 Fmake_vector (make_number (1),
1374 * Various mappings to try and get a better fit.
1377 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1378 if (!tgetstr (cap1, address)) \
1380 char *sequence = tgetstr (cap2, address); \
1382 Fdefine_key (kboard->Vlocal_function_key_map, build_string (sequence), \
1383 Fmake_vector (make_number (1), \
1387 /* if there's no key_next keycap, map key_npage to `next' keysym */
1388 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1389 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1390 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1391 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1392 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1393 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1394 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1396 /* IBM has their own non-standard dialect of terminfo.
1397 If the standard name isn't found, try the IBM name. */
1398 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1399 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1400 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1401 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1402 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1403 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1404 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1405 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1406 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1407 #undef CONDITIONAL_REASSIGN
1414 /***********************************************************************
1415 Character Display Information
1416 ***********************************************************************/
1418 /* Avoid name clash with functions defined in xterm.c */
1420 #define append_glyph append_glyph_term
1421 #define produce_stretch_glyph produce_stretch_glyph_term
1424 static void append_glyph
P_ ((struct it
*));
1425 static void produce_stretch_glyph
P_ ((struct it
*));
1428 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1429 terminal frames if IT->glyph_row != NULL. IT->char_to_display is
1430 the character for which to produce glyphs; IT->face_id contains the
1431 character's face. Padding glyphs are appended if IT->c has a
1432 IT->pixel_width > 1. */
1438 struct glyph
*glyph
, *end
;
1441 xassert (it
->glyph_row
);
1442 glyph
= (it
->glyph_row
->glyphs
[it
->area
]
1443 + it
->glyph_row
->used
[it
->area
]);
1444 end
= it
->glyph_row
->glyphs
[1 + it
->area
];
1447 i
< it
->pixel_width
&& glyph
< end
;
1450 glyph
->type
= CHAR_GLYPH
;
1451 glyph
->pixel_width
= 1;
1452 glyph
->u
.ch
= it
->char_to_display
;
1453 glyph
->face_id
= it
->face_id
;
1454 glyph
->padding_p
= i
> 0;
1455 glyph
->charpos
= CHARPOS (it
->position
);
1456 glyph
->object
= it
->object
;
1458 ++it
->glyph_row
->used
[it
->area
];
1464 /* Produce glyphs for the display element described by IT. *IT
1465 specifies what we want to produce a glyph for (character, image, ...),
1466 and where in the glyph matrix we currently are (glyph row and hpos).
1467 produce_glyphs fills in output fields of *IT with information such as the
1468 pixel width and height of a character, and maybe output actual glyphs at
1469 the same time if IT->glyph_row is non-null. See the explanation of
1470 struct display_iterator in dispextern.h for an overview.
1472 produce_glyphs also stores the result of glyph width, ascent
1473 etc. computations in *IT.
1475 IT->glyph_row may be null, in which case produce_glyphs does not
1476 actually fill in the glyphs. This is used in the move_* functions
1477 in xdisp.c for text width and height computations.
1479 Callers usually don't call produce_glyphs directly;
1480 instead they use the macro PRODUCE_GLYPHS. */
1486 /* If a hook is installed, let it do the work. */
1487 xassert (it
->what
== IT_CHARACTER
1488 || it
->what
== IT_COMPOSITION
1489 || it
->what
== IT_STRETCH
);
1491 if (it
->what
== IT_STRETCH
)
1493 produce_stretch_glyph (it
);
1497 /* Nothing but characters are supported on terminal frames. For a
1498 composition sequence, it->c is the first character of the
1500 xassert (it
->what
== IT_CHARACTER
1501 || it
->what
== IT_COMPOSITION
);
1503 /* Maybe translate single-byte characters to multibyte. */
1504 it
->char_to_display
= it
->c
;
1506 if (it
->c
>= 040 && it
->c
< 0177)
1508 it
->pixel_width
= it
->nglyphs
= 1;
1512 else if (it
->c
== '\n')
1513 it
->pixel_width
= it
->nglyphs
= 0;
1514 else if (it
->c
== '\t')
1516 int absolute_x
= (it
->current_x
1517 + it
->continuation_lines_width
);
1519 = (((1 + absolute_x
+ it
->tab_width
- 1)
1524 /* If part of the TAB has been displayed on the previous line
1525 which is continued now, continuation_lines_width will have
1526 been incremented already by the part that fitted on the
1527 continued line. So, we will get the right number of spaces
1529 nspaces
= next_tab_x
- absolute_x
;
1535 it
->char_to_display
= ' ';
1536 it
->pixel_width
= it
->len
= 1;
1542 it
->pixel_width
= nspaces
;
1543 it
->nglyphs
= nspaces
;
1545 else if (SINGLE_BYTE_CHAR_P (it
->c
))
1547 if (unibyte_display_via_language_environment
1549 || !NILP (Vnonascii_translation_table
)))
1553 it
->char_to_display
= unibyte_char_to_multibyte (it
->c
);
1554 charset
= CHAR_CHARSET (it
->char_to_display
);
1555 it
->pixel_width
= CHARSET_WIDTH (charset
);
1556 it
->nglyphs
= it
->pixel_width
;
1562 /* Coming here means that it->c is from display table, thus we
1563 must send the code as is to the terminal. Although there's
1564 no way to know how many columns it occupies on a screen, it
1565 is a good assumption that a single byte code has 1-column
1567 it
->pixel_width
= it
->nglyphs
= 1;
1574 /* A multi-byte character. The display width is fixed for all
1575 characters of the set. Some of the glyphs may have to be
1576 ignored because they are already displayed in a continued
1578 int charset
= CHAR_CHARSET (it
->c
);
1580 it
->pixel_width
= CHARSET_WIDTH (charset
);
1581 it
->nglyphs
= it
->pixel_width
;
1588 /* Advance current_x by the pixel width as a convenience for
1590 if (it
->area
== TEXT_AREA
)
1591 it
->current_x
+= it
->pixel_width
;
1592 it
->ascent
= it
->max_ascent
= it
->phys_ascent
= it
->max_phys_ascent
= 0;
1593 it
->descent
= it
->max_descent
= it
->phys_descent
= it
->max_phys_descent
= 1;
1597 /* Produce a stretch glyph for iterator IT. IT->object is the value
1598 of the glyph property displayed. The value must be a list
1599 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1602 1. `:width WIDTH' specifies that the space should be WIDTH *
1603 canonical char width wide. WIDTH may be an integer or floating
1606 2. `:align-to HPOS' specifies that the space should be wide enough
1607 to reach HPOS, a value in canonical character units. */
1610 produce_stretch_glyph (it
)
1613 /* (space :width WIDTH ...) */
1614 Lisp_Object prop
, plist
;
1615 int width
= 0, align_to
= -1;
1616 int zero_width_ok_p
= 0;
1619 /* List should start with `space'. */
1620 xassert (CONSP (it
->object
) && EQ (XCAR (it
->object
), Qspace
));
1621 plist
= XCDR (it
->object
);
1623 /* Compute the width of the stretch. */
1624 if ((prop
= Fplist_get (plist
, QCwidth
), !NILP (prop
))
1625 && calc_pixel_width_or_height (&tem
, it
, prop
, 0, 1, 0))
1627 /* Absolute width `:width WIDTH' specified and valid. */
1628 zero_width_ok_p
= 1;
1629 width
= (int)(tem
+ 0.5);
1631 else if ((prop
= Fplist_get (plist
, QCalign_to
), !NILP (prop
))
1632 && calc_pixel_width_or_height (&tem
, it
, prop
, 0, 1, &align_to
))
1634 if (it
->glyph_row
== NULL
|| !it
->glyph_row
->mode_line_p
)
1635 align_to
= (align_to
< 0
1637 : align_to
- window_box_left_offset (it
->w
, TEXT_AREA
));
1638 else if (align_to
< 0)
1639 align_to
= window_box_left_offset (it
->w
, TEXT_AREA
);
1640 width
= max (0, (int)(tem
+ 0.5) + align_to
- it
->current_x
);
1641 zero_width_ok_p
= 1;
1644 /* Nothing specified -> width defaults to canonical char width. */
1645 width
= FRAME_COLUMN_WIDTH (it
->f
);
1647 if (width
<= 0 && (width
< 0 || !zero_width_ok_p
))
1650 if (width
> 0 && it
->glyph_row
)
1652 Lisp_Object o_object
= it
->object
;
1653 Lisp_Object object
= it
->stack
[it
->sp
- 1].string
;
1656 if (!STRINGP (object
))
1657 object
= it
->w
->buffer
;
1658 it
->object
= object
;
1659 it
->char_to_display
= ' ';
1660 it
->pixel_width
= it
->len
= 1;
1663 it
->object
= o_object
;
1665 it
->pixel_width
= width
;
1666 it
->nglyphs
= width
;
1670 /* Get information about special display element WHAT in an
1671 environment described by IT. WHAT is one of IT_TRUNCATION or
1672 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1673 non-null glyph_row member. This function ensures that fields like
1674 face_id, c, len of IT are left untouched. */
1677 produce_special_glyphs (it
, what
)
1679 enum display_element_type what
;
1686 temp_it
.what
= IT_CHARACTER
;
1688 temp_it
.object
= make_number (0);
1689 bzero (&temp_it
.current
, sizeof temp_it
.current
);
1691 if (what
== IT_CONTINUATION
)
1693 /* Continuation glyph. */
1695 && INTEGERP (DISP_CONTINUE_GLYPH (it
->dp
))
1696 && GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (it
->dp
))))
1698 glyph
= XINT (DISP_CONTINUE_GLYPH (it
->dp
));
1699 glyph
= spec_glyph_lookup_face (XWINDOW (it
->window
), glyph
);
1704 else if (what
== IT_TRUNCATION
)
1706 /* Truncation glyph. */
1708 && INTEGERP (DISP_TRUNC_GLYPH (it
->dp
))
1709 && GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (it
->dp
))))
1711 glyph
= XINT (DISP_TRUNC_GLYPH (it
->dp
));
1712 glyph
= spec_glyph_lookup_face (XWINDOW (it
->window
), glyph
);
1720 temp_it
.c
= FAST_GLYPH_CHAR (glyph
);
1721 temp_it
.face_id
= FAST_GLYPH_FACE (glyph
);
1722 temp_it
.len
= CHAR_BYTES (temp_it
.c
);
1724 produce_glyphs (&temp_it
);
1725 it
->pixel_width
= temp_it
.pixel_width
;
1726 it
->nglyphs
= temp_it
.pixel_width
;
1731 /***********************************************************************
1733 ***********************************************************************/
1735 /* Value is non-zero if attribute ATTR may be used. ATTR should be
1736 one of the enumerators from enum no_color_bit, or a bit set built
1737 from them. Some display attributes may not be used together with
1738 color; the termcap capability `NC' specifies which ones. */
1740 #define MAY_USE_WITH_COLORS_P(tty, ATTR) \
1741 (tty->TN_max_colors > 0 \
1742 ? (tty->TN_no_color_video & (ATTR)) == 0 \
1745 /* Turn appearances of face FACE_ID on tty frame F on.
1746 FACE_ID is a realized face ID number, in the face cache. */
1749 turn_on_face (f
, face_id
)
1753 struct face
*face
= FACE_FROM_ID (f
, face_id
);
1754 long fg
= face
->foreground
;
1755 long bg
= face
->background
;
1756 struct tty_display_info
*tty
= FRAME_TTY (f
);
1758 /* Do this first because TS_end_standout_mode may be the same
1759 as TS_exit_attribute_mode, which turns all appearances off. */
1760 if (MAY_USE_WITH_COLORS_P (tty
, NC_REVERSE
))
1762 if (tty
->TN_max_colors
> 0)
1764 if (fg
>= 0 && bg
>= 0)
1766 /* If the terminal supports colors, we can set them
1767 below without using reverse video. The face's fg
1768 and bg colors are set as they should appear on
1769 the screen, i.e. they take the inverse-video'ness
1770 of the face already into account. */
1772 else if (inverse_video
)
1774 if (fg
== FACE_TTY_DEFAULT_FG_COLOR
1775 || bg
== FACE_TTY_DEFAULT_BG_COLOR
)
1776 tty_toggle_highlight (tty
);
1780 if (fg
== FACE_TTY_DEFAULT_BG_COLOR
1781 || bg
== FACE_TTY_DEFAULT_FG_COLOR
)
1782 tty_toggle_highlight (tty
);
1787 /* If we can't display colors, use reverse video
1788 if the face specifies that. */
1791 if (fg
== FACE_TTY_DEFAULT_FG_COLOR
1792 || bg
== FACE_TTY_DEFAULT_BG_COLOR
)
1793 tty_toggle_highlight (tty
);
1797 if (fg
== FACE_TTY_DEFAULT_BG_COLOR
1798 || bg
== FACE_TTY_DEFAULT_FG_COLOR
)
1799 tty_toggle_highlight (tty
);
1804 if (face
->tty_bold_p
)
1806 if (MAY_USE_WITH_COLORS_P (tty
, NC_BOLD
))
1807 OUTPUT1_IF (tty
, tty
->TS_enter_bold_mode
);
1809 else if (face
->tty_dim_p
)
1810 if (MAY_USE_WITH_COLORS_P (tty
, NC_DIM
))
1811 OUTPUT1_IF (tty
, tty
->TS_enter_dim_mode
);
1813 /* Alternate charset and blinking not yet used. */
1814 if (face
->tty_alt_charset_p
1815 && MAY_USE_WITH_COLORS_P (tty
, NC_ALT_CHARSET
))
1816 OUTPUT1_IF (tty
, tty
->TS_enter_alt_charset_mode
);
1818 if (face
->tty_blinking_p
1819 && MAY_USE_WITH_COLORS_P (tty
, NC_BLINK
))
1820 OUTPUT1_IF (tty
, tty
->TS_enter_blink_mode
);
1822 if (face
->tty_underline_p
&& MAY_USE_WITH_COLORS_P (tty
, NC_UNDERLINE
))
1823 OUTPUT1_IF (tty
, tty
->TS_enter_underline_mode
);
1825 if (tty
->TN_max_colors
> 0)
1829 ts
= tty
->standout_mode
? tty
->TS_set_background
: tty
->TS_set_foreground
;
1832 p
= tparam (ts
, NULL
, 0, (int) fg
);
1837 ts
= tty
->standout_mode
? tty
->TS_set_foreground
: tty
->TS_set_background
;
1840 p
= tparam (ts
, NULL
, 0, (int) bg
);
1848 /* Turn off appearances of face FACE_ID on tty frame F. */
1851 turn_off_face (f
, face_id
)
1855 struct face
*face
= FACE_FROM_ID (f
, face_id
);
1856 struct tty_display_info
*tty
= FRAME_TTY (f
);
1858 xassert (face
!= NULL
);
1860 if (tty
->TS_exit_attribute_mode
)
1862 /* Capability "me" will turn off appearance modes double-bright,
1863 half-bright, reverse-video, standout, underline. It may or
1864 may not turn off alt-char-mode. */
1865 if (face
->tty_bold_p
1867 || face
->tty_reverse_p
1868 || face
->tty_alt_charset_p
1869 || face
->tty_blinking_p
1870 || face
->tty_underline_p
)
1872 OUTPUT1_IF (tty
, tty
->TS_exit_attribute_mode
);
1873 if (strcmp (tty
->TS_exit_attribute_mode
, tty
->TS_end_standout_mode
) == 0)
1874 tty
->standout_mode
= 0;
1877 if (face
->tty_alt_charset_p
)
1878 OUTPUT_IF (tty
, tty
->TS_exit_alt_charset_mode
);
1882 /* If we don't have "me" we can only have those appearances
1883 that have exit sequences defined. */
1884 if (face
->tty_alt_charset_p
)
1885 OUTPUT_IF (tty
, tty
->TS_exit_alt_charset_mode
);
1887 if (face
->tty_underline_p
)
1888 OUTPUT_IF (tty
, tty
->TS_exit_underline_mode
);
1891 /* Switch back to default colors. */
1892 if (tty
->TN_max_colors
> 0
1893 && ((face
->foreground
!= FACE_TTY_DEFAULT_COLOR
1894 && face
->foreground
!= FACE_TTY_DEFAULT_FG_COLOR
)
1895 || (face
->background
!= FACE_TTY_DEFAULT_COLOR
1896 && face
->background
!= FACE_TTY_DEFAULT_BG_COLOR
)))
1897 OUTPUT1_IF (tty
, tty
->TS_orig_pair
);
1901 /* Return non-zero if the terminal on frame F supports all of the
1902 capabilities in CAPS simultaneously, with foreground and background
1903 colors FG and BG. */
1906 tty_capable_p (tty
, caps
, fg
, bg
)
1907 struct tty_display_info
*tty
;
1909 unsigned long fg
, bg
;
1911 #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
1912 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
1915 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_INVERSE
, tty
->TS_standout_mode
, NC_REVERSE
);
1916 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_UNDERLINE
, tty
->TS_enter_underline_mode
, NC_UNDERLINE
);
1917 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_BOLD
, tty
->TS_enter_bold_mode
, NC_BOLD
);
1918 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_DIM
, tty
->TS_enter_dim_mode
, NC_DIM
);
1919 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_BLINK
, tty
->TS_enter_blink_mode
, NC_BLINK
);
1920 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_ALT_CHARSET
, tty
->TS_enter_alt_charset_mode
, NC_ALT_CHARSET
);
1926 /* Return non-zero if the terminal is capable to display colors. */
1928 DEFUN ("tty-display-color-p", Ftty_display_color_p
, Stty_display_color_p
,
1930 doc
: /* Return non-nil if the tty device TERMINAL can display colors.
1932 TERMINAL can be a terminal id, a frame or nil (meaning the selected
1933 frame's terminal). This function always returns nil if TERMINAL
1934 is not on a tty device. */)
1936 Lisp_Object terminal
;
1938 struct terminal
*t
= get_tty_terminal (terminal
, 0);
1942 return t
->display_info
.tty
->TN_max_colors
> 0 ? Qt
: Qnil
;
1945 /* Return the number of supported colors. */
1946 DEFUN ("tty-display-color-cells", Ftty_display_color_cells
,
1947 Stty_display_color_cells
, 0, 1, 0,
1948 doc
: /* Return the number of colors supported by the tty device TERMINAL.
1950 TERMINAL can be a terminal id, a frame or nil (meaning the selected
1951 frame's terminal). This function always returns 0 if TERMINAL
1952 is not on a tty device. */)
1954 Lisp_Object terminal
;
1956 struct terminal
*t
= get_tty_terminal (terminal
, 0);
1958 return make_number (0);
1960 return make_number (t
->display_info
.tty
->TN_max_colors
);
1965 /* Declare here rather than in the function, as in the rest of Emacs,
1966 to work around an HPUX compiler bug (?). See
1967 http://lists.gnu.org/archive/html/emacs-devel/2007-08/msg00410.html */
1968 static int default_max_colors
;
1969 static int default_max_pairs
;
1970 static int default_no_color_video
;
1971 static char *default_orig_pair
;
1972 static char *default_set_foreground
;
1973 static char *default_set_background
;
1975 /* Save or restore the default color-related capabilities of this
1978 tty_default_color_capabilities (struct tty_display_info
*tty
, int save
)
1983 if (default_orig_pair
)
1984 xfree (default_orig_pair
);
1985 default_orig_pair
= tty
->TS_orig_pair
? xstrdup (tty
->TS_orig_pair
) : NULL
;
1987 if (default_set_foreground
)
1988 xfree (default_set_foreground
);
1989 default_set_foreground
= tty
->TS_set_foreground
? xstrdup (tty
->TS_set_foreground
)
1992 if (default_set_background
)
1993 xfree (default_set_background
);
1994 default_set_background
= tty
->TS_set_background
? xstrdup (tty
->TS_set_background
)
1997 default_max_colors
= tty
->TN_max_colors
;
1998 default_max_pairs
= tty
->TN_max_pairs
;
1999 default_no_color_video
= tty
->TN_no_color_video
;
2003 tty
->TS_orig_pair
= default_orig_pair
;
2004 tty
->TS_set_foreground
= default_set_foreground
;
2005 tty
->TS_set_background
= default_set_background
;
2006 tty
->TN_max_colors
= default_max_colors
;
2007 tty
->TN_max_pairs
= default_max_pairs
;
2008 tty
->TN_no_color_video
= default_no_color_video
;
2012 /* Setup one of the standard tty color schemes according to MODE.
2013 MODE's value is generally the number of colors which we want to
2014 support; zero means set up for the default capabilities, the ones
2015 we saw at init_tty time; -1 means turn off color support. */
2017 tty_setup_colors (struct tty_display_info
*tty
, int mode
)
2019 /* Canonicalize all negative values of MODE. */
2025 case -1: /* no colors at all */
2026 tty
->TN_max_colors
= 0;
2027 tty
->TN_max_pairs
= 0;
2028 tty
->TN_no_color_video
= 0;
2029 tty
->TS_set_foreground
= tty
->TS_set_background
= tty
->TS_orig_pair
= NULL
;
2031 case 0: /* default colors, if any */
2033 tty_default_color_capabilities (tty
, 0);
2035 case 8: /* 8 standard ANSI colors */
2036 tty
->TS_orig_pair
= "\033[0m";
2038 tty
->TS_set_foreground
= "\033[3%p1%dm";
2039 tty
->TS_set_background
= "\033[4%p1%dm";
2041 tty
->TS_set_foreground
= "\033[3%dm";
2042 tty
->TS_set_background
= "\033[4%dm";
2044 tty
->TN_max_colors
= 8;
2045 tty
->TN_max_pairs
= 64;
2046 tty
->TN_no_color_video
= 0;
2052 set_tty_color_mode (f
, val
)
2056 Lisp_Object color_mode_spec
, current_mode_spec
;
2057 Lisp_Object color_mode
, current_mode
;
2059 extern Lisp_Object Qtty_color_mode
;
2060 Lisp_Object tty_color_mode_alist
;
2062 tty_color_mode_alist
= Fintern_soft (build_string ("tty-color-mode-alist"),
2069 if (NILP (tty_color_mode_alist
))
2070 color_mode_spec
= Qnil
;
2072 color_mode_spec
= Fassq (val
, XSYMBOL (tty_color_mode_alist
)->value
);
2074 if (CONSP (color_mode_spec
))
2075 color_mode
= XCDR (color_mode_spec
);
2080 current_mode_spec
= assq_no_quit (Qtty_color_mode
, f
->param_alist
);
2082 if (CONSP (current_mode_spec
))
2083 current_mode
= XCDR (current_mode_spec
);
2085 current_mode
= Qnil
;
2086 if (INTEGERP (color_mode
))
2087 mode
= XINT (color_mode
);
2089 mode
= 0; /* meaning default */
2090 if (INTEGERP (current_mode
))
2091 old_mode
= XINT (current_mode
);
2095 if (mode
!= old_mode
)
2097 tty_setup_colors (FRAME_TTY (f
), mode
);
2098 /* This recomputes all the faces given the new color
2100 call0 (intern ("tty-set-up-initial-frame-faces"));
2105 #endif /* !WINDOWSNT */
2109 /* Return the tty display object specified by TERMINAL. */
2112 get_tty_terminal (Lisp_Object terminal
, int throw)
2114 struct terminal
*t
= get_terminal (terminal
, throw);
2116 if (t
&& t
->type
!= output_termcap
)
2119 error ("Device %d is not a termcap terminal device", t
->id
);
2127 /* Return an active termcap device that uses the tty device with the
2130 This function ignores suspended devices.
2132 Returns NULL if the named terminal device is not opened. */
2135 get_named_tty (name
)
2143 for (t
= terminal_list
; t
; t
= t
->next_terminal
)
2145 if (t
->type
== output_termcap
2146 && !strcmp (t
->display_info
.tty
->name
, name
)
2147 && TERMINAL_ACTIVE_P (t
))
2155 DEFUN ("tty-type", Ftty_type
, Stty_type
, 0, 1, 0,
2156 doc
: /* Return the type of the tty device that TERMINAL uses.
2157 Returns nil if TERMINAL is not on a tty device.
2159 TERMINAL can be a terminal id, a frame or nil (meaning the selected
2160 frame's terminal). */)
2162 Lisp_Object terminal
;
2164 struct terminal
*t
= get_terminal (terminal
, 1);
2166 if (t
->type
!= output_termcap
)
2169 if (t
->display_info
.tty
->type
)
2170 return build_string (t
->display_info
.tty
->type
);
2175 DEFUN ("controlling-tty-p", Fcontrolling_tty_p
, Scontrolling_tty_p
, 0, 1, 0,
2176 doc
: /* Return non-nil if TERMINAL is on the controlling tty of the Emacs process.
2178 TERMINAL can be a terminal id, a frame or nil (meaning the selected
2179 frame's terminal). This function always returns nil if TERMINAL
2180 is not on a tty device. */)
2182 Lisp_Object terminal
;
2184 struct terminal
*t
= get_terminal (terminal
, 1);
2186 if (t
->type
!= output_termcap
|| strcmp (t
->display_info
.tty
->name
, DEV_TTY
))
2192 DEFUN ("tty-no-underline", Ftty_no_underline
, Stty_no_underline
, 0, 1, 0,
2193 doc
: /* Declare that the tty used by TERMINAL does not handle underlining.
2194 This is used to override the terminfo data, for certain terminals that
2195 do not really do underlining, but say that they do. This function has
2196 no effect if used on a non-tty terminal.
2198 TERMINAL can be a terminal id, a frame or nil (meaning the selected
2199 frame's terminal). This function always returns nil if TERMINAL
2200 is not on a tty device. */)
2202 Lisp_Object terminal
;
2204 struct terminal
*t
= get_terminal (terminal
, 1);
2206 if (t
->type
== output_termcap
)
2207 t
->display_info
.tty
->TS_enter_underline_mode
= 0;
2213 DEFUN ("suspend-tty", Fsuspend_tty
, Ssuspend_tty
, 0, 1, 0,
2214 doc
: /* Suspend the terminal device TTY.
2216 The device is restored to its default state, and Emacs ceases all
2217 access to the tty device. Frames that use the device are not deleted,
2218 but input is not read from them and if they change, their display is
2221 TTY may be a terminal id, a frame, or nil for the terminal device of
2222 the currently selected frame.
2224 This function runs `suspend-tty-functions' after suspending the
2225 device. The functions are run with one arg, the id of the suspended
2228 `suspend-tty' does nothing if it is called on a device that is already
2231 A suspended tty may be resumed by calling `resume-tty' on it. */)
2235 struct terminal
*t
= get_tty_terminal (tty
, 1);
2239 error ("Unknown tty device");
2241 f
= t
->display_info
.tty
->input
;
2245 /* First run `suspend-tty-functions' and then clean up the tty
2246 state because `suspend-tty-functions' might need to change
2248 if (!NILP (Vrun_hooks
))
2250 Lisp_Object args
[2];
2251 args
[0] = intern ("suspend-tty-functions");
2252 XSETTERMINAL (args
[1], t
);
2253 Frun_hook_with_args (2, args
);
2256 reset_sys_modes (t
->display_info
.tty
);
2258 delete_keyboard_wait_descriptor (fileno (f
));
2261 if (f
!= t
->display_info
.tty
->output
)
2262 fclose (t
->display_info
.tty
->output
);
2264 t
->display_info
.tty
->input
= 0;
2265 t
->display_info
.tty
->output
= 0;
2267 if (FRAMEP (t
->display_info
.tty
->top_frame
))
2268 FRAME_SET_VISIBLE (XFRAME (t
->display_info
.tty
->top_frame
), 0);
2272 /* Clear display hooks to prevent further output. */
2273 clear_tty_hooks (t
);
2278 DEFUN ("resume-tty", Fresume_tty
, Sresume_tty
, 0, 1, 0,
2279 doc
: /* Resume the previously suspended terminal device TTY.
2280 The terminal is opened and reinitialized. Frames that are on the
2281 suspended terminal are revived.
2283 It is an error to resume a terminal while another terminal is active
2286 This function runs `resume-tty-functions' after resuming the terminal.
2287 The functions are run with one arg, the id of the resumed terminal
2290 `resume-tty' does nothing if it is called on a device that is not
2293 TTY may be a terminal id, a frame, or nil for the terminal device of
2294 the currently selected frame. */)
2298 struct terminal
*t
= get_tty_terminal (tty
, 1);
2302 error ("Unknown tty device");
2304 if (!t
->display_info
.tty
->input
)
2306 if (get_named_tty (t
->display_info
.tty
->name
))
2307 error ("Cannot resume display while another display is active on the same device");
2309 fd
= emacs_open (t
->display_info
.tty
->name
, O_RDWR
| O_NOCTTY
, 0);
2312 error ("Can not reopen tty device %s: %s", t
->display_info
.tty
->name
, strerror (errno
));
2314 if (strcmp (t
->display_info
.tty
->name
, DEV_TTY
))
2315 dissociate_if_controlling_tty (fd
);
2317 t
->display_info
.tty
->output
= fdopen (fd
, "w+");
2318 t
->display_info
.tty
->input
= t
->display_info
.tty
->output
;
2320 add_keyboard_wait_descriptor (fd
);
2322 if (FRAMEP (t
->display_info
.tty
->top_frame
))
2323 FRAME_SET_VISIBLE (XFRAME (t
->display_info
.tty
->top_frame
), 1);
2325 init_sys_modes (t
->display_info
.tty
);
2327 /* Run `resume-tty-functions'. */
2328 if (!NILP (Vrun_hooks
))
2330 Lisp_Object args
[2];
2331 args
[0] = intern ("resume-tty-functions");
2332 XSETTERMINAL (args
[1], t
);
2333 Frun_hook_with_args (2, args
);
2343 /***********************************************************************
2345 ***********************************************************************/
2349 term_mouse_moveto (int x
, int y
)
2351 /* TODO: how to set mouse position?
2354 name = (const char *) ttyname (0);
2355 fd = open (name, O_WRONLY);
2356 SOME_FUNCTION (x, y, fd);
2359 last_mouse_y = y; */
2363 term_show_mouse_face (enum draw_glyphs_face draw
)
2365 struct window
*w
= XWINDOW (mouse_face_window
);
2369 struct frame
*f
= XFRAME (w
->frame
);
2370 struct tty_display_info
*tty
= FRAME_TTY (f
);
2372 if (/* If window is in the process of being destroyed, don't bother
2374 w
->current_matrix
!= NULL
2375 /* Recognize when we are called to operate on rows that don't exist
2376 anymore. This can happen when a window is split. */
2377 && mouse_face_end_row
< w
->current_matrix
->nrows
)
2379 /* write_glyphs writes at cursor position, so we need to
2380 temporarily move cursor coordinates to the beginning of
2381 the highlight region. */
2383 /* Save current cursor co-ordinates */
2384 save_y
= curY (tty
);
2385 save_x
= curX (tty
);
2387 /* Note that mouse_face_beg_row etc. are window relative. */
2388 for (i
= mouse_face_beg_row
; i
<= mouse_face_end_row
; i
++)
2390 int start_hpos
, end_hpos
, nglyphs
;
2391 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, i
);
2393 /* Don't do anything if row doesn't have valid contents. */
2394 if (!row
->enabled_p
)
2397 /* For all but the first row, the highlight starts at column 0. */
2398 if (i
== mouse_face_beg_row
)
2399 start_hpos
= mouse_face_beg_col
;
2403 if (i
== mouse_face_end_row
)
2404 end_hpos
= mouse_face_end_col
;
2407 end_hpos
= row
->used
[TEXT_AREA
];
2408 if (draw
== DRAW_NORMAL_TEXT
)
2409 row
->fill_line_p
= 1; /* Clear to end of line */
2412 if (end_hpos
<= start_hpos
)
2414 /* Record that some glyphs of this row are displayed in
2416 row
->mouse_face_p
= draw
> 0;
2418 nglyphs
= end_hpos
- start_hpos
;
2420 if (end_hpos
>= row
->used
[TEXT_AREA
])
2421 nglyphs
= row
->used
[TEXT_AREA
] - start_hpos
;
2423 pos_y
= row
->y
+ WINDOW_TOP_EDGE_Y (w
);
2424 pos_x
= row
->used
[LEFT_MARGIN_AREA
] + start_hpos
2425 + WINDOW_LEFT_EDGE_X (w
);
2427 cursor_to (f
, pos_y
, pos_x
);
2429 if (draw
== DRAW_MOUSE_FACE
)
2431 tty_write_glyphs_with_face (f
, row
->glyphs
[TEXT_AREA
] + start_hpos
,
2432 nglyphs
, mouse_face_face_id
);
2434 else /* draw == DRAW_NORMAL_TEXT */
2435 write_glyphs (f
, row
->glyphs
[TEXT_AREA
] + start_hpos
, nglyphs
);
2437 cursor_to (f
, save_y
, save_x
);
2442 term_clear_mouse_face ()
2444 if (!NILP (mouse_face_window
))
2445 term_show_mouse_face (DRAW_NORMAL_TEXT
);
2447 mouse_face_beg_row
= mouse_face_beg_col
= -1;
2448 mouse_face_end_row
= mouse_face_end_col
= -1;
2449 mouse_face_window
= Qnil
;
2452 /* Find the glyph matrix position of buffer position POS in window W.
2453 *HPOS and *VPOS are set to the positions found. W's current glyphs
2454 must be up to date. If POS is above window start return (0, 0).
2455 If POS is after end of W, return end of last line in W.
2456 - taken from msdos.c */
2458 fast_find_position (struct window
*w
, int pos
, int *hpos
, int *vpos
)
2460 int i
, lastcol
, line_start_position
, maybe_next_line_p
= 0;
2461 int yb
= window_text_bottom_y (w
);
2462 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, 0), *best_row
= row
;
2466 if (row
->used
[TEXT_AREA
])
2467 line_start_position
= row
->glyphs
[TEXT_AREA
]->charpos
;
2469 line_start_position
= 0;
2471 if (line_start_position
> pos
)
2473 /* If the position sought is the end of the buffer,
2474 don't include the blank lines at the bottom of the window. */
2475 else if (line_start_position
== pos
2476 && pos
== BUF_ZV (XBUFFER (w
->buffer
)))
2478 maybe_next_line_p
= 1;
2481 else if (line_start_position
> 0)
2484 /* Don't overstep the last matrix row, lest we get into the
2485 never-never land... */
2486 if (row
->y
+ 1 >= yb
)
2492 /* Find the right column within BEST_ROW. */
2495 for (i
= 0; i
< row
->used
[TEXT_AREA
]; i
++)
2497 struct glyph
*glyph
= row
->glyphs
[TEXT_AREA
] + i
;
2500 charpos
= glyph
->charpos
;
2507 else if (charpos
> pos
)
2509 else if (charpos
> 0)
2513 /* If we're looking for the end of the buffer,
2514 and we didn't find it in the line we scanned,
2515 use the start of the following line. */
2516 if (maybe_next_line_p
)
2523 *hpos
= lastcol
+ 1;
2528 term_mouse_highlight (struct frame
*f
, int x
, int y
)
2530 enum window_part part
;
2535 if (NILP (Vmouse_highlight
)
2536 || !f
->glyphs_initialized_p
)
2539 /* Which window is that in? */
2540 window
= window_from_coordinates (f
, x
, y
, &part
, &x
, &y
, 0);
2542 /* Not on a window -> return. */
2543 if (!WINDOWP (window
))
2546 if (!EQ (window
, mouse_face_window
))
2547 term_clear_mouse_face ();
2549 w
= XWINDOW (window
);
2551 /* Are we in a window whose display is up to date?
2552 And verify the buffer's text has not changed. */
2553 b
= XBUFFER (w
->buffer
);
2555 && EQ (w
->window_end_valid
, w
->buffer
)
2556 && XFASTINT (w
->last_modified
) == BUF_MODIFF (b
)
2557 && XFASTINT (w
->last_overlay_modified
) == BUF_OVERLAY_MODIFF (b
))
2559 int pos
, i
, nrows
= w
->current_matrix
->nrows
;
2560 struct glyph_row
*row
;
2561 struct glyph
*glyph
;
2563 /* Find the glyph under X/Y. */
2565 if (y
>= 0 && y
< nrows
)
2567 row
= MATRIX_ROW (w
->current_matrix
, y
);
2568 /* Give up if some row before the one we are looking for is
2570 for (i
= 0; i
<= y
; i
++)
2571 if (!MATRIX_ROW (w
->current_matrix
, i
)->enabled_p
)
2573 if (i
> y
/* all rows upto and including the one at Y are enabled */
2574 && row
->displays_text_p
2575 && x
< window_box_width (w
, TEXT_AREA
))
2577 glyph
= row
->glyphs
[TEXT_AREA
];
2578 if (x
>= row
->used
[TEXT_AREA
])
2583 if (!BUFFERP (glyph
->object
))
2589 /* Clear mouse face if X/Y not over text. */
2592 term_clear_mouse_face ();
2596 if (!BUFFERP (glyph
->object
))
2598 pos
= glyph
->charpos
;
2600 /* Check for mouse-face. */
2602 extern Lisp_Object Qmouse_face
;
2603 Lisp_Object mouse_face
, overlay
, position
, *overlay_vec
;
2604 int noverlays
, obegv
, ozv
;
2605 struct buffer
*obuf
;
2607 /* If we get an out-of-range value, return now; avoid an error. */
2608 if (pos
> BUF_Z (b
))
2611 /* Make the window's buffer temporarily current for
2612 overlays_at and compute_char_face. */
2613 obuf
= current_buffer
;
2620 /* Is this char mouse-active? */
2621 XSETINT (position
, pos
);
2623 /* Put all the overlays we want in a vector in overlay_vec. */
2624 GET_OVERLAYS_AT (pos
, overlay_vec
, noverlays
, NULL
, 0);
2625 /* Sort overlays into increasing priority order. */
2626 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
2628 /* Check mouse-face highlighting. */
2629 if (!(EQ (window
, mouse_face_window
)
2630 && y
>= mouse_face_beg_row
2631 && y
<= mouse_face_end_row
2632 && (y
> mouse_face_beg_row
2633 || x
>= mouse_face_beg_col
)
2634 && (y
< mouse_face_end_row
2635 || x
< mouse_face_end_col
2636 || mouse_face_past_end
)))
2638 /* Clear the display of the old active region, if any. */
2639 term_clear_mouse_face ();
2641 /* Find the highest priority overlay that has a mouse-face
2644 for (i
= noverlays
- 1; i
>= 0; --i
)
2646 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
2647 if (!NILP (mouse_face
))
2649 overlay
= overlay_vec
[i
];
2654 /* If no overlay applies, get a text property. */
2656 mouse_face
= Fget_text_property (position
, Qmouse_face
,
2659 /* Handle the overlay case. */
2660 if (!NILP (overlay
))
2662 /* Find the range of text around this char that
2663 should be active. */
2664 Lisp_Object before
, after
;
2668 before
= Foverlay_start (overlay
);
2669 after
= Foverlay_end (overlay
);
2670 /* Record this as the current active region. */
2671 fast_find_position (w
, XFASTINT (before
),
2672 &mouse_face_beg_col
,
2673 &mouse_face_beg_row
);
2676 = !fast_find_position (w
, XFASTINT (after
),
2677 &mouse_face_end_col
,
2678 &mouse_face_end_row
);
2679 mouse_face_window
= window
;
2682 = face_at_buffer_position (w
, pos
, 0, 0,
2683 &ignore
, pos
+ 1, 1);
2685 /* Display it as active. */
2686 term_show_mouse_face (DRAW_MOUSE_FACE
);
2688 /* Handle the text property case. */
2689 else if (!NILP (mouse_face
))
2691 /* Find the range of text around this char that
2692 should be active. */
2693 Lisp_Object before
, after
, beginning
, end
;
2696 beginning
= Fmarker_position (w
->start
);
2697 XSETINT (end
, (BUF_Z (b
) - XFASTINT (w
->window_end_pos
)));
2699 = Fprevious_single_property_change (make_number (pos
+ 1),
2701 w
->buffer
, beginning
);
2703 = Fnext_single_property_change (position
, Qmouse_face
,
2706 /* Record this as the current active region. */
2707 fast_find_position (w
, XFASTINT (before
),
2708 &mouse_face_beg_col
,
2709 &mouse_face_beg_row
);
2711 = !fast_find_position (w
, XFASTINT (after
),
2712 &mouse_face_end_col
,
2713 &mouse_face_end_row
);
2714 mouse_face_window
= window
;
2717 = face_at_buffer_position (w
, pos
, 0, 0,
2718 &ignore
, pos
+ 1, 1);
2720 /* Display it as active. */
2721 term_show_mouse_face (DRAW_MOUSE_FACE
);
2725 /* Look for a `help-echo' property. */
2728 extern Lisp_Object Qhelp_echo
;
2730 /* Check overlays first. */
2732 for (i
= noverlays
- 1; i
>= 0 && NILP (help
); --i
)
2734 overlay
= overlay_vec
[i
];
2735 help
= Foverlay_get (overlay
, Qhelp_echo
);
2740 help_echo_string
= help
;
2741 help_echo_window
= window
;
2742 help_echo_object
= overlay
;
2743 help_echo_pos
= pos
;
2745 /* Try text properties. */
2746 else if (NILP (help
)
2747 && ((STRINGP (glyph
->object
)
2748 && glyph
->charpos
>= 0
2749 && glyph
->charpos
< SCHARS (glyph
->object
))
2750 || (BUFFERP (glyph
->object
)
2751 && glyph
->charpos
>= BEGV
2752 && glyph
->charpos
< ZV
)))
2754 help
= Fget_text_property (make_number (glyph
->charpos
),
2755 Qhelp_echo
, glyph
->object
);
2758 help_echo_string
= help
;
2759 help_echo_window
= window
;
2760 help_echo_object
= glyph
->object
;
2761 help_echo_pos
= glyph
->charpos
;
2768 current_buffer
= obuf
;
2774 term_mouse_movement (FRAME_PTR frame
, Gpm_Event
*event
)
2776 /* Has the mouse moved off the glyph it was on at the last sighting? */
2777 if (event
->x
!= last_mouse_x
|| event
->y
!= last_mouse_y
)
2779 frame
->mouse_moved
= 1;
2780 term_mouse_highlight (frame
, event
->x
, event
->y
);
2781 /* Remember which glyph we're now on. */
2782 last_mouse_x
= event
->x
;
2783 last_mouse_y
= event
->y
;
2789 /* Return the current position of the mouse.
2791 Set *f to the frame the mouse is in, or zero if the mouse is in no
2792 Emacs frame. If it is set to zero, all the other arguments are
2795 Set *bar_window to Qnil, and *x and *y to the column and
2796 row of the character cell the mouse is over.
2798 Set *time to the time the mouse was at the returned position.
2800 This clears mouse_moved until the next motion
2803 term_mouse_position (FRAME_PTR
*fp
, int insist
, Lisp_Object
*bar_window
,
2804 enum scroll_bar_part
*part
, Lisp_Object
*x
,
2805 Lisp_Object
*y
, unsigned long *time
)
2809 *fp
= SELECTED_FRAME ();
2810 (*fp
)->mouse_moved
= 0;
2815 XSETINT (*x
, last_mouse_x
);
2816 XSETINT (*y
, last_mouse_y
);
2817 gettimeofday(&now
, 0);
2818 *time
= (now
.tv_sec
* 1000) + (now
.tv_usec
/ 1000);
2821 /* Prepare a mouse-event in *RESULT for placement in the input queue.
2823 If the event is a button press, then note that we have grabbed
2827 term_mouse_click (struct input_event
*result
, Gpm_Event
*event
,
2833 result
->kind
= GPM_CLICK_EVENT
;
2834 for (i
= 0, j
= GPM_B_LEFT
; i
< 3; i
++, j
>>= 1 )
2836 if (event
->buttons
& j
) {
2837 result
->code
= i
; /* button number */
2841 gettimeofday(&now
, 0);
2842 result
->timestamp
= (now
.tv_sec
* 1000) + (now
.tv_usec
/ 1000);
2844 if (event
->type
& GPM_UP
)
2845 result
->modifiers
= up_modifier
;
2846 else if (event
->type
& GPM_DOWN
)
2847 result
->modifiers
= down_modifier
;
2849 result
->modifiers
= 0;
2851 if (event
->type
& GPM_SINGLE
)
2852 result
->modifiers
|= click_modifier
;
2854 if (event
->type
& GPM_DOUBLE
)
2855 result
->modifiers
|= double_modifier
;
2857 if (event
->type
& GPM_TRIPLE
)
2858 result
->modifiers
|= triple_modifier
;
2860 if (event
->type
& GPM_DRAG
)
2861 result
->modifiers
|= drag_modifier
;
2863 if (!(event
->type
& (GPM_MOVE
| GPM_DRAG
))) {
2866 if (event
->modifiers
& (1 << 0))
2867 result
->modifiers
|= shift_modifier
;
2870 if (event
->modifiers
& (1 << 2))
2871 result
->modifiers
|= ctrl_modifier
;
2873 /* 1 << KG_ALT || KG_ALTGR */
2874 if (event
->modifiers
& (1 << 3)
2875 || event
->modifiers
& (1 << 1))
2876 result
->modifiers
|= meta_modifier
;
2879 XSETINT (result
->x
, event
->x
);
2880 XSETINT (result
->y
, event
->y
);
2881 XSETFRAME (result
->frame_or_window
, f
);
2887 handle_one_term_event (struct tty_display_info
*tty
, Gpm_Event
*event
, struct input_event
* hold_quit
)
2889 struct frame
*f
= XFRAME (tty
->top_frame
);
2890 struct input_event ie
;
2898 if (event
->type
& (GPM_MOVE
| GPM_DRAG
)) {
2899 previous_help_echo_string
= help_echo_string
;
2900 help_echo_string
= Qnil
;
2902 Gpm_DrawPointer (event
->x
, event
->y
, fileno (tty
->output
));
2904 if (!term_mouse_movement (f
, event
))
2905 help_echo_string
= previous_help_echo_string
;
2907 /* If the contents of the global variable help_echo_string
2908 has changed, generate a HELP_EVENT. */
2909 if (!NILP (help_echo_string
)
2910 || !NILP (previous_help_echo_string
))
2917 term_mouse_click (&ie
, event
, f
);
2921 if (ie
.kind
!= NO_EVENT
)
2923 kbd_buffer_store_event_hold (&ie
, hold_quit
);
2928 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
2933 XSETFRAME (frame
, f
);
2937 gen_help_event (help_echo_string
, frame
, help_echo_window
,
2938 help_echo_object
, help_echo_pos
);
2945 DEFUN ("gpm-mouse-start", Fgpm_mouse_start
, Sgpm_mouse_start
,
2947 doc
: /* Open a connection to Gpm.
2948 Gpm-mouse can only be activated for one tty at a time. */)
2951 struct frame
*f
= SELECTED_FRAME ();
2952 struct tty_display_info
*tty
2953 = ((f
)->output_method
== output_termcap
2954 ? (f
)->terminal
->display_info
.tty
: NULL
);
2955 Gpm_Connect connection
;
2958 error ("Gpm-mouse only works in the GNU/Linux console");
2960 return Qnil
; /* Already activated, nothing to do. */
2962 error ("Gpm-mouse can only be activated for one tty at a time");
2964 connection
.eventMask
= ~0;
2965 connection
.defaultMask
= ~GPM_HARD
;
2966 connection
.maxMod
= ~0;
2967 connection
.minMod
= 0;
2970 if (Gpm_Open (&connection
, 0) < 0)
2971 error ("Gpm-mouse failed to connect to the gpm daemon");
2975 /* `init_sys_modes' arranges for mouse movements sent through gpm_fd
2976 to generate SIGIOs. Apparently we need to call reset_sys_modes
2977 before calling init_sys_modes. */
2978 reset_sys_modes (tty
);
2979 init_sys_modes (tty
);
2980 add_gpm_wait_descriptor (gpm_fd
);
2985 DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop
, Sgpm_mouse_stop
,
2987 doc
: /* Close a connection to Gpm. */)
2990 struct frame
*f
= SELECTED_FRAME ();
2991 struct tty_display_info
*tty
2992 = ((f
)->output_method
== output_termcap
2993 ? (f
)->terminal
->display_info
.tty
: NULL
);
2995 if (!tty
|| gpm_tty
!= tty
)
2996 return Qnil
; /* Not activated on this terminal, nothing to do. */
2999 delete_gpm_wait_descriptor (gpm_fd
);
3000 while (Gpm_Close()); /* close all the stack */
3004 #endif /* HAVE_GPM */
3007 /***********************************************************************
3009 ***********************************************************************/
3011 /* Initialize the tty-dependent part of frame F. The frame must
3012 already have its device initialized. */
3015 create_tty_output (struct frame
*f
)
3017 struct tty_output
*t
;
3019 if (! FRAME_TERMCAP_P (f
))
3022 t
= xmalloc (sizeof (struct tty_output
));
3023 bzero (t
, sizeof (struct tty_output
));
3025 t
->display_info
= FRAME_TERMINAL (f
)->display_info
.tty
;
3027 f
->output_data
.tty
= t
;
3030 /* Delete the tty-dependent part of frame F. */
3033 delete_tty_output (struct frame
*f
)
3035 if (! FRAME_TERMCAP_P (f
))
3038 xfree (f
->output_data
.tty
);
3042 /* Reset the hooks in TERMINAL. */
3045 clear_tty_hooks (struct terminal
*terminal
)
3048 terminal
->cursor_to_hook
= 0;
3049 terminal
->raw_cursor_to_hook
= 0;
3050 terminal
->clear_to_end_hook
= 0;
3051 terminal
->clear_frame_hook
= 0;
3052 terminal
->clear_end_of_line_hook
= 0;
3053 terminal
->ins_del_lines_hook
= 0;
3054 terminal
->insert_glyphs_hook
= 0;
3055 terminal
->write_glyphs_hook
= 0;
3056 terminal
->delete_glyphs_hook
= 0;
3057 terminal
->ring_bell_hook
= 0;
3058 terminal
->reset_terminal_modes_hook
= 0;
3059 terminal
->set_terminal_modes_hook
= 0;
3060 terminal
->update_begin_hook
= 0;
3061 terminal
->update_end_hook
= 0;
3062 terminal
->set_terminal_window_hook
= 0;
3063 terminal
->mouse_position_hook
= 0;
3064 terminal
->frame_rehighlight_hook
= 0;
3065 terminal
->frame_raise_lower_hook
= 0;
3066 terminal
->fullscreen_hook
= 0;
3067 terminal
->set_vertical_scroll_bar_hook
= 0;
3068 terminal
->condemn_scroll_bars_hook
= 0;
3069 terminal
->redeem_scroll_bar_hook
= 0;
3070 terminal
->judge_scroll_bars_hook
= 0;
3071 terminal
->read_socket_hook
= 0;
3072 terminal
->frame_up_to_date_hook
= 0;
3074 /* Leave these two set, or suspended frames are not deleted
3076 terminal
->delete_frame_hook
= &delete_tty_output
;
3077 terminal
->delete_terminal_hook
= &delete_tty
;
3080 /* Initialize hooks in TERMINAL with the values needed for a tty. */
3083 set_tty_hooks (struct terminal
*terminal
)
3085 terminal
->rif
= 0; /* ttys don't support window-based redisplay. */
3087 terminal
->cursor_to_hook
= &tty_cursor_to
;
3088 terminal
->raw_cursor_to_hook
= &tty_raw_cursor_to
;
3090 terminal
->clear_to_end_hook
= &tty_clear_to_end
;
3091 terminal
->clear_frame_hook
= &tty_clear_frame
;
3092 terminal
->clear_end_of_line_hook
= &tty_clear_end_of_line
;
3094 terminal
->ins_del_lines_hook
= &tty_ins_del_lines
;
3096 terminal
->insert_glyphs_hook
= &tty_insert_glyphs
;
3097 terminal
->write_glyphs_hook
= &tty_write_glyphs
;
3098 terminal
->delete_glyphs_hook
= &tty_delete_glyphs
;
3100 terminal
->ring_bell_hook
= &tty_ring_bell
;
3102 terminal
->reset_terminal_modes_hook
= &tty_reset_terminal_modes
;
3103 terminal
->set_terminal_modes_hook
= &tty_set_terminal_modes
;
3104 terminal
->update_begin_hook
= 0; /* Not needed. */
3105 terminal
->update_end_hook
= &tty_update_end
;
3106 terminal
->set_terminal_window_hook
= &tty_set_terminal_window
;
3108 terminal
->mouse_position_hook
= 0; /* Not needed. */
3109 terminal
->frame_rehighlight_hook
= 0; /* Not needed. */
3110 terminal
->frame_raise_lower_hook
= 0; /* Not needed. */
3112 terminal
->set_vertical_scroll_bar_hook
= 0; /* Not needed. */
3113 terminal
->condemn_scroll_bars_hook
= 0; /* Not needed. */
3114 terminal
->redeem_scroll_bar_hook
= 0; /* Not needed. */
3115 terminal
->judge_scroll_bars_hook
= 0; /* Not needed. */
3117 terminal
->read_socket_hook
= &tty_read_avail_input
; /* keyboard.c */
3118 terminal
->frame_up_to_date_hook
= 0; /* Not needed. */
3120 terminal
->delete_frame_hook
= &delete_tty_output
;
3121 terminal
->delete_terminal_hook
= &delete_tty
;
3124 /* Drop the controlling terminal if fd is the same device. */
3126 dissociate_if_controlling_tty (int fd
)
3130 EMACS_GET_TTY_PGRP (fd
, &pgid
); /* If tcgetpgrp succeeds, fd is the ctty. */
3133 #if defined (USG) && !defined (BSD_PGRPS)
3135 no_controlling_tty
= 1;
3136 #elif defined (CYGWIN)
3138 no_controlling_tty
= 1;
3140 #ifdef TIOCNOTTY /* Try BSD ioctls. */
3141 sigblock (sigmask (SIGTTOU
));
3142 fd
= emacs_open (DEV_TTY
, O_RDWR
, 0);
3143 if (fd
!= -1 && ioctl (fd
, TIOCNOTTY
, 0) != -1)
3145 no_controlling_tty
= 1;
3149 sigunblock (sigmask (SIGTTOU
));
3151 /* Unknown system. */
3153 #endif /* ! TIOCNOTTY */
3156 #endif /* !WINDOWSNT */
3159 static void maybe_fatal();
3161 /* Create a termcap display on the tty device with the given name and
3164 If NAME is NULL, then use the controlling tty, i.e., "/dev/tty".
3165 Otherwise NAME should be a path to the tty device file,
3168 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
3170 If MUST_SUCCEED is true, then all errors are fatal. */
3173 init_tty (char *name
, char *terminal_type
, int must_succeed
)
3176 char **address
= &area
;
3177 char *buffer
= NULL
;
3178 int buffer_size
= 4096;
3179 register char *p
= NULL
;
3181 struct tty_display_info
*tty
= NULL
;
3182 struct terminal
*terminal
= NULL
;
3183 int ctty
= 0; /* 1 if asked to open controlling tty. */
3186 maybe_fatal (must_succeed
, 0, 0,
3187 "Unknown terminal type",
3188 "Unknown terminal type");
3192 if (!strcmp (name
, DEV_TTY
))
3195 /* If we already have a terminal on the given device, use that. If
3196 all such terminals are suspended, create a new one instead. */
3197 /* XXX Perhaps this should be made explicit by having init_tty
3198 always create a new terminal and separating terminal and frame
3199 creation on Lisp level. */
3200 terminal
= get_named_tty (name
);
3204 terminal
= create_terminal ();
3205 tty
= (struct tty_display_info
*) xmalloc (sizeof (struct tty_display_info
));
3206 bzero (tty
, sizeof (struct tty_display_info
));
3207 tty
->next
= tty_list
;
3210 terminal
->type
= output_termcap
;
3211 terminal
->display_info
.tty
= tty
;
3212 tty
->terminal
= terminal
;
3214 tty
->Wcm
= (struct cm
*) xmalloc (sizeof (struct cm
));
3218 set_tty_hooks (terminal
);
3224 #ifdef O_IGNORE_CTTY
3226 /* Open the terminal device. Don't recognize it as our
3227 controlling terminal, and don't make it the controlling tty
3228 if we don't have one at the moment. */
3229 fd
= emacs_open (name
, O_RDWR
| O_IGNORE_CTTY
| O_NOCTTY
, 0);
3232 /* Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
3233 defined on Hurd. On other systems, we need to explicitly
3234 dissociate ourselves from the controlling tty when we want to
3235 open a frame on the same terminal. */
3236 fd
= emacs_open (name
, O_RDWR
| O_NOCTTY
, 0);
3237 #endif /* O_IGNORE_CTTY */
3240 maybe_fatal (must_succeed
, buffer
, terminal
,
3241 "Could not open file: %s",
3242 "Could not open file: %s",
3247 maybe_fatal (must_succeed
, buffer
, terminal
,
3248 "Not a tty device: %s",
3249 "Not a tty device: %s",
3253 #ifndef O_IGNORE_CTTY
3255 dissociate_if_controlling_tty (fd
);
3258 file
= fdopen (fd
, "w+");
3259 tty
->name
= xstrdup (name
);
3260 terminal
->name
= xstrdup (name
);
3265 tty
->type
= xstrdup (terminal_type
);
3267 add_keyboard_wait_descriptor (fileno (tty
->input
));
3271 encode_terminal_bufsize
= 0;
3274 terminal
->mouse_position_hook
= term_mouse_position
;
3275 mouse_face_window
= Qnil
;
3279 initialize_w32_display (terminal
);
3280 /* The following two are inaccessible from w32console.c. */
3281 terminal
->delete_frame_hook
= &delete_tty_output
;
3282 terminal
->delete_terminal_hook
= &delete_tty
;
3284 tty
->name
= xstrdup (name
);
3285 terminal
->name
= xstrdup (name
);
3286 tty
->type
= xstrdup (terminal_type
);
3288 tty
->output
= stdout
;
3290 add_keyboard_wait_descriptor (0);
3295 struct frame
*f
= XFRAME (selected_frame
);
3297 FrameRows (tty
) = FRAME_LINES (f
);
3298 FrameCols (tty
) = FRAME_COLS (f
);
3299 tty
->specified_window
= FRAME_LINES (f
);
3301 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 0;
3302 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_none
;
3304 tty
->delete_in_insert_mode
= 1;
3307 terminal
->scroll_region_ok
= 0;
3309 /* Seems to insert lines when it's not supposed to, messing up the
3310 display. In doing a trace, it didn't seem to be called much, so I
3311 don't think we're losing anything by turning it off. */
3312 terminal
->line_ins_del_ok
= 0;
3313 terminal
->char_ins_del_ok
= 1;
3317 tty
->TN_max_colors
= 16; /* Required to be non-zero for tty-display-color-p */
3319 #else /* not WINDOWSNT */
3323 buffer
= (char *) xmalloc (buffer_size
);
3325 /* On some systems, tgetent tries to access the controlling
3327 sigblock (sigmask (SIGTTOU
));
3328 status
= tgetent (buffer
, terminal_type
);
3329 sigunblock (sigmask (SIGTTOU
));
3334 maybe_fatal (must_succeed
, buffer
, terminal
,
3335 "Cannot open terminfo database file",
3336 "Cannot open terminfo database file");
3338 maybe_fatal (must_succeed
, buffer
, terminal
,
3339 "Cannot open termcap database file",
3340 "Cannot open termcap database file");
3346 maybe_fatal (must_succeed
, buffer
, terminal
,
3347 "Terminal type %s is not defined",
3348 "Terminal type %s is not defined.\n\
3349 If that is not the actual type of terminal you have,\n\
3350 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3351 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3352 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3355 maybe_fatal (must_succeed
, buffer
, terminal
,
3356 "Terminal type %s is not defined",
3357 "Terminal type %s is not defined.\n\
3358 If that is not the actual type of terminal you have,\n\
3359 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3360 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3361 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3367 if (strlen (buffer
) >= buffer_size
)
3369 buffer_size
= strlen (buffer
);
3371 area
= (char *) xmalloc (buffer_size
);
3373 tty
->TS_ins_line
= tgetstr ("al", address
);
3374 tty
->TS_ins_multi_lines
= tgetstr ("AL", address
);
3375 tty
->TS_bell
= tgetstr ("bl", address
);
3376 BackTab (tty
) = tgetstr ("bt", address
);
3377 tty
->TS_clr_to_bottom
= tgetstr ("cd", address
);
3378 tty
->TS_clr_line
= tgetstr ("ce", address
);
3379 tty
->TS_clr_frame
= tgetstr ("cl", address
);
3380 ColPosition (tty
) = NULL
; /* tgetstr ("ch", address); */
3381 AbsPosition (tty
) = tgetstr ("cm", address
);
3382 CR (tty
) = tgetstr ("cr", address
);
3383 tty
->TS_set_scroll_region
= tgetstr ("cs", address
);
3384 tty
->TS_set_scroll_region_1
= tgetstr ("cS", address
);
3385 RowPosition (tty
) = tgetstr ("cv", address
);
3386 tty
->TS_del_char
= tgetstr ("dc", address
);
3387 tty
->TS_del_multi_chars
= tgetstr ("DC", address
);
3388 tty
->TS_del_line
= tgetstr ("dl", address
);
3389 tty
->TS_del_multi_lines
= tgetstr ("DL", address
);
3390 tty
->TS_delete_mode
= tgetstr ("dm", address
);
3391 tty
->TS_end_delete_mode
= tgetstr ("ed", address
);
3392 tty
->TS_end_insert_mode
= tgetstr ("ei", address
);
3393 Home (tty
) = tgetstr ("ho", address
);
3394 tty
->TS_ins_char
= tgetstr ("ic", address
);
3395 tty
->TS_ins_multi_chars
= tgetstr ("IC", address
);
3396 tty
->TS_insert_mode
= tgetstr ("im", address
);
3397 tty
->TS_pad_inserted_char
= tgetstr ("ip", address
);
3398 tty
->TS_end_keypad_mode
= tgetstr ("ke", address
);
3399 tty
->TS_keypad_mode
= tgetstr ("ks", address
);
3400 LastLine (tty
) = tgetstr ("ll", address
);
3401 Right (tty
) = tgetstr ("nd", address
);
3402 Down (tty
) = tgetstr ("do", address
);
3404 Down (tty
) = tgetstr ("nl", address
); /* Obsolete name for "do" */
3406 /* VMS puts a carriage return before each linefeed,
3407 so it is not safe to use linefeeds. */
3408 if (Down (tty
) && Down (tty
)[0] == '\n' && Down (tty
)[1] == '\0')
3411 if (tgetflag ("bs"))
3412 Left (tty
) = "\b"; /* can't possibly be longer! */
3413 else /* (Actually, "bs" is obsolete...) */
3414 Left (tty
) = tgetstr ("le", address
);
3416 Left (tty
) = tgetstr ("bc", address
); /* Obsolete name for "le" */
3417 tty
->TS_pad_char
= tgetstr ("pc", address
);
3418 tty
->TS_repeat
= tgetstr ("rp", address
);
3419 tty
->TS_end_standout_mode
= tgetstr ("se", address
);
3420 tty
->TS_fwd_scroll
= tgetstr ("sf", address
);
3421 tty
->TS_standout_mode
= tgetstr ("so", address
);
3422 tty
->TS_rev_scroll
= tgetstr ("sr", address
);
3423 tty
->Wcm
->cm_tab
= tgetstr ("ta", address
);
3424 tty
->TS_end_termcap_modes
= tgetstr ("te", address
);
3425 tty
->TS_termcap_modes
= tgetstr ("ti", address
);
3426 Up (tty
) = tgetstr ("up", address
);
3427 tty
->TS_visible_bell
= tgetstr ("vb", address
);
3428 tty
->TS_cursor_normal
= tgetstr ("ve", address
);
3429 tty
->TS_cursor_visible
= tgetstr ("vs", address
);
3430 tty
->TS_cursor_invisible
= tgetstr ("vi", address
);
3431 tty
->TS_set_window
= tgetstr ("wi", address
);
3433 tty
->TS_enter_underline_mode
= tgetstr ("us", address
);
3434 tty
->TS_exit_underline_mode
= tgetstr ("ue", address
);
3435 tty
->TS_enter_bold_mode
= tgetstr ("md", address
);
3436 tty
->TS_enter_dim_mode
= tgetstr ("mh", address
);
3437 tty
->TS_enter_blink_mode
= tgetstr ("mb", address
);
3438 tty
->TS_enter_reverse_mode
= tgetstr ("mr", address
);
3439 tty
->TS_enter_alt_charset_mode
= tgetstr ("as", address
);
3440 tty
->TS_exit_alt_charset_mode
= tgetstr ("ae", address
);
3441 tty
->TS_exit_attribute_mode
= tgetstr ("me", address
);
3443 MultiUp (tty
) = tgetstr ("UP", address
);
3444 MultiDown (tty
) = tgetstr ("DO", address
);
3445 MultiLeft (tty
) = tgetstr ("LE", address
);
3446 MultiRight (tty
) = tgetstr ("RI", address
);
3448 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
3449 color because we can't switch back to the default foreground and
3451 tty
->TS_orig_pair
= tgetstr ("op", address
);
3452 if (tty
->TS_orig_pair
)
3454 tty
->TS_set_foreground
= tgetstr ("AF", address
);
3455 tty
->TS_set_background
= tgetstr ("AB", address
);
3456 if (!tty
->TS_set_foreground
)
3459 tty
->TS_set_foreground
= tgetstr ("Sf", address
);
3460 tty
->TS_set_background
= tgetstr ("Sb", address
);
3463 tty
->TN_max_colors
= tgetnum ("Co");
3464 tty
->TN_max_pairs
= tgetnum ("pa");
3466 tty
->TN_no_color_video
= tgetnum ("NC");
3467 if (tty
->TN_no_color_video
== -1)
3468 tty
->TN_no_color_video
= 0;
3471 tty_default_color_capabilities (tty
, 1);
3473 MagicWrap (tty
) = tgetflag ("xn");
3474 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
3475 the former flag imply the latter. */
3476 AutoWrap (tty
) = MagicWrap (tty
) || tgetflag ("am");
3477 terminal
->memory_below_frame
= tgetflag ("db");
3478 tty
->TF_hazeltine
= tgetflag ("hz");
3479 terminal
->must_write_spaces
= tgetflag ("in");
3480 tty
->meta_key
= tgetflag ("km") || tgetflag ("MT");
3481 tty
->TF_insmode_motion
= tgetflag ("mi");
3482 tty
->TF_standout_motion
= tgetflag ("ms");
3483 tty
->TF_underscore
= tgetflag ("ul");
3484 tty
->TF_teleray
= tgetflag ("xt");
3486 #endif /* !WINDOWSNT */
3488 terminal
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
3489 init_kboard (terminal
->kboard
);
3490 terminal
->kboard
->next_kboard
= all_kboards
;
3491 all_kboards
= terminal
->kboard
;
3492 terminal
->kboard
->reference_count
++;
3493 /* Don't let the initial kboard remain current longer than necessary.
3494 That would cause problems if a file loaded on startup tries to
3495 prompt in the mini-buffer. */
3496 if (current_kboard
== initial_kboard
)
3497 current_kboard
= terminal
->kboard
;
3499 term_get_fkeys (address
, terminal
->kboard
);
3504 /* Get frame size from system, or else from termcap. */
3507 get_tty_size (fileno (tty
->input
), &width
, &height
);
3508 FrameCols (tty
) = width
;
3509 FrameRows (tty
) = height
;
3512 if (FrameCols (tty
) <= 0)
3513 FrameCols (tty
) = tgetnum ("co");
3514 if (FrameRows (tty
) <= 0)
3515 FrameRows (tty
) = tgetnum ("li");
3517 if (FrameRows (tty
) < 3 || FrameCols (tty
) < 3)
3518 maybe_fatal (must_succeed
, NULL
, terminal
,
3519 "Screen size %dx%d is too small"
3520 "Screen size %dx%d is too small",
3521 FrameCols (tty
), FrameRows (tty
));
3523 #if 0 /* This is not used anywhere. */
3524 tty
->terminal
->min_padding_speed
= tgetnum ("pb");
3527 TabWidth (tty
) = tgetnum ("tw");
3530 /* These capabilities commonly use ^J.
3531 I don't know why, but sending them on VMS does not work;
3532 it causes following spaces to be lost, sometimes.
3533 For now, the simplest fix is to avoid using these capabilities ever. */
3534 if (Down (tty
) && Down (tty
)[0] == '\n')
3539 tty
->TS_bell
= "\07";
3541 if (!tty
->TS_fwd_scroll
)
3542 tty
->TS_fwd_scroll
= Down (tty
);
3544 PC
= tty
->TS_pad_char
? *tty
->TS_pad_char
: 0;
3546 if (TabWidth (tty
) < 0)
3549 /* Turned off since /etc/termcap seems to have :ta= for most terminals
3550 and newer termcap doc does not seem to say there is a default.
3551 if (!tty->Wcm->cm_tab)
3552 tty->Wcm->cm_tab = "\t";
3555 /* We don't support standout modes that use `magic cookies', so
3556 turn off any that do. */
3557 if (tty
->TS_standout_mode
&& tgetnum ("sg") >= 0)
3559 tty
->TS_standout_mode
= 0;
3560 tty
->TS_end_standout_mode
= 0;
3562 if (tty
->TS_enter_underline_mode
&& tgetnum ("ug") >= 0)
3564 tty
->TS_enter_underline_mode
= 0;
3565 tty
->TS_exit_underline_mode
= 0;
3568 /* If there's no standout mode, try to use underlining instead. */
3569 if (tty
->TS_standout_mode
== 0)
3571 tty
->TS_standout_mode
= tty
->TS_enter_underline_mode
;
3572 tty
->TS_end_standout_mode
= tty
->TS_exit_underline_mode
;
3575 /* If no `se' string, try using a `me' string instead.
3576 If that fails, we can't use standout mode at all. */
3577 if (tty
->TS_end_standout_mode
== 0)
3579 char *s
= tgetstr ("me", address
);
3581 tty
->TS_end_standout_mode
= s
;
3583 tty
->TS_standout_mode
= 0;
3586 if (tty
->TF_teleray
)
3588 tty
->Wcm
->cm_tab
= 0;
3589 /* We can't support standout mode, because it uses magic cookies. */
3590 tty
->TS_standout_mode
= 0;
3591 /* But that means we cannot rely on ^M to go to column zero! */
3593 /* LF can't be trusted either -- can alter hpos */
3594 /* if move at column 0 thru a line with TS_standout_mode */
3598 /* Special handling for certain terminal types known to need it */
3600 if (!strcmp (terminal_type
, "supdup"))
3602 terminal
->memory_below_frame
= 1;
3603 tty
->Wcm
->cm_losewrap
= 1;
3605 if (!strncmp (terminal_type
, "c10", 3)
3606 || !strcmp (terminal_type
, "perq"))
3608 /* Supply a makeshift :wi string.
3609 This string is not valid in general since it works only
3610 for windows starting at the upper left corner;
3611 but that is all Emacs uses.
3613 This string works only if the frame is using
3614 the top of the video memory, because addressing is memory-relative.
3615 So first check the :ti string to see if that is true.
3617 It would be simpler if the :wi string could go in the termcap
3618 entry, but it can't because it is not fully valid.
3619 If it were in the termcap entry, it would confuse other programs. */
3620 if (!tty
->TS_set_window
)
3622 p
= tty
->TS_termcap_modes
;
3623 while (*p
&& strcmp (p
, "\033v "))
3626 tty
->TS_set_window
= "\033v%C %C %C %C ";
3628 /* Termcap entry often fails to have :in: flag */
3629 terminal
->must_write_spaces
= 1;
3630 /* :ti string typically fails to have \E^G! in it */
3631 /* This limits scope of insert-char to one line. */
3632 strcpy (area
, tty
->TS_termcap_modes
);
3633 strcat (area
, "\033\007!");
3634 tty
->TS_termcap_modes
= area
;
3635 area
+= strlen (area
) + 1;
3636 p
= AbsPosition (tty
);
3637 /* Change all %+ parameters to %C, to handle
3638 values above 96 correctly for the C100. */
3641 if (p
[0] == '%' && p
[1] == '+')
3647 tty
->specified_window
= FrameRows (tty
);
3649 if (Wcm_init (tty
) == -1) /* can't do cursor motion */
3651 maybe_fatal (must_succeed
, NULL
, terminal
,
3652 "Terminal type \"%s\" is not powerful enough to run Emacs",
3654 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3655 It lacks the ability to position the cursor.\n\
3656 If that is not the actual type of terminal you have, use either the\n\
3657 DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
3658 or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
3661 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3662 It lacks the ability to position the cursor.\n\
3663 If that is not the actual type of terminal you have,\n\
3664 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3665 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3666 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3667 # else /* TERMCAP */
3668 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3669 It lacks the ability to position the cursor.\n\
3670 If that is not the actual type of terminal you have,\n\
3671 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3672 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3673 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3674 # endif /* TERMINFO */
3679 if (FrameRows (tty
) <= 0 || FrameCols (tty
) <= 0)
3680 maybe_fatal (must_succeed
, NULL
, terminal
,
3681 "Could not determine the frame size",
3682 "Could not determine the frame size");
3684 tty
->delete_in_insert_mode
3685 = tty
->TS_delete_mode
&& tty
->TS_insert_mode
3686 && !strcmp (tty
->TS_delete_mode
, tty
->TS_insert_mode
);
3688 tty
->se_is_so
= (tty
->TS_standout_mode
3689 && tty
->TS_end_standout_mode
3690 && !strcmp (tty
->TS_standout_mode
, tty
->TS_end_standout_mode
));
3692 UseTabs (tty
) = tabs_safe_p (fileno (tty
->input
)) && TabWidth (tty
) == 8;
3694 terminal
->scroll_region_ok
3696 && (tty
->TS_set_window
|| tty
->TS_set_scroll_region
|| tty
->TS_set_scroll_region_1
));
3698 terminal
->line_ins_del_ok
3699 = (((tty
->TS_ins_line
|| tty
->TS_ins_multi_lines
)
3700 && (tty
->TS_del_line
|| tty
->TS_del_multi_lines
))
3701 || (terminal
->scroll_region_ok
3702 && tty
->TS_fwd_scroll
&& tty
->TS_rev_scroll
));
3704 terminal
->char_ins_del_ok
3705 = ((tty
->TS_ins_char
|| tty
->TS_insert_mode
3706 || tty
->TS_pad_inserted_char
|| tty
->TS_ins_multi_chars
)
3707 && (tty
->TS_del_char
|| tty
->TS_del_multi_chars
));
3709 terminal
->fast_clear_end_of_line
= tty
->TS_clr_line
!= 0;
3711 init_baud_rate (fileno (tty
->input
));
3714 /* The HFT system on AIX doesn't optimize for scrolling, so it's
3715 really ugly at times. */
3716 terminal
->line_ins_del_ok
= 0;
3717 terminal
->char_ins_del_ok
= 0;
3720 /* Don't do this. I think termcap may still need the buffer. */
3721 /* xfree (buffer); */
3723 #endif /* not WINDOWSNT */
3725 /* Init system terminal modes (RAW or CBREAK, etc.). */
3726 init_sys_modes (tty
);
3731 /* Auxiliary error-handling function for init_tty.
3732 Free BUFFER and delete TERMINAL, then call error or fatal
3733 with str1 or str2, respectively, according to MUST_SUCCEED. */
3736 maybe_fatal (must_succeed
, buffer
, terminal
, str1
, str2
, arg1
, arg2
)
3739 struct terminal
*terminal
;
3740 char *str1
, *str2
, *arg1
, *arg2
;
3746 delete_tty (terminal
);
3749 fatal (str2
, arg1
, arg2
);
3751 error (str1
, arg1
, arg2
);
3758 fatal (str
, arg1
, arg2
)
3759 char *str
, *arg1
, *arg2
;
3761 fprintf (stderr
, "emacs: ");
3762 fprintf (stderr
, str
, arg1
, arg2
);
3763 fprintf (stderr
, "\n");
3770 /* Delete the given tty terminal, closing all frames on it. */
3773 delete_tty (struct terminal
*terminal
)
3775 struct tty_display_info
*tty
;
3776 Lisp_Object tail
, frame
;
3779 /* Protect against recursive calls. Fdelete_frame in
3780 delete_terminal calls us back when it deletes our last frame. */
3781 if (!terminal
->name
)
3784 if (terminal
->type
!= output_termcap
)
3787 tty
= terminal
->display_info
.tty
;
3790 FOR_EACH_FRAME (tail
, frame
)
3792 struct frame
*f
= XFRAME (frame
);
3793 if (FRAME_LIVE_P (f
) && (!FRAME_TERMCAP_P (f
) || FRAME_TTY (f
) != tty
))
3800 error ("Attempt to delete the sole terminal device with live frames");
3802 if (tty
== tty_list
)
3803 tty_list
= tty
->next
;
3806 struct tty_display_info
*p
;
3807 for (p
= tty_list
; p
&& p
->next
!= tty
; p
= p
->next
)
3811 /* This should not happen. */
3814 p
->next
= tty
->next
;
3818 /* reset_sys_modes needs a valid device, so this call needs to be
3819 before delete_terminal. */
3820 reset_sys_modes (tty
);
3822 delete_terminal (terminal
);
3832 delete_keyboard_wait_descriptor (fileno (tty
->input
));
3833 if (tty
->input
!= stdin
)
3834 fclose (tty
->input
);
3836 if (tty
->output
&& tty
->output
!= stdout
&& tty
->output
!= tty
->input
)
3837 fclose (tty
->output
);
3838 if (tty
->termscript
)
3839 fclose (tty
->termscript
);
3842 xfree (tty
->old_tty
);
3847 bzero (tty
, sizeof (struct tty_display_info
));
3853 /* Mark the pointers in the tty_display_info objects.
3854 Called by the Fgarbage_collector. */
3859 struct tty_display_info
*tty
;
3861 for (tty
= tty_list
; tty
; tty
= tty
->next
)
3862 mark_object (tty
->top_frame
);
3870 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo
,
3871 doc
: /* Non-nil means the system uses terminfo rather than termcap.
3872 This variable can be used by terminal emulator packages. */);
3874 system_uses_terminfo
= 1;
3876 system_uses_terminfo
= 0;
3879 DEFVAR_LISP ("suspend-tty-functions", &Vsuspend_tty_functions
,
3880 doc
: /* Functions to be run after suspending a tty.
3881 The functions are run with one argument, the terminal id to be suspended.
3882 See `suspend-tty'. */);
3883 Vsuspend_tty_functions
= Qnil
;
3886 DEFVAR_LISP ("resume-tty-functions", &Vresume_tty_functions
,
3887 doc
: /* Functions to be run after resuming a tty.
3888 The functions are run with one argument, the terminal id that was revived.
3889 See `resume-tty'. */);
3890 Vresume_tty_functions
= Qnil
;
3892 DEFVAR_BOOL ("visible-cursor", &visible_cursor
,
3893 doc
: /* Non-nil means to make the cursor very visible.
3894 This only has an effect when running in a text terminal.
3895 What means \"very visible\" is up to your terminal. It may make the cursor
3896 bigger, or it may make it blink, or it may do nothing at all. */);
3899 defsubr (&Stty_display_color_p
);
3900 defsubr (&Stty_display_color_cells
);
3901 defsubr (&Stty_no_underline
);
3902 defsubr (&Stty_type
);
3903 defsubr (&Scontrolling_tty_p
);
3904 defsubr (&Ssuspend_tty
);
3905 defsubr (&Sresume_tty
);
3907 defsubr (&Sgpm_mouse_start
);
3908 defsubr (&Sgpm_mouse_stop
);
3910 staticpro (&mouse_face_window
);
3911 #endif /* HAVE_GPM */
3916 /* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193
3917 (do not change this comment) */