* term.el (term-default-fg-color, term-default-bg-color): Fix custom type.
[emacs.git] / src / term.c
blobb09aad13dbbdc032f00e21ff94739d2f716650cb
1 /* Terminal control module for terminals described by TERMCAP
2 Copyright (C) 1985-1987, 1993-1995, 1998, 2000-2013 Free Software
3 Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20 /* New redisplay, TTY faces by Gerd Moellmann <gerd@gnu.org>. */
22 #include <config.h>
23 #include <stdio.h>
24 #include <errno.h>
25 #include <sys/file.h>
26 #include <sys/time.h>
27 #include <unistd.h>
29 #include "lisp.h"
30 #include "termchar.h"
31 #include "tparam.h"
32 #include "character.h"
33 #include "buffer.h"
34 #include "charset.h"
35 #include "coding.h"
36 #include "composite.h"
37 #include "keyboard.h"
38 #include "frame.h"
39 #include "disptab.h"
40 #include "termhooks.h"
41 #include "dispextern.h"
42 #include "window.h"
43 #include "keymap.h"
44 #include "blockinput.h"
45 #include "syssignal.h"
46 #include "systty.h"
47 #include "intervals.h"
48 #ifdef MSDOS
49 #include "msdos.h"
50 static int been_here = -1;
51 #endif
53 #include "cm.h"
54 #ifdef HAVE_X_WINDOWS
55 #include "xterm.h"
56 #endif
58 #ifndef O_RDWR
59 #define O_RDWR 2
60 #endif
62 #ifndef O_NOCTTY
63 #define O_NOCTTY 0
64 #endif
66 /* The name of the default console device. */
67 #ifdef WINDOWSNT
68 #define DEV_TTY "CONOUT$"
69 #include "w32term.h"
70 #else
71 #define DEV_TTY "/dev/tty"
72 #endif
74 static void tty_set_scroll_region (struct frame *f, int start, int stop);
75 static void turn_on_face (struct frame *, int face_id);
76 static void turn_off_face (struct frame *, int face_id);
77 static void tty_turn_off_highlight (struct tty_display_info *);
78 static void tty_show_cursor (struct tty_display_info *);
79 static void tty_hide_cursor (struct tty_display_info *);
80 static void tty_background_highlight (struct tty_display_info *tty);
81 static struct terminal *get_tty_terminal (Lisp_Object, int);
82 static void clear_tty_hooks (struct terminal *terminal);
83 static void set_tty_hooks (struct terminal *terminal);
84 static void dissociate_if_controlling_tty (int fd);
85 static void delete_tty (struct terminal *);
86 static _Noreturn void maybe_fatal (int must_succeed, struct terminal *terminal,
87 const char *str1, const char *str2, ...)
88 ATTRIBUTE_FORMAT_PRINTF (3, 5) ATTRIBUTE_FORMAT_PRINTF (4, 5);
89 static _Noreturn void vfatal (const char *str, va_list ap)
90 ATTRIBUTE_FORMAT_PRINTF (1, 0);
93 #define OUTPUT(tty, a) \
94 emacs_tputs ((tty), a, \
95 (int) (FRAME_LINES (XFRAME (selected_frame)) \
96 - curY (tty)), \
97 cmputc)
99 #define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
100 #define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
102 #define OUTPUT_IF(tty, a) \
103 do { \
104 if (a) \
105 OUTPUT (tty, a); \
106 } while (0)
108 #define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
110 /* Display space properties */
112 /* Chain of all tty device parameters. */
113 struct tty_display_info *tty_list;
115 /* Meaning of bits in no_color_video. Each bit set means that the
116 corresponding attribute cannot be combined with colors. */
118 enum no_color_bit
120 NC_STANDOUT = 1 << 0,
121 NC_UNDERLINE = 1 << 1,
122 NC_REVERSE = 1 << 2,
123 NC_ITALIC = 1 << 3,
124 NC_DIM = 1 << 4,
125 NC_BOLD = 1 << 5,
126 NC_INVIS = 1 << 6,
127 NC_PROTECT = 1 << 7
130 /* internal state */
132 /* The largest frame width in any call to calculate_costs. */
134 static int max_frame_cols;
136 /* Non-zero if we have dropped our controlling tty and therefore
137 should not open a frame on stdout. */
138 static int no_controlling_tty;
142 #ifdef HAVE_GPM
143 #include <sys/fcntl.h>
145 /* The device for which we have enabled gpm support (or NULL). */
146 struct tty_display_info *gpm_tty = NULL;
148 /* Last recorded mouse coordinates. */
149 static int last_mouse_x, last_mouse_y;
150 #endif /* HAVE_GPM */
152 /* Ring the bell on a tty. */
154 static void
155 tty_ring_bell (struct frame *f)
157 struct tty_display_info *tty = FRAME_TTY (f);
159 if (tty->output)
161 OUTPUT (tty, (tty->TS_visible_bell && visible_bell
162 ? tty->TS_visible_bell
163 : tty->TS_bell));
164 fflush (tty->output);
168 /* Set up termcap modes for Emacs. */
170 static void
171 tty_set_terminal_modes (struct terminal *terminal)
173 struct tty_display_info *tty = terminal->display_info.tty;
175 if (tty->output)
177 if (tty->TS_termcap_modes)
178 OUTPUT (tty, tty->TS_termcap_modes);
179 else
181 /* Output enough newlines to scroll all the old screen contents
182 off the screen, so it won't be overwritten and lost. */
183 int i;
184 current_tty = tty;
185 for (i = 0; i < FRAME_LINES (XFRAME (selected_frame)); i++)
186 cmputc ('\n');
189 OUTPUT_IF (tty, visible_cursor ? tty->TS_cursor_visible : tty->TS_cursor_normal);
190 OUTPUT_IF (tty, tty->TS_keypad_mode);
191 losecursor (tty);
192 fflush (tty->output);
196 /* Reset termcap modes before exiting Emacs. */
198 static void
199 tty_reset_terminal_modes (struct terminal *terminal)
201 struct tty_display_info *tty = terminal->display_info.tty;
203 if (tty->output)
205 tty_turn_off_highlight (tty);
206 tty_turn_off_insert (tty);
207 OUTPUT_IF (tty, tty->TS_end_keypad_mode);
208 OUTPUT_IF (tty, tty->TS_cursor_normal);
209 OUTPUT_IF (tty, tty->TS_end_termcap_modes);
210 OUTPUT_IF (tty, tty->TS_orig_pair);
211 /* Output raw CR so kernel can track the cursor hpos. */
212 current_tty = tty;
213 cmputc ('\r');
214 fflush (tty->output);
218 /* Flag the end of a display update on a termcap terminal. */
220 static void
221 tty_update_end (struct frame *f)
223 struct tty_display_info *tty = FRAME_TTY (f);
225 if (!XWINDOW (selected_window)->cursor_off_p)
226 tty_show_cursor (tty);
227 tty_turn_off_insert (tty);
228 tty_background_highlight (tty);
231 /* The implementation of set_terminal_window for termcap frames. */
233 static void
234 tty_set_terminal_window (struct frame *f, int size)
236 struct tty_display_info *tty = FRAME_TTY (f);
238 tty->specified_window = size ? size : FRAME_LINES (f);
239 if (FRAME_SCROLL_REGION_OK (f))
240 tty_set_scroll_region (f, 0, tty->specified_window);
243 static void
244 tty_set_scroll_region (struct frame *f, int start, int stop)
246 char *buf;
247 struct tty_display_info *tty = FRAME_TTY (f);
249 if (tty->TS_set_scroll_region)
250 buf = tparam (tty->TS_set_scroll_region, 0, 0, start, stop - 1, 0, 0);
251 else if (tty->TS_set_scroll_region_1)
252 buf = tparam (tty->TS_set_scroll_region_1, 0, 0,
253 FRAME_LINES (f), start,
254 FRAME_LINES (f) - stop,
255 FRAME_LINES (f));
256 else
257 buf = tparam (tty->TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (f));
259 OUTPUT (tty, buf);
260 xfree (buf);
261 losecursor (tty);
265 static void
266 tty_turn_on_insert (struct tty_display_info *tty)
268 if (!tty->insert_mode)
269 OUTPUT (tty, tty->TS_insert_mode);
270 tty->insert_mode = 1;
273 void
274 tty_turn_off_insert (struct tty_display_info *tty)
276 if (tty->insert_mode)
277 OUTPUT (tty, tty->TS_end_insert_mode);
278 tty->insert_mode = 0;
281 /* Handle highlighting. */
283 static void
284 tty_turn_off_highlight (struct tty_display_info *tty)
286 if (tty->standout_mode)
287 OUTPUT_IF (tty, tty->TS_end_standout_mode);
288 tty->standout_mode = 0;
291 static void
292 tty_turn_on_highlight (struct tty_display_info *tty)
294 if (!tty->standout_mode)
295 OUTPUT_IF (tty, tty->TS_standout_mode);
296 tty->standout_mode = 1;
299 static void
300 tty_toggle_highlight (struct tty_display_info *tty)
302 if (tty->standout_mode)
303 tty_turn_off_highlight (tty);
304 else
305 tty_turn_on_highlight (tty);
309 /* Make cursor invisible. */
311 static void
312 tty_hide_cursor (struct tty_display_info *tty)
314 if (tty->cursor_hidden == 0)
316 tty->cursor_hidden = 1;
317 OUTPUT_IF (tty, tty->TS_cursor_invisible);
322 /* Ensure that cursor is visible. */
324 static void
325 tty_show_cursor (struct tty_display_info *tty)
327 if (tty->cursor_hidden)
329 tty->cursor_hidden = 0;
330 OUTPUT_IF (tty, tty->TS_cursor_normal);
331 if (visible_cursor)
332 OUTPUT_IF (tty, tty->TS_cursor_visible);
337 /* Set standout mode to the state it should be in for
338 empty space inside windows. What this is,
339 depends on the user option inverse-video. */
341 static void
342 tty_background_highlight (struct tty_display_info *tty)
344 if (inverse_video)
345 tty_turn_on_highlight (tty);
346 else
347 tty_turn_off_highlight (tty);
350 /* Set standout mode to the mode specified for the text to be output. */
352 static void
353 tty_highlight_if_desired (struct tty_display_info *tty)
355 if (inverse_video)
356 tty_turn_on_highlight (tty);
357 else
358 tty_turn_off_highlight (tty);
362 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
363 frame-relative coordinates. */
365 static void
366 tty_cursor_to (struct frame *f, int vpos, int hpos)
368 struct tty_display_info *tty = FRAME_TTY (f);
370 /* Detect the case where we are called from reset_sys_modes
371 and the costs have never been calculated. Do nothing. */
372 if (! tty->costs_set)
373 return;
375 if (curY (tty) == vpos
376 && curX (tty) == hpos)
377 return;
378 if (!tty->TF_standout_motion)
379 tty_background_highlight (tty);
380 if (!tty->TF_insmode_motion)
381 tty_turn_off_insert (tty);
382 cmgoto (tty, vpos, hpos);
385 /* Similar but don't take any account of the wasted characters. */
387 static void
388 tty_raw_cursor_to (struct frame *f, int row, int col)
390 struct tty_display_info *tty = FRAME_TTY (f);
392 if (curY (tty) == row
393 && curX (tty) == col)
394 return;
395 if (!tty->TF_standout_motion)
396 tty_background_highlight (tty);
397 if (!tty->TF_insmode_motion)
398 tty_turn_off_insert (tty);
399 cmgoto (tty, row, col);
402 /* Erase operations */
404 /* Clear from cursor to end of frame on a termcap device. */
406 static void
407 tty_clear_to_end (struct frame *f)
409 register int i;
410 struct tty_display_info *tty = FRAME_TTY (f);
412 if (tty->TS_clr_to_bottom)
414 tty_background_highlight (tty);
415 OUTPUT (tty, tty->TS_clr_to_bottom);
417 else
419 for (i = curY (tty); i < FRAME_LINES (f); i++)
421 cursor_to (f, i, 0);
422 clear_end_of_line (f, FRAME_COLS (f));
427 /* Clear an entire termcap frame. */
429 static void
430 tty_clear_frame (struct frame *f)
432 struct tty_display_info *tty = FRAME_TTY (f);
434 if (tty->TS_clr_frame)
436 tty_background_highlight (tty);
437 OUTPUT (tty, tty->TS_clr_frame);
438 cmat (tty, 0, 0);
440 else
442 cursor_to (f, 0, 0);
443 clear_to_end (f);
447 /* An implementation of clear_end_of_line for termcap frames.
449 Note that the cursor may be moved, on terminals lacking a `ce' string. */
451 static void
452 tty_clear_end_of_line (struct frame *f, int first_unused_hpos)
454 register int i;
455 struct tty_display_info *tty = FRAME_TTY (f);
457 /* Detect the case where we are called from reset_sys_modes
458 and the costs have never been calculated. Do nothing. */
459 if (! tty->costs_set)
460 return;
462 if (curX (tty) >= first_unused_hpos)
463 return;
464 tty_background_highlight (tty);
465 if (tty->TS_clr_line)
467 OUTPUT1 (tty, tty->TS_clr_line);
469 else
470 { /* have to do it the hard way */
471 tty_turn_off_insert (tty);
473 /* Do not write in last row last col with Auto-wrap on. */
474 if (AutoWrap (tty)
475 && curY (tty) == FrameRows (tty) - 1
476 && first_unused_hpos == FrameCols (tty))
477 first_unused_hpos--;
479 for (i = curX (tty); i < first_unused_hpos; i++)
481 if (tty->termscript)
482 fputc (' ', tty->termscript);
483 fputc (' ', tty->output);
485 cmplus (tty, first_unused_hpos - curX (tty));
489 /* Buffers to store the source and result of code conversion for terminal. */
490 static unsigned char *encode_terminal_src;
491 static unsigned char *encode_terminal_dst;
492 /* Allocated sizes of the above buffers. */
493 static ptrdiff_t encode_terminal_src_size;
494 static ptrdiff_t encode_terminal_dst_size;
496 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes.
497 Set CODING->produced to the byte-length of the resulting byte
498 sequence, and return a pointer to that byte sequence. */
500 unsigned char *
501 encode_terminal_code (struct glyph *src, int src_len, struct coding_system *coding)
503 struct glyph *src_end = src + src_len;
504 unsigned char *buf;
505 ptrdiff_t nchars, nbytes, required;
506 ptrdiff_t tlen = GLYPH_TABLE_LENGTH;
507 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
508 Lisp_Object charset_list;
510 /* Allocate sufficient size of buffer to store all characters in
511 multibyte-form. But, it may be enlarged on demand if
512 Vglyph_table contains a string or a composite glyph is
513 encountered. */
514 if (min (PTRDIFF_MAX, SIZE_MAX) / MAX_MULTIBYTE_LENGTH < src_len)
515 memory_full (SIZE_MAX);
516 required = src_len;
517 required *= MAX_MULTIBYTE_LENGTH;
518 if (encode_terminal_src_size < required)
520 encode_terminal_src = xrealloc (encode_terminal_src, required);
521 encode_terminal_src_size = required;
524 charset_list = coding_charset_list (coding);
526 buf = encode_terminal_src;
527 nchars = 0;
528 while (src < src_end)
530 if (src->type == COMPOSITE_GLYPH)
532 struct composition *cmp IF_LINT (= NULL);
533 Lisp_Object gstring IF_LINT (= Qnil);
534 int i;
536 nbytes = buf - encode_terminal_src;
537 if (src->u.cmp.automatic)
539 gstring = composition_gstring_from_id (src->u.cmp.id);
540 required = src->slice.cmp.to - src->slice.cmp.from + 1;
542 else
544 cmp = composition_table[src->u.cmp.id];
545 required = cmp->glyph_len;
546 required *= MAX_MULTIBYTE_LENGTH;
549 if (encode_terminal_src_size - nbytes < required)
551 encode_terminal_src =
552 xpalloc (encode_terminal_src, &encode_terminal_src_size,
553 required - (encode_terminal_src_size - nbytes),
554 -1, 1);
555 buf = encode_terminal_src + nbytes;
558 if (src->u.cmp.automatic)
559 for (i = src->slice.cmp.from; i <= src->slice.cmp.to; i++)
561 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
562 int c = LGLYPH_CHAR (g);
564 if (! char_charset (c, charset_list, NULL))
565 c = '?';
566 buf += CHAR_STRING (c, buf);
567 nchars++;
569 else
570 for (i = 0; i < cmp->glyph_len; i++)
572 int c = COMPOSITION_GLYPH (cmp, i);
574 /* TAB in a composition means display glyphs with
575 padding space on the left or right. */
576 if (c == '\t')
577 continue;
578 if (char_charset (c, charset_list, NULL))
580 if (CHAR_WIDTH (c) == 0
581 && i > 0 && COMPOSITION_GLYPH (cmp, i - 1) == '\t')
582 /* Should be left-padded */
584 buf += CHAR_STRING (' ', buf);
585 nchars++;
588 else
589 c = '?';
590 buf += CHAR_STRING (c, buf);
591 nchars++;
594 /* We must skip glyphs to be padded for a wide character. */
595 else if (! CHAR_GLYPH_PADDING_P (*src))
597 GLYPH g;
598 int c IF_LINT (= 0);
599 Lisp_Object string;
601 string = Qnil;
602 SET_GLYPH_FROM_CHAR_GLYPH (g, src[0]);
604 if (GLYPH_INVALID_P (g) || GLYPH_SIMPLE_P (tbase, tlen, g))
606 /* This glyph doesn't have an entry in Vglyph_table. */
607 c = src->u.ch;
609 else
611 /* This glyph has an entry in Vglyph_table,
612 so process any alias before testing for simpleness. */
613 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
615 if (GLYPH_SIMPLE_P (tbase, tlen, g))
616 /* We set the multi-byte form of a character in G
617 (that should be an ASCII character) at WORKBUF. */
618 c = GLYPH_CHAR (g);
619 else
620 /* We have a string in Vglyph_table. */
621 string = tbase[GLYPH_CHAR (g)];
624 if (NILP (string))
626 nbytes = buf - encode_terminal_src;
627 if (encode_terminal_src_size - nbytes < MAX_MULTIBYTE_LENGTH)
629 encode_terminal_src =
630 xpalloc (encode_terminal_src, &encode_terminal_src_size,
631 MAX_MULTIBYTE_LENGTH, -1, 1);
632 buf = encode_terminal_src + nbytes;
634 if (CHAR_BYTE8_P (c)
635 || char_charset (c, charset_list, NULL))
637 /* Store the multibyte form of C at BUF. */
638 buf += CHAR_STRING (c, buf);
639 nchars++;
641 else
643 /* C is not encodable. */
644 *buf++ = '?';
645 nchars++;
646 while (src + 1 < src_end && CHAR_GLYPH_PADDING_P (src[1]))
648 *buf++ = '?';
649 nchars++;
650 src++;
654 else
656 if (! STRING_MULTIBYTE (string))
657 string = string_to_multibyte (string);
658 nbytes = buf - encode_terminal_src;
659 if (encode_terminal_src_size - nbytes < SBYTES (string))
661 encode_terminal_src =
662 xpalloc (encode_terminal_src, &encode_terminal_src_size,
663 (SBYTES (string)
664 - (encode_terminal_src_size - nbytes)),
665 -1, 1);
666 buf = encode_terminal_src + nbytes;
668 memcpy (buf, SDATA (string), SBYTES (string));
669 buf += SBYTES (string);
670 nchars += SCHARS (string);
673 src++;
676 if (nchars == 0)
678 coding->produced = 0;
679 return NULL;
682 nbytes = buf - encode_terminal_src;
683 coding->source = encode_terminal_src;
684 if (encode_terminal_dst_size == 0)
686 encode_terminal_dst = xrealloc (encode_terminal_dst,
687 encode_terminal_src_size);
688 encode_terminal_dst_size = encode_terminal_src_size;
690 coding->destination = encode_terminal_dst;
691 coding->dst_bytes = encode_terminal_dst_size;
692 encode_coding_object (coding, Qnil, 0, 0, nchars, nbytes, Qnil);
693 /* coding->destination may have been reallocated. */
694 encode_terminal_dst = coding->destination;
695 encode_terminal_dst_size = coding->dst_bytes;
697 return (encode_terminal_dst);
702 /* An implementation of write_glyphs for termcap frames. */
704 static void
705 tty_write_glyphs (struct frame *f, struct glyph *string, int len)
707 unsigned char *conversion_buffer;
708 struct coding_system *coding;
709 size_t n, stringlen;
711 struct tty_display_info *tty = FRAME_TTY (f);
713 tty_turn_off_insert (tty);
714 tty_hide_cursor (tty);
716 /* Don't dare write in last column of bottom line, if Auto-Wrap,
717 since that would scroll the whole frame on some terminals. */
719 if (AutoWrap (tty)
720 && curY (tty) + 1 == FRAME_LINES (f)
721 && (curX (tty) + len) == FRAME_COLS (f))
722 len --;
723 if (len <= 0)
724 return;
726 cmplus (tty, len);
728 /* If terminal_coding does any conversion, use it, otherwise use
729 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
730 because it always return 1 if the member src_multibyte is 1. */
731 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
732 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
733 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
734 the tail. */
735 coding->mode &= ~CODING_MODE_LAST_BLOCK;
737 for (stringlen = len; stringlen != 0; stringlen -= n)
739 /* Identify a run of glyphs with the same face. */
740 int face_id = string->face_id;
742 for (n = 1; n < stringlen; ++n)
743 if (string[n].face_id != face_id)
744 break;
746 /* Turn appearance modes of the face of the run on. */
747 tty_highlight_if_desired (tty);
748 turn_on_face (f, face_id);
750 if (n == stringlen)
751 /* This is the last run. */
752 coding->mode |= CODING_MODE_LAST_BLOCK;
753 conversion_buffer = encode_terminal_code (string, n, coding);
754 if (coding->produced > 0)
756 block_input ();
757 fwrite (conversion_buffer, 1, coding->produced, tty->output);
758 if (ferror (tty->output))
759 clearerr (tty->output);
760 if (tty->termscript)
761 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
762 unblock_input ();
764 string += n;
766 /* Turn appearance modes off. */
767 turn_off_face (f, face_id);
768 tty_turn_off_highlight (tty);
771 cmcheckmagic (tty);
774 #ifdef HAVE_GPM /* Only used by GPM code. */
776 static void
777 tty_write_glyphs_with_face (register struct frame *f, register struct glyph *string,
778 register int len, register int face_id)
780 unsigned char *conversion_buffer;
781 struct coding_system *coding;
783 struct tty_display_info *tty = FRAME_TTY (f);
785 tty_turn_off_insert (tty);
786 tty_hide_cursor (tty);
788 /* Don't dare write in last column of bottom line, if Auto-Wrap,
789 since that would scroll the whole frame on some terminals. */
791 if (AutoWrap (tty)
792 && curY (tty) + 1 == FRAME_LINES (f)
793 && (curX (tty) + len) == FRAME_COLS (f))
794 len --;
795 if (len <= 0)
796 return;
798 cmplus (tty, len);
800 /* If terminal_coding does any conversion, use it, otherwise use
801 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
802 because it always return 1 if the member src_multibyte is 1. */
803 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
804 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
805 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
806 the tail. */
807 coding->mode &= ~CODING_MODE_LAST_BLOCK;
809 /* Turn appearance modes of the face. */
810 tty_highlight_if_desired (tty);
811 turn_on_face (f, face_id);
813 coding->mode |= CODING_MODE_LAST_BLOCK;
814 conversion_buffer = encode_terminal_code (string, len, coding);
815 if (coding->produced > 0)
817 block_input ();
818 fwrite (conversion_buffer, 1, coding->produced, tty->output);
819 if (ferror (tty->output))
820 clearerr (tty->output);
821 if (tty->termscript)
822 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
823 unblock_input ();
826 /* Turn appearance modes off. */
827 turn_off_face (f, face_id);
828 tty_turn_off_highlight (tty);
830 cmcheckmagic (tty);
832 #endif
834 /* An implementation of insert_glyphs for termcap frames. */
836 static void
837 tty_insert_glyphs (struct frame *f, struct glyph *start, int len)
839 char *buf;
840 struct glyph *glyph = NULL;
841 unsigned char *conversion_buffer;
842 unsigned char space[1];
843 struct coding_system *coding;
845 struct tty_display_info *tty = FRAME_TTY (f);
847 if (tty->TS_ins_multi_chars)
849 buf = tparam (tty->TS_ins_multi_chars, 0, 0, len, 0, 0, 0);
850 OUTPUT1 (tty, buf);
851 xfree (buf);
852 if (start)
853 write_glyphs (f, start, len);
854 return;
857 tty_turn_on_insert (tty);
858 cmplus (tty, len);
860 if (! start)
861 space[0] = SPACEGLYPH;
863 /* If terminal_coding does any conversion, use it, otherwise use
864 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
865 because it always return 1 if the member src_multibyte is 1. */
866 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
867 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
868 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
869 the tail. */
870 coding->mode &= ~CODING_MODE_LAST_BLOCK;
872 while (len-- > 0)
874 OUTPUT1_IF (tty, tty->TS_ins_char);
875 if (!start)
877 conversion_buffer = space;
878 coding->produced = 1;
880 else
882 tty_highlight_if_desired (tty);
883 turn_on_face (f, start->face_id);
884 glyph = start;
885 ++start;
886 /* We must open sufficient space for a character which
887 occupies more than one column. */
888 while (len && CHAR_GLYPH_PADDING_P (*start))
890 OUTPUT1_IF (tty, tty->TS_ins_char);
891 start++, len--;
894 if (len <= 0)
895 /* This is the last glyph. */
896 coding->mode |= CODING_MODE_LAST_BLOCK;
898 conversion_buffer = encode_terminal_code (glyph, 1, coding);
901 if (coding->produced > 0)
903 block_input ();
904 fwrite (conversion_buffer, 1, coding->produced, tty->output);
905 if (ferror (tty->output))
906 clearerr (tty->output);
907 if (tty->termscript)
908 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
909 unblock_input ();
912 OUTPUT1_IF (tty, tty->TS_pad_inserted_char);
913 if (start)
915 turn_off_face (f, glyph->face_id);
916 tty_turn_off_highlight (tty);
920 cmcheckmagic (tty);
923 /* An implementation of delete_glyphs for termcap frames. */
925 static void
926 tty_delete_glyphs (struct frame *f, int n)
928 char *buf;
929 register int i;
931 struct tty_display_info *tty = FRAME_TTY (f);
933 if (tty->delete_in_insert_mode)
935 tty_turn_on_insert (tty);
937 else
939 tty_turn_off_insert (tty);
940 OUTPUT_IF (tty, tty->TS_delete_mode);
943 if (tty->TS_del_multi_chars)
945 buf = tparam (tty->TS_del_multi_chars, 0, 0, n, 0, 0, 0);
946 OUTPUT1 (tty, buf);
947 xfree (buf);
949 else
950 for (i = 0; i < n; i++)
951 OUTPUT1 (tty, tty->TS_del_char);
952 if (!tty->delete_in_insert_mode)
953 OUTPUT_IF (tty, tty->TS_end_delete_mode);
956 /* An implementation of ins_del_lines for termcap frames. */
958 static void
959 tty_ins_del_lines (struct frame *f, int vpos, int n)
961 struct tty_display_info *tty = FRAME_TTY (f);
962 const char *multi =
963 n > 0 ? tty->TS_ins_multi_lines : tty->TS_del_multi_lines;
964 const char *single = n > 0 ? tty->TS_ins_line : tty->TS_del_line;
965 const char *scroll = n > 0 ? tty->TS_rev_scroll : tty->TS_fwd_scroll;
967 register int i = n > 0 ? n : -n;
968 register char *buf;
970 /* If the lines below the insertion are being pushed
971 into the end of the window, this is the same as clearing;
972 and we know the lines are already clear, since the matching
973 deletion has already been done. So can ignore this. */
974 /* If the lines below the deletion are blank lines coming
975 out of the end of the window, don't bother,
976 as there will be a matching inslines later that will flush them. */
977 if (FRAME_SCROLL_REGION_OK (f)
978 && vpos + i >= tty->specified_window)
979 return;
980 if (!FRAME_MEMORY_BELOW_FRAME (f)
981 && vpos + i >= FRAME_LINES (f))
982 return;
984 if (multi)
986 raw_cursor_to (f, vpos, 0);
987 tty_background_highlight (tty);
988 buf = tparam (multi, 0, 0, i, 0, 0, 0);
989 OUTPUT (tty, buf);
990 xfree (buf);
992 else if (single)
994 raw_cursor_to (f, vpos, 0);
995 tty_background_highlight (tty);
996 while (--i >= 0)
997 OUTPUT (tty, single);
998 if (tty->TF_teleray)
999 curX (tty) = 0;
1001 else
1003 tty_set_scroll_region (f, vpos, tty->specified_window);
1004 if (n < 0)
1005 raw_cursor_to (f, tty->specified_window - 1, 0);
1006 else
1007 raw_cursor_to (f, vpos, 0);
1008 tty_background_highlight (tty);
1009 while (--i >= 0)
1010 OUTPUTL (tty, scroll, tty->specified_window - vpos);
1011 tty_set_scroll_region (f, 0, tty->specified_window);
1014 if (!FRAME_SCROLL_REGION_OK (f)
1015 && FRAME_MEMORY_BELOW_FRAME (f)
1016 && n < 0)
1018 cursor_to (f, FRAME_LINES (f) + n, 0);
1019 clear_to_end (f);
1023 /* Compute cost of sending "str", in characters,
1024 not counting any line-dependent padding. */
1027 string_cost (const char *str)
1029 cost = 0;
1030 if (str)
1031 tputs (str, 0, evalcost);
1032 return cost;
1035 /* Compute cost of sending "str", in characters,
1036 counting any line-dependent padding at one line. */
1038 static int
1039 string_cost_one_line (const char *str)
1041 cost = 0;
1042 if (str)
1043 tputs (str, 1, evalcost);
1044 return cost;
1047 /* Compute per line amount of line-dependent padding,
1048 in tenths of characters. */
1051 per_line_cost (const char *str)
1053 cost = 0;
1054 if (str)
1055 tputs (str, 0, evalcost);
1056 cost = - cost;
1057 if (str)
1058 tputs (str, 10, evalcost);
1059 return cost;
1062 /* char_ins_del_cost[n] is cost of inserting N characters.
1063 char_ins_del_cost[-n] is cost of deleting N characters.
1064 The length of this vector is based on max_frame_cols. */
1066 int *char_ins_del_vector;
1068 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
1070 /* ARGSUSED */
1071 static void
1072 calculate_ins_del_char_costs (struct frame *f)
1074 struct tty_display_info *tty = FRAME_TTY (f);
1075 int ins_startup_cost, del_startup_cost;
1076 int ins_cost_per_char, del_cost_per_char;
1077 register int i;
1078 register int *p;
1080 if (tty->TS_ins_multi_chars)
1082 ins_cost_per_char = 0;
1083 ins_startup_cost = string_cost_one_line (tty->TS_ins_multi_chars);
1085 else if (tty->TS_ins_char || tty->TS_pad_inserted_char
1086 || (tty->TS_insert_mode && tty->TS_end_insert_mode))
1088 ins_startup_cost = (30 * (string_cost (tty->TS_insert_mode)
1089 + string_cost (tty->TS_end_insert_mode))) / 100;
1090 ins_cost_per_char = (string_cost_one_line (tty->TS_ins_char)
1091 + string_cost_one_line (tty->TS_pad_inserted_char));
1093 else
1095 ins_startup_cost = 9999;
1096 ins_cost_per_char = 0;
1099 if (tty->TS_del_multi_chars)
1101 del_cost_per_char = 0;
1102 del_startup_cost = string_cost_one_line (tty->TS_del_multi_chars);
1104 else if (tty->TS_del_char)
1106 del_startup_cost = (string_cost (tty->TS_delete_mode)
1107 + string_cost (tty->TS_end_delete_mode));
1108 if (tty->delete_in_insert_mode)
1109 del_startup_cost /= 2;
1110 del_cost_per_char = string_cost_one_line (tty->TS_del_char);
1112 else
1114 del_startup_cost = 9999;
1115 del_cost_per_char = 0;
1118 /* Delete costs are at negative offsets */
1119 p = &char_ins_del_cost (f)[0];
1120 for (i = FRAME_COLS (f); --i >= 0;)
1121 *--p = (del_startup_cost += del_cost_per_char);
1123 /* Doing nothing is free */
1124 p = &char_ins_del_cost (f)[0];
1125 *p++ = 0;
1127 /* Insert costs are at positive offsets */
1128 for (i = FRAME_COLS (f); --i >= 0;)
1129 *p++ = (ins_startup_cost += ins_cost_per_char);
1132 void
1133 calculate_costs (struct frame *frame)
1135 FRAME_COST_BAUD_RATE (frame) = baud_rate;
1137 if (FRAME_TERMCAP_P (frame))
1139 struct tty_display_info *tty = FRAME_TTY (frame);
1140 register const char *f = (tty->TS_set_scroll_region
1141 ? tty->TS_set_scroll_region
1142 : tty->TS_set_scroll_region_1);
1144 FRAME_SCROLL_REGION_COST (frame) = string_cost (f);
1146 tty->costs_set = 1;
1148 /* These variables are only used for terminal stuff. They are
1149 allocated once for the terminal frame of X-windows emacs, but not
1150 used afterwards.
1152 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1153 X turns off char_ins_del_ok. */
1155 max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
1156 if ((min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) - 1) / 2
1157 < max_frame_cols)
1158 memory_full (SIZE_MAX);
1160 char_ins_del_vector =
1161 xrealloc (char_ins_del_vector,
1162 (sizeof (int) + 2 * sizeof (int) * max_frame_cols));
1164 memset (char_ins_del_vector, 0,
1165 (sizeof (int) + 2 * sizeof (int) * max_frame_cols));
1168 if (f && (!tty->TS_ins_line && !tty->TS_del_line))
1169 do_line_insertion_deletion_costs (frame,
1170 tty->TS_rev_scroll, tty->TS_ins_multi_lines,
1171 tty->TS_fwd_scroll, tty->TS_del_multi_lines,
1172 f, f, 1);
1173 else
1174 do_line_insertion_deletion_costs (frame,
1175 tty->TS_ins_line, tty->TS_ins_multi_lines,
1176 tty->TS_del_line, tty->TS_del_multi_lines,
1177 0, 0, 1);
1179 calculate_ins_del_char_costs (frame);
1181 /* Don't use TS_repeat if its padding is worse than sending the chars */
1182 if (tty->TS_repeat && per_line_cost (tty->TS_repeat) * baud_rate < 9000)
1183 tty->RPov = string_cost (tty->TS_repeat);
1184 else
1185 tty->RPov = FRAME_COLS (frame) * 2;
1187 cmcostinit (FRAME_TTY (frame)); /* set up cursor motion costs */
1191 struct fkey_table {
1192 const char *cap, *name;
1195 /* Termcap capability names that correspond directly to X keysyms.
1196 Some of these (marked "terminfo") aren't supplied by old-style
1197 (Berkeley) termcap entries. They're listed in X keysym order;
1198 except we put the keypad keys first, so that if they clash with
1199 other keys (as on the IBM PC keyboard) they get overridden.
1202 static const struct fkey_table keys[] =
1204 {"kh", "home"}, /* termcap */
1205 {"kl", "left"}, /* termcap */
1206 {"ku", "up"}, /* termcap */
1207 {"kr", "right"}, /* termcap */
1208 {"kd", "down"}, /* termcap */
1209 {"%8", "prior"}, /* terminfo */
1210 {"%5", "next"}, /* terminfo */
1211 {"@7", "end"}, /* terminfo */
1212 {"@1", "begin"}, /* terminfo */
1213 {"*6", "select"}, /* terminfo */
1214 {"%9", "print"}, /* terminfo */
1215 {"@4", "execute"}, /* terminfo --- actually the `command' key */
1217 * "insert" --- see below
1219 {"&8", "undo"}, /* terminfo */
1220 {"%0", "redo"}, /* terminfo */
1221 {"%7", "menu"}, /* terminfo --- actually the `options' key */
1222 {"@0", "find"}, /* terminfo */
1223 {"@2", "cancel"}, /* terminfo */
1224 {"%1", "help"}, /* terminfo */
1226 * "break" goes here, but can't be reliably intercepted with termcap
1228 {"&4", "reset"}, /* terminfo --- actually `restart' */
1230 * "system" and "user" --- no termcaps
1232 {"kE", "clearline"}, /* terminfo */
1233 {"kA", "insertline"}, /* terminfo */
1234 {"kL", "deleteline"}, /* terminfo */
1235 {"kI", "insertchar"}, /* terminfo */
1236 {"kD", "deletechar"}, /* terminfo */
1237 {"kB", "backtab"}, /* terminfo */
1239 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1241 {"@8", "kp-enter"}, /* terminfo */
1243 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1244 * "kp-multiply", "kp-add", "kp-separator",
1245 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1246 * --- no termcaps for any of these.
1248 {"K4", "kp-1"}, /* terminfo */
1250 * "kp-2" --- no termcap
1252 {"K5", "kp-3"}, /* terminfo */
1254 * "kp-4" --- no termcap
1256 {"K2", "kp-5"}, /* terminfo */
1258 * "kp-6" --- no termcap
1260 {"K1", "kp-7"}, /* terminfo */
1262 * "kp-8" --- no termcap
1264 {"K3", "kp-9"}, /* terminfo */
1266 * "kp-equal" --- no termcap
1268 {"k1", "f1"},
1269 {"k2", "f2"},
1270 {"k3", "f3"},
1271 {"k4", "f4"},
1272 {"k5", "f5"},
1273 {"k6", "f6"},
1274 {"k7", "f7"},
1275 {"k8", "f8"},
1276 {"k9", "f9"},
1278 {"&0", "S-cancel"}, /*shifted cancel key*/
1279 {"&9", "S-begin"}, /*shifted begin key*/
1280 {"*0", "S-find"}, /*shifted find key*/
1281 {"*1", "S-execute"}, /*shifted execute? actually shifted command key*/
1282 {"*4", "S-delete"}, /*shifted delete-character key*/
1283 {"*7", "S-end"}, /*shifted end key*/
1284 {"*8", "S-clearline"}, /*shifted clear-to end-of-line key*/
1285 {"#1", "S-help"}, /*shifted help key*/
1286 {"#2", "S-home"}, /*shifted home key*/
1287 {"#3", "S-insert"}, /*shifted insert-character key*/
1288 {"#4", "S-left"}, /*shifted left-arrow key*/
1289 {"%d", "S-menu"}, /*shifted menu? actually shifted options key*/
1290 {"%c", "S-next"}, /*shifted next key*/
1291 {"%e", "S-prior"}, /*shifted previous key*/
1292 {"%f", "S-print"}, /*shifted print key*/
1293 {"%g", "S-redo"}, /*shifted redo key*/
1294 {"%i", "S-right"}, /*shifted right-arrow key*/
1295 {"!3", "S-undo"} /*shifted undo key*/
1298 #ifndef DOS_NT
1299 static char **term_get_fkeys_address;
1300 static KBOARD *term_get_fkeys_kboard;
1301 static Lisp_Object term_get_fkeys_1 (void);
1303 /* Find the escape codes sent by the function keys for Vinput_decode_map.
1304 This function scans the termcap function key sequence entries, and
1305 adds entries to Vinput_decode_map for each function key it finds. */
1307 static void
1308 term_get_fkeys (char **address, KBOARD *kboard)
1310 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1311 errors during the call. The only errors should be from Fdefine_key
1312 when given a key sequence containing an invalid prefix key. If the
1313 termcap defines function keys which use a prefix that is already bound
1314 to a command by the default bindings, we should silently ignore that
1315 function key specification, rather than giving the user an error and
1316 refusing to run at all on such a terminal. */
1318 term_get_fkeys_address = address;
1319 term_get_fkeys_kboard = kboard;
1320 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1323 static Lisp_Object
1324 term_get_fkeys_1 (void)
1326 int i;
1328 char **address = term_get_fkeys_address;
1329 KBOARD *kboard = term_get_fkeys_kboard;
1331 /* This can happen if CANNOT_DUMP or with strange options. */
1332 if (!KEYMAPP (KVAR (kboard, Vinput_decode_map)))
1333 kset_input_decode_map (kboard, Fmake_sparse_keymap (Qnil));
1335 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1337 char *sequence = tgetstr (keys[i].cap, address);
1338 if (sequence)
1339 Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (sequence),
1340 Fmake_vector (make_number (1),
1341 intern (keys[i].name)));
1344 /* The uses of the "k0" capability are inconsistent; sometimes it
1345 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1346 We will attempt to politely accommodate both systems by testing for
1347 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1350 const char *k_semi = tgetstr ("k;", address);
1351 const char *k0 = tgetstr ("k0", address);
1352 const char *k0_name = "f10";
1354 if (k_semi)
1356 if (k0)
1357 /* Define f0 first, so that f10 takes precedence in case the
1358 key sequences happens to be the same. */
1359 Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (k0),
1360 Fmake_vector (make_number (1), intern ("f0")));
1361 Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (k_semi),
1362 Fmake_vector (make_number (1), intern ("f10")));
1364 else if (k0)
1365 Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (k0),
1366 Fmake_vector (make_number (1), intern (k0_name)));
1369 /* Set up cookies for numbered function keys above f10. */
1371 char fcap[3], fkey[4];
1373 fcap[0] = 'F'; fcap[2] = '\0';
1374 for (i = 11; i < 64; i++)
1376 if (i <= 19)
1377 fcap[1] = '1' + i - 11;
1378 else if (i <= 45)
1379 fcap[1] = 'A' + i - 20;
1380 else
1381 fcap[1] = 'a' + i - 46;
1384 char *sequence = tgetstr (fcap, address);
1385 if (sequence)
1387 sprintf (fkey, "f%d", i);
1388 Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (sequence),
1389 Fmake_vector (make_number (1),
1390 intern (fkey)));
1397 * Various mappings to try and get a better fit.
1400 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1401 if (!tgetstr (cap1, address)) \
1403 char *sequence = tgetstr (cap2, address); \
1404 if (sequence) \
1405 Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (sequence), \
1406 Fmake_vector (make_number (1), \
1407 intern (sym))); \
1410 /* if there's no key_next keycap, map key_npage to `next' keysym */
1411 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1412 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1413 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1414 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1415 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1416 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1417 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1419 /* IBM has their own non-standard dialect of terminfo.
1420 If the standard name isn't found, try the IBM name. */
1421 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1422 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1423 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1424 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1425 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1426 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1427 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1428 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1429 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1430 #undef CONDITIONAL_REASSIGN
1433 return Qnil;
1435 #endif /* not DOS_NT */
1438 /***********************************************************************
1439 Character Display Information
1440 ***********************************************************************/
1441 static void append_glyph (struct it *);
1442 static void append_composite_glyph (struct it *);
1443 static void produce_composite_glyph (struct it *);
1444 static void append_glyphless_glyph (struct it *, int, const char *);
1445 static void produce_glyphless_glyph (struct it *, int, Lisp_Object);
1447 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1448 terminal frames if IT->glyph_row != NULL. IT->char_to_display is
1449 the character for which to produce glyphs; IT->face_id contains the
1450 character's face. Padding glyphs are appended if IT->c has a
1451 IT->pixel_width > 1. */
1453 static void
1454 append_glyph (struct it *it)
1456 struct glyph *glyph, *end;
1457 int i;
1459 eassert (it->glyph_row);
1460 glyph = (it->glyph_row->glyphs[it->area]
1461 + it->glyph_row->used[it->area]);
1462 end = it->glyph_row->glyphs[1 + it->area];
1464 /* If the glyph row is reversed, we need to prepend the glyph rather
1465 than append it. */
1466 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1468 struct glyph *g;
1469 int move_by = it->pixel_width;
1471 /* Make room for the new glyphs. */
1472 if (move_by > end - glyph) /* don't overstep end of this area */
1473 move_by = end - glyph;
1474 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1475 g[move_by] = *g;
1476 glyph = it->glyph_row->glyphs[it->area];
1477 end = glyph + move_by;
1480 /* BIDI Note: we put the glyphs of a "multi-pixel" character left to
1481 right, even in the REVERSED_P case, since (a) all of its u.ch are
1482 identical, and (b) the PADDING_P flag needs to be set for the
1483 leftmost one, because we write to the terminal left-to-right. */
1484 for (i = 0;
1485 i < it->pixel_width && glyph < end;
1486 ++i)
1488 glyph->type = CHAR_GLYPH;
1489 glyph->pixel_width = 1;
1490 glyph->u.ch = it->char_to_display;
1491 glyph->face_id = it->face_id;
1492 glyph->padding_p = i > 0;
1493 glyph->charpos = CHARPOS (it->position);
1494 glyph->object = it->object;
1495 if (it->bidi_p)
1497 glyph->resolved_level = it->bidi_it.resolved_level;
1498 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1499 emacs_abort ();
1500 glyph->bidi_type = it->bidi_it.type;
1502 else
1504 glyph->resolved_level = 0;
1505 glyph->bidi_type = UNKNOWN_BT;
1508 ++it->glyph_row->used[it->area];
1509 ++glyph;
1513 /* For external use. */
1514 void
1515 tty_append_glyph (struct it *it)
1517 append_glyph (it);
1521 /* Produce glyphs for the display element described by IT. *IT
1522 specifies what we want to produce a glyph for (character, image, ...),
1523 and where in the glyph matrix we currently are (glyph row and hpos).
1524 produce_glyphs fills in output fields of *IT with information such as the
1525 pixel width and height of a character, and maybe output actual glyphs at
1526 the same time if IT->glyph_row is non-null. For an overview, see
1527 the explanation in dispextern.h, before the definition of the
1528 display_element_type enumeration.
1530 produce_glyphs also stores the result of glyph width, ascent
1531 etc. computations in *IT.
1533 IT->glyph_row may be null, in which case produce_glyphs does not
1534 actually fill in the glyphs. This is used in the move_* functions
1535 in xdisp.c for text width and height computations.
1537 Callers usually don't call produce_glyphs directly;
1538 instead they use the macro PRODUCE_GLYPHS. */
1540 void
1541 produce_glyphs (struct it *it)
1543 /* If a hook is installed, let it do the work. */
1545 /* Nothing but characters are supported on terminal frames. */
1546 eassert (it->what == IT_CHARACTER
1547 || it->what == IT_COMPOSITION
1548 || it->what == IT_STRETCH
1549 || it->what == IT_GLYPHLESS);
1551 if (it->what == IT_STRETCH)
1553 produce_stretch_glyph (it);
1554 goto done;
1557 if (it->what == IT_COMPOSITION)
1559 produce_composite_glyph (it);
1560 goto done;
1563 if (it->what == IT_GLYPHLESS)
1565 produce_glyphless_glyph (it, 0, Qnil);
1566 goto done;
1569 if (it->char_to_display >= 040 && it->char_to_display < 0177)
1571 it->pixel_width = it->nglyphs = 1;
1572 if (it->glyph_row)
1573 append_glyph (it);
1575 else if (it->char_to_display == '\n')
1576 it->pixel_width = it->nglyphs = 0;
1577 else if (it->char_to_display == '\t')
1579 int absolute_x = (it->current_x
1580 + it->continuation_lines_width);
1581 int next_tab_x
1582 = (((1 + absolute_x + it->tab_width - 1)
1583 / it->tab_width)
1584 * it->tab_width);
1585 int nspaces;
1587 /* If part of the TAB has been displayed on the previous line
1588 which is continued now, continuation_lines_width will have
1589 been incremented already by the part that fitted on the
1590 continued line. So, we will get the right number of spaces
1591 here. */
1592 nspaces = next_tab_x - absolute_x;
1594 if (it->glyph_row)
1596 int n = nspaces;
1598 it->char_to_display = ' ';
1599 it->pixel_width = it->len = 1;
1601 while (n--)
1602 append_glyph (it);
1605 it->pixel_width = nspaces;
1606 it->nglyphs = nspaces;
1608 else if (CHAR_BYTE8_P (it->char_to_display))
1610 /* Coming here means that we must send the raw 8-bit byte as is
1611 to the terminal. Although there's no way to know how many
1612 columns it occupies on a screen, it is a good assumption that
1613 a single byte code has 1-column width. */
1614 it->pixel_width = it->nglyphs = 1;
1615 if (it->glyph_row)
1616 append_glyph (it);
1618 else
1620 Lisp_Object charset_list = FRAME_TERMINAL (it->f)->charset_list;
1622 if (char_charset (it->char_to_display, charset_list, NULL))
1624 it->pixel_width = CHAR_WIDTH (it->char_to_display);
1625 it->nglyphs = it->pixel_width;
1626 if (it->glyph_row)
1627 append_glyph (it);
1629 else
1631 Lisp_Object acronym = lookup_glyphless_char_display (-1, it);
1633 eassert (it->what == IT_GLYPHLESS);
1634 produce_glyphless_glyph (it, 1, acronym);
1638 done:
1639 /* Advance current_x by the pixel width as a convenience for
1640 the caller. */
1641 if (it->area == TEXT_AREA)
1642 it->current_x += it->pixel_width;
1643 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1644 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
1647 /* Append glyphs to IT's glyph_row for the composition IT->cmp_id.
1648 Called from produce_composite_glyph for terminal frames if
1649 IT->glyph_row != NULL. IT->face_id contains the character's
1650 face. */
1652 static void
1653 append_composite_glyph (struct it *it)
1655 struct glyph *glyph;
1657 eassert (it->glyph_row);
1658 glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
1659 if (glyph < it->glyph_row->glyphs[1 + it->area])
1661 /* If the glyph row is reversed, we need to prepend the glyph
1662 rather than append it. */
1663 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1665 struct glyph *g;
1667 /* Make room for the new glyph. */
1668 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1669 g[1] = *g;
1670 glyph = it->glyph_row->glyphs[it->area];
1672 glyph->type = COMPOSITE_GLYPH;
1673 glyph->pixel_width = it->pixel_width;
1674 glyph->u.cmp.id = it->cmp_it.id;
1675 if (it->cmp_it.ch < 0)
1677 glyph->u.cmp.automatic = 0;
1678 glyph->u.cmp.id = it->cmp_it.id;
1680 else
1682 glyph->u.cmp.automatic = 1;
1683 glyph->u.cmp.id = it->cmp_it.id;
1684 glyph->slice.cmp.from = it->cmp_it.from;
1685 glyph->slice.cmp.to = it->cmp_it.to - 1;
1688 glyph->face_id = it->face_id;
1689 glyph->padding_p = 0;
1690 glyph->charpos = CHARPOS (it->position);
1691 glyph->object = it->object;
1692 if (it->bidi_p)
1694 glyph->resolved_level = it->bidi_it.resolved_level;
1695 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1696 emacs_abort ();
1697 glyph->bidi_type = it->bidi_it.type;
1699 else
1701 glyph->resolved_level = 0;
1702 glyph->bidi_type = UNKNOWN_BT;
1705 ++it->glyph_row->used[it->area];
1706 ++glyph;
1711 /* Produce a composite glyph for iterator IT. IT->cmp_id is the ID of
1712 the composition. We simply produces components of the composition
1713 assuming that the terminal has a capability to layout/render it
1714 correctly. */
1716 static void
1717 produce_composite_glyph (struct it *it)
1719 if (it->cmp_it.ch < 0)
1721 struct composition *cmp = composition_table[it->cmp_it.id];
1723 it->pixel_width = cmp->width;
1725 else
1727 Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id);
1729 it->pixel_width = composition_gstring_width (gstring, it->cmp_it.from,
1730 it->cmp_it.to, NULL);
1732 it->nglyphs = 1;
1733 if (it->glyph_row)
1734 append_composite_glyph (it);
1738 /* Append a glyph for a glyphless character to IT->glyph_row. FACE_ID
1739 is a face ID to be used for the glyph. What is actually appended
1740 are glyphs of type CHAR_GLYPH whose characters are in STR (which
1741 comes from it->nglyphs bytes). */
1743 static void
1744 append_glyphless_glyph (struct it *it, int face_id, const char *str)
1746 struct glyph *glyph, *end;
1747 int i;
1749 eassert (it->glyph_row);
1750 glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
1751 end = it->glyph_row->glyphs[1 + it->area];
1753 /* If the glyph row is reversed, we need to prepend the glyph rather
1754 than append it. */
1755 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1757 struct glyph *g;
1758 int move_by = it->pixel_width;
1760 /* Make room for the new glyphs. */
1761 if (move_by > end - glyph) /* don't overstep end of this area */
1762 move_by = end - glyph;
1763 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1764 g[move_by] = *g;
1765 glyph = it->glyph_row->glyphs[it->area];
1766 end = glyph + move_by;
1769 if (glyph >= end)
1770 return;
1771 glyph->type = CHAR_GLYPH;
1772 glyph->pixel_width = 1;
1773 glyph->face_id = face_id;
1774 glyph->padding_p = 0;
1775 glyph->charpos = CHARPOS (it->position);
1776 glyph->object = it->object;
1777 if (it->bidi_p)
1779 glyph->resolved_level = it->bidi_it.resolved_level;
1780 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1781 emacs_abort ();
1782 glyph->bidi_type = it->bidi_it.type;
1784 else
1786 glyph->resolved_level = 0;
1787 glyph->bidi_type = UNKNOWN_BT;
1790 /* BIDI Note: we put the glyphs of characters left to right, even in
1791 the REVERSED_P case because we write to the terminal
1792 left-to-right. */
1793 for (i = 0; i < it->nglyphs && glyph < end; ++i)
1795 if (i > 0)
1796 glyph[0] = glyph[-1];
1797 glyph->u.ch = str[i];
1798 ++it->glyph_row->used[it->area];
1799 ++glyph;
1803 /* Produce glyphs for a glyphless character for iterator IT.
1804 IT->glyphless_method specifies which method to use for displaying
1805 the character. See the description of enum
1806 glyphless_display_method in dispextern.h for the details.
1808 FOR_NO_FONT is nonzero if and only if this is for a character that
1809 is not supported by the coding system of the terminal. ACRONYM, if
1810 non-nil, is an acronym string for the character.
1812 The glyphs actually produced are of type CHAR_GLYPH. */
1814 static void
1815 produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym)
1817 int face_id;
1818 int len;
1819 char buf[sizeof "\\x" + max (6, (sizeof it->c * CHAR_BIT + 3) / 4)];
1820 char const *str = " ";
1822 /* Get a face ID for the glyph by utilizing a cache (the same way as
1823 done for `escape-glyph' in get_next_display_element). */
1824 if (it->f == last_glyphless_glyph_frame
1825 && it->face_id == last_glyphless_glyph_face_id)
1827 face_id = last_glyphless_glyph_merged_face_id;
1829 else
1831 /* Merge the `glyphless-char' face into the current face. */
1832 face_id = merge_faces (it->f, Qglyphless_char, 0, it->face_id);
1833 last_glyphless_glyph_frame = it->f;
1834 last_glyphless_glyph_face_id = it->face_id;
1835 last_glyphless_glyph_merged_face_id = face_id;
1838 if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE)
1840 /* As there's no way to produce a thin space, we produce a space
1841 of canonical width. */
1842 len = 1;
1844 else if (it->glyphless_method == GLYPHLESS_DISPLAY_EMPTY_BOX)
1846 len = CHAR_WIDTH (it->c);
1847 if (len == 0)
1848 len = 1;
1849 else if (len > 4)
1850 len = 4;
1851 len = sprintf (buf, "[%.*s]", len, str);
1852 str = buf;
1854 else
1856 if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM)
1858 if (! STRINGP (acronym) && CHAR_TABLE_P (Vglyphless_char_display))
1859 acronym = CHAR_TABLE_REF (Vglyphless_char_display, it->c);
1860 if (CONSP (acronym))
1861 acronym = XCDR (acronym);
1862 buf[0] = '[';
1863 str = STRINGP (acronym) ? SSDATA (acronym) : "";
1864 for (len = 0; len < 6 && str[len] && ASCII_BYTE_P (str[len]); len++)
1865 buf[1 + len] = str[len];
1866 buf[1 + len] = ']';
1867 len += 2;
1869 else
1871 eassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEX_CODE);
1872 len = (it->c < 0x10000 ? sprintf (buf, "\\u%04X", it->c)
1873 : it->c <= MAX_UNICODE_CHAR ? sprintf (buf, "\\U%06X", it->c)
1874 : sprintf (buf, "\\x%06X", it->c));
1876 str = buf;
1879 it->pixel_width = len;
1880 it->nglyphs = len;
1881 if (it->glyph_row)
1882 append_glyphless_glyph (it, face_id, str);
1886 /***********************************************************************
1887 Faces
1888 ***********************************************************************/
1890 /* Value is non-zero if attribute ATTR may be used. ATTR should be
1891 one of the enumerators from enum no_color_bit, or a bit set built
1892 from them. Some display attributes may not be used together with
1893 color; the termcap capability `NC' specifies which ones. */
1895 #define MAY_USE_WITH_COLORS_P(tty, ATTR) \
1896 (tty->TN_max_colors > 0 \
1897 ? (tty->TN_no_color_video & (ATTR)) == 0 \
1898 : 1)
1900 /* Turn appearances of face FACE_ID on tty frame F on.
1901 FACE_ID is a realized face ID number, in the face cache. */
1903 static void
1904 turn_on_face (struct frame *f, int face_id)
1906 struct face *face = FACE_FROM_ID (f, face_id);
1907 long fg = face->foreground;
1908 long bg = face->background;
1909 struct tty_display_info *tty = FRAME_TTY (f);
1911 /* Do this first because TS_end_standout_mode may be the same
1912 as TS_exit_attribute_mode, which turns all appearances off. */
1913 if (MAY_USE_WITH_COLORS_P (tty, NC_REVERSE))
1915 if (tty->TN_max_colors > 0)
1917 if (fg >= 0 && bg >= 0)
1919 /* If the terminal supports colors, we can set them
1920 below without using reverse video. The face's fg
1921 and bg colors are set as they should appear on
1922 the screen, i.e. they take the inverse-video'ness
1923 of the face already into account. */
1925 else if (inverse_video)
1927 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1928 || bg == FACE_TTY_DEFAULT_BG_COLOR)
1929 tty_toggle_highlight (tty);
1931 else
1933 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1934 || bg == FACE_TTY_DEFAULT_FG_COLOR)
1935 tty_toggle_highlight (tty);
1938 else
1940 /* If we can't display colors, use reverse video
1941 if the face specifies that. */
1942 if (inverse_video)
1944 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1945 || bg == FACE_TTY_DEFAULT_BG_COLOR)
1946 tty_toggle_highlight (tty);
1948 else
1950 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1951 || bg == FACE_TTY_DEFAULT_FG_COLOR)
1952 tty_toggle_highlight (tty);
1957 if (face->tty_bold_p && MAY_USE_WITH_COLORS_P (tty, NC_BOLD))
1958 OUTPUT1_IF (tty, tty->TS_enter_bold_mode);
1960 if (face->tty_italic_p && MAY_USE_WITH_COLORS_P (tty, NC_ITALIC))
1962 if (tty->TS_enter_italic_mode)
1963 OUTPUT1 (tty, tty->TS_enter_italic_mode);
1964 else
1965 /* Italics mode is unavailable on many terminals. In that
1966 case, map slant to dimmed text; we want italic text to
1967 appear different and dimming is not otherwise used. */
1968 OUTPUT1 (tty, tty->TS_enter_dim_mode);
1971 if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (tty, NC_UNDERLINE))
1972 OUTPUT1_IF (tty, tty->TS_enter_underline_mode);
1974 if (tty->TN_max_colors > 0)
1976 const char *ts;
1977 char *p;
1979 ts = tty->standout_mode ? tty->TS_set_background : tty->TS_set_foreground;
1980 if (fg >= 0 && ts)
1982 p = tparam (ts, NULL, 0, (int) fg, 0, 0, 0);
1983 OUTPUT (tty, p);
1984 xfree (p);
1987 ts = tty->standout_mode ? tty->TS_set_foreground : tty->TS_set_background;
1988 if (bg >= 0 && ts)
1990 p = tparam (ts, NULL, 0, (int) bg, 0, 0, 0);
1991 OUTPUT (tty, p);
1992 xfree (p);
1998 /* Turn off appearances of face FACE_ID on tty frame F. */
2000 static void
2001 turn_off_face (struct frame *f, int face_id)
2003 struct face *face = FACE_FROM_ID (f, face_id);
2004 struct tty_display_info *tty = FRAME_TTY (f);
2006 eassert (face != NULL);
2008 if (tty->TS_exit_attribute_mode)
2010 /* Capability "me" will turn off appearance modes double-bright,
2011 half-bright, reverse-video, standout, underline. It may or
2012 may not turn off alt-char-mode. */
2013 if (face->tty_bold_p
2014 || face->tty_italic_p
2015 || face->tty_reverse_p
2016 || face->tty_underline_p)
2018 OUTPUT1_IF (tty, tty->TS_exit_attribute_mode);
2019 if (strcmp (tty->TS_exit_attribute_mode, tty->TS_end_standout_mode) == 0)
2020 tty->standout_mode = 0;
2023 else
2025 /* If we don't have "me" we can only have those appearances
2026 that have exit sequences defined. */
2027 if (face->tty_underline_p)
2028 OUTPUT_IF (tty, tty->TS_exit_underline_mode);
2031 /* Switch back to default colors. */
2032 if (tty->TN_max_colors > 0
2033 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
2034 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
2035 || (face->background != FACE_TTY_DEFAULT_COLOR
2036 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
2037 OUTPUT1_IF (tty, tty->TS_orig_pair);
2041 /* Return non-zero if the terminal on frame F supports all of the
2042 capabilities in CAPS simultaneously, with foreground and background
2043 colors FG and BG. */
2046 tty_capable_p (struct tty_display_info *tty, unsigned int caps,
2047 unsigned long fg, unsigned long bg)
2049 #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
2050 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
2051 return 0;
2053 TTY_CAPABLE_P_TRY (tty, TTY_CAP_INVERSE, tty->TS_standout_mode, NC_REVERSE);
2054 TTY_CAPABLE_P_TRY (tty, TTY_CAP_UNDERLINE, tty->TS_enter_underline_mode, NC_UNDERLINE);
2055 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BOLD, tty->TS_enter_bold_mode, NC_BOLD);
2056 TTY_CAPABLE_P_TRY (tty, TTY_CAP_DIM, tty->TS_enter_dim_mode, NC_DIM);
2057 TTY_CAPABLE_P_TRY (tty, TTY_CAP_ITALIC, tty->TS_enter_italic_mode, NC_ITALIC);
2059 /* We can do it! */
2060 return 1;
2063 /* Return non-zero if the terminal is capable to display colors. */
2065 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
2066 0, 1, 0,
2067 doc: /* Return non-nil if the tty device TERMINAL can display colors.
2069 TERMINAL can be a terminal object, a frame, or nil (meaning the
2070 selected frame's terminal). This function always returns nil if
2071 TERMINAL does not refer to a text terminal. */)
2072 (Lisp_Object terminal)
2074 struct terminal *t = get_tty_terminal (terminal, 0);
2075 if (!t)
2076 return Qnil;
2077 else
2078 return t->display_info.tty->TN_max_colors > 0 ? Qt : Qnil;
2081 /* Return the number of supported colors. */
2082 DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
2083 Stty_display_color_cells, 0, 1, 0,
2084 doc: /* Return the number of colors supported by the tty device TERMINAL.
2086 TERMINAL can be a terminal object, a frame, or nil (meaning the
2087 selected frame's terminal). This function always returns 0 if
2088 TERMINAL does not refer to a text terminal. */)
2089 (Lisp_Object terminal)
2091 struct terminal *t = get_tty_terminal (terminal, 0);
2092 if (!t)
2093 return make_number (0);
2094 else
2095 return make_number (t->display_info.tty->TN_max_colors);
2098 #ifndef DOS_NT
2100 /* Declare here rather than in the function, as in the rest of Emacs,
2101 to work around an HPUX compiler bug (?). See
2102 http://lists.gnu.org/archive/html/emacs-devel/2007-08/msg00410.html */
2103 static int default_max_colors;
2104 static int default_max_pairs;
2105 static int default_no_color_video;
2106 static char *default_orig_pair;
2107 static char *default_set_foreground;
2108 static char *default_set_background;
2110 /* Save or restore the default color-related capabilities of this
2111 terminal. */
2112 static void
2113 tty_default_color_capabilities (struct tty_display_info *tty, int save)
2116 if (save)
2118 xfree (default_orig_pair);
2119 default_orig_pair = tty->TS_orig_pair ? xstrdup (tty->TS_orig_pair) : NULL;
2121 xfree (default_set_foreground);
2122 default_set_foreground = tty->TS_set_foreground ? xstrdup (tty->TS_set_foreground)
2123 : NULL;
2125 xfree (default_set_background);
2126 default_set_background = tty->TS_set_background ? xstrdup (tty->TS_set_background)
2127 : NULL;
2129 default_max_colors = tty->TN_max_colors;
2130 default_max_pairs = tty->TN_max_pairs;
2131 default_no_color_video = tty->TN_no_color_video;
2133 else
2135 tty->TS_orig_pair = default_orig_pair;
2136 tty->TS_set_foreground = default_set_foreground;
2137 tty->TS_set_background = default_set_background;
2138 tty->TN_max_colors = default_max_colors;
2139 tty->TN_max_pairs = default_max_pairs;
2140 tty->TN_no_color_video = default_no_color_video;
2144 /* Setup one of the standard tty color schemes according to MODE.
2145 MODE's value is generally the number of colors which we want to
2146 support; zero means set up for the default capabilities, the ones
2147 we saw at init_tty time; -1 means turn off color support. */
2148 static void
2149 tty_setup_colors (struct tty_display_info *tty, int mode)
2151 /* Canonicalize all negative values of MODE. */
2152 if (mode < -1)
2153 mode = -1;
2155 switch (mode)
2157 case -1: /* no colors at all */
2158 tty->TN_max_colors = 0;
2159 tty->TN_max_pairs = 0;
2160 tty->TN_no_color_video = 0;
2161 tty->TS_set_foreground = tty->TS_set_background = tty->TS_orig_pair = NULL;
2162 break;
2163 case 0: /* default colors, if any */
2164 default:
2165 tty_default_color_capabilities (tty, 0);
2166 break;
2167 case 8: /* 8 standard ANSI colors */
2168 tty->TS_orig_pair = "\033[0m";
2169 #ifdef TERMINFO
2170 tty->TS_set_foreground = "\033[3%p1%dm";
2171 tty->TS_set_background = "\033[4%p1%dm";
2172 #else
2173 tty->TS_set_foreground = "\033[3%dm";
2174 tty->TS_set_background = "\033[4%dm";
2175 #endif
2176 tty->TN_max_colors = 8;
2177 tty->TN_max_pairs = 64;
2178 tty->TN_no_color_video = 0;
2179 break;
2183 void
2184 set_tty_color_mode (struct tty_display_info *tty, struct frame *f)
2186 Lisp_Object tem, val;
2187 Lisp_Object color_mode;
2188 int mode;
2189 Lisp_Object tty_color_mode_alist
2190 = Fintern_soft (build_string ("tty-color-mode-alist"), Qnil);
2192 tem = assq_no_quit (Qtty_color_mode, f->param_alist);
2193 val = CONSP (tem) ? XCDR (tem) : Qnil;
2195 if (INTEGERP (val))
2196 color_mode = val;
2197 else if (SYMBOLP (tty_color_mode_alist))
2199 tem = Fassq (val, Fsymbol_value (tty_color_mode_alist));
2200 color_mode = CONSP (tem) ? XCDR (tem) : Qnil;
2202 else
2203 color_mode = Qnil;
2205 mode = TYPE_RANGED_INTEGERP (int, color_mode) ? XINT (color_mode) : 0;
2207 if (mode != tty->previous_color_mode)
2209 tty->previous_color_mode = mode;
2210 tty_setup_colors (tty , mode);
2211 /* This recomputes all the faces given the new color definitions. */
2212 safe_call (1, intern ("tty-set-up-initial-frame-faces"));
2216 #endif /* !DOS_NT */
2220 /* Return the tty display object specified by TERMINAL. */
2222 static struct terminal *
2223 get_tty_terminal (Lisp_Object terminal, int throw)
2225 struct terminal *t = get_terminal (terminal, throw);
2227 if (t && t->type != output_termcap && t->type != output_msdos_raw)
2229 if (throw)
2230 error ("Device %d is not a termcap terminal device", t->id);
2231 else
2232 return NULL;
2235 return t;
2238 /* Return an active termcap device that uses the tty device with the
2239 given name.
2241 This function ignores suspended devices.
2243 Returns NULL if the named terminal device is not opened. */
2245 struct terminal *
2246 get_named_tty (const char *name)
2248 struct terminal *t;
2250 if (!name)
2251 emacs_abort ();
2253 for (t = terminal_list; t; t = t->next_terminal)
2255 if ((t->type == output_termcap || t->type == output_msdos_raw)
2256 && !strcmp (t->display_info.tty->name, name)
2257 && TERMINAL_ACTIVE_P (t))
2258 return t;
2261 return 0;
2265 DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0,
2266 doc: /* Return the type of the tty device that TERMINAL uses.
2267 Returns nil if TERMINAL is not on a tty device.
2269 TERMINAL can be a terminal object, a frame, or nil (meaning the
2270 selected frame's terminal). */)
2271 (Lisp_Object terminal)
2273 struct terminal *t = get_terminal (terminal, 1);
2275 if (t->type != output_termcap && t->type != output_msdos_raw)
2276 return Qnil;
2278 if (t->display_info.tty->type)
2279 return build_string (t->display_info.tty->type);
2280 else
2281 return Qnil;
2284 DEFUN ("controlling-tty-p", Fcontrolling_tty_p, Scontrolling_tty_p, 0, 1, 0,
2285 doc: /* Return non-nil if TERMINAL is the controlling tty of the Emacs process.
2287 TERMINAL can be a terminal object, a frame, or nil (meaning the
2288 selected frame's terminal). This function always returns nil if
2289 TERMINAL is not on a tty device. */)
2290 (Lisp_Object terminal)
2292 struct terminal *t = get_terminal (terminal, 1);
2294 if ((t->type != output_termcap && t->type != output_msdos_raw)
2295 || strcmp (t->display_info.tty->name, DEV_TTY) != 0)
2296 return Qnil;
2297 else
2298 return Qt;
2301 DEFUN ("tty-no-underline", Ftty_no_underline, Stty_no_underline, 0, 1, 0,
2302 doc: /* Declare that the tty used by TERMINAL does not handle underlining.
2303 This is used to override the terminfo data, for certain terminals that
2304 do not really do underlining, but say that they do. This function has
2305 no effect if used on a non-tty terminal.
2307 TERMINAL can be a terminal object, a frame or nil (meaning the
2308 selected frame's terminal). This function always returns nil if
2309 TERMINAL does not refer to a text terminal. */)
2310 (Lisp_Object terminal)
2312 struct terminal *t = get_terminal (terminal, 1);
2314 if (t->type == output_termcap)
2315 t->display_info.tty->TS_enter_underline_mode = 0;
2316 return Qnil;
2319 DEFUN ("tty-top-frame", Ftty_top_frame, Stty_top_frame, 0, 1, 0,
2320 doc: /* Return the topmost terminal frame on TERMINAL.
2321 TERMINAL can be a terminal object, a frame or nil (meaning the
2322 selected frame's terminal). This function returns nil if TERMINAL
2323 does not refer to a text terminal. Otherwise, it returns the
2324 top-most frame on the text terminal. */)
2325 (Lisp_Object terminal)
2327 struct terminal *t = get_terminal (terminal, 1);
2329 if (t->type == output_termcap)
2330 return t->display_info.tty->top_frame;
2331 return Qnil;
2336 DEFUN ("suspend-tty", Fsuspend_tty, Ssuspend_tty, 0, 1, 0,
2337 doc: /* Suspend the terminal device TTY.
2339 The device is restored to its default state, and Emacs ceases all
2340 access to the tty device. Frames that use the device are not deleted,
2341 but input is not read from them and if they change, their display is
2342 not updated.
2344 TTY may be a terminal object, a frame, or nil for the terminal device
2345 of the currently selected frame.
2347 This function runs `suspend-tty-functions' after suspending the
2348 device. The functions are run with one arg, the id of the suspended
2349 terminal device.
2351 `suspend-tty' does nothing if it is called on a device that is already
2352 suspended.
2354 A suspended tty may be resumed by calling `resume-tty' on it. */)
2355 (Lisp_Object tty)
2357 struct terminal *t = get_tty_terminal (tty, 1);
2358 FILE *f;
2360 if (!t)
2361 error ("Unknown tty device");
2363 f = t->display_info.tty->input;
2365 if (f)
2367 /* First run `suspend-tty-functions' and then clean up the tty
2368 state because `suspend-tty-functions' might need to change
2369 the tty state. */
2370 Lisp_Object args[2];
2371 args[0] = intern ("suspend-tty-functions");
2372 XSETTERMINAL (args[1], t);
2373 Frun_hook_with_args (2, args);
2375 reset_sys_modes (t->display_info.tty);
2376 delete_keyboard_wait_descriptor (fileno (f));
2378 #ifndef MSDOS
2379 fclose (f);
2380 if (f != t->display_info.tty->output)
2381 fclose (t->display_info.tty->output);
2382 #endif
2384 t->display_info.tty->input = 0;
2385 t->display_info.tty->output = 0;
2387 if (FRAMEP (t->display_info.tty->top_frame))
2388 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0);
2392 /* Clear display hooks to prevent further output. */
2393 clear_tty_hooks (t);
2395 return Qnil;
2398 DEFUN ("resume-tty", Fresume_tty, Sresume_tty, 0, 1, 0,
2399 doc: /* Resume the previously suspended terminal device TTY.
2400 The terminal is opened and reinitialized. Frames that are on the
2401 suspended terminal are revived.
2403 It is an error to resume a terminal while another terminal is active
2404 on the same device.
2406 This function runs `resume-tty-functions' after resuming the terminal.
2407 The functions are run with one arg, the id of the resumed terminal
2408 device.
2410 `resume-tty' does nothing if it is called on a device that is not
2411 suspended.
2413 TTY may be a terminal object, a frame, or nil (meaning the selected
2414 frame's terminal). */)
2415 (Lisp_Object tty)
2417 struct terminal *t = get_tty_terminal (tty, 1);
2418 int fd;
2420 if (!t)
2421 error ("Unknown tty device");
2423 if (!t->display_info.tty->input)
2425 if (get_named_tty (t->display_info.tty->name))
2426 error ("Cannot resume display while another display is active on the same device");
2428 #ifdef MSDOS
2429 t->display_info.tty->output = stdout;
2430 t->display_info.tty->input = stdin;
2431 #else /* !MSDOS */
2432 fd = emacs_open (t->display_info.tty->name, O_RDWR | O_NOCTTY, 0);
2434 if (fd == -1)
2435 error ("Can not reopen tty device %s: %s", t->display_info.tty->name, strerror (errno));
2437 if (strcmp (t->display_info.tty->name, DEV_TTY))
2438 dissociate_if_controlling_tty (fd);
2440 t->display_info.tty->output = fdopen (fd, "w+");
2441 t->display_info.tty->input = t->display_info.tty->output;
2442 #endif
2444 add_keyboard_wait_descriptor (fd);
2446 if (FRAMEP (t->display_info.tty->top_frame))
2448 struct frame *f = XFRAME (t->display_info.tty->top_frame);
2449 int width, height;
2450 int old_height = FRAME_COLS (f);
2451 int old_width = FRAME_LINES (f);
2453 /* Check if terminal/window size has changed while the frame
2454 was suspended. */
2455 get_tty_size (fileno (t->display_info.tty->input), &width, &height);
2456 if (width != old_width || height != old_height)
2457 change_frame_size (f, height, width, 0, 0, 0);
2458 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
2461 set_tty_hooks (t);
2462 init_sys_modes (t->display_info.tty);
2465 /* Run `resume-tty-functions'. */
2466 Lisp_Object args[2];
2467 args[0] = intern ("resume-tty-functions");
2468 XSETTERMINAL (args[1], t);
2469 Frun_hook_with_args (2, args);
2473 set_tty_hooks (t);
2475 return Qnil;
2479 /***********************************************************************
2480 Mouse
2481 ***********************************************************************/
2483 #ifdef HAVE_GPM
2485 #ifndef HAVE_WINDOW_SYSTEM
2486 void
2487 term_mouse_moveto (int x, int y)
2489 /* TODO: how to set mouse position?
2490 const char *name;
2491 int fd;
2492 name = (const char *) ttyname (0);
2493 fd = open (name, O_WRONLY);
2494 SOME_FUNCTION (x, y, fd);
2495 close (fd);
2496 last_mouse_x = x;
2497 last_mouse_y = y; */
2499 #endif /* HAVE_WINDOW_SYSTEM */
2501 /* Implementation of draw_row_with_mouse_face for TTY/GPM. */
2502 void
2503 tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *row,
2504 int start_hpos, int end_hpos,
2505 enum draw_glyphs_face draw)
2507 int nglyphs = end_hpos - start_hpos;
2508 struct frame *f = XFRAME (WINDOW_FRAME (w));
2509 struct tty_display_info *tty = FRAME_TTY (f);
2510 int face_id = tty->mouse_highlight.mouse_face_face_id;
2511 int save_x, save_y, pos_x, pos_y;
2513 if (end_hpos >= row->used[TEXT_AREA])
2514 nglyphs = row->used[TEXT_AREA] - start_hpos;
2516 pos_y = row->y + WINDOW_TOP_EDGE_Y (w);
2517 pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos + WINDOW_LEFT_EDGE_X (w);
2519 /* Save current cursor co-ordinates. */
2520 save_y = curY (tty);
2521 save_x = curX (tty);
2522 cursor_to (f, pos_y, pos_x);
2524 if (draw == DRAW_MOUSE_FACE)
2525 tty_write_glyphs_with_face (f, row->glyphs[TEXT_AREA] + start_hpos,
2526 nglyphs, face_id);
2527 else if (draw == DRAW_NORMAL_TEXT)
2528 write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
2530 cursor_to (f, save_y, save_x);
2533 static int
2534 term_mouse_movement (FRAME_PTR frame, Gpm_Event *event)
2536 /* Has the mouse moved off the glyph it was on at the last sighting? */
2537 if (event->x != last_mouse_x || event->y != last_mouse_y)
2539 frame->mouse_moved = 1;
2540 note_mouse_highlight (frame, event->x, event->y);
2541 /* Remember which glyph we're now on. */
2542 last_mouse_x = event->x;
2543 last_mouse_y = event->y;
2544 return 1;
2546 return 0;
2549 /* Return the Time that corresponds to T. Wrap around on overflow. */
2550 static Time
2551 timeval_to_Time (struct timeval const *t)
2553 Time s_1000, ms;
2555 s_1000 = t->tv_sec;
2556 s_1000 *= 1000;
2557 ms = t->tv_usec / 1000;
2558 return s_1000 + ms;
2561 /* Return the current position of the mouse.
2563 Set *f to the frame the mouse is in, or zero if the mouse is in no
2564 Emacs frame. If it is set to zero, all the other arguments are
2565 garbage.
2567 Set *bar_window to Qnil, and *x and *y to the column and
2568 row of the character cell the mouse is over.
2570 Set *timeptr to the time the mouse was at the returned position.
2572 This clears mouse_moved until the next motion
2573 event arrives. */
2574 static void
2575 term_mouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
2576 enum scroll_bar_part *part, Lisp_Object *x,
2577 Lisp_Object *y, Time *timeptr)
2579 struct timeval now;
2581 *fp = SELECTED_FRAME ();
2582 (*fp)->mouse_moved = 0;
2584 *bar_window = Qnil;
2585 *part = 0;
2587 XSETINT (*x, last_mouse_x);
2588 XSETINT (*y, last_mouse_y);
2589 gettimeofday(&now, 0);
2590 *timeptr = timeval_to_Time (&now);
2593 /* Prepare a mouse-event in *RESULT for placement in the input queue.
2595 If the event is a button press, then note that we have grabbed
2596 the mouse. */
2598 static Lisp_Object
2599 term_mouse_click (struct input_event *result, Gpm_Event *event,
2600 struct frame *f)
2602 struct timeval now;
2603 int i, j;
2605 result->kind = GPM_CLICK_EVENT;
2606 for (i = 0, j = GPM_B_LEFT; i < 3; i++, j >>= 1 )
2608 if (event->buttons & j) {
2609 result->code = i; /* button number */
2610 break;
2613 gettimeofday(&now, 0);
2614 result->timestamp = timeval_to_Time (&now);
2616 if (event->type & GPM_UP)
2617 result->modifiers = up_modifier;
2618 else if (event->type & GPM_DOWN)
2619 result->modifiers = down_modifier;
2620 else
2621 result->modifiers = 0;
2623 if (event->type & GPM_SINGLE)
2624 result->modifiers |= click_modifier;
2626 if (event->type & GPM_DOUBLE)
2627 result->modifiers |= double_modifier;
2629 if (event->type & GPM_TRIPLE)
2630 result->modifiers |= triple_modifier;
2632 if (event->type & GPM_DRAG)
2633 result->modifiers |= drag_modifier;
2635 if (!(event->type & (GPM_MOVE | GPM_DRAG))) {
2637 /* 1 << KG_SHIFT */
2638 if (event->modifiers & (1 << 0))
2639 result->modifiers |= shift_modifier;
2641 /* 1 << KG_CTRL */
2642 if (event->modifiers & (1 << 2))
2643 result->modifiers |= ctrl_modifier;
2645 /* 1 << KG_ALT || KG_ALTGR */
2646 if (event->modifiers & (1 << 3)
2647 || event->modifiers & (1 << 1))
2648 result->modifiers |= meta_modifier;
2651 XSETINT (result->x, event->x);
2652 XSETINT (result->y, event->y);
2653 XSETFRAME (result->frame_or_window, f);
2654 result->arg = Qnil;
2655 return Qnil;
2659 handle_one_term_event (struct tty_display_info *tty, Gpm_Event *event, struct input_event* hold_quit)
2661 struct frame *f = XFRAME (tty->top_frame);
2662 struct input_event ie;
2663 int do_help = 0;
2664 int count = 0;
2666 EVENT_INIT (ie);
2667 ie.kind = NO_EVENT;
2668 ie.arg = Qnil;
2670 if (event->type & (GPM_MOVE | GPM_DRAG)) {
2671 previous_help_echo_string = help_echo_string;
2672 help_echo_string = Qnil;
2674 Gpm_DrawPointer (event->x, event->y, fileno (tty->output));
2676 if (!term_mouse_movement (f, event))
2677 help_echo_string = previous_help_echo_string;
2679 /* If the contents of the global variable help_echo_string
2680 has changed, generate a HELP_EVENT. */
2681 if (!NILP (help_echo_string)
2682 || !NILP (previous_help_echo_string))
2683 do_help = 1;
2685 goto done;
2687 else {
2688 f->mouse_moved = 0;
2689 term_mouse_click (&ie, event, f);
2692 done:
2693 if (ie.kind != NO_EVENT)
2695 kbd_buffer_store_event_hold (&ie, hold_quit);
2696 count++;
2699 if (do_help
2700 && !(hold_quit && hold_quit->kind != NO_EVENT))
2702 Lisp_Object frame;
2704 if (f)
2705 XSETFRAME (frame, f);
2706 else
2707 frame = Qnil;
2709 gen_help_event (help_echo_string, frame, help_echo_window,
2710 help_echo_object, help_echo_pos);
2711 count++;
2714 return count;
2717 DEFUN ("gpm-mouse-start", Fgpm_mouse_start, Sgpm_mouse_start,
2718 0, 0, 0,
2719 doc: /* Open a connection to Gpm.
2720 Gpm-mouse can only be activated for one tty at a time. */)
2721 (void)
2723 struct frame *f = SELECTED_FRAME ();
2724 struct tty_display_info *tty
2725 = ((f)->output_method == output_termcap
2726 ? (f)->terminal->display_info.tty : NULL);
2727 Gpm_Connect connection;
2729 if (!tty)
2730 error ("Gpm-mouse only works in the GNU/Linux console");
2731 if (gpm_tty == tty)
2732 return Qnil; /* Already activated, nothing to do. */
2733 if (gpm_tty)
2734 error ("Gpm-mouse can only be activated for one tty at a time");
2736 connection.eventMask = ~0;
2737 connection.defaultMask = ~GPM_HARD;
2738 connection.maxMod = ~0;
2739 connection.minMod = 0;
2740 gpm_zerobased = 1;
2742 if (Gpm_Open (&connection, 0) < 0)
2743 error ("Gpm-mouse failed to connect to the gpm daemon");
2744 else
2746 gpm_tty = tty;
2747 /* `init_sys_modes' arranges for mouse movements sent through gpm_fd
2748 to generate SIGIOs. Apparently we need to call reset_sys_modes
2749 before calling init_sys_modes. */
2750 reset_sys_modes (tty);
2751 init_sys_modes (tty);
2752 add_gpm_wait_descriptor (gpm_fd);
2753 return Qnil;
2757 void
2758 close_gpm (int fd)
2760 if (fd >= 0)
2761 delete_gpm_wait_descriptor (fd);
2762 while (Gpm_Close()); /* close all the stack */
2763 gpm_tty = NULL;
2766 DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop, Sgpm_mouse_stop,
2767 0, 0, 0,
2768 doc: /* Close a connection to Gpm. */)
2769 (void)
2771 struct frame *f = SELECTED_FRAME ();
2772 struct tty_display_info *tty
2773 = ((f)->output_method == output_termcap
2774 ? (f)->terminal->display_info.tty : NULL);
2776 if (!tty || gpm_tty != tty)
2777 return Qnil; /* Not activated on this terminal, nothing to do. */
2779 close_gpm (gpm_fd);
2780 return Qnil;
2782 #endif /* HAVE_GPM */
2785 #ifndef MSDOS
2786 /***********************************************************************
2787 Initialization
2788 ***********************************************************************/
2790 /* Initialize the tty-dependent part of frame F. The frame must
2791 already have its device initialized. */
2793 void
2794 create_tty_output (struct frame *f)
2796 struct tty_output *t = xzalloc (sizeof *t);
2798 if (! FRAME_TERMCAP_P (f))
2799 emacs_abort ();
2801 t->display_info = FRAME_TERMINAL (f)->display_info.tty;
2803 f->output_data.tty = t;
2806 /* Delete frame F's face cache, and its tty-dependent part. */
2808 static void
2809 tty_free_frame_resources (struct frame *f)
2811 if (! FRAME_TERMCAP_P (f))
2812 emacs_abort ();
2814 if (FRAME_FACE_CACHE (f))
2815 free_frame_faces (f);
2817 xfree (f->output_data.tty);
2820 #else /* MSDOS */
2822 /* Delete frame F's face cache. */
2824 static void
2825 tty_free_frame_resources (struct frame *f)
2827 if (! FRAME_TERMCAP_P (f) && ! FRAME_MSDOS_P (f))
2828 emacs_abort ();
2830 if (FRAME_FACE_CACHE (f))
2831 free_frame_faces (f);
2833 #endif /* MSDOS */
2835 /* Reset the hooks in TERMINAL. */
2837 static void
2838 clear_tty_hooks (struct terminal *terminal)
2840 terminal->rif = 0;
2841 terminal->cursor_to_hook = 0;
2842 terminal->raw_cursor_to_hook = 0;
2843 terminal->clear_to_end_hook = 0;
2844 terminal->clear_frame_hook = 0;
2845 terminal->clear_end_of_line_hook = 0;
2846 terminal->ins_del_lines_hook = 0;
2847 terminal->insert_glyphs_hook = 0;
2848 terminal->write_glyphs_hook = 0;
2849 terminal->delete_glyphs_hook = 0;
2850 terminal->ring_bell_hook = 0;
2851 terminal->reset_terminal_modes_hook = 0;
2852 terminal->set_terminal_modes_hook = 0;
2853 terminal->update_begin_hook = 0;
2854 terminal->update_end_hook = 0;
2855 terminal->set_terminal_window_hook = 0;
2856 terminal->mouse_position_hook = 0;
2857 terminal->frame_rehighlight_hook = 0;
2858 terminal->frame_raise_lower_hook = 0;
2859 terminal->fullscreen_hook = 0;
2860 terminal->set_vertical_scroll_bar_hook = 0;
2861 terminal->condemn_scroll_bars_hook = 0;
2862 terminal->redeem_scroll_bar_hook = 0;
2863 terminal->judge_scroll_bars_hook = 0;
2864 terminal->read_socket_hook = 0;
2865 terminal->frame_up_to_date_hook = 0;
2867 /* Leave these two set, or suspended frames are not deleted
2868 correctly. */
2869 terminal->delete_frame_hook = &tty_free_frame_resources;
2870 terminal->delete_terminal_hook = &delete_tty;
2873 /* Initialize hooks in TERMINAL with the values needed for a tty. */
2875 static void
2876 set_tty_hooks (struct terminal *terminal)
2878 terminal->rif = 0; /* ttys don't support window-based redisplay. */
2880 terminal->cursor_to_hook = &tty_cursor_to;
2881 terminal->raw_cursor_to_hook = &tty_raw_cursor_to;
2883 terminal->clear_to_end_hook = &tty_clear_to_end;
2884 terminal->clear_frame_hook = &tty_clear_frame;
2885 terminal->clear_end_of_line_hook = &tty_clear_end_of_line;
2887 terminal->ins_del_lines_hook = &tty_ins_del_lines;
2889 terminal->insert_glyphs_hook = &tty_insert_glyphs;
2890 terminal->write_glyphs_hook = &tty_write_glyphs;
2891 terminal->delete_glyphs_hook = &tty_delete_glyphs;
2893 terminal->ring_bell_hook = &tty_ring_bell;
2895 terminal->reset_terminal_modes_hook = &tty_reset_terminal_modes;
2896 terminal->set_terminal_modes_hook = &tty_set_terminal_modes;
2897 terminal->update_begin_hook = 0; /* Not needed. */
2898 terminal->update_end_hook = &tty_update_end;
2899 terminal->set_terminal_window_hook = &tty_set_terminal_window;
2901 terminal->mouse_position_hook = 0; /* Not needed. */
2902 terminal->frame_rehighlight_hook = 0; /* Not needed. */
2903 terminal->frame_raise_lower_hook = 0; /* Not needed. */
2905 terminal->set_vertical_scroll_bar_hook = 0; /* Not needed. */
2906 terminal->condemn_scroll_bars_hook = 0; /* Not needed. */
2907 terminal->redeem_scroll_bar_hook = 0; /* Not needed. */
2908 terminal->judge_scroll_bars_hook = 0; /* Not needed. */
2910 terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */
2911 terminal->frame_up_to_date_hook = 0; /* Not needed. */
2913 terminal->delete_frame_hook = &tty_free_frame_resources;
2914 terminal->delete_terminal_hook = &delete_tty;
2917 /* Drop the controlling terminal if fd is the same device. */
2918 static void
2919 dissociate_if_controlling_tty (int fd)
2921 #ifndef DOS_NT
2922 pid_t pgid = tcgetpgrp (fd); /* If tcgetpgrp succeeds, fd is the ctty. */
2923 if (pgid != -1)
2925 #if defined (USG5)
2926 setpgrp ();
2927 no_controlling_tty = 1;
2928 #elif defined (CYGWIN)
2929 setsid ();
2930 no_controlling_tty = 1;
2931 #else
2932 #ifdef TIOCNOTTY /* Try BSD ioctls. */
2933 sigset_t blocked;
2934 sigemptyset (&blocked);
2935 sigaddset (&blocked, SIGTTOU);
2936 pthread_sigmask (SIG_BLOCK, &blocked, 0);
2937 fd = emacs_open (DEV_TTY, O_RDWR, 0);
2938 if (fd != -1 && ioctl (fd, TIOCNOTTY, 0) != -1)
2940 no_controlling_tty = 1;
2942 if (fd != -1)
2943 emacs_close (fd);
2944 pthread_sigmask (SIG_UNBLOCK, &blocked, 0);
2945 #else
2946 # error "Unknown system."
2947 #endif /* ! TIOCNOTTY */
2948 #endif /* ! USG */
2950 #endif /* !DOS_NT */
2953 /* Create a termcap display on the tty device with the given name and
2954 type.
2956 If NAME is NULL, then use the controlling tty, i.e., "/dev/tty".
2957 Otherwise NAME should be a path to the tty device file,
2958 e.g. "/dev/pts/7".
2960 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
2962 If MUST_SUCCEED is true, then all errors are fatal. */
2964 struct terminal *
2965 init_tty (const char *name, const char *terminal_type, int must_succeed)
2967 char *area = NULL;
2968 char **address = &area;
2969 int buffer_size = 4096;
2970 int status;
2971 struct tty_display_info *tty = NULL;
2972 struct terminal *terminal = NULL;
2973 int ctty = 0; /* 1 if asked to open controlling tty. */
2975 if (!terminal_type)
2976 maybe_fatal (must_succeed, 0,
2977 "Unknown terminal type",
2978 "Unknown terminal type");
2980 if (name == NULL)
2981 name = DEV_TTY;
2982 if (!strcmp (name, DEV_TTY))
2983 ctty = 1;
2985 /* If we already have a terminal on the given device, use that. If
2986 all such terminals are suspended, create a new one instead. */
2987 /* XXX Perhaps this should be made explicit by having init_tty
2988 always create a new terminal and separating terminal and frame
2989 creation on Lisp level. */
2990 terminal = get_named_tty (name);
2991 if (terminal)
2992 return terminal;
2994 terminal = create_terminal ();
2995 #ifdef MSDOS
2996 if (been_here > 0)
2997 maybe_fatal (0, 0, "Attempt to create another terminal %s", "",
2998 name, "");
2999 been_here = 1;
3000 tty = &the_only_display_info;
3001 #else
3002 tty = xzalloc (sizeof *tty);
3003 #endif
3004 tty->top_frame = Qnil;
3005 tty->next = tty_list;
3006 tty_list = tty;
3008 terminal->type = output_termcap;
3009 terminal->display_info.tty = tty;
3010 tty->terminal = terminal;
3012 tty->Wcm = xmalloc (sizeof *tty->Wcm);
3013 Wcm_clear (tty);
3015 encode_terminal_src_size = 0;
3016 encode_terminal_dst_size = 0;
3019 #ifndef DOS_NT
3020 set_tty_hooks (terminal);
3023 int fd;
3024 FILE *file;
3026 #ifdef O_IGNORE_CTTY
3027 if (!ctty)
3028 /* Open the terminal device. Don't recognize it as our
3029 controlling terminal, and don't make it the controlling tty
3030 if we don't have one at the moment. */
3031 fd = emacs_open (name, O_RDWR | O_IGNORE_CTTY | O_NOCTTY, 0);
3032 else
3033 #endif /* O_IGNORE_CTTY */
3034 /* Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
3035 defined on Hurd. On other systems, we need to explicitly
3036 dissociate ourselves from the controlling tty when we want to
3037 open a frame on the same terminal. */
3038 fd = emacs_open (name, O_RDWR | O_NOCTTY, 0);
3040 tty->name = xstrdup (name);
3041 terminal->name = xstrdup (name);
3043 if (fd < 0)
3044 maybe_fatal (must_succeed, terminal,
3045 "Could not open file: %s",
3046 "Could not open file: %s",
3047 name);
3048 if (!isatty (fd))
3050 close (fd);
3051 maybe_fatal (must_succeed, terminal,
3052 "Not a tty device: %s",
3053 "Not a tty device: %s",
3054 name);
3057 #ifndef O_IGNORE_CTTY
3058 if (!ctty)
3059 dissociate_if_controlling_tty (fd);
3060 #endif
3062 file = fdopen (fd, "w+");
3063 tty->input = file;
3064 tty->output = file;
3067 tty->type = xstrdup (terminal_type);
3069 add_keyboard_wait_descriptor (fileno (tty->input));
3071 Wcm_clear (tty);
3073 tty->termcap_term_buffer = xmalloc (buffer_size);
3075 /* On some systems, tgetent tries to access the controlling
3076 terminal. */
3078 sigset_t blocked;
3079 sigemptyset (&blocked);
3080 sigaddset (&blocked, SIGTTOU);
3081 pthread_sigmask (SIG_BLOCK, &blocked, 0);
3082 status = tgetent (tty->termcap_term_buffer, terminal_type);
3083 pthread_sigmask (SIG_UNBLOCK, &blocked, 0);
3086 if (status < 0)
3088 #ifdef TERMINFO
3089 maybe_fatal (must_succeed, terminal,
3090 "Cannot open terminfo database file",
3091 "Cannot open terminfo database file");
3092 #else
3093 maybe_fatal (must_succeed, terminal,
3094 "Cannot open termcap database file",
3095 "Cannot open termcap database file");
3096 #endif
3098 if (status == 0)
3100 maybe_fatal (must_succeed, terminal,
3101 "Terminal type %s is not defined",
3102 "Terminal type %s is not defined.\n\
3103 If that is not the actual type of terminal you have,\n\
3104 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3105 `setenv TERM ...') to specify the correct type. It may be necessary\n"
3106 #ifdef TERMINFO
3107 "to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3108 #else
3109 "to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3110 #endif
3111 terminal_type);
3114 #ifndef TERMINFO
3115 if (strlen (tty->termcap_term_buffer) >= buffer_size)
3116 emacs_abort ();
3117 buffer_size = strlen (tty->termcap_term_buffer);
3118 #endif
3119 tty->termcap_strings_buffer = area = xmalloc (buffer_size);
3120 tty->TS_ins_line = tgetstr ("al", address);
3121 tty->TS_ins_multi_lines = tgetstr ("AL", address);
3122 tty->TS_bell = tgetstr ("bl", address);
3123 BackTab (tty) = tgetstr ("bt", address);
3124 tty->TS_clr_to_bottom = tgetstr ("cd", address);
3125 tty->TS_clr_line = tgetstr ("ce", address);
3126 tty->TS_clr_frame = tgetstr ("cl", address);
3127 ColPosition (tty) = NULL; /* tgetstr ("ch", address); */
3128 AbsPosition (tty) = tgetstr ("cm", address);
3129 CR (tty) = tgetstr ("cr", address);
3130 tty->TS_set_scroll_region = tgetstr ("cs", address);
3131 tty->TS_set_scroll_region_1 = tgetstr ("cS", address);
3132 RowPosition (tty) = tgetstr ("cv", address);
3133 tty->TS_del_char = tgetstr ("dc", address);
3134 tty->TS_del_multi_chars = tgetstr ("DC", address);
3135 tty->TS_del_line = tgetstr ("dl", address);
3136 tty->TS_del_multi_lines = tgetstr ("DL", address);
3137 tty->TS_delete_mode = tgetstr ("dm", address);
3138 tty->TS_end_delete_mode = tgetstr ("ed", address);
3139 tty->TS_end_insert_mode = tgetstr ("ei", address);
3140 Home (tty) = tgetstr ("ho", address);
3141 tty->TS_ins_char = tgetstr ("ic", address);
3142 tty->TS_ins_multi_chars = tgetstr ("IC", address);
3143 tty->TS_insert_mode = tgetstr ("im", address);
3144 tty->TS_pad_inserted_char = tgetstr ("ip", address);
3145 tty->TS_end_keypad_mode = tgetstr ("ke", address);
3146 tty->TS_keypad_mode = tgetstr ("ks", address);
3147 LastLine (tty) = tgetstr ("ll", address);
3148 Right (tty) = tgetstr ("nd", address);
3149 Down (tty) = tgetstr ("do", address);
3150 if (!Down (tty))
3151 Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do" */
3152 if (tgetflag ("bs"))
3153 Left (tty) = "\b"; /* can't possibly be longer! */
3154 else /* (Actually, "bs" is obsolete...) */
3155 Left (tty) = tgetstr ("le", address);
3156 if (!Left (tty))
3157 Left (tty) = tgetstr ("bc", address); /* Obsolete name for "le" */
3158 tty->TS_pad_char = tgetstr ("pc", address);
3159 tty->TS_repeat = tgetstr ("rp", address);
3160 tty->TS_end_standout_mode = tgetstr ("se", address);
3161 tty->TS_fwd_scroll = tgetstr ("sf", address);
3162 tty->TS_standout_mode = tgetstr ("so", address);
3163 tty->TS_rev_scroll = tgetstr ("sr", address);
3164 tty->Wcm->cm_tab = tgetstr ("ta", address);
3165 tty->TS_end_termcap_modes = tgetstr ("te", address);
3166 tty->TS_termcap_modes = tgetstr ("ti", address);
3167 Up (tty) = tgetstr ("up", address);
3168 tty->TS_visible_bell = tgetstr ("vb", address);
3169 tty->TS_cursor_normal = tgetstr ("ve", address);
3170 tty->TS_cursor_visible = tgetstr ("vs", address);
3171 tty->TS_cursor_invisible = tgetstr ("vi", address);
3172 tty->TS_set_window = tgetstr ("wi", address);
3174 tty->TS_enter_underline_mode = tgetstr ("us", address);
3175 tty->TS_exit_underline_mode = tgetstr ("ue", address);
3176 tty->TS_enter_bold_mode = tgetstr ("md", address);
3177 tty->TS_enter_italic_mode = tgetstr ("ZH", address);
3178 tty->TS_enter_dim_mode = tgetstr ("mh", address);
3179 tty->TS_enter_reverse_mode = tgetstr ("mr", address);
3180 tty->TS_enter_alt_charset_mode = tgetstr ("as", address);
3181 tty->TS_exit_alt_charset_mode = tgetstr ("ae", address);
3182 tty->TS_exit_attribute_mode = tgetstr ("me", address);
3184 MultiUp (tty) = tgetstr ("UP", address);
3185 MultiDown (tty) = tgetstr ("DO", address);
3186 MultiLeft (tty) = tgetstr ("LE", address);
3187 MultiRight (tty) = tgetstr ("RI", address);
3189 /* SVr4/ANSI color support. If "op" isn't available, don't support
3190 color because we can't switch back to the default foreground and
3191 background. */
3192 tty->TS_orig_pair = tgetstr ("op", address);
3193 if (tty->TS_orig_pair)
3195 tty->TS_set_foreground = tgetstr ("AF", address);
3196 tty->TS_set_background = tgetstr ("AB", address);
3197 if (!tty->TS_set_foreground)
3199 /* SVr4. */
3200 tty->TS_set_foreground = tgetstr ("Sf", address);
3201 tty->TS_set_background = tgetstr ("Sb", address);
3204 tty->TN_max_colors = tgetnum ("Co");
3205 tty->TN_max_pairs = tgetnum ("pa");
3207 tty->TN_no_color_video = tgetnum ("NC");
3208 if (tty->TN_no_color_video == -1)
3209 tty->TN_no_color_video = 0;
3212 tty_default_color_capabilities (tty, 1);
3214 MagicWrap (tty) = tgetflag ("xn");
3215 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
3216 the former flag imply the latter. */
3217 AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
3218 terminal->memory_below_frame = tgetflag ("db");
3219 tty->TF_hazeltine = tgetflag ("hz");
3220 terminal->must_write_spaces = tgetflag ("in");
3221 tty->meta_key = tgetflag ("km") || tgetflag ("MT");
3222 tty->TF_insmode_motion = tgetflag ("mi");
3223 tty->TF_standout_motion = tgetflag ("ms");
3224 tty->TF_underscore = tgetflag ("ul");
3225 tty->TF_teleray = tgetflag ("xt");
3227 #else /* DOS_NT */
3228 #ifdef WINDOWSNT
3230 struct frame *f = XFRAME (selected_frame);
3232 initialize_w32_display (terminal);
3234 FrameRows (tty) = FRAME_LINES (f);
3235 FrameCols (tty) = FRAME_COLS (f);
3236 tty->specified_window = FRAME_LINES (f);
3238 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
3239 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
3240 terminal->char_ins_del_ok = 1;
3241 baud_rate = 19200;
3243 #else /* MSDOS */
3245 int height, width;
3246 if (strcmp (terminal_type, "internal") == 0)
3247 terminal->type = output_msdos_raw;
3248 initialize_msdos_display (terminal);
3250 get_tty_size (fileno (tty->input), &width, &height);
3251 FrameCols (tty) = width;
3252 FrameRows (tty) = height;
3253 terminal->char_ins_del_ok = 0;
3254 init_baud_rate (fileno (tty->input));
3256 #endif /* MSDOS */
3257 tty->output = stdout;
3258 tty->input = stdin;
3259 /* The following two are inaccessible from w32console.c. */
3260 terminal->delete_frame_hook = &tty_free_frame_resources;
3261 terminal->delete_terminal_hook = &delete_tty;
3263 tty->name = xstrdup (name);
3264 terminal->name = xstrdup (name);
3265 tty->type = xstrdup (terminal_type);
3267 add_keyboard_wait_descriptor (0);
3269 tty->delete_in_insert_mode = 1;
3271 UseTabs (tty) = 0;
3272 terminal->scroll_region_ok = 0;
3274 /* Seems to insert lines when it's not supposed to, messing up the
3275 display. In doing a trace, it didn't seem to be called much, so I
3276 don't think we're losing anything by turning it off. */
3277 terminal->line_ins_del_ok = 0;
3279 tty->TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
3280 #endif /* DOS_NT */
3282 #ifdef HAVE_GPM
3283 terminal->mouse_position_hook = term_mouse_position;
3284 tty->mouse_highlight.mouse_face_window = Qnil;
3285 #endif
3287 terminal->kboard = xmalloc (sizeof *terminal->kboard);
3288 init_kboard (terminal->kboard);
3289 kset_window_system (terminal->kboard, Qnil);
3290 terminal->kboard->next_kboard = all_kboards;
3291 all_kboards = terminal->kboard;
3292 terminal->kboard->reference_count++;
3293 /* Don't let the initial kboard remain current longer than necessary.
3294 That would cause problems if a file loaded on startup tries to
3295 prompt in the mini-buffer. */
3296 if (current_kboard == initial_kboard)
3297 current_kboard = terminal->kboard;
3298 #ifndef DOS_NT
3299 term_get_fkeys (address, terminal->kboard);
3301 /* Get frame size from system, or else from termcap. */
3303 int height, width;
3304 get_tty_size (fileno (tty->input), &width, &height);
3305 FrameCols (tty) = width;
3306 FrameRows (tty) = height;
3309 if (FrameCols (tty) <= 0)
3310 FrameCols (tty) = tgetnum ("co");
3311 if (FrameRows (tty) <= 0)
3312 FrameRows (tty) = tgetnum ("li");
3314 if (FrameRows (tty) < 3 || FrameCols (tty) < 3)
3315 maybe_fatal (must_succeed, terminal,
3316 "Screen size %dx%d is too small",
3317 "Screen size %dx%d is too small",
3318 FrameCols (tty), FrameRows (tty));
3320 TabWidth (tty) = tgetnum ("tw");
3322 if (!tty->TS_bell)
3323 tty->TS_bell = "\07";
3325 if (!tty->TS_fwd_scroll)
3326 tty->TS_fwd_scroll = Down (tty);
3328 PC = tty->TS_pad_char ? *tty->TS_pad_char : 0;
3330 if (TabWidth (tty) < 0)
3331 TabWidth (tty) = 8;
3333 /* Turned off since /etc/termcap seems to have :ta= for most terminals
3334 and newer termcap doc does not seem to say there is a default.
3335 if (!tty->Wcm->cm_tab)
3336 tty->Wcm->cm_tab = "\t";
3339 /* We don't support standout modes that use `magic cookies', so
3340 turn off any that do. */
3341 if (tty->TS_standout_mode && tgetnum ("sg") >= 0)
3343 tty->TS_standout_mode = 0;
3344 tty->TS_end_standout_mode = 0;
3346 if (tty->TS_enter_underline_mode && tgetnum ("ug") >= 0)
3348 tty->TS_enter_underline_mode = 0;
3349 tty->TS_exit_underline_mode = 0;
3352 /* If there's no standout mode, try to use underlining instead. */
3353 if (tty->TS_standout_mode == 0)
3355 tty->TS_standout_mode = tty->TS_enter_underline_mode;
3356 tty->TS_end_standout_mode = tty->TS_exit_underline_mode;
3359 /* If no `se' string, try using a `me' string instead.
3360 If that fails, we can't use standout mode at all. */
3361 if (tty->TS_end_standout_mode == 0)
3363 char *s = tgetstr ("me", address);
3364 if (s != 0)
3365 tty->TS_end_standout_mode = s;
3366 else
3367 tty->TS_standout_mode = 0;
3370 if (tty->TF_teleray)
3372 tty->Wcm->cm_tab = 0;
3373 /* We can't support standout mode, because it uses magic cookies. */
3374 tty->TS_standout_mode = 0;
3375 /* But that means we cannot rely on ^M to go to column zero! */
3376 CR (tty) = 0;
3377 /* LF can't be trusted either -- can alter hpos */
3378 /* if move at column 0 thru a line with TS_standout_mode */
3379 Down (tty) = 0;
3382 tty->specified_window = FrameRows (tty);
3384 if (Wcm_init (tty) == -1) /* can't do cursor motion */
3386 maybe_fatal (must_succeed, terminal,
3387 "Terminal type \"%s\" is not powerful enough to run Emacs",
3388 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3389 It lacks the ability to position the cursor.\n\
3390 If that is not the actual type of terminal you have,\n\
3391 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3392 `setenv TERM ...') to specify the correct type. It may be necessary\n"
3393 # ifdef TERMINFO
3394 "to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3395 # else /* TERMCAP */
3396 "to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3397 # endif /* TERMINFO */
3398 terminal_type);
3401 if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
3402 maybe_fatal (must_succeed, terminal,
3403 "Could not determine the frame size",
3404 "Could not determine the frame size");
3406 tty->delete_in_insert_mode
3407 = tty->TS_delete_mode && tty->TS_insert_mode
3408 && !strcmp (tty->TS_delete_mode, tty->TS_insert_mode);
3410 tty->se_is_so = (tty->TS_standout_mode
3411 && tty->TS_end_standout_mode
3412 && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode));
3414 UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8;
3416 terminal->scroll_region_ok
3417 = (tty->Wcm->cm_abs
3418 && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
3420 terminal->line_ins_del_ok
3421 = (((tty->TS_ins_line || tty->TS_ins_multi_lines)
3422 && (tty->TS_del_line || tty->TS_del_multi_lines))
3423 || (terminal->scroll_region_ok
3424 && tty->TS_fwd_scroll && tty->TS_rev_scroll));
3426 terminal->char_ins_del_ok
3427 = ((tty->TS_ins_char || tty->TS_insert_mode
3428 || tty->TS_pad_inserted_char || tty->TS_ins_multi_chars)
3429 && (tty->TS_del_char || tty->TS_del_multi_chars));
3431 terminal->fast_clear_end_of_line = tty->TS_clr_line != 0;
3433 init_baud_rate (fileno (tty->input));
3435 #endif /* not DOS_NT */
3437 /* Init system terminal modes (RAW or CBREAK, etc.). */
3438 init_sys_modes (tty);
3440 return terminal;
3444 static void
3445 vfatal (const char *str, va_list ap)
3447 fprintf (stderr, "emacs: ");
3448 vfprintf (stderr, str, ap);
3449 if (!(strlen (str) > 0 && str[strlen (str) - 1] == '\n'))
3450 fprintf (stderr, "\n");
3451 fflush (stderr);
3452 exit (1);
3456 /* Auxiliary error-handling function for init_tty.
3457 Delete TERMINAL, then call error or fatal with str1 or str2,
3458 respectively, according to whether MUST_SUCCEED is zero or not. */
3460 static void
3461 maybe_fatal (int must_succeed, struct terminal *terminal,
3462 const char *str1, const char *str2, ...)
3464 va_list ap;
3465 va_start (ap, str2);
3466 if (terminal)
3467 delete_tty (terminal);
3469 if (must_succeed)
3470 vfatal (str2, ap);
3471 else
3472 verror (str1, ap);
3474 va_end (ap);
3475 emacs_abort ();
3478 void
3479 fatal (const char *str, ...)
3481 va_list ap;
3482 va_start (ap, str);
3483 vfatal (str, ap);
3484 va_end (ap);
3489 /* Delete the given tty terminal, closing all frames on it. */
3491 static void
3492 delete_tty (struct terminal *terminal)
3494 struct tty_display_info *tty;
3496 /* Protect against recursive calls. delete_frame in
3497 delete_terminal calls us back when it deletes our last frame. */
3498 if (!terminal->name)
3499 return;
3501 if (terminal->type != output_termcap)
3502 emacs_abort ();
3504 tty = terminal->display_info.tty;
3506 if (tty == tty_list)
3507 tty_list = tty->next;
3508 else
3510 struct tty_display_info *p;
3511 for (p = tty_list; p && p->next != tty; p = p->next)
3514 if (! p)
3515 /* This should not happen. */
3516 emacs_abort ();
3518 p->next = tty->next;
3519 tty->next = 0;
3522 /* reset_sys_modes needs a valid device, so this call needs to be
3523 before delete_terminal. */
3524 reset_sys_modes (tty);
3526 delete_terminal (terminal);
3528 xfree (tty->name);
3529 xfree (tty->type);
3531 if (tty->input)
3533 delete_keyboard_wait_descriptor (fileno (tty->input));
3534 if (tty->input != stdin)
3535 fclose (tty->input);
3537 if (tty->output && tty->output != stdout && tty->output != tty->input)
3538 fclose (tty->output);
3539 if (tty->termscript)
3540 fclose (tty->termscript);
3542 xfree (tty->old_tty);
3543 xfree (tty->Wcm);
3544 xfree (tty->termcap_strings_buffer);
3545 xfree (tty->termcap_term_buffer);
3547 xfree (tty);
3550 void
3551 syms_of_term (void)
3553 DEFVAR_BOOL ("system-uses-terminfo", system_uses_terminfo,
3554 doc: /* Non-nil means the system uses terminfo rather than termcap.
3555 This variable can be used by terminal emulator packages. */);
3556 #ifdef TERMINFO
3557 system_uses_terminfo = 1;
3558 #else
3559 system_uses_terminfo = 0;
3560 #endif
3562 DEFVAR_LISP ("suspend-tty-functions", Vsuspend_tty_functions,
3563 doc: /* Functions run after suspending a tty.
3564 The functions are run with one argument, the terminal object to be suspended.
3565 See `suspend-tty'. */);
3566 Vsuspend_tty_functions = Qnil;
3569 DEFVAR_LISP ("resume-tty-functions", Vresume_tty_functions,
3570 doc: /* Functions run after resuming a tty.
3571 The functions are run with one argument, the terminal object that was revived.
3572 See `resume-tty'. */);
3573 Vresume_tty_functions = Qnil;
3575 DEFVAR_BOOL ("visible-cursor", visible_cursor,
3576 doc: /* Non-nil means to make the cursor very visible.
3577 This only has an effect when running in a text terminal.
3578 What means \"very visible\" is up to your terminal. It may make the cursor
3579 bigger, or it may make it blink, or it may do nothing at all. */);
3580 visible_cursor = 1;
3582 defsubr (&Stty_display_color_p);
3583 defsubr (&Stty_display_color_cells);
3584 defsubr (&Stty_no_underline);
3585 defsubr (&Stty_type);
3586 defsubr (&Scontrolling_tty_p);
3587 defsubr (&Stty_top_frame);
3588 defsubr (&Ssuspend_tty);
3589 defsubr (&Sresume_tty);
3590 #ifdef HAVE_GPM
3591 defsubr (&Sgpm_mouse_start);
3592 defsubr (&Sgpm_mouse_stop);
3593 #endif /* HAVE_GPM */
3595 #ifndef DOS_NT
3596 default_orig_pair = NULL;
3597 default_set_foreground = NULL;
3598 default_set_background = NULL;
3599 #endif /* !DOS_NT */
3601 encode_terminal_src = NULL;
3602 encode_terminal_dst = NULL;