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, 2009
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"
62 static int been_here
= -1;
65 /* For now, don't try to include termcap.h. On some systems,
66 configure finds a non-standard termcap.h that the main build
69 #if defined HAVE_TERMCAP_H && 0
72 extern void tputs
P_ ((const char *, int, int (*)(int)));
73 extern int tgetent
P_ ((char *, const char *));
74 extern int tgetflag
P_ ((char *id
));
75 extern int tgetnum
P_ ((char *id
));
91 /* The name of the default console device. */
93 #define DEV_TTY "CONOUT$"
95 #define DEV_TTY "/dev/tty"
98 static void tty_set_scroll_region
P_ ((struct frame
*f
, int start
, int stop
));
99 static void turn_on_face
P_ ((struct frame
*, int face_id
));
100 static void turn_off_face
P_ ((struct frame
*, int face_id
));
101 static void tty_show_cursor
P_ ((struct tty_display_info
*));
102 static void tty_hide_cursor
P_ ((struct tty_display_info
*));
103 static void tty_background_highlight
P_ ((struct tty_display_info
*tty
));
104 static void clear_tty_hooks
P_ ((struct terminal
*terminal
));
105 static void set_tty_hooks
P_ ((struct terminal
*terminal
));
106 static void dissociate_if_controlling_tty
P_ ((int fd
));
107 static void delete_tty
P_ ((struct terminal
*));
109 #define OUTPUT(tty, a) \
110 emacs_tputs ((tty), a, \
111 (int) (FRAME_LINES (XFRAME (selected_frame)) \
115 #define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
116 #define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
118 #define OUTPUT_IF(tty, a) \
121 emacs_tputs ((tty), a, \
122 (int) (FRAME_LINES (XFRAME (selected_frame)) \
127 #define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
129 /* If true, use "vs", otherwise use "ve" to make the cursor visible. */
131 static int visible_cursor
;
133 /* Display space properties */
135 extern Lisp_Object Qspace
, QCalign_to
, QCwidth
;
137 /* Functions to call after suspending a tty. */
138 Lisp_Object Vsuspend_tty_functions
;
140 /* Functions to call after resuming a tty. */
141 Lisp_Object Vresume_tty_functions
;
143 /* Chain of all tty device parameters. */
144 struct tty_display_info
*tty_list
;
146 /* Nonzero means no need to redraw the entire frame on resuming a
147 suspended Emacs. This is useful on terminals with multiple
148 pages, where one page is used for Emacs and another for all
150 int no_redraw_on_reenter
;
152 /* Meaning of bits in no_color_video. Each bit set means that the
153 corresponding attribute cannot be combined with colors. */
157 NC_STANDOUT
= 1 << 0,
158 NC_UNDERLINE
= 1 << 1,
165 NC_ALT_CHARSET
= 1 << 8
170 /* The largest frame width in any call to calculate_costs. */
174 /* The largest frame height in any call to calculate_costs. */
178 /* Non-zero if we have dropped our controlling tty and therefore
179 should not open a frame on stdout. */
180 static int no_controlling_tty
;
182 /* Provided for lisp packages. */
184 static int system_uses_terminfo
;
188 extern char *tgetstr ();
192 #include <sys/fcntl.h>
194 static void term_clear_mouse_face ();
195 static void term_mouse_highlight (struct frame
*f
, int x
, int y
);
197 /* The device for which we have enabled gpm support (or NULL). */
198 struct tty_display_info
*gpm_tty
= NULL
;
200 /* These variables describe the range of text currently shown in its
201 mouse-face, together with the window they apply to. As long as
202 the mouse stays within this range, we need not redraw anything on
203 its account. Rows and columns are glyph matrix positions in
204 MOUSE_FACE_WINDOW. */
205 static int mouse_face_beg_row
, mouse_face_beg_col
;
206 static int mouse_face_end_row
, mouse_face_end_col
;
207 static int mouse_face_past_end
;
208 static Lisp_Object mouse_face_window
;
209 static int mouse_face_face_id
;
211 static int pos_x
, pos_y
;
212 static int last_mouse_x
, last_mouse_y
;
213 #endif /* HAVE_GPM */
215 /* Ring the bell on a tty. */
218 tty_ring_bell (struct frame
*f
)
220 struct tty_display_info
*tty
= FRAME_TTY (f
);
224 OUTPUT (tty
, (tty
->TS_visible_bell
&& visible_bell
225 ? tty
->TS_visible_bell
227 fflush (tty
->output
);
231 /* Set up termcap modes for Emacs. */
234 tty_set_terminal_modes (struct terminal
*terminal
)
236 struct tty_display_info
*tty
= terminal
->display_info
.tty
;
240 if (tty
->TS_termcap_modes
)
241 OUTPUT (tty
, tty
->TS_termcap_modes
);
244 /* Output enough newlines to scroll all the old screen contents
245 off the screen, so it won't be overwritten and lost. */
248 for (i
= 0; i
< FRAME_LINES (XFRAME (selected_frame
)); i
++)
252 OUTPUT_IF (tty
, tty
->TS_termcap_modes
);
253 OUTPUT_IF (tty
, visible_cursor
? tty
->TS_cursor_visible
: tty
->TS_cursor_normal
);
254 OUTPUT_IF (tty
, tty
->TS_keypad_mode
);
256 fflush (tty
->output
);
260 /* Reset termcap modes before exiting Emacs. */
263 tty_reset_terminal_modes (struct terminal
*terminal
)
265 struct tty_display_info
*tty
= terminal
->display_info
.tty
;
269 tty_turn_off_highlight (tty
);
270 tty_turn_off_insert (tty
);
271 OUTPUT_IF (tty
, tty
->TS_end_keypad_mode
);
272 OUTPUT_IF (tty
, tty
->TS_cursor_normal
);
273 OUTPUT_IF (tty
, tty
->TS_end_termcap_modes
);
274 OUTPUT_IF (tty
, tty
->TS_orig_pair
);
275 /* Output raw CR so kernel can track the cursor hpos. */
278 fflush (tty
->output
);
282 /* Flag the end of a display update on a termcap terminal. */
285 tty_update_end (struct frame
*f
)
287 struct tty_display_info
*tty
= FRAME_TTY (f
);
289 if (!XWINDOW (selected_window
)->cursor_off_p
)
290 tty_show_cursor (tty
);
291 tty_turn_off_insert (tty
);
292 tty_background_highlight (tty
);
295 /* The implementation of set_terminal_window for termcap frames. */
298 tty_set_terminal_window (struct frame
*f
, int size
)
300 struct tty_display_info
*tty
= FRAME_TTY (f
);
302 tty
->specified_window
= size
? size
: FRAME_LINES (f
);
303 if (FRAME_SCROLL_REGION_OK (f
))
304 tty_set_scroll_region (f
, 0, tty
->specified_window
);
308 tty_set_scroll_region (struct frame
*f
, int start
, int stop
)
311 struct tty_display_info
*tty
= FRAME_TTY (f
);
313 if (tty
->TS_set_scroll_region
)
314 buf
= tparam (tty
->TS_set_scroll_region
, 0, 0, start
, stop
- 1);
315 else if (tty
->TS_set_scroll_region_1
)
316 buf
= tparam (tty
->TS_set_scroll_region_1
, 0, 0,
317 FRAME_LINES (f
), start
,
318 FRAME_LINES (f
) - stop
,
321 buf
= tparam (tty
->TS_set_window
, 0, 0, start
, 0, stop
, FRAME_COLS (f
));
330 tty_turn_on_insert (struct tty_display_info
*tty
)
332 if (!tty
->insert_mode
)
333 OUTPUT (tty
, tty
->TS_insert_mode
);
334 tty
->insert_mode
= 1;
338 tty_turn_off_insert (struct tty_display_info
*tty
)
340 if (tty
->insert_mode
)
341 OUTPUT (tty
, tty
->TS_end_insert_mode
);
342 tty
->insert_mode
= 0;
345 /* Handle highlighting. */
348 tty_turn_off_highlight (struct tty_display_info
*tty
)
350 if (tty
->standout_mode
)
351 OUTPUT_IF (tty
, tty
->TS_end_standout_mode
);
352 tty
->standout_mode
= 0;
356 tty_turn_on_highlight (struct tty_display_info
*tty
)
358 if (!tty
->standout_mode
)
359 OUTPUT_IF (tty
, tty
->TS_standout_mode
);
360 tty
->standout_mode
= 1;
364 tty_toggle_highlight (struct tty_display_info
*tty
)
366 if (tty
->standout_mode
)
367 tty_turn_off_highlight (tty
);
369 tty_turn_on_highlight (tty
);
373 /* Make cursor invisible. */
376 tty_hide_cursor (struct tty_display_info
*tty
)
378 if (tty
->cursor_hidden
== 0)
380 tty
->cursor_hidden
= 1;
381 OUTPUT_IF (tty
, tty
->TS_cursor_invisible
);
386 /* Ensure that cursor is visible. */
389 tty_show_cursor (struct tty_display_info
*tty
)
391 if (tty
->cursor_hidden
)
393 tty
->cursor_hidden
= 0;
394 OUTPUT_IF (tty
, tty
->TS_cursor_normal
);
396 OUTPUT_IF (tty
, tty
->TS_cursor_visible
);
401 /* Set standout mode to the state it should be in for
402 empty space inside windows. What this is,
403 depends on the user option inverse-video. */
406 tty_background_highlight (struct tty_display_info
*tty
)
409 tty_turn_on_highlight (tty
);
411 tty_turn_off_highlight (tty
);
414 /* Set standout mode to the mode specified for the text to be output. */
417 tty_highlight_if_desired (struct tty_display_info
*tty
)
420 tty_turn_on_highlight (tty
);
422 tty_turn_off_highlight (tty
);
426 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
427 frame-relative coordinates. */
430 tty_cursor_to (struct frame
*f
, int vpos
, int hpos
)
432 struct tty_display_info
*tty
= FRAME_TTY (f
);
434 /* Detect the case where we are called from reset_sys_modes
435 and the costs have never been calculated. Do nothing. */
436 if (! tty
->costs_set
)
439 if (curY (tty
) == vpos
440 && curX (tty
) == hpos
)
442 if (!tty
->TF_standout_motion
)
443 tty_background_highlight (tty
);
444 if (!tty
->TF_insmode_motion
)
445 tty_turn_off_insert (tty
);
446 cmgoto (tty
, vpos
, hpos
);
449 /* Similar but don't take any account of the wasted characters. */
452 tty_raw_cursor_to (struct frame
*f
, int row
, int col
)
454 struct tty_display_info
*tty
= FRAME_TTY (f
);
456 if (curY (tty
) == row
457 && curX (tty
) == col
)
459 if (!tty
->TF_standout_motion
)
460 tty_background_highlight (tty
);
461 if (!tty
->TF_insmode_motion
)
462 tty_turn_off_insert (tty
);
463 cmgoto (tty
, row
, col
);
466 /* Erase operations */
468 /* Clear from cursor to end of frame on a termcap device. */
471 tty_clear_to_end (struct frame
*f
)
474 struct tty_display_info
*tty
= FRAME_TTY (f
);
476 if (tty
->TS_clr_to_bottom
)
478 tty_background_highlight (tty
);
479 OUTPUT (tty
, tty
->TS_clr_to_bottom
);
483 for (i
= curY (tty
); i
< FRAME_LINES (f
); i
++)
486 clear_end_of_line (f
, FRAME_COLS (f
));
491 /* Clear an entire termcap frame. */
494 tty_clear_frame (struct frame
*f
)
496 struct tty_display_info
*tty
= FRAME_TTY (f
);
498 if (tty
->TS_clr_frame
)
500 tty_background_highlight (tty
);
501 OUTPUT (tty
, tty
->TS_clr_frame
);
511 /* An implementation of clear_end_of_line for termcap frames.
513 Note that the cursor may be moved, on terminals lacking a `ce' string. */
516 tty_clear_end_of_line (struct frame
*f
, int first_unused_hpos
)
519 struct tty_display_info
*tty
= FRAME_TTY (f
);
521 /* Detect the case where we are called from reset_sys_modes
522 and the costs have never been calculated. Do nothing. */
523 if (! tty
->costs_set
)
526 if (curX (tty
) >= first_unused_hpos
)
528 tty_background_highlight (tty
);
529 if (tty
->TS_clr_line
)
531 OUTPUT1 (tty
, tty
->TS_clr_line
);
534 { /* have to do it the hard way */
535 tty_turn_off_insert (tty
);
537 /* Do not write in last row last col with Auto-wrap on. */
539 && curY (tty
) == FrameRows (tty
) - 1
540 && first_unused_hpos
== FrameCols (tty
))
543 for (i
= curX (tty
); i
< first_unused_hpos
; i
++)
546 fputc (' ', tty
->termscript
);
547 fputc (' ', tty
->output
);
549 cmplus (tty
, first_unused_hpos
- curX (tty
));
553 /* Buffers to store the source and result of code conversion for terminal. */
554 static unsigned char *encode_terminal_src
;
555 static unsigned char *encode_terminal_dst
;
556 /* Allocated sizes of the above buffers. */
557 static int encode_terminal_src_size
;
558 static int encode_terminal_dst_size
;
560 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes.
561 Set CODING->produced to the byte-length of the resulting byte
562 sequence, and return a pointer to that byte sequence. */
565 encode_terminal_code (src
, src_len
, coding
)
568 struct coding_system
*coding
;
570 struct glyph
*src_end
= src
+ src_len
;
572 int nchars
, nbytes
, required
;
573 register int tlen
= GLYPH_TABLE_LENGTH
;
574 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
575 Lisp_Object charset_list
;
577 /* Allocate sufficient size of buffer to store all characters in
578 multibyte-form. But, it may be enlarged on demand if
579 Vglyph_table contains a string or a composite glyph is
581 required
= MAX_MULTIBYTE_LENGTH
* src_len
;
582 if (encode_terminal_src_size
< required
)
584 if (encode_terminal_src
)
585 encode_terminal_src
= xrealloc (encode_terminal_src
, required
);
587 encode_terminal_src
= xmalloc (required
);
588 encode_terminal_src_size
= required
;
591 charset_list
= coding_charset_list (coding
);
593 buf
= encode_terminal_src
;
595 while (src
< src_end
)
597 if (src
->type
== COMPOSITE_GLYPH
)
599 struct composition
*cmp
;
603 nbytes
= buf
- encode_terminal_src
;
604 if (src
->u
.cmp
.automatic
)
606 gstring
= composition_gstring_from_id (src
->u
.cmp
.id
);
607 required
= src
->u
.cmp
.to
+ 1 - src
->u
.cmp
.from
;
611 cmp
= composition_table
[src
->u
.cmp
.id
];
612 required
= MAX_MULTIBYTE_LENGTH
* cmp
->glyph_len
;
615 if (encode_terminal_src_size
< nbytes
+ required
)
617 encode_terminal_src_size
= nbytes
+ required
;
618 encode_terminal_src
= xrealloc (encode_terminal_src
,
619 encode_terminal_src_size
);
620 buf
= encode_terminal_src
+ nbytes
;
623 if (src
->u
.cmp
.automatic
)
624 for (i
= src
->u
.cmp
.from
; i
<= src
->u
.cmp
.to
; i
++)
626 Lisp_Object g
= LGSTRING_GLYPH (gstring
, i
);
627 int c
= LGLYPH_CHAR (g
);
629 if (! char_charset (c
, charset_list
, NULL
))
631 buf
+= CHAR_STRING (c
, buf
);
635 for (i
= 0; i
< cmp
->glyph_len
; i
++)
637 int c
= COMPOSITION_GLYPH (cmp
, i
);
641 if (char_charset (c
, charset_list
, NULL
))
643 if (CHAR_WIDTH (c
) == 0
644 && i
> 0 && COMPOSITION_GLYPH (cmp
, i
- 1) == '\t')
645 /* Should be left-padded */
647 buf
+= CHAR_STRING (' ', buf
);
653 buf
+= CHAR_STRING (c
, buf
);
657 /* We must skip glyphs to be padded for a wide character. */
658 else if (! CHAR_GLYPH_PADDING_P (*src
))
665 SET_GLYPH_FROM_CHAR_GLYPH (g
, src
[0]);
667 if (GLYPH_INVALID_P (g
) || GLYPH_SIMPLE_P (tbase
, tlen
, g
))
669 /* This glyph doesn't have an entry in Vglyph_table. */
674 /* This glyph has an entry in Vglyph_table,
675 so process any alias before testing for simpleness. */
676 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
678 if (GLYPH_SIMPLE_P (tbase
, tlen
, g
))
679 /* We set the multi-byte form of a character in G
680 (that should be an ASCII character) at WORKBUF. */
683 /* We have a string in Vglyph_table. */
684 string
= tbase
[GLYPH_CHAR (g
)];
689 nbytes
= buf
- encode_terminal_src
;
690 if (encode_terminal_src_size
< nbytes
+ MAX_MULTIBYTE_LENGTH
)
692 encode_terminal_src_size
= nbytes
+ MAX_MULTIBYTE_LENGTH
;
693 encode_terminal_src
= xrealloc (encode_terminal_src
,
694 encode_terminal_src_size
);
695 buf
= encode_terminal_src
+ nbytes
;
697 if (char_charset (c
, charset_list
, NULL
))
699 /* Store the multibyte form of C at BUF. */
700 buf
+= CHAR_STRING (c
, buf
);
705 /* C is not encodable. */
708 while (src
+ 1 < src_end
&& CHAR_GLYPH_PADDING_P (src
[1]))
718 unsigned char *p
= SDATA (string
), *pend
= p
+ SBYTES (string
);
720 if (! STRING_MULTIBYTE (string
))
721 string
= string_to_multibyte (string
);
722 nbytes
= buf
- encode_terminal_src
;
723 if (encode_terminal_src_size
< nbytes
+ SBYTES (string
))
725 encode_terminal_src_size
= nbytes
+ SBYTES (string
);
726 encode_terminal_src
= xrealloc (encode_terminal_src
,
727 encode_terminal_src_size
);
728 buf
= encode_terminal_src
+ nbytes
;
730 bcopy (SDATA (string
), buf
, SBYTES (string
));
731 buf
+= SBYTES (string
);
732 nchars
+= SCHARS (string
);
740 coding
->produced
= 0;
744 nbytes
= buf
- encode_terminal_src
;
745 coding
->source
= encode_terminal_src
;
746 if (encode_terminal_dst_size
== 0)
748 encode_terminal_dst_size
= encode_terminal_src_size
;
749 if (encode_terminal_dst
)
750 encode_terminal_dst
= xrealloc (encode_terminal_dst
,
751 encode_terminal_dst_size
);
753 encode_terminal_dst
= xmalloc (encode_terminal_dst_size
);
755 coding
->destination
= encode_terminal_dst
;
756 coding
->dst_bytes
= encode_terminal_dst_size
;
757 encode_coding_object (coding
, Qnil
, 0, 0, nchars
, nbytes
, Qnil
);
758 /* coding->destination may have been reallocated. */
759 encode_terminal_dst
= coding
->destination
;
760 encode_terminal_dst_size
= coding
->dst_bytes
;
762 return (encode_terminal_dst
);
767 /* An implementation of write_glyphs for termcap frames. */
770 tty_write_glyphs (struct frame
*f
, struct glyph
*string
, int len
)
772 unsigned char *conversion_buffer
;
773 struct coding_system
*coding
;
775 struct tty_display_info
*tty
= FRAME_TTY (f
);
777 tty_turn_off_insert (tty
);
778 tty_hide_cursor (tty
);
780 /* Don't dare write in last column of bottom line, if Auto-Wrap,
781 since that would scroll the whole frame on some terminals. */
784 && curY (tty
) + 1 == FRAME_LINES (f
)
785 && (curX (tty
) + len
) == FRAME_COLS (f
))
792 /* If terminal_coding does any conversion, use it, otherwise use
793 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
794 because it always return 1 if the member src_multibyte is 1. */
795 coding
= (FRAME_TERMINAL_CODING (f
)->common_flags
& CODING_REQUIRE_ENCODING_MASK
796 ? FRAME_TERMINAL_CODING (f
) : &safe_terminal_coding
);
797 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
799 coding
->mode
&= ~CODING_MODE_LAST_BLOCK
;
803 /* Identify a run of glyphs with the same face. */
804 int face_id
= string
->face_id
;
807 for (n
= 1; n
< len
; ++n
)
808 if (string
[n
].face_id
!= face_id
)
811 /* Turn appearance modes of the face of the run on. */
812 tty_highlight_if_desired (tty
);
813 turn_on_face (f
, face_id
);
816 /* This is the last run. */
817 coding
->mode
|= CODING_MODE_LAST_BLOCK
;
818 conversion_buffer
= encode_terminal_code (string
, n
, coding
);
819 if (coding
->produced
> 0)
822 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->output
);
823 if (ferror (tty
->output
))
824 clearerr (tty
->output
);
826 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->termscript
);
832 /* Turn appearance modes off. */
833 turn_off_face (f
, face_id
);
834 tty_turn_off_highlight (tty
);
840 #ifdef HAVE_GPM /* Only used by GPM code. */
843 tty_write_glyphs_with_face (f
, string
, len
, face_id
)
844 register struct frame
*f
;
845 register struct glyph
*string
;
846 register int len
, face_id
;
848 unsigned char *conversion_buffer
;
849 struct coding_system
*coding
;
851 struct tty_display_info
*tty
= FRAME_TTY (f
);
853 tty_turn_off_insert (tty
);
854 tty_hide_cursor (tty
);
856 /* Don't dare write in last column of bottom line, if Auto-Wrap,
857 since that would scroll the whole frame on some terminals. */
860 && curY (tty
) + 1 == FRAME_LINES (f
)
861 && (curX (tty
) + len
) == FRAME_COLS (f
))
868 /* If terminal_coding does any conversion, use it, otherwise use
869 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
870 because it always return 1 if the member src_multibyte is 1. */
871 coding
= (FRAME_TERMINAL_CODING (f
)->common_flags
& CODING_REQUIRE_ENCODING_MASK
872 ? FRAME_TERMINAL_CODING (f
) : &safe_terminal_coding
);
873 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
875 coding
->mode
&= ~CODING_MODE_LAST_BLOCK
;
877 /* Turn appearance modes of the face. */
878 tty_highlight_if_desired (tty
);
879 turn_on_face (f
, face_id
);
881 coding
->mode
|= CODING_MODE_LAST_BLOCK
;
882 conversion_buffer
= encode_terminal_code (string
, len
, coding
);
883 if (coding
->produced
> 0)
886 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->output
);
887 if (ferror (tty
->output
))
888 clearerr (tty
->output
);
890 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->termscript
);
894 /* Turn appearance modes off. */
895 turn_off_face (f
, face_id
);
896 tty_turn_off_highlight (tty
);
902 /* An implementation of insert_glyphs for termcap frames. */
905 tty_insert_glyphs (struct frame
*f
, struct glyph
*start
, int len
)
908 struct glyph
*glyph
= NULL
;
909 unsigned char *conversion_buffer
;
910 unsigned char space
[1];
911 struct coding_system
*coding
;
913 struct tty_display_info
*tty
= FRAME_TTY (f
);
915 if (tty
->TS_ins_multi_chars
)
917 buf
= tparam (tty
->TS_ins_multi_chars
, 0, 0, len
);
921 write_glyphs (f
, start
, len
);
925 tty_turn_on_insert (tty
);
929 space
[0] = SPACEGLYPH
;
931 /* If terminal_coding does any conversion, use it, otherwise use
932 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
933 because it always return 1 if the member src_multibyte is 1. */
934 coding
= (FRAME_TERMINAL_CODING (f
)->common_flags
& CODING_REQUIRE_ENCODING_MASK
935 ? FRAME_TERMINAL_CODING (f
) : &safe_terminal_coding
);
936 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
938 coding
->mode
&= ~CODING_MODE_LAST_BLOCK
;
942 OUTPUT1_IF (tty
, tty
->TS_ins_char
);
945 conversion_buffer
= space
;
946 coding
->produced
= 1;
950 tty_highlight_if_desired (tty
);
951 turn_on_face (f
, start
->face_id
);
954 /* We must open sufficient space for a character which
955 occupies more than one column. */
956 while (len
&& CHAR_GLYPH_PADDING_P (*start
))
958 OUTPUT1_IF (tty
, tty
->TS_ins_char
);
963 /* This is the last glyph. */
964 coding
->mode
|= CODING_MODE_LAST_BLOCK
;
966 conversion_buffer
= encode_terminal_code (glyph
, 1, coding
);
969 if (coding
->produced
> 0)
972 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->output
);
973 if (ferror (tty
->output
))
974 clearerr (tty
->output
);
976 fwrite (conversion_buffer
, 1, coding
->produced
, tty
->termscript
);
980 OUTPUT1_IF (tty
, tty
->TS_pad_inserted_char
);
983 turn_off_face (f
, glyph
->face_id
);
984 tty_turn_off_highlight (tty
);
991 /* An implementation of delete_glyphs for termcap frames. */
994 tty_delete_glyphs (struct frame
*f
, int n
)
999 struct tty_display_info
*tty
= FRAME_TTY (f
);
1001 if (tty
->delete_in_insert_mode
)
1003 tty_turn_on_insert (tty
);
1007 tty_turn_off_insert (tty
);
1008 OUTPUT_IF (tty
, tty
->TS_delete_mode
);
1011 if (tty
->TS_del_multi_chars
)
1013 buf
= tparam (tty
->TS_del_multi_chars
, 0, 0, n
);
1018 for (i
= 0; i
< n
; i
++)
1019 OUTPUT1 (tty
, tty
->TS_del_char
);
1020 if (!tty
->delete_in_insert_mode
)
1021 OUTPUT_IF (tty
, tty
->TS_end_delete_mode
);
1024 /* An implementation of ins_del_lines for termcap frames. */
1027 tty_ins_del_lines (struct frame
*f
, int vpos
, int n
)
1029 struct tty_display_info
*tty
= FRAME_TTY (f
);
1030 char *multi
= n
> 0 ? tty
->TS_ins_multi_lines
: tty
->TS_del_multi_lines
;
1031 char *single
= n
> 0 ? tty
->TS_ins_line
: tty
->TS_del_line
;
1032 char *scroll
= n
> 0 ? tty
->TS_rev_scroll
: tty
->TS_fwd_scroll
;
1034 register int i
= n
> 0 ? n
: -n
;
1037 /* If the lines below the insertion are being pushed
1038 into the end of the window, this is the same as clearing;
1039 and we know the lines are already clear, since the matching
1040 deletion has already been done. So can ignore this. */
1041 /* If the lines below the deletion are blank lines coming
1042 out of the end of the window, don't bother,
1043 as there will be a matching inslines later that will flush them. */
1044 if (FRAME_SCROLL_REGION_OK (f
)
1045 && vpos
+ i
>= tty
->specified_window
)
1047 if (!FRAME_MEMORY_BELOW_FRAME (f
)
1048 && vpos
+ i
>= FRAME_LINES (f
))
1053 raw_cursor_to (f
, vpos
, 0);
1054 tty_background_highlight (tty
);
1055 buf
= tparam (multi
, 0, 0, i
);
1061 raw_cursor_to (f
, vpos
, 0);
1062 tty_background_highlight (tty
);
1064 OUTPUT (tty
, single
);
1065 if (tty
->TF_teleray
)
1070 tty_set_scroll_region (f
, vpos
, tty
->specified_window
);
1072 raw_cursor_to (f
, tty
->specified_window
- 1, 0);
1074 raw_cursor_to (f
, vpos
, 0);
1075 tty_background_highlight (tty
);
1077 OUTPUTL (tty
, scroll
, tty
->specified_window
- vpos
);
1078 tty_set_scroll_region (f
, 0, tty
->specified_window
);
1081 if (!FRAME_SCROLL_REGION_OK (f
)
1082 && FRAME_MEMORY_BELOW_FRAME (f
)
1085 cursor_to (f
, FRAME_LINES (f
) + n
, 0);
1090 /* Compute cost of sending "str", in characters,
1091 not counting any line-dependent padding. */
1094 string_cost (char *str
)
1098 tputs (str
, 0, evalcost
);
1102 /* Compute cost of sending "str", in characters,
1103 counting any line-dependent padding at one line. */
1106 string_cost_one_line (char *str
)
1110 tputs (str
, 1, evalcost
);
1114 /* Compute per line amount of line-dependent padding,
1115 in tenths of characters. */
1118 per_line_cost (char *str
)
1122 tputs (str
, 0, evalcost
);
1125 tputs (str
, 10, evalcost
);
1130 /* char_ins_del_cost[n] is cost of inserting N characters.
1131 char_ins_del_cost[-n] is cost of deleting N characters.
1132 The length of this vector is based on max_frame_cols. */
1134 int *char_ins_del_vector
;
1136 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
1141 calculate_ins_del_char_costs (struct frame
*f
)
1143 struct tty_display_info
*tty
= FRAME_TTY (f
);
1144 int ins_startup_cost
, del_startup_cost
;
1145 int ins_cost_per_char
, del_cost_per_char
;
1149 if (tty
->TS_ins_multi_chars
)
1151 ins_cost_per_char
= 0;
1152 ins_startup_cost
= string_cost_one_line (tty
->TS_ins_multi_chars
);
1154 else if (tty
->TS_ins_char
|| tty
->TS_pad_inserted_char
1155 || (tty
->TS_insert_mode
&& tty
->TS_end_insert_mode
))
1157 ins_startup_cost
= (30 * (string_cost (tty
->TS_insert_mode
)
1158 + string_cost (tty
->TS_end_insert_mode
))) / 100;
1159 ins_cost_per_char
= (string_cost_one_line (tty
->TS_ins_char
)
1160 + string_cost_one_line (tty
->TS_pad_inserted_char
));
1164 ins_startup_cost
= 9999;
1165 ins_cost_per_char
= 0;
1168 if (tty
->TS_del_multi_chars
)
1170 del_cost_per_char
= 0;
1171 del_startup_cost
= string_cost_one_line (tty
->TS_del_multi_chars
);
1173 else if (tty
->TS_del_char
)
1175 del_startup_cost
= (string_cost (tty
->TS_delete_mode
)
1176 + string_cost (tty
->TS_end_delete_mode
));
1177 if (tty
->delete_in_insert_mode
)
1178 del_startup_cost
/= 2;
1179 del_cost_per_char
= string_cost_one_line (tty
->TS_del_char
);
1183 del_startup_cost
= 9999;
1184 del_cost_per_char
= 0;
1187 /* Delete costs are at negative offsets */
1188 p
= &char_ins_del_cost (f
)[0];
1189 for (i
= FRAME_COLS (f
); --i
>= 0;)
1190 *--p
= (del_startup_cost
+= del_cost_per_char
);
1192 /* Doing nothing is free */
1193 p
= &char_ins_del_cost (f
)[0];
1196 /* Insert costs are at positive offsets */
1197 for (i
= FRAME_COLS (f
); --i
>= 0;)
1198 *p
++ = (ins_startup_cost
+= ins_cost_per_char
);
1202 calculate_costs (struct frame
*frame
)
1204 FRAME_COST_BAUD_RATE (frame
) = baud_rate
;
1206 if (FRAME_TERMCAP_P (frame
))
1208 struct tty_display_info
*tty
= FRAME_TTY (frame
);
1209 register char *f
= (tty
->TS_set_scroll_region
1210 ? tty
->TS_set_scroll_region
1211 : tty
->TS_set_scroll_region_1
);
1213 FRAME_SCROLL_REGION_COST (frame
) = string_cost (f
);
1217 /* These variables are only used for terminal stuff. They are
1218 allocated once for the terminal frame of X-windows emacs, but not
1221 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1222 X turns off char_ins_del_ok. */
1224 max_frame_lines
= max (max_frame_lines
, FRAME_LINES (frame
));
1225 max_frame_cols
= max (max_frame_cols
, FRAME_COLS (frame
));
1227 if (char_ins_del_vector
!= 0)
1229 = (int *) xrealloc (char_ins_del_vector
,
1231 + 2 * max_frame_cols
* sizeof (int)));
1234 = (int *) xmalloc (sizeof (int)
1235 + 2 * max_frame_cols
* sizeof (int));
1237 bzero (char_ins_del_vector
, (sizeof (int)
1238 + 2 * max_frame_cols
* sizeof (int)));
1241 if (f
&& (!tty
->TS_ins_line
&& !tty
->TS_del_line
))
1242 do_line_insertion_deletion_costs (frame
,
1243 tty
->TS_rev_scroll
, tty
->TS_ins_multi_lines
,
1244 tty
->TS_fwd_scroll
, tty
->TS_del_multi_lines
,
1247 do_line_insertion_deletion_costs (frame
,
1248 tty
->TS_ins_line
, tty
->TS_ins_multi_lines
,
1249 tty
->TS_del_line
, tty
->TS_del_multi_lines
,
1252 calculate_ins_del_char_costs (frame
);
1254 /* Don't use TS_repeat if its padding is worse than sending the chars */
1255 if (tty
->TS_repeat
&& per_line_cost (tty
->TS_repeat
) * baud_rate
< 9000)
1256 tty
->RPov
= string_cost (tty
->TS_repeat
);
1258 tty
->RPov
= FRAME_COLS (frame
) * 2;
1260 cmcostinit (FRAME_TTY (frame
)); /* set up cursor motion costs */
1268 /* Termcap capability names that correspond directly to X keysyms.
1269 Some of these (marked "terminfo") aren't supplied by old-style
1270 (Berkeley) termcap entries. They're listed in X keysym order;
1271 except we put the keypad keys first, so that if they clash with
1272 other keys (as on the IBM PC keyboard) they get overridden.
1275 static struct fkey_table keys
[] =
1277 {"kh", "home"}, /* termcap */
1278 {"kl", "left"}, /* termcap */
1279 {"ku", "up"}, /* termcap */
1280 {"kr", "right"}, /* termcap */
1281 {"kd", "down"}, /* termcap */
1282 {"%8", "prior"}, /* terminfo */
1283 {"%5", "next"}, /* terminfo */
1284 {"@7", "end"}, /* terminfo */
1285 {"@1", "begin"}, /* terminfo */
1286 {"*6", "select"}, /* terminfo */
1287 {"%9", "print"}, /* terminfo */
1288 {"@4", "execute"}, /* terminfo --- actually the `command' key */
1290 * "insert" --- see below
1292 {"&8", "undo"}, /* terminfo */
1293 {"%0", "redo"}, /* terminfo */
1294 {"%7", "menu"}, /* terminfo --- actually the `options' key */
1295 {"@0", "find"}, /* terminfo */
1296 {"@2", "cancel"}, /* terminfo */
1297 {"%1", "help"}, /* terminfo */
1299 * "break" goes here, but can't be reliably intercepted with termcap
1301 {"&4", "reset"}, /* terminfo --- actually `restart' */
1303 * "system" and "user" --- no termcaps
1305 {"kE", "clearline"}, /* terminfo */
1306 {"kA", "insertline"}, /* terminfo */
1307 {"kL", "deleteline"}, /* terminfo */
1308 {"kI", "insertchar"}, /* terminfo */
1309 {"kD", "deletechar"}, /* terminfo */
1310 {"kB", "backtab"}, /* terminfo */
1312 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1314 {"@8", "kp-enter"}, /* terminfo */
1316 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1317 * "kp-multiply", "kp-add", "kp-separator",
1318 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1319 * --- no termcaps for any of these.
1321 {"K4", "kp-1"}, /* terminfo */
1323 * "kp-2" --- no termcap
1325 {"K5", "kp-3"}, /* terminfo */
1327 * "kp-4" --- no termcap
1329 {"K2", "kp-5"}, /* terminfo */
1331 * "kp-6" --- no termcap
1333 {"K1", "kp-7"}, /* terminfo */
1335 * "kp-8" --- no termcap
1337 {"K3", "kp-9"}, /* terminfo */
1339 * "kp-equal" --- no termcap
1351 {"&0", "S-cancel"}, /*shifted cancel key*/
1352 {"&9", "S-begin"}, /*shifted begin key*/
1353 {"*0", "S-find"}, /*shifted find key*/
1354 {"*1", "S-execute"}, /*shifted execute? actually shifted command key*/
1355 {"*4", "S-delete"}, /*shifted delete-character key*/
1356 {"*7", "S-end"}, /*shifted end key*/
1357 {"*8", "S-clearline"}, /*shifted clear-to end-of-line key*/
1358 {"#1", "S-help"}, /*shifted help key*/
1359 {"#2", "S-home"}, /*shifted home key*/
1360 {"#3", "S-insert"}, /*shifted insert-character key*/
1361 {"#4", "S-left"}, /*shifted left-arrow key*/
1362 {"%d", "S-menu"}, /*shifted menu? actually shifted options key*/
1363 {"%c", "S-next"}, /*shifted next key*/
1364 {"%e", "S-prior"}, /*shifted previous key*/
1365 {"%f", "S-print"}, /*shifted print key*/
1366 {"%g", "S-redo"}, /*shifted redo key*/
1367 {"%i", "S-right"}, /*shifted right-arrow key*/
1368 {"!3", "S-undo"} /*shifted undo key*/
1371 static char **term_get_fkeys_address
;
1372 static KBOARD
*term_get_fkeys_kboard
;
1373 static Lisp_Object
term_get_fkeys_1 ();
1375 /* Find the escape codes sent by the function keys for Vinput_decode_map.
1376 This function scans the termcap function key sequence entries, and
1377 adds entries to Vinput_decode_map for each function key it finds. */
1380 term_get_fkeys (address
, kboard
)
1384 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1385 errors during the call. The only errors should be from Fdefine_key
1386 when given a key sequence containing an invalid prefix key. If the
1387 termcap defines function keys which use a prefix that is already bound
1388 to a command by the default bindings, we should silently ignore that
1389 function key specification, rather than giving the user an error and
1390 refusing to run at all on such a terminal. */
1392 extern Lisp_Object
Fidentity ();
1393 term_get_fkeys_address
= address
;
1394 term_get_fkeys_kboard
= kboard
;
1395 internal_condition_case (term_get_fkeys_1
, Qerror
, Fidentity
);
1403 char **address
= term_get_fkeys_address
;
1404 KBOARD
*kboard
= term_get_fkeys_kboard
;
1406 /* This can happen if CANNOT_DUMP or with strange options. */
1407 if (!KEYMAPP (kboard
->Vinput_decode_map
))
1408 kboard
->Vinput_decode_map
= Fmake_sparse_keymap (Qnil
);
1410 for (i
= 0; i
< (sizeof (keys
)/sizeof (keys
[0])); i
++)
1412 char *sequence
= tgetstr (keys
[i
].cap
, address
);
1414 Fdefine_key (kboard
->Vinput_decode_map
, build_string (sequence
),
1415 Fmake_vector (make_number (1),
1416 intern (keys
[i
].name
)));
1419 /* The uses of the "k0" capability are inconsistent; sometimes it
1420 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1421 We will attempt to politely accommodate both systems by testing for
1422 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1425 char *k_semi
= tgetstr ("k;", address
);
1426 char *k0
= tgetstr ("k0", address
);
1427 char *k0_name
= "f10";
1432 /* Define f0 first, so that f10 takes precedence in case the
1433 key sequences happens to be the same. */
1434 Fdefine_key (kboard
->Vinput_decode_map
, build_string (k0
),
1435 Fmake_vector (make_number (1), intern ("f0")));
1436 Fdefine_key (kboard
->Vinput_decode_map
, build_string (k_semi
),
1437 Fmake_vector (make_number (1), intern ("f10")));
1440 Fdefine_key (kboard
->Vinput_decode_map
, build_string (k0
),
1441 Fmake_vector (make_number (1), intern (k0_name
)));
1444 /* Set up cookies for numbered function keys above f10. */
1446 char fcap
[3], fkey
[4];
1448 fcap
[0] = 'F'; fcap
[2] = '\0';
1449 for (i
= 11; i
< 64; i
++)
1452 fcap
[1] = '1' + i
- 11;
1454 fcap
[1] = 'A' + i
- 20;
1456 fcap
[1] = 'a' + i
- 46;
1459 char *sequence
= tgetstr (fcap
, address
);
1462 sprintf (fkey
, "f%d", i
);
1463 Fdefine_key (kboard
->Vinput_decode_map
, build_string (sequence
),
1464 Fmake_vector (make_number (1),
1472 * Various mappings to try and get a better fit.
1475 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1476 if (!tgetstr (cap1, address)) \
1478 char *sequence = tgetstr (cap2, address); \
1480 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence), \
1481 Fmake_vector (make_number (1), \
1485 /* if there's no key_next keycap, map key_npage to `next' keysym */
1486 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1487 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1488 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1489 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1490 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1491 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1492 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1494 /* IBM has their own non-standard dialect of terminfo.
1495 If the standard name isn't found, try the IBM name. */
1496 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1497 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1498 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1499 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1500 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1501 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1502 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1503 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1504 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1505 #undef CONDITIONAL_REASSIGN
1512 /***********************************************************************
1513 Character Display Information
1514 ***********************************************************************/
1516 /* Avoid name clash with functions defined in xterm.c */
1518 #define append_glyph append_glyph_term
1519 #define produce_stretch_glyph produce_stretch_glyph_term
1520 #define append_composite_glyph append_composite_glyph_term
1521 #define produce_composite_glyph produce_composite_glyph_term
1524 static void append_glyph
P_ ((struct it
*));
1525 static void produce_stretch_glyph
P_ ((struct it
*));
1526 static void append_composite_glyph
P_ ((struct it
*));
1527 static void produce_composite_glyph
P_ ((struct it
*));
1529 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1530 terminal frames if IT->glyph_row != NULL. IT->char_to_display is
1531 the character for which to produce glyphs; IT->face_id contains the
1532 character's face. Padding glyphs are appended if IT->c has a
1533 IT->pixel_width > 1. */
1539 struct glyph
*glyph
, *end
;
1542 xassert (it
->glyph_row
);
1543 glyph
= (it
->glyph_row
->glyphs
[it
->area
]
1544 + it
->glyph_row
->used
[it
->area
]);
1545 end
= it
->glyph_row
->glyphs
[1 + it
->area
];
1548 i
< it
->pixel_width
&& glyph
< end
;
1551 glyph
->type
= CHAR_GLYPH
;
1552 glyph
->pixel_width
= 1;
1553 glyph
->u
.ch
= it
->char_to_display
;
1554 glyph
->face_id
= it
->face_id
;
1555 glyph
->padding_p
= i
> 0;
1556 glyph
->charpos
= CHARPOS (it
->position
);
1557 glyph
->object
= it
->object
;
1559 ++it
->glyph_row
->used
[it
->area
];
1565 /* Produce glyphs for the display element described by IT. *IT
1566 specifies what we want to produce a glyph for (character, image, ...),
1567 and where in the glyph matrix we currently are (glyph row and hpos).
1568 produce_glyphs fills in output fields of *IT with information such as the
1569 pixel width and height of a character, and maybe output actual glyphs at
1570 the same time if IT->glyph_row is non-null. See the explanation of
1571 struct display_iterator in dispextern.h for an overview.
1573 produce_glyphs also stores the result of glyph width, ascent
1574 etc. computations in *IT.
1576 IT->glyph_row may be null, in which case produce_glyphs does not
1577 actually fill in the glyphs. This is used in the move_* functions
1578 in xdisp.c for text width and height computations.
1580 Callers usually don't call produce_glyphs directly;
1581 instead they use the macro PRODUCE_GLYPHS. */
1587 /* If a hook is installed, let it do the work. */
1589 /* Nothing but characters are supported on terminal frames. */
1590 xassert (it
->what
== IT_CHARACTER
1591 || it
->what
== IT_COMPOSITION
1592 || it
->what
== IT_STRETCH
);
1594 if (it
->what
== IT_STRETCH
)
1596 produce_stretch_glyph (it
);
1600 if (it
->what
== IT_COMPOSITION
)
1602 produce_composite_glyph (it
);
1606 /* Maybe translate single-byte characters to multibyte. */
1607 it
->char_to_display
= it
->c
;
1609 if (it
->c
>= 040 && it
->c
< 0177)
1611 it
->pixel_width
= it
->nglyphs
= 1;
1615 else if (it
->c
== '\n')
1616 it
->pixel_width
= it
->nglyphs
= 0;
1617 else if (it
->c
== '\t')
1619 int absolute_x
= (it
->current_x
1620 + it
->continuation_lines_width
);
1622 = (((1 + absolute_x
+ it
->tab_width
- 1)
1627 /* If part of the TAB has been displayed on the previous line
1628 which is continued now, continuation_lines_width will have
1629 been incremented already by the part that fitted on the
1630 continued line. So, we will get the right number of spaces
1632 nspaces
= next_tab_x
- absolute_x
;
1638 it
->char_to_display
= ' ';
1639 it
->pixel_width
= it
->len
= 1;
1645 it
->pixel_width
= nspaces
;
1646 it
->nglyphs
= nspaces
;
1648 else if (CHAR_BYTE8_P (it
->c
))
1650 if (unibyte_display_via_language_environment
1653 it
->char_to_display
= unibyte_char_to_multibyte (it
->c
);
1654 it
->pixel_width
= CHAR_WIDTH (it
->char_to_display
);
1655 it
->nglyphs
= it
->pixel_width
;
1661 /* Coming here means that it->c is from display table, thus
1662 we must send the raw 8-bit byte as is to the terminal.
1663 Although there's no way to know how many columns it
1664 occupies on a screen, it is a good assumption that a
1665 single byte code has 1-column width. */
1666 it
->pixel_width
= it
->nglyphs
= 1;
1673 it
->pixel_width
= CHAR_WIDTH (it
->c
);
1674 it
->nglyphs
= it
->pixel_width
;
1681 /* Advance current_x by the pixel width as a convenience for
1683 if (it
->area
== TEXT_AREA
)
1684 it
->current_x
+= it
->pixel_width
;
1685 it
->ascent
= it
->max_ascent
= it
->phys_ascent
= it
->max_phys_ascent
= 0;
1686 it
->descent
= it
->max_descent
= it
->phys_descent
= it
->max_phys_descent
= 1;
1690 /* Produce a stretch glyph for iterator IT. IT->object is the value
1691 of the glyph property displayed. The value must be a list
1692 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1695 1. `:width WIDTH' specifies that the space should be WIDTH *
1696 canonical char width wide. WIDTH may be an integer or floating
1699 2. `:align-to HPOS' specifies that the space should be wide enough
1700 to reach HPOS, a value in canonical character units. */
1703 produce_stretch_glyph (it
)
1706 /* (space :width WIDTH ...) */
1707 Lisp_Object prop
, plist
;
1708 int width
= 0, align_to
= -1;
1709 int zero_width_ok_p
= 0;
1712 /* List should start with `space'. */
1713 xassert (CONSP (it
->object
) && EQ (XCAR (it
->object
), Qspace
));
1714 plist
= XCDR (it
->object
);
1716 /* Compute the width of the stretch. */
1717 if ((prop
= Fplist_get (plist
, QCwidth
), !NILP (prop
))
1718 && calc_pixel_width_or_height (&tem
, it
, prop
, 0, 1, 0))
1720 /* Absolute width `:width WIDTH' specified and valid. */
1721 zero_width_ok_p
= 1;
1722 width
= (int)(tem
+ 0.5);
1724 else if ((prop
= Fplist_get (plist
, QCalign_to
), !NILP (prop
))
1725 && calc_pixel_width_or_height (&tem
, it
, prop
, 0, 1, &align_to
))
1727 if (it
->glyph_row
== NULL
|| !it
->glyph_row
->mode_line_p
)
1728 align_to
= (align_to
< 0
1730 : align_to
- window_box_left_offset (it
->w
, TEXT_AREA
));
1731 else if (align_to
< 0)
1732 align_to
= window_box_left_offset (it
->w
, TEXT_AREA
);
1733 width
= max (0, (int)(tem
+ 0.5) + align_to
- it
->current_x
);
1734 zero_width_ok_p
= 1;
1737 /* Nothing specified -> width defaults to canonical char width. */
1738 width
= FRAME_COLUMN_WIDTH (it
->f
);
1740 if (width
<= 0 && (width
< 0 || !zero_width_ok_p
))
1743 if (width
> 0 && it
->glyph_row
)
1745 Lisp_Object o_object
= it
->object
;
1746 Lisp_Object object
= it
->stack
[it
->sp
- 1].string
;
1749 if (!STRINGP (object
))
1750 object
= it
->w
->buffer
;
1751 it
->object
= object
;
1752 it
->char_to_display
= ' ';
1753 it
->pixel_width
= it
->len
= 1;
1756 it
->object
= o_object
;
1758 it
->pixel_width
= width
;
1759 it
->nglyphs
= width
;
1763 /* Append glyphs to IT's glyph_row for the composition IT->cmp_id.
1764 Called from produce_composite_glyph for terminal frames if
1765 IT->glyph_row != NULL. IT->face_id contains the character's
1769 append_composite_glyph (it
)
1772 struct glyph
*glyph
;
1774 xassert (it
->glyph_row
);
1775 glyph
= it
->glyph_row
->glyphs
[it
->area
] + it
->glyph_row
->used
[it
->area
];
1776 if (glyph
< it
->glyph_row
->glyphs
[1 + it
->area
])
1778 glyph
->type
= COMPOSITE_GLYPH
;
1779 glyph
->pixel_width
= it
->pixel_width
;
1780 glyph
->u
.cmp
.id
= it
->cmp_it
.id
;
1781 if (it
->cmp_it
.ch
< 0)
1783 glyph
->u
.cmp
.automatic
= 0;
1784 glyph
->u
.cmp
.id
= it
->cmp_it
.id
;
1788 glyph
->u
.cmp
.automatic
= 1;
1789 glyph
->u
.cmp
.id
= it
->cmp_it
.id
;
1790 glyph
->u
.cmp
.from
= it
->cmp_it
.from
;
1791 glyph
->u
.cmp
.to
= it
->cmp_it
.to
- 1;
1794 glyph
->face_id
= it
->face_id
;
1795 glyph
->padding_p
= 0;
1796 glyph
->charpos
= CHARPOS (it
->position
);
1797 glyph
->object
= it
->object
;
1799 ++it
->glyph_row
->used
[it
->area
];
1805 /* Produce a composite glyph for iterator IT. IT->cmp_id is the ID of
1806 the composition. We simply produces components of the composition
1807 assuming that that the terminal has a capability to layout/render
1811 produce_composite_glyph (it
)
1816 if (it
->cmp_it
.ch
< 0)
1818 struct composition
*cmp
= composition_table
[it
->cmp_it
.id
];
1820 it
->pixel_width
= cmp
->width
;
1824 Lisp_Object gstring
= composition_gstring_from_id (it
->cmp_it
.id
);
1826 it
->pixel_width
= composition_gstring_width (gstring
, it
->cmp_it
.from
,
1827 it
->cmp_it
.to
, NULL
);
1831 append_composite_glyph (it
);
1835 /* Get information about special display element WHAT in an
1836 environment described by IT. WHAT is one of IT_TRUNCATION or
1837 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1838 non-null glyph_row member. This function ensures that fields like
1839 face_id, c, len of IT are left untouched. */
1842 produce_special_glyphs (it
, what
)
1844 enum display_element_type what
;
1852 temp_it
.what
= IT_CHARACTER
;
1854 temp_it
.object
= make_number (0);
1855 bzero (&temp_it
.current
, sizeof temp_it
.current
);
1857 if (what
== IT_CONTINUATION
)
1859 /* Continuation glyph. */
1860 SET_GLYPH_FROM_CHAR (glyph
, '\\');
1862 && (gc
= DISP_CONTINUE_GLYPH (it
->dp
), GLYPH_CODE_P (gc
))
1863 && GLYPH_CODE_CHAR_VALID_P (gc
))
1865 SET_GLYPH_FROM_GLYPH_CODE (glyph
, gc
);
1866 spec_glyph_lookup_face (XWINDOW (it
->window
), &glyph
);
1869 else if (what
== IT_TRUNCATION
)
1871 /* Truncation glyph. */
1872 SET_GLYPH_FROM_CHAR (glyph
, '$');
1874 && (gc
= DISP_TRUNC_GLYPH (it
->dp
), GLYPH_CODE_P (gc
))
1875 && GLYPH_CODE_CHAR_VALID_P (gc
))
1877 SET_GLYPH_FROM_GLYPH_CODE (glyph
, gc
);
1878 spec_glyph_lookup_face (XWINDOW (it
->window
), &glyph
);
1884 temp_it
.c
= GLYPH_CHAR (glyph
);
1885 temp_it
.face_id
= GLYPH_FACE (glyph
);
1886 temp_it
.len
= CHAR_BYTES (temp_it
.c
);
1888 produce_glyphs (&temp_it
);
1889 it
->pixel_width
= temp_it
.pixel_width
;
1890 it
->nglyphs
= temp_it
.pixel_width
;
1895 /***********************************************************************
1897 ***********************************************************************/
1899 /* Value is non-zero if attribute ATTR may be used. ATTR should be
1900 one of the enumerators from enum no_color_bit, or a bit set built
1901 from them. Some display attributes may not be used together with
1902 color; the termcap capability `NC' specifies which ones. */
1904 #define MAY_USE_WITH_COLORS_P(tty, ATTR) \
1905 (tty->TN_max_colors > 0 \
1906 ? (tty->TN_no_color_video & (ATTR)) == 0 \
1909 /* Turn appearances of face FACE_ID on tty frame F on.
1910 FACE_ID is a realized face ID number, in the face cache. */
1913 turn_on_face (f
, face_id
)
1917 struct face
*face
= FACE_FROM_ID (f
, face_id
);
1918 long fg
= face
->foreground
;
1919 long bg
= face
->background
;
1920 struct tty_display_info
*tty
= FRAME_TTY (f
);
1922 /* Do this first because TS_end_standout_mode may be the same
1923 as TS_exit_attribute_mode, which turns all appearances off. */
1924 if (MAY_USE_WITH_COLORS_P (tty
, NC_REVERSE
))
1926 if (tty
->TN_max_colors
> 0)
1928 if (fg
>= 0 && bg
>= 0)
1930 /* If the terminal supports colors, we can set them
1931 below without using reverse video. The face's fg
1932 and bg colors are set as they should appear on
1933 the screen, i.e. they take the inverse-video'ness
1934 of the face already into account. */
1936 else if (inverse_video
)
1938 if (fg
== FACE_TTY_DEFAULT_FG_COLOR
1939 || bg
== FACE_TTY_DEFAULT_BG_COLOR
)
1940 tty_toggle_highlight (tty
);
1944 if (fg
== FACE_TTY_DEFAULT_BG_COLOR
1945 || bg
== FACE_TTY_DEFAULT_FG_COLOR
)
1946 tty_toggle_highlight (tty
);
1951 /* If we can't display colors, use reverse video
1952 if the face specifies that. */
1955 if (fg
== FACE_TTY_DEFAULT_FG_COLOR
1956 || bg
== FACE_TTY_DEFAULT_BG_COLOR
)
1957 tty_toggle_highlight (tty
);
1961 if (fg
== FACE_TTY_DEFAULT_BG_COLOR
1962 || bg
== FACE_TTY_DEFAULT_FG_COLOR
)
1963 tty_toggle_highlight (tty
);
1968 if (face
->tty_bold_p
)
1970 if (MAY_USE_WITH_COLORS_P (tty
, NC_BOLD
))
1971 OUTPUT1_IF (tty
, tty
->TS_enter_bold_mode
);
1973 else if (face
->tty_dim_p
)
1974 if (MAY_USE_WITH_COLORS_P (tty
, NC_DIM
))
1975 OUTPUT1_IF (tty
, tty
->TS_enter_dim_mode
);
1977 /* Alternate charset and blinking not yet used. */
1978 if (face
->tty_alt_charset_p
1979 && MAY_USE_WITH_COLORS_P (tty
, NC_ALT_CHARSET
))
1980 OUTPUT1_IF (tty
, tty
->TS_enter_alt_charset_mode
);
1982 if (face
->tty_blinking_p
1983 && MAY_USE_WITH_COLORS_P (tty
, NC_BLINK
))
1984 OUTPUT1_IF (tty
, tty
->TS_enter_blink_mode
);
1986 if (face
->tty_underline_p
&& MAY_USE_WITH_COLORS_P (tty
, NC_UNDERLINE
))
1987 OUTPUT1_IF (tty
, tty
->TS_enter_underline_mode
);
1989 if (tty
->TN_max_colors
> 0)
1993 ts
= tty
->standout_mode
? tty
->TS_set_background
: tty
->TS_set_foreground
;
1996 p
= tparam (ts
, NULL
, 0, (int) fg
);
2001 ts
= tty
->standout_mode
? tty
->TS_set_foreground
: tty
->TS_set_background
;
2004 p
= tparam (ts
, NULL
, 0, (int) bg
);
2012 /* Turn off appearances of face FACE_ID on tty frame F. */
2015 turn_off_face (f
, face_id
)
2019 struct face
*face
= FACE_FROM_ID (f
, face_id
);
2020 struct tty_display_info
*tty
= FRAME_TTY (f
);
2022 xassert (face
!= NULL
);
2024 if (tty
->TS_exit_attribute_mode
)
2026 /* Capability "me" will turn off appearance modes double-bright,
2027 half-bright, reverse-video, standout, underline. It may or
2028 may not turn off alt-char-mode. */
2029 if (face
->tty_bold_p
2031 || face
->tty_reverse_p
2032 || face
->tty_alt_charset_p
2033 || face
->tty_blinking_p
2034 || face
->tty_underline_p
)
2036 OUTPUT1_IF (tty
, tty
->TS_exit_attribute_mode
);
2037 if (strcmp (tty
->TS_exit_attribute_mode
, tty
->TS_end_standout_mode
) == 0)
2038 tty
->standout_mode
= 0;
2041 if (face
->tty_alt_charset_p
)
2042 OUTPUT_IF (tty
, tty
->TS_exit_alt_charset_mode
);
2046 /* If we don't have "me" we can only have those appearances
2047 that have exit sequences defined. */
2048 if (face
->tty_alt_charset_p
)
2049 OUTPUT_IF (tty
, tty
->TS_exit_alt_charset_mode
);
2051 if (face
->tty_underline_p
)
2052 OUTPUT_IF (tty
, tty
->TS_exit_underline_mode
);
2055 /* Switch back to default colors. */
2056 if (tty
->TN_max_colors
> 0
2057 && ((face
->foreground
!= FACE_TTY_DEFAULT_COLOR
2058 && face
->foreground
!= FACE_TTY_DEFAULT_FG_COLOR
)
2059 || (face
->background
!= FACE_TTY_DEFAULT_COLOR
2060 && face
->background
!= FACE_TTY_DEFAULT_BG_COLOR
)))
2061 OUTPUT1_IF (tty
, tty
->TS_orig_pair
);
2065 /* Return non-zero if the terminal on frame F supports all of the
2066 capabilities in CAPS simultaneously, with foreground and background
2067 colors FG and BG. */
2070 tty_capable_p (tty
, caps
, fg
, bg
)
2071 struct tty_display_info
*tty
;
2073 unsigned long fg
, bg
;
2075 #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
2076 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
2079 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_INVERSE
, tty
->TS_standout_mode
, NC_REVERSE
);
2080 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_UNDERLINE
, tty
->TS_enter_underline_mode
, NC_UNDERLINE
);
2081 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_BOLD
, tty
->TS_enter_bold_mode
, NC_BOLD
);
2082 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_DIM
, tty
->TS_enter_dim_mode
, NC_DIM
);
2083 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_BLINK
, tty
->TS_enter_blink_mode
, NC_BLINK
);
2084 TTY_CAPABLE_P_TRY (tty
, TTY_CAP_ALT_CHARSET
, tty
->TS_enter_alt_charset_mode
, NC_ALT_CHARSET
);
2090 /* Return non-zero if the terminal is capable to display colors. */
2092 DEFUN ("tty-display-color-p", Ftty_display_color_p
, Stty_display_color_p
,
2094 doc
: /* Return non-nil if the tty device TERMINAL can display colors.
2096 TERMINAL can be a terminal id, a frame or nil (meaning the selected
2097 frame's terminal). This function always returns nil if TERMINAL
2098 is not on a tty device. */)
2100 Lisp_Object terminal
;
2102 struct terminal
*t
= get_tty_terminal (terminal
, 0);
2106 return t
->display_info
.tty
->TN_max_colors
> 0 ? Qt
: Qnil
;
2109 /* Return the number of supported colors. */
2110 DEFUN ("tty-display-color-cells", Ftty_display_color_cells
,
2111 Stty_display_color_cells
, 0, 1, 0,
2112 doc
: /* Return the number of colors supported by the tty device TERMINAL.
2114 TERMINAL can be a terminal id, a frame or nil (meaning the selected
2115 frame's terminal). This function always returns 0 if TERMINAL
2116 is not on a tty device. */)
2118 Lisp_Object terminal
;
2120 struct terminal
*t
= get_tty_terminal (terminal
, 0);
2122 return make_number (0);
2124 return make_number (t
->display_info
.tty
->TN_max_colors
);
2129 /* Declare here rather than in the function, as in the rest of Emacs,
2130 to work around an HPUX compiler bug (?). See
2131 http://lists.gnu.org/archive/html/emacs-devel/2007-08/msg00410.html */
2132 static int default_max_colors
;
2133 static int default_max_pairs
;
2134 static int default_no_color_video
;
2135 static char *default_orig_pair
;
2136 static char *default_set_foreground
;
2137 static char *default_set_background
;
2139 /* Save or restore the default color-related capabilities of this
2142 tty_default_color_capabilities (struct tty_display_info
*tty
, int save
)
2147 xfree (default_orig_pair
);
2148 default_orig_pair
= tty
->TS_orig_pair
? xstrdup (tty
->TS_orig_pair
) : NULL
;
2150 xfree (default_set_foreground
);
2151 default_set_foreground
= tty
->TS_set_foreground
? xstrdup (tty
->TS_set_foreground
)
2154 xfree (default_set_background
);
2155 default_set_background
= tty
->TS_set_background
? xstrdup (tty
->TS_set_background
)
2158 default_max_colors
= tty
->TN_max_colors
;
2159 default_max_pairs
= tty
->TN_max_pairs
;
2160 default_no_color_video
= tty
->TN_no_color_video
;
2164 tty
->TS_orig_pair
= default_orig_pair
;
2165 tty
->TS_set_foreground
= default_set_foreground
;
2166 tty
->TS_set_background
= default_set_background
;
2167 tty
->TN_max_colors
= default_max_colors
;
2168 tty
->TN_max_pairs
= default_max_pairs
;
2169 tty
->TN_no_color_video
= default_no_color_video
;
2173 /* Setup one of the standard tty color schemes according to MODE.
2174 MODE's value is generally the number of colors which we want to
2175 support; zero means set up for the default capabilities, the ones
2176 we saw at init_tty time; -1 means turn off color support. */
2178 tty_setup_colors (struct tty_display_info
*tty
, int mode
)
2180 /* Canonicalize all negative values of MODE. */
2186 case -1: /* no colors at all */
2187 tty
->TN_max_colors
= 0;
2188 tty
->TN_max_pairs
= 0;
2189 tty
->TN_no_color_video
= 0;
2190 tty
->TS_set_foreground
= tty
->TS_set_background
= tty
->TS_orig_pair
= NULL
;
2192 case 0: /* default colors, if any */
2194 tty_default_color_capabilities (tty
, 0);
2196 case 8: /* 8 standard ANSI colors */
2197 tty
->TS_orig_pair
= "\033[0m";
2199 tty
->TS_set_foreground
= "\033[3%p1%dm";
2200 tty
->TS_set_background
= "\033[4%p1%dm";
2202 tty
->TS_set_foreground
= "\033[3%dm";
2203 tty
->TS_set_background
= "\033[4%dm";
2205 tty
->TN_max_colors
= 8;
2206 tty
->TN_max_pairs
= 64;
2207 tty
->TN_no_color_video
= 0;
2213 set_tty_color_mode (tty
, f
)
2214 struct tty_display_info
*tty
;
2217 Lisp_Object tem
, val
, color_mode_spec
;
2218 Lisp_Object color_mode
;
2220 extern Lisp_Object Qtty_color_mode
;
2221 Lisp_Object tty_color_mode_alist
2222 = Fintern_soft (build_string ("tty-color-mode-alist"), Qnil
);
2224 tem
= assq_no_quit (Qtty_color_mode
, f
->param_alist
);
2225 val
= CONSP (tem
) ? XCDR (tem
) : Qnil
;
2231 tem
= (NILP (tty_color_mode_alist
) ? Qnil
2232 : Fassq (val
, XSYMBOL (tty_color_mode_alist
)->value
));
2233 color_mode
= CONSP (tem
) ? XCDR (tem
) : Qnil
;
2236 mode
= INTEGERP (color_mode
) ? XINT (color_mode
) : 0;
2238 if (mode
!= tty
->previous_color_mode
)
2240 Lisp_Object funsym
= intern ("tty-set-up-initial-frame-faces");
2241 tty
->previous_color_mode
= mode
;
2242 tty_setup_colors (tty
, mode
);
2243 /* This recomputes all the faces given the new color definitions. */
2244 safe_call (1, &funsym
);
2248 #endif /* !DOS_NT */
2252 /* Return the tty display object specified by TERMINAL. */
2255 get_tty_terminal (Lisp_Object terminal
, int throw)
2257 struct terminal
*t
= get_terminal (terminal
, throw);
2259 if (t
&& t
->type
!= output_termcap
&& t
->type
!= output_msdos_raw
)
2262 error ("Device %d is not a termcap terminal device", t
->id
);
2270 /* Return an active termcap device that uses the tty device with the
2273 This function ignores suspended devices.
2275 Returns NULL if the named terminal device is not opened. */
2278 get_named_tty (name
)
2286 for (t
= terminal_list
; t
; t
= t
->next_terminal
)
2288 if ((t
->type
== output_termcap
|| t
->type
== output_msdos_raw
)
2289 && !strcmp (t
->display_info
.tty
->name
, name
)
2290 && TERMINAL_ACTIVE_P (t
))
2298 DEFUN ("tty-type", Ftty_type
, Stty_type
, 0, 1, 0,
2299 doc
: /* Return the type of the tty device that TERMINAL uses.
2300 Returns nil if TERMINAL is not on a tty device.
2302 TERMINAL can be a terminal id, a frame or nil (meaning the selected
2303 frame's terminal). */)
2305 Lisp_Object terminal
;
2307 struct terminal
*t
= get_terminal (terminal
, 1);
2309 if (t
->type
!= output_termcap
&& t
->type
!= output_msdos_raw
)
2312 if (t
->display_info
.tty
->type
)
2313 return build_string (t
->display_info
.tty
->type
);
2318 DEFUN ("controlling-tty-p", Fcontrolling_tty_p
, Scontrolling_tty_p
, 0, 1, 0,
2319 doc
: /* Return non-nil if TERMINAL is the controlling tty of the Emacs process.
2321 TERMINAL can be a terminal id, a frame or nil (meaning the selected
2322 frame's terminal). This function always returns nil if TERMINAL
2323 is not on a tty device. */)
2325 Lisp_Object terminal
;
2327 struct terminal
*t
= get_terminal (terminal
, 1);
2329 if ((t
->type
!= output_termcap
&& t
->type
!= output_msdos_raw
)
2330 || strcmp (t
->display_info
.tty
->name
, DEV_TTY
) != 0)
2336 DEFUN ("tty-no-underline", Ftty_no_underline
, Stty_no_underline
, 0, 1, 0,
2337 doc
: /* Declare that the tty used by TERMINAL does not handle underlining.
2338 This is used to override the terminfo data, for certain terminals that
2339 do not really do underlining, but say that they do. This function has
2340 no effect if used on a non-tty terminal.
2342 TERMINAL can be a terminal id, a frame or nil (meaning the selected
2343 frame's terminal). This function always returns nil if TERMINAL
2344 is not on a tty device. */)
2346 Lisp_Object terminal
;
2348 struct terminal
*t
= get_terminal (terminal
, 1);
2350 if (t
->type
== output_termcap
)
2351 t
->display_info
.tty
->TS_enter_underline_mode
= 0;
2357 DEFUN ("suspend-tty", Fsuspend_tty
, Ssuspend_tty
, 0, 1, 0,
2358 doc
: /* Suspend the terminal device TTY.
2360 The device is restored to its default state, and Emacs ceases all
2361 access to the tty device. Frames that use the device are not deleted,
2362 but input is not read from them and if they change, their display is
2365 TTY may be a terminal id, a frame, or nil for the terminal device of
2366 the currently selected frame.
2368 This function runs `suspend-tty-functions' after suspending the
2369 device. The functions are run with one arg, the id of the suspended
2372 `suspend-tty' does nothing if it is called on a device that is already
2375 A suspended tty may be resumed by calling `resume-tty' on it. */)
2379 struct terminal
*t
= get_tty_terminal (tty
, 1);
2383 error ("Unknown tty device");
2385 f
= t
->display_info
.tty
->input
;
2389 /* First run `suspend-tty-functions' and then clean up the tty
2390 state because `suspend-tty-functions' might need to change
2392 if (!NILP (Vrun_hooks
))
2394 Lisp_Object args
[2];
2395 args
[0] = intern ("suspend-tty-functions");
2396 XSETTERMINAL (args
[1], t
);
2397 Frun_hook_with_args (2, args
);
2400 reset_sys_modes (t
->display_info
.tty
);
2403 delete_keyboard_wait_descriptor (fileno (f
));
2408 if (f
!= t
->display_info
.tty
->output
)
2409 fclose (t
->display_info
.tty
->output
);
2412 t
->display_info
.tty
->input
= 0;
2413 t
->display_info
.tty
->output
= 0;
2415 if (FRAMEP (t
->display_info
.tty
->top_frame
))
2416 FRAME_SET_VISIBLE (XFRAME (t
->display_info
.tty
->top_frame
), 0);
2420 /* Clear display hooks to prevent further output. */
2421 clear_tty_hooks (t
);
2426 DEFUN ("resume-tty", Fresume_tty
, Sresume_tty
, 0, 1, 0,
2427 doc
: /* Resume the previously suspended terminal device TTY.
2428 The terminal is opened and reinitialized. Frames that are on the
2429 suspended terminal are revived.
2431 It is an error to resume a terminal while another terminal is active
2434 This function runs `resume-tty-functions' after resuming the terminal.
2435 The functions are run with one arg, the id of the resumed terminal
2438 `resume-tty' does nothing if it is called on a device that is not
2441 TTY may be a terminal id, a frame, or nil for the terminal device of
2442 the currently selected frame. */)
2446 struct terminal
*t
= get_tty_terminal (tty
, 1);
2450 error ("Unknown tty device");
2452 if (!t
->display_info
.tty
->input
)
2454 if (get_named_tty (t
->display_info
.tty
->name
))
2455 error ("Cannot resume display while another display is active on the same device");
2458 t
->display_info
.tty
->output
= stdout
;
2459 t
->display_info
.tty
->input
= stdin
;
2461 fd
= emacs_open (t
->display_info
.tty
->name
, O_RDWR
| O_NOCTTY
, 0);
2464 error ("Can not reopen tty device %s: %s", t
->display_info
.tty
->name
, strerror (errno
));
2466 if (strcmp (t
->display_info
.tty
->name
, DEV_TTY
))
2467 dissociate_if_controlling_tty (fd
);
2469 t
->display_info
.tty
->output
= fdopen (fd
, "w+");
2470 t
->display_info
.tty
->input
= t
->display_info
.tty
->output
;
2474 add_keyboard_wait_descriptor (fd
);
2477 if (FRAMEP (t
->display_info
.tty
->top_frame
))
2479 struct frame
*f
= XFRAME (t
->display_info
.tty
->top_frame
);
2481 int old_height
= FRAME_COLS (f
);
2482 int old_width
= FRAME_LINES (f
);
2484 /* Check if terminal/window size has changed while the frame
2486 get_tty_size (fileno (t
->display_info
.tty
->input
), &width
, &height
);
2487 if (width
!= old_width
|| height
!= old_height
)
2488 change_frame_size (f
, height
, width
, 0, 0, 0);
2489 FRAME_SET_VISIBLE (XFRAME (t
->display_info
.tty
->top_frame
), 1);
2492 init_sys_modes (t
->display_info
.tty
);
2494 /* Run `resume-tty-functions'. */
2495 if (!NILP (Vrun_hooks
))
2497 Lisp_Object args
[2];
2498 args
[0] = intern ("resume-tty-functions");
2499 XSETTERMINAL (args
[1], t
);
2500 Frun_hook_with_args (2, args
);
2510 /***********************************************************************
2512 ***********************************************************************/
2516 term_mouse_moveto (int x
, int y
)
2518 /* TODO: how to set mouse position?
2521 name = (const char *) ttyname (0);
2522 fd = open (name, O_WRONLY);
2523 SOME_FUNCTION (x, y, fd);
2526 last_mouse_y = y; */
2530 term_show_mouse_face (enum draw_glyphs_face draw
)
2532 struct window
*w
= XWINDOW (mouse_face_window
);
2536 struct frame
*f
= XFRAME (w
->frame
);
2537 struct tty_display_info
*tty
= FRAME_TTY (f
);
2539 if (/* If window is in the process of being destroyed, don't bother
2541 w
->current_matrix
!= NULL
2542 /* Recognize when we are called to operate on rows that don't exist
2543 anymore. This can happen when a window is split. */
2544 && mouse_face_end_row
< w
->current_matrix
->nrows
)
2546 /* write_glyphs writes at cursor position, so we need to
2547 temporarily move cursor coordinates to the beginning of
2548 the highlight region. */
2550 /* Save current cursor co-ordinates */
2551 save_y
= curY (tty
);
2552 save_x
= curX (tty
);
2554 /* Note that mouse_face_beg_row etc. are window relative. */
2555 for (i
= mouse_face_beg_row
; i
<= mouse_face_end_row
; i
++)
2557 int start_hpos
, end_hpos
, nglyphs
;
2558 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, i
);
2560 /* Don't do anything if row doesn't have valid contents. */
2561 if (!row
->enabled_p
)
2564 /* For all but the first row, the highlight starts at column 0. */
2565 if (i
== mouse_face_beg_row
)
2566 start_hpos
= mouse_face_beg_col
;
2570 if (i
== mouse_face_end_row
)
2571 end_hpos
= mouse_face_end_col
;
2574 end_hpos
= row
->used
[TEXT_AREA
];
2575 if (draw
== DRAW_NORMAL_TEXT
)
2576 row
->fill_line_p
= 1; /* Clear to end of line */
2579 if (end_hpos
<= start_hpos
)
2581 /* Record that some glyphs of this row are displayed in
2583 row
->mouse_face_p
= draw
> 0;
2585 nglyphs
= end_hpos
- start_hpos
;
2587 if (end_hpos
>= row
->used
[TEXT_AREA
])
2588 nglyphs
= row
->used
[TEXT_AREA
] - start_hpos
;
2590 pos_y
= row
->y
+ WINDOW_TOP_EDGE_Y (w
);
2591 pos_x
= row
->used
[LEFT_MARGIN_AREA
] + start_hpos
2592 + WINDOW_LEFT_EDGE_X (w
);
2594 cursor_to (f
, pos_y
, pos_x
);
2596 if (draw
== DRAW_MOUSE_FACE
)
2598 tty_write_glyphs_with_face (f
, row
->glyphs
[TEXT_AREA
] + start_hpos
,
2599 nglyphs
, mouse_face_face_id
);
2601 else /* draw == DRAW_NORMAL_TEXT */
2602 write_glyphs (f
, row
->glyphs
[TEXT_AREA
] + start_hpos
, nglyphs
);
2604 cursor_to (f
, save_y
, save_x
);
2609 term_clear_mouse_face ()
2611 if (!NILP (mouse_face_window
))
2612 term_show_mouse_face (DRAW_NORMAL_TEXT
);
2614 mouse_face_beg_row
= mouse_face_beg_col
= -1;
2615 mouse_face_end_row
= mouse_face_end_col
= -1;
2616 mouse_face_window
= Qnil
;
2619 /* Find the glyph matrix position of buffer position POS in window W.
2620 *HPOS and *VPOS are set to the positions found. W's current glyphs
2621 must be up to date. If POS is above window start return (0, 0).
2622 If POS is after end of W, return end of last line in W.
2623 - taken from msdos.c */
2625 fast_find_position (struct window
*w
, int pos
, int *hpos
, int *vpos
)
2627 int i
, lastcol
, line_start_position
, maybe_next_line_p
= 0;
2628 int yb
= window_text_bottom_y (w
);
2629 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, 0), *best_row
= row
;
2633 if (row
->used
[TEXT_AREA
])
2634 line_start_position
= row
->glyphs
[TEXT_AREA
]->charpos
;
2636 line_start_position
= 0;
2638 if (line_start_position
> pos
)
2640 /* If the position sought is the end of the buffer,
2641 don't include the blank lines at the bottom of the window. */
2642 else if (line_start_position
== pos
2643 && pos
== BUF_ZV (XBUFFER (w
->buffer
)))
2645 maybe_next_line_p
= 1;
2648 else if (line_start_position
> 0)
2651 /* Don't overstep the last matrix row, lest we get into the
2652 never-never land... */
2653 if (row
->y
+ 1 >= yb
)
2659 /* Find the right column within BEST_ROW. */
2662 for (i
= 0; i
< row
->used
[TEXT_AREA
]; i
++)
2664 struct glyph
*glyph
= row
->glyphs
[TEXT_AREA
] + i
;
2667 charpos
= glyph
->charpos
;
2674 else if (charpos
> pos
)
2676 else if (charpos
> 0)
2680 /* If we're looking for the end of the buffer,
2681 and we didn't find it in the line we scanned,
2682 use the start of the following line. */
2683 if (maybe_next_line_p
)
2690 *hpos
= lastcol
+ 1;
2695 term_mouse_highlight (struct frame
*f
, int x
, int y
)
2697 enum window_part part
;
2702 if (NILP (Vmouse_highlight
)
2703 || !f
->glyphs_initialized_p
)
2706 /* Which window is that in? */
2707 window
= window_from_coordinates (f
, x
, y
, &part
, &x
, &y
, 0);
2709 /* Not on a window -> return. */
2710 if (!WINDOWP (window
))
2713 if (!EQ (window
, mouse_face_window
))
2714 term_clear_mouse_face ();
2716 w
= XWINDOW (window
);
2718 /* Are we in a window whose display is up to date?
2719 And verify the buffer's text has not changed. */
2720 b
= XBUFFER (w
->buffer
);
2722 && EQ (w
->window_end_valid
, w
->buffer
)
2723 && XFASTINT (w
->last_modified
) == BUF_MODIFF (b
)
2724 && XFASTINT (w
->last_overlay_modified
) == BUF_OVERLAY_MODIFF (b
))
2726 int pos
, i
, nrows
= w
->current_matrix
->nrows
;
2727 struct glyph_row
*row
;
2728 struct glyph
*glyph
;
2730 /* Find the glyph under X/Y. */
2732 if (y
>= 0 && y
< nrows
)
2734 row
= MATRIX_ROW (w
->current_matrix
, y
);
2735 /* Give up if some row before the one we are looking for is
2737 for (i
= 0; i
<= y
; i
++)
2738 if (!MATRIX_ROW (w
->current_matrix
, i
)->enabled_p
)
2740 if (i
> y
/* all rows upto and including the one at Y are enabled */
2741 && row
->displays_text_p
2742 && x
< window_box_width (w
, TEXT_AREA
))
2744 glyph
= row
->glyphs
[TEXT_AREA
];
2745 if (x
>= row
->used
[TEXT_AREA
])
2750 if (!BUFFERP (glyph
->object
))
2756 /* Clear mouse face if X/Y not over text. */
2759 term_clear_mouse_face ();
2763 if (!BUFFERP (glyph
->object
))
2765 pos
= glyph
->charpos
;
2767 /* Check for mouse-face. */
2769 extern Lisp_Object Qmouse_face
;
2770 Lisp_Object mouse_face
, overlay
, position
, *overlay_vec
;
2771 int noverlays
, obegv
, ozv
;
2772 struct buffer
*obuf
;
2774 /* If we get an out-of-range value, return now; avoid an error. */
2775 if (pos
> BUF_Z (b
))
2778 /* Make the window's buffer temporarily current for
2779 overlays_at and compute_char_face. */
2780 obuf
= current_buffer
;
2787 /* Is this char mouse-active? */
2788 XSETINT (position
, pos
);
2790 /* Put all the overlays we want in a vector in overlay_vec. */
2791 GET_OVERLAYS_AT (pos
, overlay_vec
, noverlays
, NULL
, 0);
2792 /* Sort overlays into increasing priority order. */
2793 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
2795 /* Check mouse-face highlighting. */
2796 if (!(EQ (window
, mouse_face_window
)
2797 && y
>= mouse_face_beg_row
2798 && y
<= mouse_face_end_row
2799 && (y
> mouse_face_beg_row
2800 || x
>= mouse_face_beg_col
)
2801 && (y
< mouse_face_end_row
2802 || x
< mouse_face_end_col
2803 || mouse_face_past_end
)))
2805 /* Clear the display of the old active region, if any. */
2806 term_clear_mouse_face ();
2808 /* Find the highest priority overlay that has a mouse-face
2811 for (i
= noverlays
- 1; i
>= 0; --i
)
2813 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
2814 if (!NILP (mouse_face
))
2816 overlay
= overlay_vec
[i
];
2821 /* If no overlay applies, get a text property. */
2823 mouse_face
= Fget_text_property (position
, Qmouse_face
,
2826 /* Handle the overlay case. */
2827 if (!NILP (overlay
))
2829 /* Find the range of text around this char that
2830 should be active. */
2831 Lisp_Object before
, after
;
2835 before
= Foverlay_start (overlay
);
2836 after
= Foverlay_end (overlay
);
2837 /* Record this as the current active region. */
2838 fast_find_position (w
, XFASTINT (before
),
2839 &mouse_face_beg_col
,
2840 &mouse_face_beg_row
);
2843 = !fast_find_position (w
, XFASTINT (after
),
2844 &mouse_face_end_col
,
2845 &mouse_face_end_row
);
2846 mouse_face_window
= window
;
2849 = face_at_buffer_position (w
, pos
, 0, 0,
2850 &ignore
, pos
+ 1, 1);
2852 /* Display it as active. */
2853 term_show_mouse_face (DRAW_MOUSE_FACE
);
2855 /* Handle the text property case. */
2856 else if (!NILP (mouse_face
))
2858 /* Find the range of text around this char that
2859 should be active. */
2860 Lisp_Object before
, after
, beginning
, end
;
2863 beginning
= Fmarker_position (w
->start
);
2864 XSETINT (end
, (BUF_Z (b
) - XFASTINT (w
->window_end_pos
)));
2866 = Fprevious_single_property_change (make_number (pos
+ 1),
2868 w
->buffer
, beginning
);
2870 = Fnext_single_property_change (position
, Qmouse_face
,
2873 /* Record this as the current active region. */
2874 fast_find_position (w
, XFASTINT (before
),
2875 &mouse_face_beg_col
,
2876 &mouse_face_beg_row
);
2878 = !fast_find_position (w
, XFASTINT (after
),
2879 &mouse_face_end_col
,
2880 &mouse_face_end_row
);
2881 mouse_face_window
= window
;
2884 = face_at_buffer_position (w
, pos
, 0, 0,
2885 &ignore
, pos
+ 1, 1);
2887 /* Display it as active. */
2888 term_show_mouse_face (DRAW_MOUSE_FACE
);
2892 /* Look for a `help-echo' property. */
2895 extern Lisp_Object Qhelp_echo
;
2897 /* Check overlays first. */
2899 for (i
= noverlays
- 1; i
>= 0 && NILP (help
); --i
)
2901 overlay
= overlay_vec
[i
];
2902 help
= Foverlay_get (overlay
, Qhelp_echo
);
2907 help_echo_string
= help
;
2908 help_echo_window
= window
;
2909 help_echo_object
= overlay
;
2910 help_echo_pos
= pos
;
2912 /* Try text properties. */
2913 else if (NILP (help
)
2914 && ((STRINGP (glyph
->object
)
2915 && glyph
->charpos
>= 0
2916 && glyph
->charpos
< SCHARS (glyph
->object
))
2917 || (BUFFERP (glyph
->object
)
2918 && glyph
->charpos
>= BEGV
2919 && glyph
->charpos
< ZV
)))
2921 help
= Fget_text_property (make_number (glyph
->charpos
),
2922 Qhelp_echo
, glyph
->object
);
2925 help_echo_string
= help
;
2926 help_echo_window
= window
;
2927 help_echo_object
= glyph
->object
;
2928 help_echo_pos
= glyph
->charpos
;
2935 current_buffer
= obuf
;
2941 term_mouse_movement (FRAME_PTR frame
, Gpm_Event
*event
)
2943 /* Has the mouse moved off the glyph it was on at the last sighting? */
2944 if (event
->x
!= last_mouse_x
|| event
->y
!= last_mouse_y
)
2946 frame
->mouse_moved
= 1;
2947 term_mouse_highlight (frame
, event
->x
, event
->y
);
2948 /* Remember which glyph we're now on. */
2949 last_mouse_x
= event
->x
;
2950 last_mouse_y
= event
->y
;
2956 /* Return the current position of the mouse.
2958 Set *f to the frame the mouse is in, or zero if the mouse is in no
2959 Emacs frame. If it is set to zero, all the other arguments are
2962 Set *bar_window to Qnil, and *x and *y to the column and
2963 row of the character cell the mouse is over.
2965 Set *time to the time the mouse was at the returned position.
2967 This clears mouse_moved until the next motion
2970 term_mouse_position (FRAME_PTR
*fp
, int insist
, Lisp_Object
*bar_window
,
2971 enum scroll_bar_part
*part
, Lisp_Object
*x
,
2972 Lisp_Object
*y
, unsigned long *time
)
2976 *fp
= SELECTED_FRAME ();
2977 (*fp
)->mouse_moved
= 0;
2982 XSETINT (*x
, last_mouse_x
);
2983 XSETINT (*y
, last_mouse_y
);
2984 gettimeofday(&now
, 0);
2985 *time
= (now
.tv_sec
* 1000) + (now
.tv_usec
/ 1000);
2988 /* Prepare a mouse-event in *RESULT for placement in the input queue.
2990 If the event is a button press, then note that we have grabbed
2994 term_mouse_click (struct input_event
*result
, Gpm_Event
*event
,
3000 result
->kind
= GPM_CLICK_EVENT
;
3001 for (i
= 0, j
= GPM_B_LEFT
; i
< 3; i
++, j
>>= 1 )
3003 if (event
->buttons
& j
) {
3004 result
->code
= i
; /* button number */
3008 gettimeofday(&now
, 0);
3009 result
->timestamp
= (now
.tv_sec
* 1000) + (now
.tv_usec
/ 1000);
3011 if (event
->type
& GPM_UP
)
3012 result
->modifiers
= up_modifier
;
3013 else if (event
->type
& GPM_DOWN
)
3014 result
->modifiers
= down_modifier
;
3016 result
->modifiers
= 0;
3018 if (event
->type
& GPM_SINGLE
)
3019 result
->modifiers
|= click_modifier
;
3021 if (event
->type
& GPM_DOUBLE
)
3022 result
->modifiers
|= double_modifier
;
3024 if (event
->type
& GPM_TRIPLE
)
3025 result
->modifiers
|= triple_modifier
;
3027 if (event
->type
& GPM_DRAG
)
3028 result
->modifiers
|= drag_modifier
;
3030 if (!(event
->type
& (GPM_MOVE
| GPM_DRAG
))) {
3033 if (event
->modifiers
& (1 << 0))
3034 result
->modifiers
|= shift_modifier
;
3037 if (event
->modifiers
& (1 << 2))
3038 result
->modifiers
|= ctrl_modifier
;
3040 /* 1 << KG_ALT || KG_ALTGR */
3041 if (event
->modifiers
& (1 << 3)
3042 || event
->modifiers
& (1 << 1))
3043 result
->modifiers
|= meta_modifier
;
3046 XSETINT (result
->x
, event
->x
);
3047 XSETINT (result
->y
, event
->y
);
3048 XSETFRAME (result
->frame_or_window
, f
);
3054 handle_one_term_event (struct tty_display_info
*tty
, Gpm_Event
*event
, struct input_event
* hold_quit
)
3056 struct frame
*f
= XFRAME (tty
->top_frame
);
3057 struct input_event ie
;
3065 if (event
->type
& (GPM_MOVE
| GPM_DRAG
)) {
3066 previous_help_echo_string
= help_echo_string
;
3067 help_echo_string
= Qnil
;
3069 Gpm_DrawPointer (event
->x
, event
->y
, fileno (tty
->output
));
3071 if (!term_mouse_movement (f
, event
))
3072 help_echo_string
= previous_help_echo_string
;
3074 /* If the contents of the global variable help_echo_string
3075 has changed, generate a HELP_EVENT. */
3076 if (!NILP (help_echo_string
)
3077 || !NILP (previous_help_echo_string
))
3084 term_mouse_click (&ie
, event
, f
);
3088 if (ie
.kind
!= NO_EVENT
)
3090 kbd_buffer_store_event_hold (&ie
, hold_quit
);
3095 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
3100 XSETFRAME (frame
, f
);
3104 gen_help_event (help_echo_string
, frame
, help_echo_window
,
3105 help_echo_object
, help_echo_pos
);
3112 DEFUN ("gpm-mouse-start", Fgpm_mouse_start
, Sgpm_mouse_start
,
3114 doc
: /* Open a connection to Gpm.
3115 Gpm-mouse can only be activated for one tty at a time. */)
3118 struct frame
*f
= SELECTED_FRAME ();
3119 struct tty_display_info
*tty
3120 = ((f
)->output_method
== output_termcap
3121 ? (f
)->terminal
->display_info
.tty
: NULL
);
3122 Gpm_Connect connection
;
3125 error ("Gpm-mouse only works in the GNU/Linux console");
3127 return Qnil
; /* Already activated, nothing to do. */
3129 error ("Gpm-mouse can only be activated for one tty at a time");
3131 connection
.eventMask
= ~0;
3132 connection
.defaultMask
= ~GPM_HARD
;
3133 connection
.maxMod
= ~0;
3134 connection
.minMod
= 0;
3137 if (Gpm_Open (&connection
, 0) < 0)
3138 error ("Gpm-mouse failed to connect to the gpm daemon");
3142 /* `init_sys_modes' arranges for mouse movements sent through gpm_fd
3143 to generate SIGIOs. Apparently we need to call reset_sys_modes
3144 before calling init_sys_modes. */
3145 reset_sys_modes (tty
);
3146 init_sys_modes (tty
);
3147 add_gpm_wait_descriptor (gpm_fd
);
3156 delete_gpm_wait_descriptor (gpm_fd
);
3157 while (Gpm_Close()); /* close all the stack */
3161 DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop
, Sgpm_mouse_stop
,
3163 doc
: /* Close a connection to Gpm. */)
3166 struct frame
*f
= SELECTED_FRAME ();
3167 struct tty_display_info
*tty
3168 = ((f
)->output_method
== output_termcap
3169 ? (f
)->terminal
->display_info
.tty
: NULL
);
3171 if (!tty
|| gpm_tty
!= tty
)
3172 return Qnil
; /* Not activated on this terminal, nothing to do. */
3177 #endif /* HAVE_GPM */
3180 /***********************************************************************
3182 ***********************************************************************/
3184 /* Initialize the tty-dependent part of frame F. The frame must
3185 already have its device initialized. */
3188 create_tty_output (struct frame
*f
)
3190 struct tty_output
*t
;
3192 if (! FRAME_TERMCAP_P (f
))
3195 t
= xmalloc (sizeof (struct tty_output
));
3196 bzero (t
, sizeof (struct tty_output
));
3198 t
->display_info
= FRAME_TERMINAL (f
)->display_info
.tty
;
3200 f
->output_data
.tty
= t
;
3203 /* Delete frame F's face cache, and its tty-dependent part. */
3206 tty_free_frame_resources (struct frame
*f
)
3208 if (! FRAME_TERMCAP_P (f
))
3211 if (FRAME_FACE_CACHE (f
))
3212 free_frame_faces (f
);
3214 xfree (f
->output_data
.tty
);
3218 /* Reset the hooks in TERMINAL. */
3221 clear_tty_hooks (struct terminal
*terminal
)
3224 terminal
->cursor_to_hook
= 0;
3225 terminal
->raw_cursor_to_hook
= 0;
3226 terminal
->clear_to_end_hook
= 0;
3227 terminal
->clear_frame_hook
= 0;
3228 terminal
->clear_end_of_line_hook
= 0;
3229 terminal
->ins_del_lines_hook
= 0;
3230 terminal
->insert_glyphs_hook
= 0;
3231 terminal
->write_glyphs_hook
= 0;
3232 terminal
->delete_glyphs_hook
= 0;
3233 terminal
->ring_bell_hook
= 0;
3234 terminal
->reset_terminal_modes_hook
= 0;
3235 terminal
->set_terminal_modes_hook
= 0;
3236 terminal
->update_begin_hook
= 0;
3237 terminal
->update_end_hook
= 0;
3238 terminal
->set_terminal_window_hook
= 0;
3239 terminal
->mouse_position_hook
= 0;
3240 terminal
->frame_rehighlight_hook
= 0;
3241 terminal
->frame_raise_lower_hook
= 0;
3242 terminal
->fullscreen_hook
= 0;
3243 terminal
->set_vertical_scroll_bar_hook
= 0;
3244 terminal
->condemn_scroll_bars_hook
= 0;
3245 terminal
->redeem_scroll_bar_hook
= 0;
3246 terminal
->judge_scroll_bars_hook
= 0;
3247 terminal
->read_socket_hook
= 0;
3248 terminal
->frame_up_to_date_hook
= 0;
3250 /* Leave these two set, or suspended frames are not deleted
3252 terminal
->delete_frame_hook
= &tty_free_frame_resources
;
3253 terminal
->delete_terminal_hook
= &delete_tty
;
3256 /* Initialize hooks in TERMINAL with the values needed for a tty. */
3259 set_tty_hooks (struct terminal
*terminal
)
3261 terminal
->rif
= 0; /* ttys don't support window-based redisplay. */
3263 terminal
->cursor_to_hook
= &tty_cursor_to
;
3264 terminal
->raw_cursor_to_hook
= &tty_raw_cursor_to
;
3266 terminal
->clear_to_end_hook
= &tty_clear_to_end
;
3267 terminal
->clear_frame_hook
= &tty_clear_frame
;
3268 terminal
->clear_end_of_line_hook
= &tty_clear_end_of_line
;
3270 terminal
->ins_del_lines_hook
= &tty_ins_del_lines
;
3272 terminal
->insert_glyphs_hook
= &tty_insert_glyphs
;
3273 terminal
->write_glyphs_hook
= &tty_write_glyphs
;
3274 terminal
->delete_glyphs_hook
= &tty_delete_glyphs
;
3276 terminal
->ring_bell_hook
= &tty_ring_bell
;
3278 terminal
->reset_terminal_modes_hook
= &tty_reset_terminal_modes
;
3279 terminal
->set_terminal_modes_hook
= &tty_set_terminal_modes
;
3280 terminal
->update_begin_hook
= 0; /* Not needed. */
3281 terminal
->update_end_hook
= &tty_update_end
;
3282 terminal
->set_terminal_window_hook
= &tty_set_terminal_window
;
3284 terminal
->mouse_position_hook
= 0; /* Not needed. */
3285 terminal
->frame_rehighlight_hook
= 0; /* Not needed. */
3286 terminal
->frame_raise_lower_hook
= 0; /* Not needed. */
3288 terminal
->set_vertical_scroll_bar_hook
= 0; /* Not needed. */
3289 terminal
->condemn_scroll_bars_hook
= 0; /* Not needed. */
3290 terminal
->redeem_scroll_bar_hook
= 0; /* Not needed. */
3291 terminal
->judge_scroll_bars_hook
= 0; /* Not needed. */
3293 terminal
->read_socket_hook
= &tty_read_avail_input
; /* keyboard.c */
3294 terminal
->frame_up_to_date_hook
= 0; /* Not needed. */
3296 terminal
->delete_frame_hook
= &tty_free_frame_resources
;
3297 terminal
->delete_terminal_hook
= &delete_tty
;
3300 /* Drop the controlling terminal if fd is the same device. */
3302 dissociate_if_controlling_tty (int fd
)
3306 EMACS_GET_TTY_PGRP (fd
, &pgid
); /* If tcgetpgrp succeeds, fd is the ctty. */
3309 #if defined (USG) && !defined (BSD_PGRPS)
3311 no_controlling_tty
= 1;
3312 #elif defined (CYGWIN)
3314 no_controlling_tty
= 1;
3316 #ifdef TIOCNOTTY /* Try BSD ioctls. */
3317 sigblock (sigmask (SIGTTOU
));
3318 fd
= emacs_open (DEV_TTY
, O_RDWR
, 0);
3319 if (fd
!= -1 && ioctl (fd
, TIOCNOTTY
, 0) != -1)
3321 no_controlling_tty
= 1;
3325 sigunblock (sigmask (SIGTTOU
));
3327 /* Unknown system. */
3329 #endif /* ! TIOCNOTTY */
3332 #endif /* !DOS_NT */
3335 static void maybe_fatal();
3337 /* Create a termcap display on the tty device with the given name and
3340 If NAME is NULL, then use the controlling tty, i.e., "/dev/tty".
3341 Otherwise NAME should be a path to the tty device file,
3344 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
3346 If MUST_SUCCEED is true, then all errors are fatal. */
3349 init_tty (char *name
, char *terminal_type
, int must_succeed
)
3352 char **address
= &area
;
3353 int buffer_size
= 4096;
3354 register char *p
= NULL
;
3356 struct tty_display_info
*tty
= NULL
;
3357 struct terminal
*terminal
= NULL
;
3358 int ctty
= 0; /* 1 if asked to open controlling tty. */
3361 maybe_fatal (must_succeed
, 0,
3362 "Unknown terminal type",
3363 "Unknown terminal type");
3367 if (!strcmp (name
, DEV_TTY
))
3370 /* If we already have a terminal on the given device, use that. If
3371 all such terminals are suspended, create a new one instead. */
3372 /* XXX Perhaps this should be made explicit by having init_tty
3373 always create a new terminal and separating terminal and frame
3374 creation on Lisp level. */
3375 terminal
= get_named_tty (name
);
3379 terminal
= create_terminal ();
3382 maybe_fatal (1, 0, "Attempt to create another terminal %s", "",
3385 tty
= &the_only_display_info
;
3387 tty
= (struct tty_display_info
*) xmalloc (sizeof (struct tty_display_info
));
3389 bzero (tty
, sizeof (struct tty_display_info
));
3390 tty
->next
= tty_list
;
3393 terminal
->type
= output_termcap
;
3394 terminal
->display_info
.tty
= tty
;
3395 tty
->terminal
= terminal
;
3397 tty
->Wcm
= (struct cm
*) xmalloc (sizeof (struct cm
));
3401 set_tty_hooks (terminal
);
3407 #ifdef O_IGNORE_CTTY
3409 /* Open the terminal device. Don't recognize it as our
3410 controlling terminal, and don't make it the controlling tty
3411 if we don't have one at the moment. */
3412 fd
= emacs_open (name
, O_RDWR
| O_IGNORE_CTTY
| O_NOCTTY
, 0);
3415 /* Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
3416 defined on Hurd. On other systems, we need to explicitly
3417 dissociate ourselves from the controlling tty when we want to
3418 open a frame on the same terminal. */
3419 fd
= emacs_open (name
, O_RDWR
| O_NOCTTY
, 0);
3420 #endif /* O_IGNORE_CTTY */
3422 tty
->name
= xstrdup (name
);
3423 terminal
->name
= xstrdup (name
);
3426 maybe_fatal (must_succeed
, terminal
,
3427 "Could not open file: %s",
3428 "Could not open file: %s",
3433 maybe_fatal (must_succeed
, terminal
,
3434 "Not a tty device: %s",
3435 "Not a tty device: %s",
3439 #ifndef O_IGNORE_CTTY
3441 dissociate_if_controlling_tty (fd
);
3444 file
= fdopen (fd
, "w+");
3449 tty
->type
= xstrdup (terminal_type
);
3452 add_keyboard_wait_descriptor (fileno (tty
->input
));
3455 #endif /* !DOS_NT */
3457 encode_terminal_src_size
= 0;
3458 encode_terminal_dst_size
= 0;
3461 terminal
->mouse_position_hook
= term_mouse_position
;
3462 mouse_face_window
= Qnil
;
3467 initialize_w32_display (terminal
);
3469 if (strcmp (terminal_type
, "internal") == 0)
3470 terminal
->type
= output_msdos_raw
;
3471 initialize_msdos_display (terminal
);
3473 tty
->output
= stdout
;
3475 /* The following two are inaccessible from w32console.c. */
3476 terminal
->delete_frame_hook
= &tty_free_frame_resources
;
3477 terminal
->delete_terminal_hook
= &delete_tty
;
3479 tty
->name
= xstrdup (name
);
3480 terminal
->name
= xstrdup (name
);
3481 tty
->type
= xstrdup (terminal_type
);
3484 add_keyboard_wait_descriptor (0);
3491 struct frame
*f
= XFRAME (selected_frame
);
3493 FrameRows (tty
) = FRAME_LINES (f
);
3494 FrameCols (tty
) = FRAME_COLS (f
);
3495 tty
->specified_window
= FRAME_LINES (f
);
3497 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 0;
3498 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_none
;
3503 get_tty_size (fileno (tty
->input
), &width
, &height
);
3504 FrameCols (tty
) = width
;
3505 FrameRows (tty
) = height
;
3508 tty
->delete_in_insert_mode
= 1;
3511 terminal
->scroll_region_ok
= 0;
3513 /* Seems to insert lines when it's not supposed to, messing up the
3514 display. In doing a trace, it didn't seem to be called much, so I
3515 don't think we're losing anything by turning it off. */
3516 terminal
->line_ins_del_ok
= 0;
3518 terminal
->char_ins_del_ok
= 1;
3521 terminal
->char_ins_del_ok
= 0;
3522 init_baud_rate (fileno (tty
->input
));
3525 tty
->TN_max_colors
= 16; /* Required to be non-zero for tty-display-color-p */
3527 #else /* not DOS_NT */
3531 tty
->termcap_term_buffer
= (char *) xmalloc (buffer_size
);
3533 /* On some systems, tgetent tries to access the controlling
3535 sigblock (sigmask (SIGTTOU
));
3536 status
= tgetent (tty
->termcap_term_buffer
, terminal_type
);
3537 sigunblock (sigmask (SIGTTOU
));
3542 maybe_fatal (must_succeed
, terminal
,
3543 "Cannot open terminfo database file",
3544 "Cannot open terminfo database file");
3546 maybe_fatal (must_succeed
, terminal
,
3547 "Cannot open termcap database file",
3548 "Cannot open termcap database file");
3554 maybe_fatal (must_succeed
, terminal
,
3555 "Terminal type %s is not defined",
3556 "Terminal type %s is not defined.\n\
3557 If that is not the actual type of terminal you have,\n\
3558 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3559 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3560 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3563 maybe_fatal (must_succeed
, terminal
,
3564 "Terminal type %s is not defined",
3565 "Terminal type %s is not defined.\n\
3566 If that is not the actual type of terminal you have,\n\
3567 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3568 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3569 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3575 if (strlen (tty
->termcap_term_buffer
) >= buffer_size
)
3577 buffer_size
= strlen (tty
->termcap_term_buffer
);
3579 tty
->termcap_strings_buffer
= area
= (char *) xmalloc (buffer_size
);
3580 tty
->TS_ins_line
= tgetstr ("al", address
);
3581 tty
->TS_ins_multi_lines
= tgetstr ("AL", address
);
3582 tty
->TS_bell
= tgetstr ("bl", address
);
3583 BackTab (tty
) = tgetstr ("bt", address
);
3584 tty
->TS_clr_to_bottom
= tgetstr ("cd", address
);
3585 tty
->TS_clr_line
= tgetstr ("ce", address
);
3586 tty
->TS_clr_frame
= tgetstr ("cl", address
);
3587 ColPosition (tty
) = NULL
; /* tgetstr ("ch", address); */
3588 AbsPosition (tty
) = tgetstr ("cm", address
);
3589 CR (tty
) = tgetstr ("cr", address
);
3590 tty
->TS_set_scroll_region
= tgetstr ("cs", address
);
3591 tty
->TS_set_scroll_region_1
= tgetstr ("cS", address
);
3592 RowPosition (tty
) = tgetstr ("cv", address
);
3593 tty
->TS_del_char
= tgetstr ("dc", address
);
3594 tty
->TS_del_multi_chars
= tgetstr ("DC", address
);
3595 tty
->TS_del_line
= tgetstr ("dl", address
);
3596 tty
->TS_del_multi_lines
= tgetstr ("DL", address
);
3597 tty
->TS_delete_mode
= tgetstr ("dm", address
);
3598 tty
->TS_end_delete_mode
= tgetstr ("ed", address
);
3599 tty
->TS_end_insert_mode
= tgetstr ("ei", address
);
3600 Home (tty
) = tgetstr ("ho", address
);
3601 tty
->TS_ins_char
= tgetstr ("ic", address
);
3602 tty
->TS_ins_multi_chars
= tgetstr ("IC", address
);
3603 tty
->TS_insert_mode
= tgetstr ("im", address
);
3604 tty
->TS_pad_inserted_char
= tgetstr ("ip", address
);
3605 tty
->TS_end_keypad_mode
= tgetstr ("ke", address
);
3606 tty
->TS_keypad_mode
= tgetstr ("ks", address
);
3607 LastLine (tty
) = tgetstr ("ll", address
);
3608 Right (tty
) = tgetstr ("nd", address
);
3609 Down (tty
) = tgetstr ("do", address
);
3611 Down (tty
) = tgetstr ("nl", address
); /* Obsolete name for "do" */
3612 if (tgetflag ("bs"))
3613 Left (tty
) = "\b"; /* can't possibly be longer! */
3614 else /* (Actually, "bs" is obsolete...) */
3615 Left (tty
) = tgetstr ("le", address
);
3617 Left (tty
) = tgetstr ("bc", address
); /* Obsolete name for "le" */
3618 tty
->TS_pad_char
= tgetstr ("pc", address
);
3619 tty
->TS_repeat
= tgetstr ("rp", address
);
3620 tty
->TS_end_standout_mode
= tgetstr ("se", address
);
3621 tty
->TS_fwd_scroll
= tgetstr ("sf", address
);
3622 tty
->TS_standout_mode
= tgetstr ("so", address
);
3623 tty
->TS_rev_scroll
= tgetstr ("sr", address
);
3624 tty
->Wcm
->cm_tab
= tgetstr ("ta", address
);
3625 tty
->TS_end_termcap_modes
= tgetstr ("te", address
);
3626 tty
->TS_termcap_modes
= tgetstr ("ti", address
);
3627 Up (tty
) = tgetstr ("up", address
);
3628 tty
->TS_visible_bell
= tgetstr ("vb", address
);
3629 tty
->TS_cursor_normal
= tgetstr ("ve", address
);
3630 tty
->TS_cursor_visible
= tgetstr ("vs", address
);
3631 tty
->TS_cursor_invisible
= tgetstr ("vi", address
);
3632 tty
->TS_set_window
= tgetstr ("wi", address
);
3634 tty
->TS_enter_underline_mode
= tgetstr ("us", address
);
3635 tty
->TS_exit_underline_mode
= tgetstr ("ue", address
);
3636 tty
->TS_enter_bold_mode
= tgetstr ("md", address
);
3637 tty
->TS_enter_dim_mode
= tgetstr ("mh", address
);
3638 tty
->TS_enter_blink_mode
= tgetstr ("mb", address
);
3639 tty
->TS_enter_reverse_mode
= tgetstr ("mr", address
);
3640 tty
->TS_enter_alt_charset_mode
= tgetstr ("as", address
);
3641 tty
->TS_exit_alt_charset_mode
= tgetstr ("ae", address
);
3642 tty
->TS_exit_attribute_mode
= tgetstr ("me", address
);
3644 MultiUp (tty
) = tgetstr ("UP", address
);
3645 MultiDown (tty
) = tgetstr ("DO", address
);
3646 MultiLeft (tty
) = tgetstr ("LE", address
);
3647 MultiRight (tty
) = tgetstr ("RI", address
);
3649 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
3650 color because we can't switch back to the default foreground and
3652 tty
->TS_orig_pair
= tgetstr ("op", address
);
3653 if (tty
->TS_orig_pair
)
3655 tty
->TS_set_foreground
= tgetstr ("AF", address
);
3656 tty
->TS_set_background
= tgetstr ("AB", address
);
3657 if (!tty
->TS_set_foreground
)
3660 tty
->TS_set_foreground
= tgetstr ("Sf", address
);
3661 tty
->TS_set_background
= tgetstr ("Sb", address
);
3664 tty
->TN_max_colors
= tgetnum ("Co");
3665 tty
->TN_max_pairs
= tgetnum ("pa");
3667 tty
->TN_no_color_video
= tgetnum ("NC");
3668 if (tty
->TN_no_color_video
== -1)
3669 tty
->TN_no_color_video
= 0;
3672 tty_default_color_capabilities (tty
, 1);
3674 MagicWrap (tty
) = tgetflag ("xn");
3675 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
3676 the former flag imply the latter. */
3677 AutoWrap (tty
) = MagicWrap (tty
) || tgetflag ("am");
3678 terminal
->memory_below_frame
= tgetflag ("db");
3679 tty
->TF_hazeltine
= tgetflag ("hz");
3680 terminal
->must_write_spaces
= tgetflag ("in");
3681 tty
->meta_key
= tgetflag ("km") || tgetflag ("MT");
3682 tty
->TF_insmode_motion
= tgetflag ("mi");
3683 tty
->TF_standout_motion
= tgetflag ("ms");
3684 tty
->TF_underscore
= tgetflag ("ul");
3685 tty
->TF_teleray
= tgetflag ("xt");
3687 #endif /* !DOS_NT */
3688 terminal
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
3689 init_kboard (terminal
->kboard
);
3690 terminal
->kboard
->Vwindow_system
= Qnil
;
3691 terminal
->kboard
->next_kboard
= all_kboards
;
3692 all_kboards
= terminal
->kboard
;
3693 terminal
->kboard
->reference_count
++;
3694 /* Don't let the initial kboard remain current longer than necessary.
3695 That would cause problems if a file loaded on startup tries to
3696 prompt in the mini-buffer. */
3697 if (current_kboard
== initial_kboard
)
3698 current_kboard
= terminal
->kboard
;
3700 term_get_fkeys (address
, terminal
->kboard
);
3702 /* Get frame size from system, or else from termcap. */
3705 get_tty_size (fileno (tty
->input
), &width
, &height
);
3706 FrameCols (tty
) = width
;
3707 FrameRows (tty
) = height
;
3710 if (FrameCols (tty
) <= 0)
3711 FrameCols (tty
) = tgetnum ("co");
3712 if (FrameRows (tty
) <= 0)
3713 FrameRows (tty
) = tgetnum ("li");
3715 if (FrameRows (tty
) < 3 || FrameCols (tty
) < 3)
3716 maybe_fatal (must_succeed
, terminal
,
3717 "Screen size %dx%d is too small"
3718 "Screen size %dx%d is too small",
3719 FrameCols (tty
), FrameRows (tty
));
3721 #if 0 /* This is not used anywhere. */
3722 tty
->terminal
->min_padding_speed
= tgetnum ("pb");
3725 TabWidth (tty
) = tgetnum ("tw");
3728 tty
->TS_bell
= "\07";
3730 if (!tty
->TS_fwd_scroll
)
3731 tty
->TS_fwd_scroll
= Down (tty
);
3733 PC
= tty
->TS_pad_char
? *tty
->TS_pad_char
: 0;
3735 if (TabWidth (tty
) < 0)
3738 /* Turned off since /etc/termcap seems to have :ta= for most terminals
3739 and newer termcap doc does not seem to say there is a default.
3740 if (!tty->Wcm->cm_tab)
3741 tty->Wcm->cm_tab = "\t";
3744 /* We don't support standout modes that use `magic cookies', so
3745 turn off any that do. */
3746 if (tty
->TS_standout_mode
&& tgetnum ("sg") >= 0)
3748 tty
->TS_standout_mode
= 0;
3749 tty
->TS_end_standout_mode
= 0;
3751 if (tty
->TS_enter_underline_mode
&& tgetnum ("ug") >= 0)
3753 tty
->TS_enter_underline_mode
= 0;
3754 tty
->TS_exit_underline_mode
= 0;
3757 /* If there's no standout mode, try to use underlining instead. */
3758 if (tty
->TS_standout_mode
== 0)
3760 tty
->TS_standout_mode
= tty
->TS_enter_underline_mode
;
3761 tty
->TS_end_standout_mode
= tty
->TS_exit_underline_mode
;
3764 /* If no `se' string, try using a `me' string instead.
3765 If that fails, we can't use standout mode at all. */
3766 if (tty
->TS_end_standout_mode
== 0)
3768 char *s
= tgetstr ("me", address
);
3770 tty
->TS_end_standout_mode
= s
;
3772 tty
->TS_standout_mode
= 0;
3775 if (tty
->TF_teleray
)
3777 tty
->Wcm
->cm_tab
= 0;
3778 /* We can't support standout mode, because it uses magic cookies. */
3779 tty
->TS_standout_mode
= 0;
3780 /* But that means we cannot rely on ^M to go to column zero! */
3782 /* LF can't be trusted either -- can alter hpos */
3783 /* if move at column 0 thru a line with TS_standout_mode */
3787 /* Special handling for certain terminal types known to need it */
3789 if (!strcmp (terminal_type
, "supdup"))
3791 terminal
->memory_below_frame
= 1;
3792 tty
->Wcm
->cm_losewrap
= 1;
3794 if (!strncmp (terminal_type
, "c10", 3)
3795 || !strcmp (terminal_type
, "perq"))
3797 /* Supply a makeshift :wi string.
3798 This string is not valid in general since it works only
3799 for windows starting at the upper left corner;
3800 but that is all Emacs uses.
3802 This string works only if the frame is using
3803 the top of the video memory, because addressing is memory-relative.
3804 So first check the :ti string to see if that is true.
3806 It would be simpler if the :wi string could go in the termcap
3807 entry, but it can't because it is not fully valid.
3808 If it were in the termcap entry, it would confuse other programs. */
3809 if (!tty
->TS_set_window
)
3811 p
= tty
->TS_termcap_modes
;
3812 while (*p
&& strcmp (p
, "\033v "))
3815 tty
->TS_set_window
= "\033v%C %C %C %C ";
3817 /* Termcap entry often fails to have :in: flag */
3818 terminal
->must_write_spaces
= 1;
3819 /* :ti string typically fails to have \E^G! in it */
3820 /* This limits scope of insert-char to one line. */
3821 strcpy (area
, tty
->TS_termcap_modes
);
3822 strcat (area
, "\033\007!");
3823 tty
->TS_termcap_modes
= area
;
3824 area
+= strlen (area
) + 1;
3825 p
= AbsPosition (tty
);
3826 /* Change all %+ parameters to %C, to handle
3827 values above 96 correctly for the C100. */
3830 if (p
[0] == '%' && p
[1] == '+')
3836 tty
->specified_window
= FrameRows (tty
);
3838 if (Wcm_init (tty
) == -1) /* can't do cursor motion */
3840 maybe_fatal (must_succeed
, terminal
,
3841 "Terminal type \"%s\" is not powerful enough to run Emacs",
3843 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3844 It lacks the ability to position the cursor.\n\
3845 If that is not the actual type of terminal you have,\n\
3846 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3847 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3848 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3849 # else /* TERMCAP */
3850 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3851 It lacks the ability to position the cursor.\n\
3852 If that is not the actual type of terminal you have,\n\
3853 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3854 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3855 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3856 # endif /* TERMINFO */
3860 if (FrameRows (tty
) <= 0 || FrameCols (tty
) <= 0)
3861 maybe_fatal (must_succeed
, terminal
,
3862 "Could not determine the frame size",
3863 "Could not determine the frame size");
3865 tty
->delete_in_insert_mode
3866 = tty
->TS_delete_mode
&& tty
->TS_insert_mode
3867 && !strcmp (tty
->TS_delete_mode
, tty
->TS_insert_mode
);
3869 tty
->se_is_so
= (tty
->TS_standout_mode
3870 && tty
->TS_end_standout_mode
3871 && !strcmp (tty
->TS_standout_mode
, tty
->TS_end_standout_mode
));
3873 UseTabs (tty
) = tabs_safe_p (fileno (tty
->input
)) && TabWidth (tty
) == 8;
3875 terminal
->scroll_region_ok
3877 && (tty
->TS_set_window
|| tty
->TS_set_scroll_region
|| tty
->TS_set_scroll_region_1
));
3879 terminal
->line_ins_del_ok
3880 = (((tty
->TS_ins_line
|| tty
->TS_ins_multi_lines
)
3881 && (tty
->TS_del_line
|| tty
->TS_del_multi_lines
))
3882 || (terminal
->scroll_region_ok
3883 && tty
->TS_fwd_scroll
&& tty
->TS_rev_scroll
));
3885 terminal
->char_ins_del_ok
3886 = ((tty
->TS_ins_char
|| tty
->TS_insert_mode
3887 || tty
->TS_pad_inserted_char
|| tty
->TS_ins_multi_chars
)
3888 && (tty
->TS_del_char
|| tty
->TS_del_multi_chars
));
3890 terminal
->fast_clear_end_of_line
= tty
->TS_clr_line
!= 0;
3892 init_baud_rate (fileno (tty
->input
));
3894 #endif /* not DOS_NT */
3896 /* Init system terminal modes (RAW or CBREAK, etc.). */
3897 init_sys_modes (tty
);
3902 /* Auxiliary error-handling function for init_tty.
3903 Delete TERMINAL, then call error or fatal with str1 or str2,
3904 respectively, according to MUST_SUCCEED. */
3907 maybe_fatal (must_succeed
, terminal
, str1
, str2
, arg1
, arg2
)
3909 struct terminal
*terminal
;
3910 char *str1
, *str2
, *arg1
, *arg2
;
3913 delete_tty (terminal
);
3916 fatal (str2
, arg1
, arg2
);
3918 error (str1
, arg1
, arg2
);
3924 fatal (const char *str
, ...)
3928 fprintf (stderr
, "emacs: ");
3929 vfprintf (stderr
, str
, ap
);
3937 /* Delete the given tty terminal, closing all frames on it. */
3940 delete_tty (struct terminal
*terminal
)
3942 struct tty_display_info
*tty
;
3943 Lisp_Object tail
, frame
;
3946 /* Protect against recursive calls. delete_frame in
3947 delete_terminal calls us back when it deletes our last frame. */
3948 if (!terminal
->name
)
3951 if (terminal
->type
!= output_termcap
)
3954 tty
= terminal
->display_info
.tty
;
3957 FOR_EACH_FRAME (tail
, frame
)
3959 struct frame
*f
= XFRAME (frame
);
3960 if (FRAME_LIVE_P (f
) && (!FRAME_TERMCAP_P (f
) || FRAME_TTY (f
) != tty
))
3967 error ("Attempt to delete the sole terminal device with live frames");
3969 if (tty
== tty_list
)
3970 tty_list
= tty
->next
;
3973 struct tty_display_info
*p
;
3974 for (p
= tty_list
; p
&& p
->next
!= tty
; p
= p
->next
)
3978 /* This should not happen. */
3981 p
->next
= tty
->next
;
3985 /* reset_sys_modes needs a valid device, so this call needs to be
3986 before delete_terminal. */
3987 reset_sys_modes (tty
);
3989 delete_terminal (terminal
);
3997 delete_keyboard_wait_descriptor (fileno (tty
->input
));
3999 if (tty
->input
!= stdin
)
4000 fclose (tty
->input
);
4002 if (tty
->output
&& tty
->output
!= stdout
&& tty
->output
!= tty
->input
)
4003 fclose (tty
->output
);
4004 if (tty
->termscript
)
4005 fclose (tty
->termscript
);
4007 xfree (tty
->old_tty
);
4009 if (tty
->termcap_strings_buffer
)
4010 xfree (tty
->termcap_strings_buffer
);
4011 if (tty
->termcap_term_buffer
)
4012 xfree (tty
->termcap_term_buffer
);
4014 bzero (tty
, sizeof (struct tty_display_info
));
4020 /* Mark the pointers in the tty_display_info objects.
4021 Called by the Fgarbage_collector. */
4026 struct tty_display_info
*tty
;
4028 for (tty
= tty_list
; tty
; tty
= tty
->next
)
4029 mark_object (tty
->top_frame
);
4037 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo
,
4038 doc
: /* Non-nil means the system uses terminfo rather than termcap.
4039 This variable can be used by terminal emulator packages. */);
4041 system_uses_terminfo
= 1;
4043 system_uses_terminfo
= 0;
4046 DEFVAR_LISP ("suspend-tty-functions", &Vsuspend_tty_functions
,
4047 doc
: /* Functions to be run after suspending a tty.
4048 The functions are run with one argument, the terminal id to be suspended.
4049 See `suspend-tty'. */);
4050 Vsuspend_tty_functions
= Qnil
;
4053 DEFVAR_LISP ("resume-tty-functions", &Vresume_tty_functions
,
4054 doc
: /* Functions to be run after resuming a tty.
4055 The functions are run with one argument, the terminal id that was revived.
4056 See `resume-tty'. */);
4057 Vresume_tty_functions
= Qnil
;
4059 DEFVAR_BOOL ("visible-cursor", &visible_cursor
,
4060 doc
: /* Non-nil means to make the cursor very visible.
4061 This only has an effect when running in a text terminal.
4062 What means \"very visible\" is up to your terminal. It may make the cursor
4063 bigger, or it may make it blink, or it may do nothing at all. */);
4066 defsubr (&Stty_display_color_p
);
4067 defsubr (&Stty_display_color_cells
);
4068 defsubr (&Stty_no_underline
);
4069 defsubr (&Stty_type
);
4070 defsubr (&Scontrolling_tty_p
);
4071 defsubr (&Ssuspend_tty
);
4072 defsubr (&Sresume_tty
);
4074 defsubr (&Sgpm_mouse_start
);
4075 defsubr (&Sgpm_mouse_stop
);
4077 staticpro (&mouse_face_window
);
4078 #endif /* HAVE_GPM */
4081 default_orig_pair
= NULL
;
4082 default_set_foreground
= NULL
;
4083 default_set_background
= NULL
;
4084 #endif /* !DOS_NT */
4086 encode_terminal_src
= NULL
;
4087 encode_terminal_dst
= NULL
;
4092 /* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193
4093 (do not change this comment) */