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, 2008
4 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
21 /* New redisplay, TTY faces by Gerd Moellmann <gerd@gnu.org>. */
35 #include <termios.h> /* For TIOCNOTTY. */
45 #include "character.h"
48 #include "composite.h"
52 #include "termhooks.h"
53 #include "dispextern.h"
56 #include "blockinput.h"
57 #include "syssignal.h"
59 #include "intervals.h"
61 /* For now, don't try to include termcap.h. On some systems,
62 configure finds a non-standard termcap.h that the main build
65 #if defined HAVE_TERMCAP_H && 0
68 extern void tputs
P_ ((const char *, int, int (*)(int)));
69 extern int tgetent
P_ ((char *, const char *));
70 extern int tgetflag
P_ ((char *id
));
71 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>
190 static void term_clear_mouse_face ();
191 static void term_mouse_highlight (struct frame
*f
, int x
, int y
);
193 /* The device for which we have enabled gpm support (or NULL). */
194 struct tty_display_info
*gpm_tty
= NULL
;
196 /* These variables describe the range of text currently shown in its
197 mouse-face, together with the window they apply to. As long as
198 the mouse stays within this range, we need not redraw anything on
199 its account. Rows and columns are glyph matrix positions in
200 MOUSE_FACE_WINDOW. */
201 static int mouse_face_beg_row
, mouse_face_beg_col
;
202 static int mouse_face_end_row
, mouse_face_end_col
;
203 static int mouse_face_past_end
;
204 static Lisp_Object mouse_face_window
;
205 static int mouse_face_face_id
;
207 static int pos_x
, pos_y
;
208 static int last_mouse_x
, last_mouse_y
;
209 #endif /* HAVE_GPM */
211 /* Ring the bell on a tty. */
214 tty_ring_bell (struct frame
*f
)
216 struct tty_display_info
*tty
= FRAME_TTY (f
);
220 OUTPUT (tty
, (tty
->TS_visible_bell
&& visible_bell
221 ? tty
->TS_visible_bell
223 fflush (tty
->output
);
227 /* Set up termcap modes for Emacs. */
230 tty_set_terminal_modes (struct terminal
*terminal
)
232 struct tty_display_info
*tty
= terminal
->display_info
.tty
;
236 if (tty
->TS_termcap_modes
)
237 OUTPUT (tty
, tty
->TS_termcap_modes
);
240 /* Output enough newlines to scroll all the old screen contents
241 off the screen, so it won't be overwritten and lost. */
244 for (i
= 0; i
< FRAME_LINES (XFRAME (selected_frame
)); i
++)
248 OUTPUT_IF (tty
, tty
->TS_termcap_modes
);
249 OUTPUT_IF (tty
, visible_cursor
? tty
->TS_cursor_visible
: tty
->TS_cursor_normal
);
250 OUTPUT_IF (tty
, tty
->TS_keypad_mode
);
252 fflush (tty
->output
);
256 /* Reset termcap modes before exiting Emacs. */
259 tty_reset_terminal_modes (struct terminal
*terminal
)
261 struct tty_display_info
*tty
= terminal
->display_info
.tty
;
265 tty_turn_off_highlight (tty
);
266 tty_turn_off_insert (tty
);
267 OUTPUT_IF (tty
, tty
->TS_end_keypad_mode
);
268 OUTPUT_IF (tty
, tty
->TS_cursor_normal
);
269 OUTPUT_IF (tty
, tty
->TS_end_termcap_modes
);
270 OUTPUT_IF (tty
, tty
->TS_orig_pair
);
271 /* Output raw CR so kernel can track the cursor hpos. */
274 fflush (tty
->output
);
278 /* Flag the end of a display update on a termcap terminal. */
281 tty_update_end (struct frame
*f
)
283 struct tty_display_info
*tty
= FRAME_TTY (f
);
285 if (!XWINDOW (selected_window
)->cursor_off_p
)
286 tty_show_cursor (tty
);
287 tty_turn_off_insert (tty
);
288 tty_background_highlight (tty
);
291 /* The implementation of set_terminal_window for termcap frames. */
294 tty_set_terminal_window (struct frame
*f
, int size
)
296 struct tty_display_info
*tty
= FRAME_TTY (f
);
298 tty
->specified_window
= size
? size
: FRAME_LINES (f
);
299 if (FRAME_SCROLL_REGION_OK (f
))
300 tty_set_scroll_region (f
, 0, tty
->specified_window
);
304 tty_set_scroll_region (struct frame
*f
, int start
, int stop
)
307 struct tty_display_info
*tty
= FRAME_TTY (f
);
309 if (tty
->TS_set_scroll_region
)
310 buf
= tparam (tty
->TS_set_scroll_region
, 0, 0, start
, stop
- 1);
311 else if (tty
->TS_set_scroll_region_1
)
312 buf
= tparam (tty
->TS_set_scroll_region_1
, 0, 0,
313 FRAME_LINES (f
), start
,
314 FRAME_LINES (f
) - stop
,
317 buf
= tparam (tty
->TS_set_window
, 0, 0, start
, 0, stop
, FRAME_COLS (f
));
326 tty_turn_on_insert (struct tty_display_info
*tty
)
328 if (!tty
->insert_mode
)
329 OUTPUT (tty
, tty
->TS_insert_mode
);
330 tty
->insert_mode
= 1;
334 tty_turn_off_insert (struct tty_display_info
*tty
)
336 if (tty
->insert_mode
)
337 OUTPUT (tty
, tty
->TS_end_insert_mode
);
338 tty
->insert_mode
= 0;
341 /* Handle highlighting. */
344 tty_turn_off_highlight (struct tty_display_info
*tty
)
346 if (tty
->standout_mode
)
347 OUTPUT_IF (tty
, tty
->TS_end_standout_mode
);
348 tty
->standout_mode
= 0;
352 tty_turn_on_highlight (struct tty_display_info
*tty
)
354 if (!tty
->standout_mode
)
355 OUTPUT_IF (tty
, tty
->TS_standout_mode
);
356 tty
->standout_mode
= 1;
360 tty_toggle_highlight (struct tty_display_info
*tty
)
362 if (tty
->standout_mode
)
363 tty_turn_off_highlight (tty
);
365 tty_turn_on_highlight (tty
);
369 /* Make cursor invisible. */
372 tty_hide_cursor (struct tty_display_info
*tty
)
374 if (tty
->cursor_hidden
== 0)
376 tty
->cursor_hidden
= 1;
377 OUTPUT_IF (tty
, tty
->TS_cursor_invisible
);
382 /* Ensure that cursor is visible. */
385 tty_show_cursor (struct tty_display_info
*tty
)
387 if (tty
->cursor_hidden
)
389 tty
->cursor_hidden
= 0;
390 OUTPUT_IF (tty
, tty
->TS_cursor_normal
);
392 OUTPUT_IF (tty
, tty
->TS_cursor_visible
);
397 /* Set standout mode to the state it should be in for
398 empty space inside windows. What this is,
399 depends on the user option inverse-video. */
402 tty_background_highlight (struct tty_display_info
*tty
)
405 tty_turn_on_highlight (tty
);
407 tty_turn_off_highlight (tty
);
410 /* Set standout mode to the mode specified for the text to be output. */
413 tty_highlight_if_desired (struct tty_display_info
*tty
)
416 tty_turn_on_highlight (tty
);
418 tty_turn_off_highlight (tty
);
422 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
423 frame-relative coordinates. */
426 tty_cursor_to (struct frame
*f
, int vpos
, int hpos
)
428 struct tty_display_info
*tty
= FRAME_TTY (f
);
430 /* Detect the case where we are called from reset_sys_modes
431 and the costs have never been calculated. Do nothing. */
432 if (! tty
->costs_set
)
435 if (curY (tty
) == vpos
436 && curX (tty
) == hpos
)
438 if (!tty
->TF_standout_motion
)
439 tty_background_highlight (tty
);
440 if (!tty
->TF_insmode_motion
)
441 tty_turn_off_insert (tty
);
442 cmgoto (tty
, vpos
, hpos
);
445 /* Similar but don't take any account of the wasted characters. */
448 tty_raw_cursor_to (struct frame
*f
, int row
, int col
)
450 struct tty_display_info
*tty
= FRAME_TTY (f
);
452 if (curY (tty
) == row
453 && curX (tty
) == col
)
455 if (!tty
->TF_standout_motion
)
456 tty_background_highlight (tty
);
457 if (!tty
->TF_insmode_motion
)
458 tty_turn_off_insert (tty
);
459 cmgoto (tty
, row
, col
);
462 /* Erase operations */
464 /* Clear from cursor to end of frame on a termcap device. */
467 tty_clear_to_end (struct frame
*f
)
470 struct tty_display_info
*tty
= FRAME_TTY (f
);
472 if (tty
->TS_clr_to_bottom
)
474 tty_background_highlight (tty
);
475 OUTPUT (tty
, tty
->TS_clr_to_bottom
);
479 for (i
= curY (tty
); i
< FRAME_LINES (f
); i
++)
482 clear_end_of_line (f
, FRAME_COLS (f
));
487 /* Clear an entire termcap frame. */
490 tty_clear_frame (struct frame
*f
)
492 struct tty_display_info
*tty
= FRAME_TTY (f
);
494 if (tty
->TS_clr_frame
)
496 tty_background_highlight (tty
);
497 OUTPUT (tty
, tty
->TS_clr_frame
);
507 /* An implementation of clear_end_of_line for termcap frames.
509 Note that the cursor may be moved, on terminals lacking a `ce' string. */
512 tty_clear_end_of_line (struct frame
*f
, int first_unused_hpos
)
515 struct tty_display_info
*tty
= FRAME_TTY (f
);
517 /* Detect the case where we are called from reset_sys_modes
518 and the costs have never been calculated. Do nothing. */
519 if (! tty
->costs_set
)
522 if (curX (tty
) >= first_unused_hpos
)
524 tty_background_highlight (tty
);
525 if (tty
->TS_clr_line
)
527 OUTPUT1 (tty
, tty
->TS_clr_line
);
530 { /* have to do it the hard way */
531 tty_turn_off_insert (tty
);
533 /* Do not write in last row last col with Auto-wrap on. */
535 && curY (tty
) == FrameRows (tty
) - 1
536 && first_unused_hpos
== FrameCols (tty
))
539 for (i
= curX (tty
); i
< first_unused_hpos
; i
++)
542 fputc (' ', tty
->termscript
);
543 fputc (' ', tty
->output
);
545 cmplus (tty
, first_unused_hpos
- curX (tty
));
549 /* Buffers to store the source and result of code conversion for terminal. */
550 static unsigned char *encode_terminal_src
;
551 static unsigned char *encode_terminal_dst
;
552 /* Allocated sizes of the above buffers. */
553 static int encode_terminal_src_size
;
554 static int encode_terminal_dst_size
;
556 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes.
557 Set CODING->produced to the byte-length of the resulting byte
558 sequence, and return a pointer to that byte sequence. */
561 encode_terminal_code (src
, src_len
, coding
)
564 struct coding_system
*coding
;
566 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
;
571 Lisp_Object charset_list
;
573 /* Allocate sufficient size of buffer to store all characters in
574 multibyte-form. But, it may be enlarged on demand if
575 Vglyph_table contains a string or a composite glyph is
577 required
= MAX_MULTIBYTE_LENGTH
* src_len
;
578 if (encode_terminal_src_size
< required
)
580 if (encode_terminal_src_size
== 0)
581 encode_terminal_src
= xmalloc (required
);
583 encode_terminal_src
= xrealloc (encode_terminal_src
, required
);
584 encode_terminal_src_size
= required
;
587 charset_list
= coding_charset_list (coding
);
589 buf
= encode_terminal_src
;
591 while (src
< src_end
)
593 if (src
->type
== COMPOSITE_GLYPH
)
595 struct composition
*cmp
= composition_table
[src
->u
.cmp_id
];
598 nbytes
= buf
- encode_terminal_src
;
599 required
= MAX_MULTIBYTE_LENGTH
* cmp
->glyph_len
;
601 if (encode_terminal_src_size
< nbytes
+ required
)
603 encode_terminal_src_size
= nbytes
+ required
;
604 encode_terminal_src
= xrealloc (encode_terminal_src
,
605 encode_terminal_src_size
);
606 buf
= encode_terminal_src
+ nbytes
;
609 for (i
= 0; i
< cmp
->glyph_len
; i
++)
611 int c
= COMPOSITION_GLYPH (cmp
, i
);
613 if (! char_charset (c
, charset_list
, NULL
))
615 buf
+= CHAR_STRING (c
, buf
);
620 /* The first character of the composition is not encodable. */
625 /* We must skip glyphs to be padded for a wide character. */
626 else if (! CHAR_GLYPH_PADDING_P (*src
))
633 SET_GLYPH_FROM_CHAR_GLYPH (g
, src
[0]);
635 if (GLYPH_INVALID_P (g
) || GLYPH_SIMPLE_P (tbase
, tlen
, g
))
637 /* This glyph doesn't has an entry in Vglyph_table. */
642 /* This glyph has an entry in Vglyph_table,
643 so process any alias before testing for simpleness. */
644 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
646 if (GLYPH_SIMPLE_P (tbase
, tlen
, g
))
647 /* We set the multi-byte form of a character in G
648 (that should be an ASCII character) at WORKBUF. */
651 /* We have a string in Vglyph_table. */
652 string
= tbase
[GLYPH_CHAR (g
)];
657 nbytes
= buf
- encode_terminal_src
;
658 if (encode_terminal_src_size
< nbytes
+ MAX_MULTIBYTE_LENGTH
)
660 encode_terminal_src_size
= nbytes
+ MAX_MULTIBYTE_LENGTH
;
661 encode_terminal_src
= xrealloc (encode_terminal_src
,
662 encode_terminal_src_size
);
663 buf
= encode_terminal_src
+ nbytes
;
665 if (char_charset (c
, charset_list
, NULL
))
667 /* Store the multibyte form of C at BUF. */
668 buf
+= CHAR_STRING (c
, buf
);
673 /* C is not encodable. */
676 while (src
+ 1 < src_end
&& CHAR_GLYPH_PADDING_P (src
[1]))
686 unsigned char *p
= SDATA (string
), *pend
= p
+ SBYTES (string
);
688 if (! STRING_MULTIBYTE (string
))
689 string
= string_to_multibyte (string
);
690 nbytes
= buf
- encode_terminal_src
;
691 if (encode_terminal_src_size
< nbytes
+ SBYTES (string
))
693 encode_terminal_src_size
= nbytes
+ SBYTES (string
);
694 encode_terminal_src
= xrealloc (encode_terminal_src
,
695 encode_terminal_src_size
);
696 buf
= encode_terminal_src
+ nbytes
;
698 bcopy (SDATA (string
), buf
, SBYTES (string
));
699 buf
+= SBYTES (string
);
700 nchars
+= SCHARS (string
);
708 coding
->produced
= 0;
712 nbytes
= buf
- encode_terminal_src
;
713 coding
->source
= encode_terminal_src
;
714 if (encode_terminal_dst_size
== 0)
716 encode_terminal_dst_size
= encode_terminal_src_size
;
717 encode_terminal_dst
= xmalloc (encode_terminal_dst_size
);
719 coding
->destination
= encode_terminal_dst
;
720 coding
->dst_bytes
= encode_terminal_dst_size
;
721 encode_coding_object (coding
, Qnil
, 0, 0, nchars
, nbytes
, Qnil
);
722 /* coding->destination may have been reallocated. */
723 encode_terminal_dst
= coding
->destination
;
724 encode_terminal_dst_size
= coding
->dst_bytes
;
726 return (encode_terminal_dst
);
731 /* An implementation of write_glyphs for termcap frames. */
734 tty_write_glyphs (struct frame
*f
, struct glyph
*string
, int len
)
736 unsigned char *conversion_buffer
;
737 struct coding_system
*coding
;
739 struct tty_display_info
*tty
= FRAME_TTY (f
);
741 tty_turn_off_insert (tty
);
742 tty_hide_cursor (tty
);
744 /* Don't dare write in last column of bottom line, if Auto-Wrap,
745 since that would scroll the whole frame on some terminals. */
748 && curY (tty
) + 1 == FRAME_LINES (f
)
749 && (curX (tty
) + len
) == FRAME_COLS (f
))
756 /* If terminal_coding does any conversion, use it, otherwise use
757 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
758 because it always return 1 if the member src_multibyte is 1. */
759 coding
= (FRAME_TERMINAL_CODING (f
)->common_flags
& CODING_REQUIRE_ENCODING_MASK
760 ? FRAME_TERMINAL_CODING (f
) : &safe_terminal_coding
);
761 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
763 coding
->mode
&= ~CODING_MODE_LAST_BLOCK
;
767 /* Identify a run of glyphs with the same face. */
768 int face_id
= string
->face_id
;
771 for (n
= 1; n
< len
; ++n
)
772 if (string
[n
].face_id
!= face_id
)
775 /* Turn appearance modes of the face of the run on. */
776 tty_highlight_if_desired (tty
);
777 turn_on_face (f
, face_id
);
780 /* This is the last run. */
781 coding
->mode
|= CODING_MODE_LAST_BLOCK
;
782 conversion_buffer
= encode_terminal_code (string
, n
, coding
);
783 if (coding
->produced
> 0)
786 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->output
);
787 if (ferror (tty
->output
))
788 clearerr (tty
->output
);
790 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 #ifdef HAVE_GPM /* Only used by GPM code. */
807 tty_write_glyphs_with_face (f
, string
, len
, face_id
)
808 register struct frame
*f
;
809 register struct glyph
*string
;
810 register int len
, face_id
;
812 unsigned char *conversion_buffer
;
813 struct coding_system
*coding
;
815 struct tty_display_info
*tty
= FRAME_TTY (f
);
817 tty_turn_off_insert (tty
);
818 tty_hide_cursor (tty
);
820 /* Don't dare write in last column of bottom line, if Auto-Wrap,
821 since that would scroll the whole frame on some terminals. */
824 && curY (tty
) + 1 == FRAME_LINES (f
)
825 && (curX (tty
) + len
) == FRAME_COLS (f
))
832 /* If terminal_coding does any conversion, use it, otherwise use
833 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
834 because it always return 1 if the member src_multibyte is 1. */
835 coding
= (FRAME_TERMINAL_CODING (f
)->common_flags
& CODING_REQUIRE_ENCODING_MASK
836 ? FRAME_TERMINAL_CODING (f
) : &safe_terminal_coding
);
837 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
839 coding
->mode
&= ~CODING_MODE_LAST_BLOCK
;
841 /* Turn appearance modes of the face. */
842 tty_highlight_if_desired (tty
);
843 turn_on_face (f
, face_id
);
845 coding
->mode
|= CODING_MODE_LAST_BLOCK
;
846 conversion_buffer
= encode_terminal_code (string
, len
, coding
);
847 if (coding
->produced
> 0)
850 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->output
);
851 if (ferror (tty
->output
))
852 clearerr (tty
->output
);
854 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->termscript
);
858 /* Turn appearance modes off. */
859 turn_off_face (f
, face_id
);
860 tty_turn_off_highlight (tty
);
866 /* An implementation of insert_glyphs for termcap frames. */
869 tty_insert_glyphs (struct frame
*f
, struct glyph
*start
, int len
)
872 struct glyph
*glyph
= NULL
;
873 unsigned char *conversion_buffer
;
874 unsigned char space
[1];
875 struct coding_system
*coding
;
877 struct tty_display_info
*tty
= FRAME_TTY (f
);
879 if (tty
->TS_ins_multi_chars
)
881 buf
= tparam (tty
->TS_ins_multi_chars
, 0, 0, len
);
885 write_glyphs (f
, start
, len
);
889 tty_turn_on_insert (tty
);
893 space
[0] = SPACEGLYPH
;
895 /* If terminal_coding does any conversion, use it, otherwise use
896 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
897 because it always return 1 if the member src_multibyte is 1. */
898 coding
= (FRAME_TERMINAL_CODING (f
)->common_flags
& CODING_REQUIRE_ENCODING_MASK
899 ? FRAME_TERMINAL_CODING (f
) : &safe_terminal_coding
);
900 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
902 coding
->mode
&= ~CODING_MODE_LAST_BLOCK
;
906 OUTPUT1_IF (tty
, tty
->TS_ins_char
);
909 conversion_buffer
= space
;
910 coding
->produced
= 1;
914 tty_highlight_if_desired (tty
);
915 turn_on_face (f
, start
->face_id
);
918 /* We must open sufficient space for a character which
919 occupies more than one column. */
920 while (len
&& CHAR_GLYPH_PADDING_P (*start
))
922 OUTPUT1_IF (tty
, tty
->TS_ins_char
);
927 /* This is the last glyph. */
928 coding
->mode
|= CODING_MODE_LAST_BLOCK
;
930 conversion_buffer
= encode_terminal_code (glyph
, 1, coding
);
933 if (coding
->produced
> 0)
936 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->output
);
937 if (ferror (tty
->output
))
938 clearerr (tty
->output
);
940 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->termscript
);
944 OUTPUT1_IF (tty
, tty
->TS_pad_inserted_char
);
947 turn_off_face (f
, glyph
->face_id
);
948 tty_turn_off_highlight (tty
);
955 /* An implementation of delete_glyphs for termcap frames. */
958 tty_delete_glyphs (struct frame
*f
, int n
)
963 struct tty_display_info
*tty
= FRAME_TTY (f
);
965 if (tty
->delete_in_insert_mode
)
967 tty_turn_on_insert (tty
);
971 tty_turn_off_insert (tty
);
972 OUTPUT_IF (tty
, tty
->TS_delete_mode
);
975 if (tty
->TS_del_multi_chars
)
977 buf
= tparam (tty
->TS_del_multi_chars
, 0, 0, n
);
982 for (i
= 0; i
< n
; i
++)
983 OUTPUT1 (tty
, tty
->TS_del_char
);
984 if (!tty
->delete_in_insert_mode
)
985 OUTPUT_IF (tty
, tty
->TS_end_delete_mode
);
988 /* An implementation of ins_del_lines for termcap frames. */
991 tty_ins_del_lines (struct frame
*f
, int vpos
, int n
)
993 struct tty_display_info
*tty
= FRAME_TTY (f
);
994 char *multi
= n
> 0 ? tty
->TS_ins_multi_lines
: tty
->TS_del_multi_lines
;
995 char *single
= n
> 0 ? tty
->TS_ins_line
: tty
->TS_del_line
;
996 char *scroll
= n
> 0 ? tty
->TS_rev_scroll
: tty
->TS_fwd_scroll
;
998 register int i
= n
> 0 ? n
: -n
;
1001 /* If the lines below the insertion are being pushed
1002 into the end of the window, this is the same as clearing;
1003 and we know the lines are already clear, since the matching
1004 deletion has already been done. So can ignore this. */
1005 /* If the lines below the deletion are blank lines coming
1006 out of the end of the window, don't bother,
1007 as there will be a matching inslines later that will flush them. */
1008 if (FRAME_SCROLL_REGION_OK (f
)
1009 && vpos
+ i
>= tty
->specified_window
)
1011 if (!FRAME_MEMORY_BELOW_FRAME (f
)
1012 && vpos
+ i
>= FRAME_LINES (f
))
1017 raw_cursor_to (f
, vpos
, 0);
1018 tty_background_highlight (tty
);
1019 buf
= tparam (multi
, 0, 0, i
);
1025 raw_cursor_to (f
, vpos
, 0);
1026 tty_background_highlight (tty
);
1028 OUTPUT (tty
, single
);
1029 if (tty
->TF_teleray
)
1034 tty_set_scroll_region (f
, vpos
, tty
->specified_window
);
1036 raw_cursor_to (f
, tty
->specified_window
- 1, 0);
1038 raw_cursor_to (f
, vpos
, 0);
1039 tty_background_highlight (tty
);
1041 OUTPUTL (tty
, scroll
, tty
->specified_window
- vpos
);
1042 tty_set_scroll_region (f
, 0, tty
->specified_window
);
1045 if (!FRAME_SCROLL_REGION_OK (f
)
1046 && FRAME_MEMORY_BELOW_FRAME (f
)
1049 cursor_to (f
, FRAME_LINES (f
) + n
, 0);
1054 /* Compute cost of sending "str", in characters,
1055 not counting any line-dependent padding. */
1058 string_cost (char *str
)
1062 tputs (str
, 0, evalcost
);
1066 /* Compute cost of sending "str", in characters,
1067 counting any line-dependent padding at one line. */
1070 string_cost_one_line (char *str
)
1074 tputs (str
, 1, evalcost
);
1078 /* Compute per line amount of line-dependent padding,
1079 in tenths of characters. */
1082 per_line_cost (char *str
)
1086 tputs (str
, 0, evalcost
);
1089 tputs (str
, 10, evalcost
);
1094 /* char_ins_del_cost[n] is cost of inserting N characters.
1095 char_ins_del_cost[-n] is cost of deleting N characters.
1096 The length of this vector is based on max_frame_cols. */
1098 int *char_ins_del_vector
;
1100 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
1105 calculate_ins_del_char_costs (struct frame
*f
)
1107 struct tty_display_info
*tty
= FRAME_TTY (f
);
1108 int ins_startup_cost
, del_startup_cost
;
1109 int ins_cost_per_char
, del_cost_per_char
;
1113 if (tty
->TS_ins_multi_chars
)
1115 ins_cost_per_char
= 0;
1116 ins_startup_cost
= string_cost_one_line (tty
->TS_ins_multi_chars
);
1118 else if (tty
->TS_ins_char
|| tty
->TS_pad_inserted_char
1119 || (tty
->TS_insert_mode
&& tty
->TS_end_insert_mode
))
1121 ins_startup_cost
= (30 * (string_cost (tty
->TS_insert_mode
)
1122 + string_cost (tty
->TS_end_insert_mode
))) / 100;
1123 ins_cost_per_char
= (string_cost_one_line (tty
->TS_ins_char
)
1124 + string_cost_one_line (tty
->TS_pad_inserted_char
));
1128 ins_startup_cost
= 9999;
1129 ins_cost_per_char
= 0;
1132 if (tty
->TS_del_multi_chars
)
1134 del_cost_per_char
= 0;
1135 del_startup_cost
= string_cost_one_line (tty
->TS_del_multi_chars
);
1137 else if (tty
->TS_del_char
)
1139 del_startup_cost
= (string_cost (tty
->TS_delete_mode
)
1140 + string_cost (tty
->TS_end_delete_mode
));
1141 if (tty
->delete_in_insert_mode
)
1142 del_startup_cost
/= 2;
1143 del_cost_per_char
= string_cost_one_line (tty
->TS_del_char
);
1147 del_startup_cost
= 9999;
1148 del_cost_per_char
= 0;
1151 /* Delete costs are at negative offsets */
1152 p
= &char_ins_del_cost (f
)[0];
1153 for (i
= FRAME_COLS (f
); --i
>= 0;)
1154 *--p
= (del_startup_cost
+= del_cost_per_char
);
1156 /* Doing nothing is free */
1157 p
= &char_ins_del_cost (f
)[0];
1160 /* Insert costs are at positive offsets */
1161 for (i
= FRAME_COLS (f
); --i
>= 0;)
1162 *p
++ = (ins_startup_cost
+= ins_cost_per_char
);
1166 calculate_costs (struct frame
*frame
)
1168 FRAME_COST_BAUD_RATE (frame
) = baud_rate
;
1170 if (FRAME_TERMCAP_P (frame
))
1172 struct tty_display_info
*tty
= FRAME_TTY (frame
);
1173 register char *f
= (tty
->TS_set_scroll_region
1174 ? tty
->TS_set_scroll_region
1175 : tty
->TS_set_scroll_region_1
);
1177 FRAME_SCROLL_REGION_COST (frame
) = string_cost (f
);
1181 /* These variables are only used for terminal stuff. They are
1182 allocated once for the terminal frame of X-windows emacs, but not
1185 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1186 X turns off char_ins_del_ok. */
1188 max_frame_lines
= max (max_frame_lines
, FRAME_LINES (frame
));
1189 max_frame_cols
= max (max_frame_cols
, FRAME_COLS (frame
));
1191 if (char_ins_del_vector
!= 0)
1193 = (int *) xrealloc (char_ins_del_vector
,
1195 + 2 * max_frame_cols
* sizeof (int)));
1198 = (int *) xmalloc (sizeof (int)
1199 + 2 * max_frame_cols
* sizeof (int));
1201 bzero (char_ins_del_vector
, (sizeof (int)
1202 + 2 * max_frame_cols
* sizeof (int)));
1205 if (f
&& (!tty
->TS_ins_line
&& !tty
->TS_del_line
))
1206 do_line_insertion_deletion_costs (frame
,
1207 tty
->TS_rev_scroll
, tty
->TS_ins_multi_lines
,
1208 tty
->TS_fwd_scroll
, tty
->TS_del_multi_lines
,
1211 do_line_insertion_deletion_costs (frame
,
1212 tty
->TS_ins_line
, tty
->TS_ins_multi_lines
,
1213 tty
->TS_del_line
, tty
->TS_del_multi_lines
,
1216 calculate_ins_del_char_costs (frame
);
1218 /* Don't use TS_repeat if its padding is worse than sending the chars */
1219 if (tty
->TS_repeat
&& per_line_cost (tty
->TS_repeat
) * baud_rate
< 9000)
1220 tty
->RPov
= string_cost (tty
->TS_repeat
);
1222 tty
->RPov
= FRAME_COLS (frame
) * 2;
1224 cmcostinit (FRAME_TTY (frame
)); /* set up cursor motion costs */
1232 /* Termcap capability names that correspond directly to X keysyms.
1233 Some of these (marked "terminfo") aren't supplied by old-style
1234 (Berkeley) termcap entries. They're listed in X keysym order;
1235 except we put the keypad keys first, so that if they clash with
1236 other keys (as on the IBM PC keyboard) they get overridden.
1239 static struct fkey_table keys
[] =
1241 {"kh", "home"}, /* termcap */
1242 {"kl", "left"}, /* termcap */
1243 {"ku", "up"}, /* termcap */
1244 {"kr", "right"}, /* termcap */
1245 {"kd", "down"}, /* termcap */
1246 {"%8", "prior"}, /* terminfo */
1247 {"%5", "next"}, /* terminfo */
1248 {"@7", "end"}, /* terminfo */
1249 {"@1", "begin"}, /* terminfo */
1250 {"*6", "select"}, /* terminfo */
1251 {"%9", "print"}, /* terminfo */
1252 {"@4", "execute"}, /* terminfo --- actually the `command' key */
1254 * "insert" --- see below
1256 {"&8", "undo"}, /* terminfo */
1257 {"%0", "redo"}, /* terminfo */
1258 {"%7", "menu"}, /* terminfo --- actually the `options' key */
1259 {"@0", "find"}, /* terminfo */
1260 {"@2", "cancel"}, /* terminfo */
1261 {"%1", "help"}, /* terminfo */
1263 * "break" goes here, but can't be reliably intercepted with termcap
1265 {"&4", "reset"}, /* terminfo --- actually `restart' */
1267 * "system" and "user" --- no termcaps
1269 {"kE", "clearline"}, /* terminfo */
1270 {"kA", "insertline"}, /* terminfo */
1271 {"kL", "deleteline"}, /* terminfo */
1272 {"kI", "insertchar"}, /* terminfo */
1273 {"kD", "deletechar"}, /* terminfo */
1274 {"kB", "backtab"}, /* terminfo */
1276 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1278 {"@8", "kp-enter"}, /* terminfo */
1280 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1281 * "kp-multiply", "kp-add", "kp-separator",
1282 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1283 * --- no termcaps for any of these.
1285 {"K4", "kp-1"}, /* terminfo */
1287 * "kp-2" --- no termcap
1289 {"K5", "kp-3"}, /* terminfo */
1291 * "kp-4" --- no termcap
1293 {"K2", "kp-5"}, /* terminfo */
1295 * "kp-6" --- no termcap
1297 {"K1", "kp-7"}, /* terminfo */
1299 * "kp-8" --- no termcap
1301 {"K3", "kp-9"}, /* terminfo */
1303 * "kp-equal" --- no termcap
1315 {"&0", "S-cancel"}, /*shifted cancel key*/
1316 {"&9", "S-begin"}, /*shifted begin key*/
1317 {"*0", "S-find"}, /*shifted find key*/
1318 {"*1", "S-execute"}, /*shifted execute? actually shifted command key*/
1319 {"*4", "S-delete"}, /*shifted delete-character key*/
1320 {"*7", "S-end"}, /*shifted end key*/
1321 {"*8", "S-clearline"}, /*shifted clear-to end-of-line key*/
1322 {"#1", "S-help"}, /*shifted help key*/
1323 {"#2", "S-home"}, /*shifted home key*/
1324 {"#3", "S-insert"}, /*shifted insert-character key*/
1325 {"#4", "S-left"}, /*shifted left-arrow key*/
1326 {"%d", "S-menu"}, /*shifted menu? actually shifted options key*/
1327 {"%c", "S-next"}, /*shifted next key*/
1328 {"%e", "S-prior"}, /*shifted previous key*/
1329 {"%f", "S-print"}, /*shifted print key*/
1330 {"%g", "S-redo"}, /*shifted redo key*/
1331 {"%i", "S-right"}, /*shifted right-arrow key*/
1332 {"!3", "S-undo"} /*shifted undo key*/
1335 static char **term_get_fkeys_address
;
1336 static KBOARD
*term_get_fkeys_kboard
;
1337 static Lisp_Object
term_get_fkeys_1 ();
1339 /* Find the escape codes sent by the function keys for Vinput_decode_map.
1340 This function scans the termcap function key sequence entries, and
1341 adds entries to Vinput_decode_map for each function key it finds. */
1344 term_get_fkeys (address
, kboard
)
1348 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1349 errors during the call. The only errors should be from Fdefine_key
1350 when given a key sequence containing an invalid prefix key. If the
1351 termcap defines function keys which use a prefix that is already bound
1352 to a command by the default bindings, we should silently ignore that
1353 function key specification, rather than giving the user an error and
1354 refusing to run at all on such a terminal. */
1356 extern Lisp_Object
Fidentity ();
1357 term_get_fkeys_address
= address
;
1358 term_get_fkeys_kboard
= kboard
;
1359 internal_condition_case (term_get_fkeys_1
, Qerror
, Fidentity
);
1367 char **address
= term_get_fkeys_address
;
1368 KBOARD
*kboard
= term_get_fkeys_kboard
;
1370 /* This can happen if CANNOT_DUMP or with strange options. */
1371 if (!KEYMAPP (kboard
->Vinput_decode_map
))
1372 kboard
->Vinput_decode_map
= Fmake_sparse_keymap (Qnil
);
1374 for (i
= 0; i
< (sizeof (keys
)/sizeof (keys
[0])); i
++)
1376 char *sequence
= tgetstr (keys
[i
].cap
, address
);
1378 Fdefine_key (kboard
->Vinput_decode_map
, build_string (sequence
),
1379 Fmake_vector (make_number (1),
1380 intern (keys
[i
].name
)));
1383 /* The uses of the "k0" capability are inconsistent; sometimes it
1384 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1385 We will attempt to politely accommodate both systems by testing for
1386 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1389 char *k_semi
= tgetstr ("k;", address
);
1390 char *k0
= tgetstr ("k0", address
);
1391 char *k0_name
= "f10";
1396 /* Define f0 first, so that f10 takes precedence in case the
1397 key sequences happens to be the same. */
1398 Fdefine_key (kboard
->Vinput_decode_map
, build_string (k0
),
1399 Fmake_vector (make_number (1), intern ("f0")));
1400 Fdefine_key (kboard
->Vinput_decode_map
, build_string (k_semi
),
1401 Fmake_vector (make_number (1), intern ("f10")));
1404 Fdefine_key (kboard
->Vinput_decode_map
, build_string (k0
),
1405 Fmake_vector (make_number (1), intern (k0_name
)));
1408 /* Set up cookies for numbered function keys above f10. */
1410 char fcap
[3], fkey
[4];
1412 fcap
[0] = 'F'; fcap
[2] = '\0';
1413 for (i
= 11; i
< 64; i
++)
1416 fcap
[1] = '1' + i
- 11;
1418 fcap
[1] = 'A' + i
- 20;
1420 fcap
[1] = 'a' + i
- 46;
1423 char *sequence
= tgetstr (fcap
, address
);
1426 sprintf (fkey
, "f%d", i
);
1427 Fdefine_key (kboard
->Vinput_decode_map
, build_string (sequence
),
1428 Fmake_vector (make_number (1),
1436 * Various mappings to try and get a better fit.
1439 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1440 if (!tgetstr (cap1, address)) \
1442 char *sequence = tgetstr (cap2, address); \
1444 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence), \
1445 Fmake_vector (make_number (1), \
1449 /* if there's no key_next keycap, map key_npage to `next' keysym */
1450 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1451 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1452 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1453 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1454 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1455 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1456 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1458 /* IBM has their own non-standard dialect of terminfo.
1459 If the standard name isn't found, try the IBM name. */
1460 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1461 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1462 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1463 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1464 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1465 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1466 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1467 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1468 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1469 #undef CONDITIONAL_REASSIGN
1476 /***********************************************************************
1477 Character Display Information
1478 ***********************************************************************/
1480 /* Avoid name clash with functions defined in xterm.c */
1482 #define append_glyph append_glyph_term
1483 #define produce_stretch_glyph produce_stretch_glyph_term
1484 #define append_composite_glyph append_composite_glyph_term
1485 #define produce_composite_glyph produce_composite_glyph_term
1488 static void append_glyph
P_ ((struct it
*));
1489 static void produce_stretch_glyph
P_ ((struct it
*));
1490 static void append_composite_glyph
P_ ((struct it
*));
1491 static void produce_composite_glyph
P_ ((struct it
*));
1493 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1494 terminal frames if IT->glyph_row != NULL. IT->char_to_display is
1495 the character for which to produce glyphs; IT->face_id contains the
1496 character's face. Padding glyphs are appended if IT->c has a
1497 IT->pixel_width > 1. */
1503 struct glyph
*glyph
, *end
;
1506 xassert (it
->glyph_row
);
1507 glyph
= (it
->glyph_row
->glyphs
[it
->area
]
1508 + it
->glyph_row
->used
[it
->area
]);
1509 end
= it
->glyph_row
->glyphs
[1 + it
->area
];
1512 i
< it
->pixel_width
&& glyph
< end
;
1515 glyph
->type
= CHAR_GLYPH
;
1516 glyph
->pixel_width
= 1;
1517 glyph
->u
.ch
= it
->char_to_display
;
1518 glyph
->face_id
= it
->face_id
;
1519 glyph
->padding_p
= i
> 0;
1520 glyph
->charpos
= CHARPOS (it
->position
);
1521 glyph
->object
= it
->object
;
1523 ++it
->glyph_row
->used
[it
->area
];
1529 /* Produce glyphs for the display element described by IT. *IT
1530 specifies what we want to produce a glyph for (character, image, ...),
1531 and where in the glyph matrix we currently are (glyph row and hpos).
1532 produce_glyphs fills in output fields of *IT with information such as the
1533 pixel width and height of a character, and maybe output actual glyphs at
1534 the same time if IT->glyph_row is non-null. See the explanation of
1535 struct display_iterator in dispextern.h for an overview.
1537 produce_glyphs also stores the result of glyph width, ascent
1538 etc. computations in *IT.
1540 IT->glyph_row may be null, in which case produce_glyphs does not
1541 actually fill in the glyphs. This is used in the move_* functions
1542 in xdisp.c for text width and height computations.
1544 Callers usually don't call produce_glyphs directly;
1545 instead they use the macro PRODUCE_GLYPHS. */
1551 /* If a hook is installed, let it do the work. */
1553 /* Nothing but characters are supported on terminal frames. */
1554 xassert (it
->what
== IT_CHARACTER
1555 || it
->what
== IT_COMPOSITION
1556 || it
->what
== IT_STRETCH
);
1558 if (it
->what
== IT_STRETCH
)
1560 produce_stretch_glyph (it
);
1564 if (it
->what
== IT_COMPOSITION
)
1566 produce_composite_glyph (it
);
1570 /* Maybe translate single-byte characters to multibyte. */
1571 it
->char_to_display
= it
->c
;
1573 if (it
->c
>= 040 && it
->c
< 0177)
1575 it
->pixel_width
= it
->nglyphs
= 1;
1579 else if (it
->c
== '\n')
1580 it
->pixel_width
= it
->nglyphs
= 0;
1581 else if (it
->c
== '\t')
1583 int absolute_x
= (it
->current_x
1584 + it
->continuation_lines_width
);
1586 = (((1 + absolute_x
+ it
->tab_width
- 1)
1591 /* If part of the TAB has been displayed on the previous line
1592 which is continued now, continuation_lines_width will have
1593 been incremented already by the part that fitted on the
1594 continued line. So, we will get the right number of spaces
1596 nspaces
= next_tab_x
- absolute_x
;
1602 it
->char_to_display
= ' ';
1603 it
->pixel_width
= it
->len
= 1;
1609 it
->pixel_width
= nspaces
;
1610 it
->nglyphs
= nspaces
;
1612 else if (CHAR_BYTE8_P (it
->c
))
1614 if (unibyte_display_via_language_environment
1617 it
->char_to_display
= unibyte_char_to_multibyte (it
->c
);
1618 it
->pixel_width
= CHAR_WIDTH (it
->char_to_display
);
1619 it
->nglyphs
= it
->pixel_width
;
1625 /* Coming here means that it->c is from display table, thus
1626 we must send the raw 8-bit byte as is to the terminal.
1627 Although there's no way to know how many columns it
1628 occupies on a screen, it is a good assumption that a
1629 single byte code has 1-column width. */
1630 it
->pixel_width
= it
->nglyphs
= 1;
1637 it
->pixel_width
= CHAR_WIDTH (it
->c
);
1638 it
->nglyphs
= it
->pixel_width
;
1645 /* Advance current_x by the pixel width as a convenience for
1647 if (it
->area
== TEXT_AREA
)
1648 it
->current_x
+= it
->pixel_width
;
1649 it
->ascent
= it
->max_ascent
= it
->phys_ascent
= it
->max_phys_ascent
= 0;
1650 it
->descent
= it
->max_descent
= it
->phys_descent
= it
->max_phys_descent
= 1;
1654 /* Produce a stretch glyph for iterator IT. IT->object is the value
1655 of the glyph property displayed. The value must be a list
1656 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1659 1. `:width WIDTH' specifies that the space should be WIDTH *
1660 canonical char width wide. WIDTH may be an integer or floating
1663 2. `:align-to HPOS' specifies that the space should be wide enough
1664 to reach HPOS, a value in canonical character units. */
1667 produce_stretch_glyph (it
)
1670 /* (space :width WIDTH ...) */
1671 Lisp_Object prop
, plist
;
1672 int width
= 0, align_to
= -1;
1673 int zero_width_ok_p
= 0;
1676 /* List should start with `space'. */
1677 xassert (CONSP (it
->object
) && EQ (XCAR (it
->object
), Qspace
));
1678 plist
= XCDR (it
->object
);
1680 /* Compute the width of the stretch. */
1681 if ((prop
= Fplist_get (plist
, QCwidth
), !NILP (prop
))
1682 && calc_pixel_width_or_height (&tem
, it
, prop
, 0, 1, 0))
1684 /* Absolute width `:width WIDTH' specified and valid. */
1685 zero_width_ok_p
= 1;
1686 width
= (int)(tem
+ 0.5);
1688 else if ((prop
= Fplist_get (plist
, QCalign_to
), !NILP (prop
))
1689 && calc_pixel_width_or_height (&tem
, it
, prop
, 0, 1, &align_to
))
1691 if (it
->glyph_row
== NULL
|| !it
->glyph_row
->mode_line_p
)
1692 align_to
= (align_to
< 0
1694 : align_to
- window_box_left_offset (it
->w
, TEXT_AREA
));
1695 else if (align_to
< 0)
1696 align_to
= window_box_left_offset (it
->w
, TEXT_AREA
);
1697 width
= max (0, (int)(tem
+ 0.5) + align_to
- it
->current_x
);
1698 zero_width_ok_p
= 1;
1701 /* Nothing specified -> width defaults to canonical char width. */
1702 width
= FRAME_COLUMN_WIDTH (it
->f
);
1704 if (width
<= 0 && (width
< 0 || !zero_width_ok_p
))
1707 if (width
> 0 && it
->glyph_row
)
1709 Lisp_Object o_object
= it
->object
;
1710 Lisp_Object object
= it
->stack
[it
->sp
- 1].string
;
1713 if (!STRINGP (object
))
1714 object
= it
->w
->buffer
;
1715 it
->object
= object
;
1716 it
->char_to_display
= ' ';
1717 it
->pixel_width
= it
->len
= 1;
1720 it
->object
= o_object
;
1722 it
->pixel_width
= width
;
1723 it
->nglyphs
= width
;
1727 /* Append glyphs to IT's glyph_row for the composition IT->cmp_id.
1728 Called from produce_composite_glyph for terminal frames if
1729 IT->glyph_row != NULL. IT->face_id contains the character's
1733 append_composite_glyph (it
)
1736 struct glyph
*glyph
;
1738 xassert (it
->glyph_row
);
1739 glyph
= it
->glyph_row
->glyphs
[it
->area
] + it
->glyph_row
->used
[it
->area
];
1740 if (glyph
< it
->glyph_row
->glyphs
[1 + it
->area
])
1742 glyph
->type
= COMPOSITE_GLYPH
;
1743 glyph
->pixel_width
= it
->pixel_width
;
1744 glyph
->u
.cmp_id
= it
->cmp_id
;
1745 glyph
->face_id
= it
->face_id
;
1746 glyph
->padding_p
= 0;
1747 glyph
->charpos
= CHARPOS (it
->position
);
1748 glyph
->object
= it
->object
;
1750 ++it
->glyph_row
->used
[it
->area
];
1756 /* Produce a composite glyph for iterator IT. IT->cmp_id is the ID of
1757 the composition. We simply produces components of the composition
1758 assuming that that the terminal has a capability to layout/render
1762 produce_composite_glyph (it
)
1765 struct composition
*cmp
= composition_table
[it
->cmp_id
];
1768 xassert (cmp
->glyph_len
> 0);
1769 c
= COMPOSITION_GLYPH (cmp
, 0);
1770 it
->pixel_width
= CHAR_WIDTH (it
->c
);
1774 append_composite_glyph (it
);
1778 /* Get information about special display element WHAT in an
1779 environment described by IT. WHAT is one of IT_TRUNCATION or
1780 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1781 non-null glyph_row member. This function ensures that fields like
1782 face_id, c, len of IT are left untouched. */
1785 produce_special_glyphs (it
, what
)
1787 enum display_element_type what
;
1795 temp_it
.what
= IT_CHARACTER
;
1797 temp_it
.object
= make_number (0);
1798 bzero (&temp_it
.current
, sizeof temp_it
.current
);
1800 if (what
== IT_CONTINUATION
)
1802 /* Continuation glyph. */
1803 SET_GLYPH_FROM_CHAR (glyph
, '\\');
1805 && (gc
= DISP_CONTINUE_GLYPH (it
->dp
), GLYPH_CODE_P (gc
))
1806 && GLYPH_CODE_CHAR_VALID_P (gc
))
1808 SET_GLYPH_FROM_GLYPH_CODE (glyph
, gc
);
1809 spec_glyph_lookup_face (XWINDOW (it
->window
), &glyph
);
1812 else if (what
== IT_TRUNCATION
)
1814 /* Truncation glyph. */
1815 SET_GLYPH_FROM_CHAR (glyph
, '$');
1817 && (gc
= DISP_TRUNC_GLYPH (it
->dp
), GLYPH_CODE_P (gc
))
1818 && GLYPH_CODE_CHAR_VALID_P (gc
))
1820 SET_GLYPH_FROM_GLYPH_CODE (glyph
, gc
);
1821 spec_glyph_lookup_face (XWINDOW (it
->window
), &glyph
);
1827 temp_it
.c
= GLYPH_CHAR (glyph
);
1828 temp_it
.face_id
= GLYPH_FACE (glyph
);
1829 temp_it
.len
= CHAR_BYTES (temp_it
.c
);
1831 produce_glyphs (&temp_it
);
1832 it
->pixel_width
= temp_it
.pixel_width
;
1833 it
->nglyphs
= temp_it
.pixel_width
;
1838 /***********************************************************************
1840 ***********************************************************************/
1842 /* Value is non-zero if attribute ATTR may be used. ATTR should be
1843 one of the enumerators from enum no_color_bit, or a bit set built
1844 from them. Some display attributes may not be used together with
1845 color; the termcap capability `NC' specifies which ones. */
1847 #define MAY_USE_WITH_COLORS_P(tty, ATTR) \
1848 (tty->TN_max_colors > 0 \
1849 ? (tty->TN_no_color_video & (ATTR)) == 0 \
1852 /* Turn appearances of face FACE_ID on tty frame F on.
1853 FACE_ID is a realized face ID number, in the face cache. */
1856 turn_on_face (f
, face_id
)
1860 struct face
*face
= FACE_FROM_ID (f
, face_id
);
1861 long fg
= face
->foreground
;
1862 long bg
= face
->background
;
1863 struct tty_display_info
*tty
= FRAME_TTY (f
);
1865 /* Do this first because TS_end_standout_mode may be the same
1866 as TS_exit_attribute_mode, which turns all appearances off. */
1867 if (MAY_USE_WITH_COLORS_P (tty
, NC_REVERSE
))
1869 if (tty
->TN_max_colors
> 0)
1871 if (fg
>= 0 && bg
>= 0)
1873 /* If the terminal supports colors, we can set them
1874 below without using reverse video. The face's fg
1875 and bg colors are set as they should appear on
1876 the screen, i.e. they take the inverse-video'ness
1877 of the face already into account. */
1879 else if (inverse_video
)
1881 if (fg
== FACE_TTY_DEFAULT_FG_COLOR
1882 || bg
== FACE_TTY_DEFAULT_BG_COLOR
)
1883 tty_toggle_highlight (tty
);
1887 if (fg
== FACE_TTY_DEFAULT_BG_COLOR
1888 || bg
== FACE_TTY_DEFAULT_FG_COLOR
)
1889 tty_toggle_highlight (tty
);
1894 /* If we can't display colors, use reverse video
1895 if the face specifies that. */
1898 if (fg
== FACE_TTY_DEFAULT_FG_COLOR
1899 || bg
== FACE_TTY_DEFAULT_BG_COLOR
)
1900 tty_toggle_highlight (tty
);
1904 if (fg
== FACE_TTY_DEFAULT_BG_COLOR
1905 || bg
== FACE_TTY_DEFAULT_FG_COLOR
)
1906 tty_toggle_highlight (tty
);
1911 if (face
->tty_bold_p
)
1913 if (MAY_USE_WITH_COLORS_P (tty
, NC_BOLD
))
1914 OUTPUT1_IF (tty
, tty
->TS_enter_bold_mode
);
1916 else if (face
->tty_dim_p
)
1917 if (MAY_USE_WITH_COLORS_P (tty
, NC_DIM
))
1918 OUTPUT1_IF (tty
, tty
->TS_enter_dim_mode
);
1920 /* Alternate charset and blinking not yet used. */
1921 if (face
->tty_alt_charset_p
1922 && MAY_USE_WITH_COLORS_P (tty
, NC_ALT_CHARSET
))
1923 OUTPUT1_IF (tty
, tty
->TS_enter_alt_charset_mode
);
1925 if (face
->tty_blinking_p
1926 && MAY_USE_WITH_COLORS_P (tty
, NC_BLINK
))
1927 OUTPUT1_IF (tty
, tty
->TS_enter_blink_mode
);
1929 if (face
->tty_underline_p
&& MAY_USE_WITH_COLORS_P (tty
, NC_UNDERLINE
))
1930 OUTPUT1_IF (tty
, tty
->TS_enter_underline_mode
);
1932 if (tty
->TN_max_colors
> 0)
1936 ts
= tty
->standout_mode
? tty
->TS_set_background
: tty
->TS_set_foreground
;
1939 p
= tparam (ts
, NULL
, 0, (int) fg
);
1944 ts
= tty
->standout_mode
? tty
->TS_set_foreground
: tty
->TS_set_background
;
1947 p
= tparam (ts
, NULL
, 0, (int) bg
);
1955 /* Turn off appearances of face FACE_ID on tty frame F. */
1958 turn_off_face (f
, face_id
)
1962 struct face
*face
= FACE_FROM_ID (f
, face_id
);
1963 struct tty_display_info
*tty
= FRAME_TTY (f
);
1965 xassert (face
!= NULL
);
1967 if (tty
->TS_exit_attribute_mode
)
1969 /* Capability "me" will turn off appearance modes double-bright,
1970 half-bright, reverse-video, standout, underline. It may or
1971 may not turn off alt-char-mode. */
1972 if (face
->tty_bold_p
1974 || face
->tty_reverse_p
1975 || face
->tty_alt_charset_p
1976 || face
->tty_blinking_p
1977 || face
->tty_underline_p
)
1979 OUTPUT1_IF (tty
, tty
->TS_exit_attribute_mode
);
1980 if (strcmp (tty
->TS_exit_attribute_mode
, tty
->TS_end_standout_mode
) == 0)
1981 tty
->standout_mode
= 0;
1984 if (face
->tty_alt_charset_p
)
1985 OUTPUT_IF (tty
, tty
->TS_exit_alt_charset_mode
);
1989 /* If we don't have "me" we can only have those appearances
1990 that have exit sequences defined. */
1991 if (face
->tty_alt_charset_p
)
1992 OUTPUT_IF (tty
, tty
->TS_exit_alt_charset_mode
);
1994 if (face
->tty_underline_p
)
1995 OUTPUT_IF (tty
, tty
->TS_exit_underline_mode
);
1998 /* Switch back to default colors. */
1999 if (tty
->TN_max_colors
> 0
2000 && ((face
->foreground
!= FACE_TTY_DEFAULT_COLOR
2001 && face
->foreground
!= FACE_TTY_DEFAULT_FG_COLOR
)
2002 || (face
->background
!= FACE_TTY_DEFAULT_COLOR
2003 && face
->background
!= FACE_TTY_DEFAULT_BG_COLOR
)))
2004 OUTPUT1_IF (tty
, tty
->TS_orig_pair
);
2008 /* Return non-zero if the terminal on frame F supports all of the
2009 capabilities in CAPS simultaneously, with foreground and background
2010 colors FG and BG. */
2013 tty_capable_p (tty
, caps
, fg
, bg
)
2014 struct tty_display_info
*tty
;
2016 unsigned long fg
, bg
;
2018 #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
2019 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
2022 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_INVERSE
, tty
->TS_standout_mode
, NC_REVERSE
);
2023 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_UNDERLINE
, tty
->TS_enter_underline_mode
, NC_UNDERLINE
);
2024 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_BOLD
, tty
->TS_enter_bold_mode
, NC_BOLD
);
2025 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_DIM
, tty
->TS_enter_dim_mode
, NC_DIM
);
2026 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_BLINK
, tty
->TS_enter_blink_mode
, NC_BLINK
);
2027 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_ALT_CHARSET
, tty
->TS_enter_alt_charset_mode
, NC_ALT_CHARSET
);
2033 /* Return non-zero if the terminal is capable to display colors. */
2035 DEFUN ("tty-display-color-p", Ftty_display_color_p
, Stty_display_color_p
,
2037 doc
: /* Return non-nil if the tty device TERMINAL can display colors.
2039 TERMINAL can be a terminal id, a frame or nil (meaning the selected
2040 frame's terminal). This function always returns nil if TERMINAL
2041 is not on a tty device. */)
2043 Lisp_Object terminal
;
2045 struct terminal
*t
= get_tty_terminal (terminal
, 0);
2049 return t
->display_info
.tty
->TN_max_colors
> 0 ? Qt
: Qnil
;
2052 /* Return the number of supported colors. */
2053 DEFUN ("tty-display-color-cells", Ftty_display_color_cells
,
2054 Stty_display_color_cells
, 0, 1, 0,
2055 doc
: /* Return the number of colors supported by the tty device TERMINAL.
2057 TERMINAL can be a terminal id, a frame or nil (meaning the selected
2058 frame's terminal). This function always returns 0 if TERMINAL
2059 is not on a tty device. */)
2061 Lisp_Object terminal
;
2063 struct terminal
*t
= get_tty_terminal (terminal
, 0);
2065 return make_number (0);
2067 return make_number (t
->display_info
.tty
->TN_max_colors
);
2072 /* Declare here rather than in the function, as in the rest of Emacs,
2073 to work around an HPUX compiler bug (?). See
2074 http://lists.gnu.org/archive/html/emacs-devel/2007-08/msg00410.html */
2075 static int default_max_colors
;
2076 static int default_max_pairs
;
2077 static int default_no_color_video
;
2078 static char *default_orig_pair
;
2079 static char *default_set_foreground
;
2080 static char *default_set_background
;
2082 /* Save or restore the default color-related capabilities of this
2085 tty_default_color_capabilities (struct tty_display_info
*tty
, int save
)
2090 xfree (default_orig_pair
);
2091 default_orig_pair
= tty
->TS_orig_pair
? xstrdup (tty
->TS_orig_pair
) : NULL
;
2093 xfree (default_set_foreground
);
2094 default_set_foreground
= tty
->TS_set_foreground
? xstrdup (tty
->TS_set_foreground
)
2097 xfree (default_set_background
);
2098 default_set_background
= tty
->TS_set_background
? xstrdup (tty
->TS_set_background
)
2101 default_max_colors
= tty
->TN_max_colors
;
2102 default_max_pairs
= tty
->TN_max_pairs
;
2103 default_no_color_video
= tty
->TN_no_color_video
;
2107 tty
->TS_orig_pair
= default_orig_pair
;
2108 tty
->TS_set_foreground
= default_set_foreground
;
2109 tty
->TS_set_background
= default_set_background
;
2110 tty
->TN_max_colors
= default_max_colors
;
2111 tty
->TN_max_pairs
= default_max_pairs
;
2112 tty
->TN_no_color_video
= default_no_color_video
;
2116 /* Setup one of the standard tty color schemes according to MODE.
2117 MODE's value is generally the number of colors which we want to
2118 support; zero means set up for the default capabilities, the ones
2119 we saw at init_tty time; -1 means turn off color support. */
2121 tty_setup_colors (struct tty_display_info
*tty
, int mode
)
2123 /* Canonicalize all negative values of MODE. */
2129 case -1: /* no colors at all */
2130 tty
->TN_max_colors
= 0;
2131 tty
->TN_max_pairs
= 0;
2132 tty
->TN_no_color_video
= 0;
2133 tty
->TS_set_foreground
= tty
->TS_set_background
= tty
->TS_orig_pair
= NULL
;
2135 case 0: /* default colors, if any */
2137 tty_default_color_capabilities (tty
, 0);
2139 case 8: /* 8 standard ANSI colors */
2140 tty
->TS_orig_pair
= "\033[0m";
2142 tty
->TS_set_foreground
= "\033[3%p1%dm";
2143 tty
->TS_set_background
= "\033[4%p1%dm";
2145 tty
->TS_set_foreground
= "\033[3%dm";
2146 tty
->TS_set_background
= "\033[4%dm";
2148 tty
->TN_max_colors
= 8;
2149 tty
->TN_max_pairs
= 64;
2150 tty
->TN_no_color_video
= 0;
2156 set_tty_color_mode (tty
, f
)
2157 struct tty_display_info
*tty
;
2160 Lisp_Object tem
, val
, color_mode_spec
;
2161 Lisp_Object color_mode
;
2163 extern Lisp_Object Qtty_color_mode
;
2164 Lisp_Object tty_color_mode_alist
2165 = Fintern_soft (build_string ("tty-color-mode-alist"), Qnil
);
2167 tem
= assq_no_quit (Qtty_color_mode
, f
->param_alist
);
2168 val
= CONSP (tem
) ? XCDR (tem
) : Qnil
;
2174 tem
= (NILP (tty_color_mode_alist
) ? Qnil
2175 : Fassq (val
, XSYMBOL (tty_color_mode_alist
)->value
));
2176 color_mode
= CONSP (tem
) ? XCDR (tem
) : Qnil
;
2179 mode
= INTEGERP (color_mode
) ? XINT (color_mode
) : 0;
2181 if (mode
!= tty
->previous_color_mode
)
2183 Lisp_Object funsym
= intern ("tty-set-up-initial-frame-faces");
2184 tty
->previous_color_mode
= mode
;
2185 tty_setup_colors (tty
, mode
);
2186 /* This recomputes all the faces given the new color definitions. */
2187 safe_call (1, &funsym
);
2191 #endif /* !WINDOWSNT */
2195 /* Return the tty display object specified by TERMINAL. */
2198 get_tty_terminal (Lisp_Object terminal
, int throw)
2200 struct terminal
*t
= get_terminal (terminal
, throw);
2202 if (t
&& t
->type
!= output_termcap
)
2205 error ("Device %d is not a termcap terminal device", t
->id
);
2213 /* Return an active termcap device that uses the tty device with the
2216 This function ignores suspended devices.
2218 Returns NULL if the named terminal device is not opened. */
2221 get_named_tty (name
)
2229 for (t
= terminal_list
; t
; t
= t
->next_terminal
)
2231 if (t
->type
== output_termcap
2232 && !strcmp (t
->display_info
.tty
->name
, name
)
2233 && TERMINAL_ACTIVE_P (t
))
2241 DEFUN ("tty-type", Ftty_type
, Stty_type
, 0, 1, 0,
2242 doc
: /* Return the type of the tty device that TERMINAL uses.
2243 Returns nil if TERMINAL is not on a tty device.
2245 TERMINAL can be a terminal id, a frame or nil (meaning the selected
2246 frame's terminal). */)
2248 Lisp_Object terminal
;
2250 struct terminal
*t
= get_terminal (terminal
, 1);
2252 if (t
->type
!= output_termcap
)
2255 if (t
->display_info
.tty
->type
)
2256 return build_string (t
->display_info
.tty
->type
);
2261 DEFUN ("controlling-tty-p", Fcontrolling_tty_p
, Scontrolling_tty_p
, 0, 1, 0,
2262 doc
: /* Return non-nil if TERMINAL is on the controlling tty of the Emacs process.
2264 TERMINAL can be a terminal id, a frame or nil (meaning the selected
2265 frame's terminal). This function always returns nil if TERMINAL
2266 is not on a tty device. */)
2268 Lisp_Object terminal
;
2270 struct terminal
*t
= get_terminal (terminal
, 1);
2272 if (t
->type
!= output_termcap
|| strcmp (t
->display_info
.tty
->name
, DEV_TTY
))
2278 DEFUN ("tty-no-underline", Ftty_no_underline
, Stty_no_underline
, 0, 1, 0,
2279 doc
: /* Declare that the tty used by TERMINAL does not handle underlining.
2280 This is used to override the terminfo data, for certain terminals that
2281 do not really do underlining, but say that they do. This function has
2282 no effect if used on a non-tty terminal.
2284 TERMINAL can be a terminal id, a frame or nil (meaning the selected
2285 frame's terminal). This function always returns nil if TERMINAL
2286 is not on a tty device. */)
2288 Lisp_Object terminal
;
2290 struct terminal
*t
= get_terminal (terminal
, 1);
2292 if (t
->type
== output_termcap
)
2293 t
->display_info
.tty
->TS_enter_underline_mode
= 0;
2299 DEFUN ("suspend-tty", Fsuspend_tty
, Ssuspend_tty
, 0, 1, 0,
2300 doc
: /* Suspend the terminal device TTY.
2302 The device is restored to its default state, and Emacs ceases all
2303 access to the tty device. Frames that use the device are not deleted,
2304 but input is not read from them and if they change, their display is
2307 TTY may be a terminal id, a frame, or nil for the terminal device of
2308 the currently selected frame.
2310 This function runs `suspend-tty-functions' after suspending the
2311 device. The functions are run with one arg, the id of the suspended
2314 `suspend-tty' does nothing if it is called on a device that is already
2317 A suspended tty may be resumed by calling `resume-tty' on it. */)
2321 struct terminal
*t
= get_tty_terminal (tty
, 1);
2325 error ("Unknown tty device");
2327 f
= t
->display_info
.tty
->input
;
2331 /* First run `suspend-tty-functions' and then clean up the tty
2332 state because `suspend-tty-functions' might need to change
2334 if (!NILP (Vrun_hooks
))
2336 Lisp_Object args
[2];
2337 args
[0] = intern ("suspend-tty-functions");
2338 XSETTERMINAL (args
[1], t
);
2339 Frun_hook_with_args (2, args
);
2342 reset_sys_modes (t
->display_info
.tty
);
2344 delete_keyboard_wait_descriptor (fileno (f
));
2347 if (f
!= t
->display_info
.tty
->output
)
2348 fclose (t
->display_info
.tty
->output
);
2350 t
->display_info
.tty
->input
= 0;
2351 t
->display_info
.tty
->output
= 0;
2353 if (FRAMEP (t
->display_info
.tty
->top_frame
))
2354 FRAME_SET_VISIBLE (XFRAME (t
->display_info
.tty
->top_frame
), 0);
2358 /* Clear display hooks to prevent further output. */
2359 clear_tty_hooks (t
);
2364 DEFUN ("resume-tty", Fresume_tty
, Sresume_tty
, 0, 1, 0,
2365 doc
: /* Resume the previously suspended terminal device TTY.
2366 The terminal is opened and reinitialized. Frames that are on the
2367 suspended terminal are revived.
2369 It is an error to resume a terminal while another terminal is active
2372 This function runs `resume-tty-functions' after resuming the terminal.
2373 The functions are run with one arg, the id of the resumed terminal
2376 `resume-tty' does nothing if it is called on a device that is not
2379 TTY may be a terminal id, a frame, or nil for the terminal device of
2380 the currently selected frame. */)
2384 struct terminal
*t
= get_tty_terminal (tty
, 1);
2388 error ("Unknown tty device");
2390 if (!t
->display_info
.tty
->input
)
2392 if (get_named_tty (t
->display_info
.tty
->name
))
2393 error ("Cannot resume display while another display is active on the same device");
2395 fd
= emacs_open (t
->display_info
.tty
->name
, O_RDWR
| O_NOCTTY
, 0);
2398 error ("Can not reopen tty device %s: %s", t
->display_info
.tty
->name
, strerror (errno
));
2400 if (strcmp (t
->display_info
.tty
->name
, DEV_TTY
))
2401 dissociate_if_controlling_tty (fd
);
2403 t
->display_info
.tty
->output
= fdopen (fd
, "w+");
2404 t
->display_info
.tty
->input
= t
->display_info
.tty
->output
;
2406 add_keyboard_wait_descriptor (fd
);
2408 if (FRAMEP (t
->display_info
.tty
->top_frame
))
2409 FRAME_SET_VISIBLE (XFRAME (t
->display_info
.tty
->top_frame
), 1);
2411 init_sys_modes (t
->display_info
.tty
);
2413 /* Run `resume-tty-functions'. */
2414 if (!NILP (Vrun_hooks
))
2416 Lisp_Object args
[2];
2417 args
[0] = intern ("resume-tty-functions");
2418 XSETTERMINAL (args
[1], t
);
2419 Frun_hook_with_args (2, args
);
2429 /***********************************************************************
2431 ***********************************************************************/
2435 term_mouse_moveto (int x
, int y
)
2437 /* TODO: how to set mouse position?
2440 name = (const char *) ttyname (0);
2441 fd = open (name, O_WRONLY);
2442 SOME_FUNCTION (x, y, fd);
2445 last_mouse_y = y; */
2449 term_show_mouse_face (enum draw_glyphs_face draw
)
2451 struct window
*w
= XWINDOW (mouse_face_window
);
2455 struct frame
*f
= XFRAME (w
->frame
);
2456 struct tty_display_info
*tty
= FRAME_TTY (f
);
2458 if (/* If window is in the process of being destroyed, don't bother
2460 w
->current_matrix
!= NULL
2461 /* Recognize when we are called to operate on rows that don't exist
2462 anymore. This can happen when a window is split. */
2463 && mouse_face_end_row
< w
->current_matrix
->nrows
)
2465 /* write_glyphs writes at cursor position, so we need to
2466 temporarily move cursor coordinates to the beginning of
2467 the highlight region. */
2469 /* Save current cursor co-ordinates */
2470 save_y
= curY (tty
);
2471 save_x
= curX (tty
);
2473 /* Note that mouse_face_beg_row etc. are window relative. */
2474 for (i
= mouse_face_beg_row
; i
<= mouse_face_end_row
; i
++)
2476 int start_hpos
, end_hpos
, nglyphs
;
2477 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, i
);
2479 /* Don't do anything if row doesn't have valid contents. */
2480 if (!row
->enabled_p
)
2483 /* For all but the first row, the highlight starts at column 0. */
2484 if (i
== mouse_face_beg_row
)
2485 start_hpos
= mouse_face_beg_col
;
2489 if (i
== mouse_face_end_row
)
2490 end_hpos
= mouse_face_end_col
;
2493 end_hpos
= row
->used
[TEXT_AREA
];
2494 if (draw
== DRAW_NORMAL_TEXT
)
2495 row
->fill_line_p
= 1; /* Clear to end of line */
2498 if (end_hpos
<= start_hpos
)
2500 /* Record that some glyphs of this row are displayed in
2502 row
->mouse_face_p
= draw
> 0;
2504 nglyphs
= end_hpos
- start_hpos
;
2506 if (end_hpos
>= row
->used
[TEXT_AREA
])
2507 nglyphs
= row
->used
[TEXT_AREA
] - start_hpos
;
2509 pos_y
= row
->y
+ WINDOW_TOP_EDGE_Y (w
);
2510 pos_x
= row
->used
[LEFT_MARGIN_AREA
] + start_hpos
2511 + WINDOW_LEFT_EDGE_X (w
);
2513 cursor_to (f
, pos_y
, pos_x
);
2515 if (draw
== DRAW_MOUSE_FACE
)
2517 tty_write_glyphs_with_face (f
, row
->glyphs
[TEXT_AREA
] + start_hpos
,
2518 nglyphs
, mouse_face_face_id
);
2520 else /* draw == DRAW_NORMAL_TEXT */
2521 write_glyphs (f
, row
->glyphs
[TEXT_AREA
] + start_hpos
, nglyphs
);
2523 cursor_to (f
, save_y
, save_x
);
2528 term_clear_mouse_face ()
2530 if (!NILP (mouse_face_window
))
2531 term_show_mouse_face (DRAW_NORMAL_TEXT
);
2533 mouse_face_beg_row
= mouse_face_beg_col
= -1;
2534 mouse_face_end_row
= mouse_face_end_col
= -1;
2535 mouse_face_window
= Qnil
;
2538 /* Find the glyph matrix position of buffer position POS in window W.
2539 *HPOS and *VPOS are set to the positions found. W's current glyphs
2540 must be up to date. If POS is above window start return (0, 0).
2541 If POS is after end of W, return end of last line in W.
2542 - taken from msdos.c */
2544 fast_find_position (struct window
*w
, int pos
, int *hpos
, int *vpos
)
2546 int i
, lastcol
, line_start_position
, maybe_next_line_p
= 0;
2547 int yb
= window_text_bottom_y (w
);
2548 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, 0), *best_row
= row
;
2552 if (row
->used
[TEXT_AREA
])
2553 line_start_position
= row
->glyphs
[TEXT_AREA
]->charpos
;
2555 line_start_position
= 0;
2557 if (line_start_position
> pos
)
2559 /* If the position sought is the end of the buffer,
2560 don't include the blank lines at the bottom of the window. */
2561 else if (line_start_position
== pos
2562 && pos
== BUF_ZV (XBUFFER (w
->buffer
)))
2564 maybe_next_line_p
= 1;
2567 else if (line_start_position
> 0)
2570 /* Don't overstep the last matrix row, lest we get into the
2571 never-never land... */
2572 if (row
->y
+ 1 >= yb
)
2578 /* Find the right column within BEST_ROW. */
2581 for (i
= 0; i
< row
->used
[TEXT_AREA
]; i
++)
2583 struct glyph
*glyph
= row
->glyphs
[TEXT_AREA
] + i
;
2586 charpos
= glyph
->charpos
;
2593 else if (charpos
> pos
)
2595 else if (charpos
> 0)
2599 /* If we're looking for the end of the buffer,
2600 and we didn't find it in the line we scanned,
2601 use the start of the following line. */
2602 if (maybe_next_line_p
)
2609 *hpos
= lastcol
+ 1;
2614 term_mouse_highlight (struct frame
*f
, int x
, int y
)
2616 enum window_part part
;
2621 if (NILP (Vmouse_highlight
)
2622 || !f
->glyphs_initialized_p
)
2625 /* Which window is that in? */
2626 window
= window_from_coordinates (f
, x
, y
, &part
, &x
, &y
, 0);
2628 /* Not on a window -> return. */
2629 if (!WINDOWP (window
))
2632 if (!EQ (window
, mouse_face_window
))
2633 term_clear_mouse_face ();
2635 w
= XWINDOW (window
);
2637 /* Are we in a window whose display is up to date?
2638 And verify the buffer's text has not changed. */
2639 b
= XBUFFER (w
->buffer
);
2641 && EQ (w
->window_end_valid
, w
->buffer
)
2642 && XFASTINT (w
->last_modified
) == BUF_MODIFF (b
)
2643 && XFASTINT (w
->last_overlay_modified
) == BUF_OVERLAY_MODIFF (b
))
2645 int pos
, i
, nrows
= w
->current_matrix
->nrows
;
2646 struct glyph_row
*row
;
2647 struct glyph
*glyph
;
2649 /* Find the glyph under X/Y. */
2651 if (y
>= 0 && y
< nrows
)
2653 row
= MATRIX_ROW (w
->current_matrix
, y
);
2654 /* Give up if some row before the one we are looking for is
2656 for (i
= 0; i
<= y
; i
++)
2657 if (!MATRIX_ROW (w
->current_matrix
, i
)->enabled_p
)
2659 if (i
> y
/* all rows upto and including the one at Y are enabled */
2660 && row
->displays_text_p
2661 && x
< window_box_width (w
, TEXT_AREA
))
2663 glyph
= row
->glyphs
[TEXT_AREA
];
2664 if (x
>= row
->used
[TEXT_AREA
])
2669 if (!BUFFERP (glyph
->object
))
2675 /* Clear mouse face if X/Y not over text. */
2678 term_clear_mouse_face ();
2682 if (!BUFFERP (glyph
->object
))
2684 pos
= glyph
->charpos
;
2686 /* Check for mouse-face. */
2688 extern Lisp_Object Qmouse_face
;
2689 Lisp_Object mouse_face
, overlay
, position
, *overlay_vec
;
2690 int noverlays
, obegv
, ozv
;
2691 struct buffer
*obuf
;
2693 /* If we get an out-of-range value, return now; avoid an error. */
2694 if (pos
> BUF_Z (b
))
2697 /* Make the window's buffer temporarily current for
2698 overlays_at and compute_char_face. */
2699 obuf
= current_buffer
;
2706 /* Is this char mouse-active? */
2707 XSETINT (position
, pos
);
2709 /* Put all the overlays we want in a vector in overlay_vec. */
2710 GET_OVERLAYS_AT (pos
, overlay_vec
, noverlays
, NULL
, 0);
2711 /* Sort overlays into increasing priority order. */
2712 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
2714 /* Check mouse-face highlighting. */
2715 if (!(EQ (window
, mouse_face_window
)
2716 && y
>= mouse_face_beg_row
2717 && y
<= mouse_face_end_row
2718 && (y
> mouse_face_beg_row
2719 || x
>= mouse_face_beg_col
)
2720 && (y
< mouse_face_end_row
2721 || x
< mouse_face_end_col
2722 || mouse_face_past_end
)))
2724 /* Clear the display of the old active region, if any. */
2725 term_clear_mouse_face ();
2727 /* Find the highest priority overlay that has a mouse-face
2730 for (i
= noverlays
- 1; i
>= 0; --i
)
2732 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
2733 if (!NILP (mouse_face
))
2735 overlay
= overlay_vec
[i
];
2740 /* If no overlay applies, get a text property. */
2742 mouse_face
= Fget_text_property (position
, Qmouse_face
,
2745 /* Handle the overlay case. */
2746 if (!NILP (overlay
))
2748 /* Find the range of text around this char that
2749 should be active. */
2750 Lisp_Object before
, after
;
2754 before
= Foverlay_start (overlay
);
2755 after
= Foverlay_end (overlay
);
2756 /* Record this as the current active region. */
2757 fast_find_position (w
, XFASTINT (before
),
2758 &mouse_face_beg_col
,
2759 &mouse_face_beg_row
);
2762 = !fast_find_position (w
, XFASTINT (after
),
2763 &mouse_face_end_col
,
2764 &mouse_face_end_row
);
2765 mouse_face_window
= window
;
2768 = face_at_buffer_position (w
, pos
, 0, 0,
2769 &ignore
, pos
+ 1, 1);
2771 /* Display it as active. */
2772 term_show_mouse_face (DRAW_MOUSE_FACE
);
2774 /* Handle the text property case. */
2775 else if (!NILP (mouse_face
))
2777 /* Find the range of text around this char that
2778 should be active. */
2779 Lisp_Object before
, after
, beginning
, end
;
2782 beginning
= Fmarker_position (w
->start
);
2783 XSETINT (end
, (BUF_Z (b
) - XFASTINT (w
->window_end_pos
)));
2785 = Fprevious_single_property_change (make_number (pos
+ 1),
2787 w
->buffer
, beginning
);
2789 = Fnext_single_property_change (position
, Qmouse_face
,
2792 /* Record this as the current active region. */
2793 fast_find_position (w
, XFASTINT (before
),
2794 &mouse_face_beg_col
,
2795 &mouse_face_beg_row
);
2797 = !fast_find_position (w
, XFASTINT (after
),
2798 &mouse_face_end_col
,
2799 &mouse_face_end_row
);
2800 mouse_face_window
= window
;
2803 = face_at_buffer_position (w
, pos
, 0, 0,
2804 &ignore
, pos
+ 1, 1);
2806 /* Display it as active. */
2807 term_show_mouse_face (DRAW_MOUSE_FACE
);
2811 /* Look for a `help-echo' property. */
2814 extern Lisp_Object Qhelp_echo
;
2816 /* Check overlays first. */
2818 for (i
= noverlays
- 1; i
>= 0 && NILP (help
); --i
)
2820 overlay
= overlay_vec
[i
];
2821 help
= Foverlay_get (overlay
, Qhelp_echo
);
2826 help_echo_string
= help
;
2827 help_echo_window
= window
;
2828 help_echo_object
= overlay
;
2829 help_echo_pos
= pos
;
2831 /* Try text properties. */
2832 else if (NILP (help
)
2833 && ((STRINGP (glyph
->object
)
2834 && glyph
->charpos
>= 0
2835 && glyph
->charpos
< SCHARS (glyph
->object
))
2836 || (BUFFERP (glyph
->object
)
2837 && glyph
->charpos
>= BEGV
2838 && glyph
->charpos
< ZV
)))
2840 help
= Fget_text_property (make_number (glyph
->charpos
),
2841 Qhelp_echo
, glyph
->object
);
2844 help_echo_string
= help
;
2845 help_echo_window
= window
;
2846 help_echo_object
= glyph
->object
;
2847 help_echo_pos
= glyph
->charpos
;
2854 current_buffer
= obuf
;
2860 term_mouse_movement (FRAME_PTR frame
, Gpm_Event
*event
)
2862 /* Has the mouse moved off the glyph it was on at the last sighting? */
2863 if (event
->x
!= last_mouse_x
|| event
->y
!= last_mouse_y
)
2865 frame
->mouse_moved
= 1;
2866 term_mouse_highlight (frame
, event
->x
, event
->y
);
2867 /* Remember which glyph we're now on. */
2868 last_mouse_x
= event
->x
;
2869 last_mouse_y
= event
->y
;
2875 /* Return the current position of the mouse.
2877 Set *f to the frame the mouse is in, or zero if the mouse is in no
2878 Emacs frame. If it is set to zero, all the other arguments are
2881 Set *bar_window to Qnil, and *x and *y to the column and
2882 row of the character cell the mouse is over.
2884 Set *time to the time the mouse was at the returned position.
2886 This clears mouse_moved until the next motion
2889 term_mouse_position (FRAME_PTR
*fp
, int insist
, Lisp_Object
*bar_window
,
2890 enum scroll_bar_part
*part
, Lisp_Object
*x
,
2891 Lisp_Object
*y
, unsigned long *time
)
2895 *fp
= SELECTED_FRAME ();
2896 (*fp
)->mouse_moved
= 0;
2901 XSETINT (*x
, last_mouse_x
);
2902 XSETINT (*y
, last_mouse_y
);
2903 gettimeofday(&now
, 0);
2904 *time
= (now
.tv_sec
* 1000) + (now
.tv_usec
/ 1000);
2907 /* Prepare a mouse-event in *RESULT for placement in the input queue.
2909 If the event is a button press, then note that we have grabbed
2913 term_mouse_click (struct input_event
*result
, Gpm_Event
*event
,
2919 result
->kind
= GPM_CLICK_EVENT
;
2920 for (i
= 0, j
= GPM_B_LEFT
; i
< 3; i
++, j
>>= 1 )
2922 if (event
->buttons
& j
) {
2923 result
->code
= i
; /* button number */
2927 gettimeofday(&now
, 0);
2928 result
->timestamp
= (now
.tv_sec
* 1000) + (now
.tv_usec
/ 1000);
2930 if (event
->type
& GPM_UP
)
2931 result
->modifiers
= up_modifier
;
2932 else if (event
->type
& GPM_DOWN
)
2933 result
->modifiers
= down_modifier
;
2935 result
->modifiers
= 0;
2937 if (event
->type
& GPM_SINGLE
)
2938 result
->modifiers
|= click_modifier
;
2940 if (event
->type
& GPM_DOUBLE
)
2941 result
->modifiers
|= double_modifier
;
2943 if (event
->type
& GPM_TRIPLE
)
2944 result
->modifiers
|= triple_modifier
;
2946 if (event
->type
& GPM_DRAG
)
2947 result
->modifiers
|= drag_modifier
;
2949 if (!(event
->type
& (GPM_MOVE
| GPM_DRAG
))) {
2952 if (event
->modifiers
& (1 << 0))
2953 result
->modifiers
|= shift_modifier
;
2956 if (event
->modifiers
& (1 << 2))
2957 result
->modifiers
|= ctrl_modifier
;
2959 /* 1 << KG_ALT || KG_ALTGR */
2960 if (event
->modifiers
& (1 << 3)
2961 || event
->modifiers
& (1 << 1))
2962 result
->modifiers
|= meta_modifier
;
2965 XSETINT (result
->x
, event
->x
);
2966 XSETINT (result
->y
, event
->y
);
2967 XSETFRAME (result
->frame_or_window
, f
);
2973 handle_one_term_event (struct tty_display_info
*tty
, Gpm_Event
*event
, struct input_event
* hold_quit
)
2975 struct frame
*f
= XFRAME (tty
->top_frame
);
2976 struct input_event ie
;
2984 if (event
->type
& (GPM_MOVE
| GPM_DRAG
)) {
2985 previous_help_echo_string
= help_echo_string
;
2986 help_echo_string
= Qnil
;
2988 Gpm_DrawPointer (event
->x
, event
->y
, fileno (tty
->output
));
2990 if (!term_mouse_movement (f
, event
))
2991 help_echo_string
= previous_help_echo_string
;
2993 /* If the contents of the global variable help_echo_string
2994 has changed, generate a HELP_EVENT. */
2995 if (!NILP (help_echo_string
)
2996 || !NILP (previous_help_echo_string
))
3003 term_mouse_click (&ie
, event
, f
);
3007 if (ie
.kind
!= NO_EVENT
)
3009 kbd_buffer_store_event_hold (&ie
, hold_quit
);
3014 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
3019 XSETFRAME (frame
, f
);
3023 gen_help_event (help_echo_string
, frame
, help_echo_window
,
3024 help_echo_object
, help_echo_pos
);
3031 DEFUN ("gpm-mouse-start", Fgpm_mouse_start
, Sgpm_mouse_start
,
3033 doc
: /* Open a connection to Gpm.
3034 Gpm-mouse can only be activated for one tty at a time. */)
3037 struct frame
*f
= SELECTED_FRAME ();
3038 struct tty_display_info
*tty
3039 = ((f
)->output_method
== output_termcap
3040 ? (f
)->terminal
->display_info
.tty
: NULL
);
3041 Gpm_Connect connection
;
3044 error ("Gpm-mouse only works in the GNU/Linux console");
3046 return Qnil
; /* Already activated, nothing to do. */
3048 error ("Gpm-mouse can only be activated for one tty at a time");
3050 connection
.eventMask
= ~0;
3051 connection
.defaultMask
= ~GPM_HARD
;
3052 connection
.maxMod
= ~0;
3053 connection
.minMod
= 0;
3056 if (Gpm_Open (&connection
, 0) < 0)
3057 error ("Gpm-mouse failed to connect to the gpm daemon");
3061 /* `init_sys_modes' arranges for mouse movements sent through gpm_fd
3062 to generate SIGIOs. Apparently we need to call reset_sys_modes
3063 before calling init_sys_modes. */
3064 reset_sys_modes (tty
);
3065 init_sys_modes (tty
);
3066 add_gpm_wait_descriptor (gpm_fd
);
3071 DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop
, Sgpm_mouse_stop
,
3073 doc
: /* Close a connection to Gpm. */)
3076 struct frame
*f
= SELECTED_FRAME ();
3077 struct tty_display_info
*tty
3078 = ((f
)->output_method
== output_termcap
3079 ? (f
)->terminal
->display_info
.tty
: NULL
);
3081 if (!tty
|| gpm_tty
!= tty
)
3082 return Qnil
; /* Not activated on this terminal, nothing to do. */
3085 delete_gpm_wait_descriptor (gpm_fd
);
3086 while (Gpm_Close()); /* close all the stack */
3090 #endif /* HAVE_GPM */
3093 /***********************************************************************
3095 ***********************************************************************/
3097 /* Initialize the tty-dependent part of frame F. The frame must
3098 already have its device initialized. */
3101 create_tty_output (struct frame
*f
)
3103 struct tty_output
*t
;
3105 if (! FRAME_TERMCAP_P (f
))
3108 t
= xmalloc (sizeof (struct tty_output
));
3109 bzero (t
, sizeof (struct tty_output
));
3111 t
->display_info
= FRAME_TERMINAL (f
)->display_info
.tty
;
3113 f
->output_data
.tty
= t
;
3116 /* Delete the tty-dependent part of frame F. */
3119 delete_tty_output (struct frame
*f
)
3121 if (! FRAME_TERMCAP_P (f
))
3124 xfree (f
->output_data
.tty
);
3128 /* Reset the hooks in TERMINAL. */
3131 clear_tty_hooks (struct terminal
*terminal
)
3134 terminal
->cursor_to_hook
= 0;
3135 terminal
->raw_cursor_to_hook
= 0;
3136 terminal
->clear_to_end_hook
= 0;
3137 terminal
->clear_frame_hook
= 0;
3138 terminal
->clear_end_of_line_hook
= 0;
3139 terminal
->ins_del_lines_hook
= 0;
3140 terminal
->insert_glyphs_hook
= 0;
3141 terminal
->write_glyphs_hook
= 0;
3142 terminal
->delete_glyphs_hook
= 0;
3143 terminal
->ring_bell_hook
= 0;
3144 terminal
->reset_terminal_modes_hook
= 0;
3145 terminal
->set_terminal_modes_hook
= 0;
3146 terminal
->update_begin_hook
= 0;
3147 terminal
->update_end_hook
= 0;
3148 terminal
->set_terminal_window_hook
= 0;
3149 terminal
->mouse_position_hook
= 0;
3150 terminal
->frame_rehighlight_hook
= 0;
3151 terminal
->frame_raise_lower_hook
= 0;
3152 terminal
->fullscreen_hook
= 0;
3153 terminal
->set_vertical_scroll_bar_hook
= 0;
3154 terminal
->condemn_scroll_bars_hook
= 0;
3155 terminal
->redeem_scroll_bar_hook
= 0;
3156 terminal
->judge_scroll_bars_hook
= 0;
3157 terminal
->read_socket_hook
= 0;
3158 terminal
->frame_up_to_date_hook
= 0;
3160 /* Leave these two set, or suspended frames are not deleted
3162 terminal
->delete_frame_hook
= &delete_tty_output
;
3163 terminal
->delete_terminal_hook
= &delete_tty
;
3166 /* Initialize hooks in TERMINAL with the values needed for a tty. */
3169 set_tty_hooks (struct terminal
*terminal
)
3171 terminal
->rif
= 0; /* ttys don't support window-based redisplay. */
3173 terminal
->cursor_to_hook
= &tty_cursor_to
;
3174 terminal
->raw_cursor_to_hook
= &tty_raw_cursor_to
;
3176 terminal
->clear_to_end_hook
= &tty_clear_to_end
;
3177 terminal
->clear_frame_hook
= &tty_clear_frame
;
3178 terminal
->clear_end_of_line_hook
= &tty_clear_end_of_line
;
3180 terminal
->ins_del_lines_hook
= &tty_ins_del_lines
;
3182 terminal
->insert_glyphs_hook
= &tty_insert_glyphs
;
3183 terminal
->write_glyphs_hook
= &tty_write_glyphs
;
3184 terminal
->delete_glyphs_hook
= &tty_delete_glyphs
;
3186 terminal
->ring_bell_hook
= &tty_ring_bell
;
3188 terminal
->reset_terminal_modes_hook
= &tty_reset_terminal_modes
;
3189 terminal
->set_terminal_modes_hook
= &tty_set_terminal_modes
;
3190 terminal
->update_begin_hook
= 0; /* Not needed. */
3191 terminal
->update_end_hook
= &tty_update_end
;
3192 terminal
->set_terminal_window_hook
= &tty_set_terminal_window
;
3194 terminal
->mouse_position_hook
= 0; /* Not needed. */
3195 terminal
->frame_rehighlight_hook
= 0; /* Not needed. */
3196 terminal
->frame_raise_lower_hook
= 0; /* Not needed. */
3198 terminal
->set_vertical_scroll_bar_hook
= 0; /* Not needed. */
3199 terminal
->condemn_scroll_bars_hook
= 0; /* Not needed. */
3200 terminal
->redeem_scroll_bar_hook
= 0; /* Not needed. */
3201 terminal
->judge_scroll_bars_hook
= 0; /* Not needed. */
3203 terminal
->read_socket_hook
= &tty_read_avail_input
; /* keyboard.c */
3204 terminal
->frame_up_to_date_hook
= 0; /* Not needed. */
3206 terminal
->delete_frame_hook
= &delete_tty_output
;
3207 terminal
->delete_terminal_hook
= &delete_tty
;
3210 /* Drop the controlling terminal if fd is the same device. */
3212 dissociate_if_controlling_tty (int fd
)
3216 EMACS_GET_TTY_PGRP (fd
, &pgid
); /* If tcgetpgrp succeeds, fd is the ctty. */
3219 #if defined (USG) && !defined (BSD_PGRPS)
3221 no_controlling_tty
= 1;
3222 #elif defined (CYGWIN)
3224 no_controlling_tty
= 1;
3226 #ifdef TIOCNOTTY /* Try BSD ioctls. */
3227 sigblock (sigmask (SIGTTOU
));
3228 fd
= emacs_open (DEV_TTY
, O_RDWR
, 0);
3229 if (fd
!= -1 && ioctl (fd
, TIOCNOTTY
, 0) != -1)
3231 no_controlling_tty
= 1;
3235 sigunblock (sigmask (SIGTTOU
));
3237 /* Unknown system. */
3239 #endif /* ! TIOCNOTTY */
3242 #endif /* !WINDOWSNT */
3245 static void maybe_fatal();
3247 /* Create a termcap display on the tty device with the given name and
3250 If NAME is NULL, then use the controlling tty, i.e., "/dev/tty".
3251 Otherwise NAME should be a path to the tty device file,
3254 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
3256 If MUST_SUCCEED is true, then all errors are fatal. */
3259 init_tty (char *name
, char *terminal_type
, int must_succeed
)
3262 char **address
= &area
;
3263 char *buffer
= NULL
;
3264 int buffer_size
= 4096;
3265 register char *p
= NULL
;
3267 struct tty_display_info
*tty
= NULL
;
3268 struct terminal
*terminal
= NULL
;
3269 int ctty
= 0; /* 1 if asked to open controlling tty. */
3272 maybe_fatal (must_succeed
, 0, 0,
3273 "Unknown terminal type",
3274 "Unknown terminal type");
3278 if (!strcmp (name
, DEV_TTY
))
3281 /* If we already have a terminal on the given device, use that. If
3282 all such terminals are suspended, create a new one instead. */
3283 /* XXX Perhaps this should be made explicit by having init_tty
3284 always create a new terminal and separating terminal and frame
3285 creation on Lisp level. */
3286 terminal
= get_named_tty (name
);
3290 terminal
= create_terminal ();
3291 tty
= (struct tty_display_info
*) xmalloc (sizeof (struct tty_display_info
));
3292 bzero (tty
, sizeof (struct tty_display_info
));
3293 tty
->next
= tty_list
;
3296 terminal
->type
= output_termcap
;
3297 terminal
->display_info
.tty
= tty
;
3298 tty
->terminal
= terminal
;
3300 tty
->Wcm
= (struct cm
*) xmalloc (sizeof (struct cm
));
3304 set_tty_hooks (terminal
);
3310 #ifdef O_IGNORE_CTTY
3312 /* Open the terminal device. Don't recognize it as our
3313 controlling terminal, and don't make it the controlling tty
3314 if we don't have one at the moment. */
3315 fd
= emacs_open (name
, O_RDWR
| O_IGNORE_CTTY
| O_NOCTTY
, 0);
3318 /* Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
3319 defined on Hurd. On other systems, we need to explicitly
3320 dissociate ourselves from the controlling tty when we want to
3321 open a frame on the same terminal. */
3322 fd
= emacs_open (name
, O_RDWR
| O_NOCTTY
, 0);
3323 #endif /* O_IGNORE_CTTY */
3326 maybe_fatal (must_succeed
, buffer
, terminal
,
3327 "Could not open file: %s",
3328 "Could not open file: %s",
3333 maybe_fatal (must_succeed
, buffer
, terminal
,
3334 "Not a tty device: %s",
3335 "Not a tty device: %s",
3339 #ifndef O_IGNORE_CTTY
3341 dissociate_if_controlling_tty (fd
);
3344 file
= fdopen (fd
, "w+");
3345 tty
->name
= xstrdup (name
);
3346 terminal
->name
= xstrdup (name
);
3351 tty
->type
= xstrdup (terminal_type
);
3353 add_keyboard_wait_descriptor (fileno (tty
->input
));
3357 encode_terminal_src_size
= 0;
3358 encode_terminal_dst_size
= 0;
3361 terminal
->mouse_position_hook
= term_mouse_position
;
3362 mouse_face_window
= Qnil
;
3366 initialize_w32_display (terminal
);
3367 /* The following two are inaccessible from w32console.c. */
3368 terminal
->delete_frame_hook
= &delete_tty_output
;
3369 terminal
->delete_terminal_hook
= &delete_tty
;
3371 tty
->name
= xstrdup (name
);
3372 terminal
->name
= xstrdup (name
);
3373 tty
->type
= xstrdup (terminal_type
);
3375 tty
->output
= stdout
;
3377 add_keyboard_wait_descriptor (0);
3382 struct frame
*f
= XFRAME (selected_frame
);
3384 FrameRows (tty
) = FRAME_LINES (f
);
3385 FrameCols (tty
) = FRAME_COLS (f
);
3386 tty
->specified_window
= FRAME_LINES (f
);
3388 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 0;
3389 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_none
;
3391 tty
->delete_in_insert_mode
= 1;
3394 terminal
->scroll_region_ok
= 0;
3396 /* Seems to insert lines when it's not supposed to, messing up the
3397 display. In doing a trace, it didn't seem to be called much, so I
3398 don't think we're losing anything by turning it off. */
3399 terminal
->line_ins_del_ok
= 0;
3400 terminal
->char_ins_del_ok
= 1;
3404 tty
->TN_max_colors
= 16; /* Required to be non-zero for tty-display-color-p */
3406 #else /* not WINDOWSNT */
3410 buffer
= (char *) xmalloc (buffer_size
);
3412 /* On some systems, tgetent tries to access the controlling
3414 sigblock (sigmask (SIGTTOU
));
3415 status
= tgetent (buffer
, terminal_type
);
3416 sigunblock (sigmask (SIGTTOU
));
3421 maybe_fatal (must_succeed
, buffer
, terminal
,
3422 "Cannot open terminfo database file",
3423 "Cannot open terminfo database file");
3425 maybe_fatal (must_succeed
, buffer
, terminal
,
3426 "Cannot open termcap database file",
3427 "Cannot open termcap database file");
3433 maybe_fatal (must_succeed
, buffer
, terminal
,
3434 "Terminal type %s is not defined",
3435 "Terminal type %s is not defined.\n\
3436 If that is not the actual type of terminal you have,\n\
3437 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3438 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3439 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3442 maybe_fatal (must_succeed
, buffer
, terminal
,
3443 "Terminal type %s is not defined",
3444 "Terminal type %s is not defined.\n\
3445 If that is not the actual type of terminal you have,\n\
3446 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3447 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3448 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3454 if (strlen (buffer
) >= buffer_size
)
3456 buffer_size
= strlen (buffer
);
3458 area
= (char *) xmalloc (buffer_size
);
3460 tty
->TS_ins_line
= tgetstr ("al", address
);
3461 tty
->TS_ins_multi_lines
= tgetstr ("AL", address
);
3462 tty
->TS_bell
= tgetstr ("bl", address
);
3463 BackTab (tty
) = tgetstr ("bt", address
);
3464 tty
->TS_clr_to_bottom
= tgetstr ("cd", address
);
3465 tty
->TS_clr_line
= tgetstr ("ce", address
);
3466 tty
->TS_clr_frame
= tgetstr ("cl", address
);
3467 ColPosition (tty
) = NULL
; /* tgetstr ("ch", address); */
3468 AbsPosition (tty
) = tgetstr ("cm", address
);
3469 CR (tty
) = tgetstr ("cr", address
);
3470 tty
->TS_set_scroll_region
= tgetstr ("cs", address
);
3471 tty
->TS_set_scroll_region_1
= tgetstr ("cS", address
);
3472 RowPosition (tty
) = tgetstr ("cv", address
);
3473 tty
->TS_del_char
= tgetstr ("dc", address
);
3474 tty
->TS_del_multi_chars
= tgetstr ("DC", address
);
3475 tty
->TS_del_line
= tgetstr ("dl", address
);
3476 tty
->TS_del_multi_lines
= tgetstr ("DL", address
);
3477 tty
->TS_delete_mode
= tgetstr ("dm", address
);
3478 tty
->TS_end_delete_mode
= tgetstr ("ed", address
);
3479 tty
->TS_end_insert_mode
= tgetstr ("ei", address
);
3480 Home (tty
) = tgetstr ("ho", address
);
3481 tty
->TS_ins_char
= tgetstr ("ic", address
);
3482 tty
->TS_ins_multi_chars
= tgetstr ("IC", address
);
3483 tty
->TS_insert_mode
= tgetstr ("im", address
);
3484 tty
->TS_pad_inserted_char
= tgetstr ("ip", address
);
3485 tty
->TS_end_keypad_mode
= tgetstr ("ke", address
);
3486 tty
->TS_keypad_mode
= tgetstr ("ks", address
);
3487 LastLine (tty
) = tgetstr ("ll", address
);
3488 Right (tty
) = tgetstr ("nd", address
);
3489 Down (tty
) = tgetstr ("do", address
);
3491 Down (tty
) = tgetstr ("nl", address
); /* Obsolete name for "do" */
3493 /* VMS puts a carriage return before each linefeed,
3494 so it is not safe to use linefeeds. */
3495 if (Down (tty
) && Down (tty
)[0] == '\n' && Down (tty
)[1] == '\0')
3498 if (tgetflag ("bs"))
3499 Left (tty
) = "\b"; /* can't possibly be longer! */
3500 else /* (Actually, "bs" is obsolete...) */
3501 Left (tty
) = tgetstr ("le", address
);
3503 Left (tty
) = tgetstr ("bc", address
); /* Obsolete name for "le" */
3504 tty
->TS_pad_char
= tgetstr ("pc", address
);
3505 tty
->TS_repeat
= tgetstr ("rp", address
);
3506 tty
->TS_end_standout_mode
= tgetstr ("se", address
);
3507 tty
->TS_fwd_scroll
= tgetstr ("sf", address
);
3508 tty
->TS_standout_mode
= tgetstr ("so", address
);
3509 tty
->TS_rev_scroll
= tgetstr ("sr", address
);
3510 tty
->Wcm
->cm_tab
= tgetstr ("ta", address
);
3511 tty
->TS_end_termcap_modes
= tgetstr ("te", address
);
3512 tty
->TS_termcap_modes
= tgetstr ("ti", address
);
3513 Up (tty
) = tgetstr ("up", address
);
3514 tty
->TS_visible_bell
= tgetstr ("vb", address
);
3515 tty
->TS_cursor_normal
= tgetstr ("ve", address
);
3516 tty
->TS_cursor_visible
= tgetstr ("vs", address
);
3517 tty
->TS_cursor_invisible
= tgetstr ("vi", address
);
3518 tty
->TS_set_window
= tgetstr ("wi", address
);
3520 tty
->TS_enter_underline_mode
= tgetstr ("us", address
);
3521 tty
->TS_exit_underline_mode
= tgetstr ("ue", address
);
3522 tty
->TS_enter_bold_mode
= tgetstr ("md", address
);
3523 tty
->TS_enter_dim_mode
= tgetstr ("mh", address
);
3524 tty
->TS_enter_blink_mode
= tgetstr ("mb", address
);
3525 tty
->TS_enter_reverse_mode
= tgetstr ("mr", address
);
3526 tty
->TS_enter_alt_charset_mode
= tgetstr ("as", address
);
3527 tty
->TS_exit_alt_charset_mode
= tgetstr ("ae", address
);
3528 tty
->TS_exit_attribute_mode
= tgetstr ("me", address
);
3530 MultiUp (tty
) = tgetstr ("UP", address
);
3531 MultiDown (tty
) = tgetstr ("DO", address
);
3532 MultiLeft (tty
) = tgetstr ("LE", address
);
3533 MultiRight (tty
) = tgetstr ("RI", address
);
3535 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
3536 color because we can't switch back to the default foreground and
3538 tty
->TS_orig_pair
= tgetstr ("op", address
);
3539 if (tty
->TS_orig_pair
)
3541 tty
->TS_set_foreground
= tgetstr ("AF", address
);
3542 tty
->TS_set_background
= tgetstr ("AB", address
);
3543 if (!tty
->TS_set_foreground
)
3546 tty
->TS_set_foreground
= tgetstr ("Sf", address
);
3547 tty
->TS_set_background
= tgetstr ("Sb", address
);
3550 tty
->TN_max_colors
= tgetnum ("Co");
3551 tty
->TN_max_pairs
= tgetnum ("pa");
3553 tty
->TN_no_color_video
= tgetnum ("NC");
3554 if (tty
->TN_no_color_video
== -1)
3555 tty
->TN_no_color_video
= 0;
3558 tty_default_color_capabilities (tty
, 1);
3560 MagicWrap (tty
) = tgetflag ("xn");
3561 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
3562 the former flag imply the latter. */
3563 AutoWrap (tty
) = MagicWrap (tty
) || tgetflag ("am");
3564 terminal
->memory_below_frame
= tgetflag ("db");
3565 tty
->TF_hazeltine
= tgetflag ("hz");
3566 terminal
->must_write_spaces
= tgetflag ("in");
3567 tty
->meta_key
= tgetflag ("km") || tgetflag ("MT");
3568 tty
->TF_insmode_motion
= tgetflag ("mi");
3569 tty
->TF_standout_motion
= tgetflag ("ms");
3570 tty
->TF_underscore
= tgetflag ("ul");
3571 tty
->TF_teleray
= tgetflag ("xt");
3573 #endif /* !WINDOWSNT */
3575 terminal
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
3576 init_kboard (terminal
->kboard
);
3577 terminal
->kboard
->Vwindow_system
= Qnil
;
3578 terminal
->kboard
->next_kboard
= all_kboards
;
3579 all_kboards
= terminal
->kboard
;
3580 terminal
->kboard
->reference_count
++;
3581 /* Don't let the initial kboard remain current longer than necessary.
3582 That would cause problems if a file loaded on startup tries to
3583 prompt in the mini-buffer. */
3584 if (current_kboard
== initial_kboard
)
3585 current_kboard
= terminal
->kboard
;
3587 term_get_fkeys (address
, terminal
->kboard
);
3592 /* Get frame size from system, or else from termcap. */
3595 get_tty_size (fileno (tty
->input
), &width
, &height
);
3596 FrameCols (tty
) = width
;
3597 FrameRows (tty
) = height
;
3600 if (FrameCols (tty
) <= 0)
3601 FrameCols (tty
) = tgetnum ("co");
3602 if (FrameRows (tty
) <= 0)
3603 FrameRows (tty
) = tgetnum ("li");
3605 if (FrameRows (tty
) < 3 || FrameCols (tty
) < 3)
3606 maybe_fatal (must_succeed
, NULL
, terminal
,
3607 "Screen size %dx%d is too small"
3608 "Screen size %dx%d is too small",
3609 FrameCols (tty
), FrameRows (tty
));
3611 #if 0 /* This is not used anywhere. */
3612 tty
->terminal
->min_padding_speed
= tgetnum ("pb");
3615 TabWidth (tty
) = tgetnum ("tw");
3618 /* These capabilities commonly use ^J.
3619 I don't know why, but sending them on VMS does not work;
3620 it causes following spaces to be lost, sometimes.
3621 For now, the simplest fix is to avoid using these capabilities ever. */
3622 if (Down (tty
) && Down (tty
)[0] == '\n')
3627 tty
->TS_bell
= "\07";
3629 if (!tty
->TS_fwd_scroll
)
3630 tty
->TS_fwd_scroll
= Down (tty
);
3632 PC
= tty
->TS_pad_char
? *tty
->TS_pad_char
: 0;
3634 if (TabWidth (tty
) < 0)
3637 /* Turned off since /etc/termcap seems to have :ta= for most terminals
3638 and newer termcap doc does not seem to say there is a default.
3639 if (!tty->Wcm->cm_tab)
3640 tty->Wcm->cm_tab = "\t";
3643 /* We don't support standout modes that use `magic cookies', so
3644 turn off any that do. */
3645 if (tty
->TS_standout_mode
&& tgetnum ("sg") >= 0)
3647 tty
->TS_standout_mode
= 0;
3648 tty
->TS_end_standout_mode
= 0;
3650 if (tty
->TS_enter_underline_mode
&& tgetnum ("ug") >= 0)
3652 tty
->TS_enter_underline_mode
= 0;
3653 tty
->TS_exit_underline_mode
= 0;
3656 /* If there's no standout mode, try to use underlining instead. */
3657 if (tty
->TS_standout_mode
== 0)
3659 tty
->TS_standout_mode
= tty
->TS_enter_underline_mode
;
3660 tty
->TS_end_standout_mode
= tty
->TS_exit_underline_mode
;
3663 /* If no `se' string, try using a `me' string instead.
3664 If that fails, we can't use standout mode at all. */
3665 if (tty
->TS_end_standout_mode
== 0)
3667 char *s
= tgetstr ("me", address
);
3669 tty
->TS_end_standout_mode
= s
;
3671 tty
->TS_standout_mode
= 0;
3674 if (tty
->TF_teleray
)
3676 tty
->Wcm
->cm_tab
= 0;
3677 /* We can't support standout mode, because it uses magic cookies. */
3678 tty
->TS_standout_mode
= 0;
3679 /* But that means we cannot rely on ^M to go to column zero! */
3681 /* LF can't be trusted either -- can alter hpos */
3682 /* if move at column 0 thru a line with TS_standout_mode */
3686 /* Special handling for certain terminal types known to need it */
3688 if (!strcmp (terminal_type
, "supdup"))
3690 terminal
->memory_below_frame
= 1;
3691 tty
->Wcm
->cm_losewrap
= 1;
3693 if (!strncmp (terminal_type
, "c10", 3)
3694 || !strcmp (terminal_type
, "perq"))
3696 /* Supply a makeshift :wi string.
3697 This string is not valid in general since it works only
3698 for windows starting at the upper left corner;
3699 but that is all Emacs uses.
3701 This string works only if the frame is using
3702 the top of the video memory, because addressing is memory-relative.
3703 So first check the :ti string to see if that is true.
3705 It would be simpler if the :wi string could go in the termcap
3706 entry, but it can't because it is not fully valid.
3707 If it were in the termcap entry, it would confuse other programs. */
3708 if (!tty
->TS_set_window
)
3710 p
= tty
->TS_termcap_modes
;
3711 while (*p
&& strcmp (p
, "\033v "))
3714 tty
->TS_set_window
= "\033v%C %C %C %C ";
3716 /* Termcap entry often fails to have :in: flag */
3717 terminal
->must_write_spaces
= 1;
3718 /* :ti string typically fails to have \E^G! in it */
3719 /* This limits scope of insert-char to one line. */
3720 strcpy (area
, tty
->TS_termcap_modes
);
3721 strcat (area
, "\033\007!");
3722 tty
->TS_termcap_modes
= area
;
3723 area
+= strlen (area
) + 1;
3724 p
= AbsPosition (tty
);
3725 /* Change all %+ parameters to %C, to handle
3726 values above 96 correctly for the C100. */
3729 if (p
[0] == '%' && p
[1] == '+')
3735 tty
->specified_window
= FrameRows (tty
);
3737 if (Wcm_init (tty
) == -1) /* can't do cursor motion */
3739 maybe_fatal (must_succeed
, NULL
, terminal
,
3740 "Terminal type \"%s\" is not powerful enough to run Emacs",
3742 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3743 It lacks the ability to position the cursor.\n\
3744 If that is not the actual type of terminal you have, use either the\n\
3745 DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
3746 or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
3749 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3750 It lacks the ability to position the cursor.\n\
3751 If that is not the actual type of terminal you have,\n\
3752 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3753 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3754 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3755 # else /* TERMCAP */
3756 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3757 It lacks the ability to position the cursor.\n\
3758 If that is not the actual type of terminal you have,\n\
3759 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3760 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3761 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3762 # endif /* TERMINFO */
3767 if (FrameRows (tty
) <= 0 || FrameCols (tty
) <= 0)
3768 maybe_fatal (must_succeed
, NULL
, terminal
,
3769 "Could not determine the frame size",
3770 "Could not determine the frame size");
3772 tty
->delete_in_insert_mode
3773 = tty
->TS_delete_mode
&& tty
->TS_insert_mode
3774 && !strcmp (tty
->TS_delete_mode
, tty
->TS_insert_mode
);
3776 tty
->se_is_so
= (tty
->TS_standout_mode
3777 && tty
->TS_end_standout_mode
3778 && !strcmp (tty
->TS_standout_mode
, tty
->TS_end_standout_mode
));
3780 UseTabs (tty
) = tabs_safe_p (fileno (tty
->input
)) && TabWidth (tty
) == 8;
3782 terminal
->scroll_region_ok
3784 && (tty
->TS_set_window
|| tty
->TS_set_scroll_region
|| tty
->TS_set_scroll_region_1
));
3786 terminal
->line_ins_del_ok
3787 = (((tty
->TS_ins_line
|| tty
->TS_ins_multi_lines
)
3788 && (tty
->TS_del_line
|| tty
->TS_del_multi_lines
))
3789 || (terminal
->scroll_region_ok
3790 && tty
->TS_fwd_scroll
&& tty
->TS_rev_scroll
));
3792 terminal
->char_ins_del_ok
3793 = ((tty
->TS_ins_char
|| tty
->TS_insert_mode
3794 || tty
->TS_pad_inserted_char
|| tty
->TS_ins_multi_chars
)
3795 && (tty
->TS_del_char
|| tty
->TS_del_multi_chars
));
3797 terminal
->fast_clear_end_of_line
= tty
->TS_clr_line
!= 0;
3799 init_baud_rate (fileno (tty
->input
));
3801 /* Don't do this. I think termcap may still need the buffer. */
3802 /* xfree (buffer); */
3804 #endif /* not WINDOWSNT */
3806 /* Init system terminal modes (RAW or CBREAK, etc.). */
3807 init_sys_modes (tty
);
3812 /* Auxiliary error-handling function for init_tty.
3813 Free BUFFER and delete TERMINAL, then call error or fatal
3814 with str1 or str2, respectively, according to MUST_SUCCEED. */
3817 maybe_fatal (must_succeed
, buffer
, terminal
, str1
, str2
, arg1
, arg2
)
3820 struct terminal
*terminal
;
3821 char *str1
, *str2
, *arg1
, *arg2
;
3826 delete_tty (terminal
);
3829 fatal (str2
, arg1
, arg2
);
3831 error (str1
, arg1
, arg2
);
3837 fatal (const char *str
, ...)
3841 fprintf (stderr
, "emacs: ");
3842 vfprintf (stderr
, str
, ap
);
3850 /* Delete the given tty terminal, closing all frames on it. */
3853 delete_tty (struct terminal
*terminal
)
3855 struct tty_display_info
*tty
;
3856 Lisp_Object tail
, frame
;
3859 /* Protect against recursive calls. Fdelete_frame in
3860 delete_terminal calls us back when it deletes our last frame. */
3861 if (!terminal
->name
)
3864 if (terminal
->type
!= output_termcap
)
3867 tty
= terminal
->display_info
.tty
;
3870 FOR_EACH_FRAME (tail
, frame
)
3872 struct frame
*f
= XFRAME (frame
);
3873 if (FRAME_LIVE_P (f
) && (!FRAME_TERMCAP_P (f
) || FRAME_TTY (f
) != tty
))
3880 error ("Attempt to delete the sole terminal device with live frames");
3882 if (tty
== tty_list
)
3883 tty_list
= tty
->next
;
3886 struct tty_display_info
*p
;
3887 for (p
= tty_list
; p
&& p
->next
!= tty
; p
= p
->next
)
3891 /* This should not happen. */
3894 p
->next
= tty
->next
;
3898 /* reset_sys_modes needs a valid device, so this call needs to be
3899 before delete_terminal. */
3900 reset_sys_modes (tty
);
3902 delete_terminal (terminal
);
3909 delete_keyboard_wait_descriptor (fileno (tty
->input
));
3910 if (tty
->input
!= stdin
)
3911 fclose (tty
->input
);
3913 if (tty
->output
&& tty
->output
!= stdout
&& tty
->output
!= tty
->input
)
3914 fclose (tty
->output
);
3915 if (tty
->termscript
)
3916 fclose (tty
->termscript
);
3918 xfree (tty
->old_tty
);
3921 bzero (tty
, sizeof (struct tty_display_info
));
3927 /* Mark the pointers in the tty_display_info objects.
3928 Called by the Fgarbage_collector. */
3933 struct tty_display_info
*tty
;
3935 for (tty
= tty_list
; tty
; tty
= tty
->next
)
3936 mark_object (tty
->top_frame
);
3944 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo
,
3945 doc
: /* Non-nil means the system uses terminfo rather than termcap.
3946 This variable can be used by terminal emulator packages. */);
3948 system_uses_terminfo
= 1;
3950 system_uses_terminfo
= 0;
3953 DEFVAR_LISP ("suspend-tty-functions", &Vsuspend_tty_functions
,
3954 doc
: /* Functions to be run after suspending a tty.
3955 The functions are run with one argument, the terminal id to be suspended.
3956 See `suspend-tty'. */);
3957 Vsuspend_tty_functions
= Qnil
;
3960 DEFVAR_LISP ("resume-tty-functions", &Vresume_tty_functions
,
3961 doc
: /* Functions to be run after resuming a tty.
3962 The functions are run with one argument, the terminal id that was revived.
3963 See `resume-tty'. */);
3964 Vresume_tty_functions
= Qnil
;
3966 DEFVAR_BOOL ("visible-cursor", &visible_cursor
,
3967 doc
: /* Non-nil means to make the cursor very visible.
3968 This only has an effect when running in a text terminal.
3969 What means \"very visible\" is up to your terminal. It may make the cursor
3970 bigger, or it may make it blink, or it may do nothing at all. */);
3973 defsubr (&Stty_display_color_p
);
3974 defsubr (&Stty_display_color_cells
);
3975 defsubr (&Stty_no_underline
);
3976 defsubr (&Stty_type
);
3977 defsubr (&Scontrolling_tty_p
);
3978 defsubr (&Ssuspend_tty
);
3979 defsubr (&Sresume_tty
);
3981 defsubr (&Sgpm_mouse_start
);
3982 defsubr (&Sgpm_mouse_stop
);
3984 staticpro (&mouse_face_window
);
3985 #endif /* HAVE_GPM */
3988 default_orig_pair
= NULL
;
3989 default_set_foreground
= NULL
;
3990 default_set_background
= NULL
;
3991 #endif /* WINDOWSNT */
3996 /* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193
3997 (do not change this comment) */