Fix C-g during `make-network-process'. (Reported by Mark Plaksin.)
[emacs.git] / src / term.c
blob899739de6ae6cd5c0537133f0ac0344d4db9db5d
1 /* Terminal control module for terminals described by TERMCAP
2 Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1998, 2000, 2001,
3 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 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; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 /* New redisplay, TTY faces by Gerd Moellmann <gerd@gnu.org>. */
24 #include <config.h>
25 #include <stdio.h>
26 #include <ctype.h>
27 #include <string.h>
29 #include <sys/file.h>
31 #include <unistd.h> /* For isatty. */
33 #if HAVE_TERMIOS_H
34 #include <termios.h> /* For TIOCNOTTY. */
35 #endif
37 #include <signal.h>
39 #include "lisp.h"
40 #include "termchar.h"
41 #include "termopts.h"
42 #include "charset.h"
43 #include "coding.h"
44 #include "keyboard.h"
45 #include "frame.h"
46 #include "disptab.h"
47 #include "termhooks.h"
48 #include "dispextern.h"
49 #include "window.h"
50 #include "keymap.h"
51 #include "syssignal.h"
52 #include "systty.h"
54 /* For now, don't try to include termcap.h. On some systems,
55 configure finds a non-standard termcap.h that the main build
56 won't find. */
58 #if defined HAVE_TERMCAP_H && 0
59 #include <termcap.h>
60 #else
61 extern void tputs P_ ((const char *, int, int (*)(int)));
62 extern int tgetent P_ ((char *, const char *));
63 extern int tgetflag P_ ((char *id));
64 extern int tgetnum P_ ((char *id));
65 #endif
67 #include "cm.h"
68 #ifdef HAVE_X_WINDOWS
69 #include "xterm.h"
70 #endif
71 #ifdef MAC_OS
72 #include "macterm.h"
73 #endif
75 #ifndef O_RDWR
76 #define O_RDWR 2
77 #endif
79 #ifndef O_NOCTTY
80 #define O_NOCTTY 0
81 #endif
83 static void tty_set_scroll_region P_ ((struct frame *f, int start, int stop));
84 static void turn_on_face P_ ((struct frame *, int face_id));
85 static void turn_off_face P_ ((struct frame *, int face_id));
86 static void tty_show_cursor P_ ((struct tty_display_info *));
87 static void tty_hide_cursor P_ ((struct tty_display_info *));
88 static void tty_background_highlight P_ ((struct tty_display_info *tty));
89 static void dissociate_if_controlling_tty P_ ((int fd));
90 static void delete_tty P_ ((struct terminal *));
92 #define OUTPUT(tty, a) \
93 emacs_tputs ((tty), a, \
94 (int) (FRAME_LINES (XFRAME (selected_frame)) \
95 - curY (tty)), \
96 cmputc)
98 #define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
99 #define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
101 #define OUTPUT_IF(tty, a) \
102 do { \
103 if (a) \
104 emacs_tputs ((tty), a, \
105 (int) (FRAME_LINES (XFRAME (selected_frame)) \
106 - curY (tty) ), \
107 cmputc); \
108 } while (0)
110 #define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
112 /* If true, use "vs", otherwise use "ve" to make the cursor visible. */
114 static int visible_cursor;
116 /* Display space properties */
118 extern Lisp_Object Qspace, QCalign_to, QCwidth;
120 /* Functions to call after suspending a tty. */
121 Lisp_Object Vsuspend_tty_functions;
123 /* Functions to call after resuming a tty. */
124 Lisp_Object Vresume_tty_functions;
126 /* Chain of all tty device parameters. */
127 struct tty_display_info *tty_list;
129 /* Nonzero means no need to redraw the entire frame on resuming a
130 suspended Emacs. This is useful on terminals with multiple
131 pages, where one page is used for Emacs and another for all
132 else. */
133 int no_redraw_on_reenter;
135 /* Meaning of bits in no_color_video. Each bit set means that the
136 corresponding attribute cannot be combined with colors. */
138 enum no_color_bit
140 NC_STANDOUT = 1 << 0,
141 NC_UNDERLINE = 1 << 1,
142 NC_REVERSE = 1 << 2,
143 NC_BLINK = 1 << 3,
144 NC_DIM = 1 << 4,
145 NC_BOLD = 1 << 5,
146 NC_INVIS = 1 << 6,
147 NC_PROTECT = 1 << 7,
148 NC_ALT_CHARSET = 1 << 8
151 /* internal state */
153 /* The largest frame width in any call to calculate_costs. */
155 int max_frame_cols;
157 /* The largest frame height in any call to calculate_costs. */
159 int max_frame_lines;
161 /* Non-zero if we have dropped our controlling tty and therefore
162 should not open a frame on stdout. */
163 static int no_controlling_tty;
165 /* Provided for lisp packages. */
167 static int system_uses_terminfo;
169 char *tparam ();
171 extern char *tgetstr ();
174 #ifdef WINDOWSNT
175 /* We aren't X windows, but we aren't termcap either. This makes me
176 uncertain as to what value to use for frame.output_method. For
177 this file, we'll define FRAME_TERMCAP_P to be zero so that our
178 output hooks get called instead of the termcap functions. Probably
179 the best long-term solution is to define an output_windows_nt... */
181 #undef FRAME_TERMCAP_P
182 #define FRAME_TERMCAP_P(_f_) 0
183 #endif /* WINDOWSNT */
186 /* Ring the bell on a tty. */
188 static void
189 tty_ring_bell (struct frame *f)
191 struct tty_display_info *tty = FRAME_TTY (f);
193 if (tty->output)
195 OUTPUT (tty, (tty->TS_visible_bell && visible_bell
196 ? tty->TS_visible_bell
197 : tty->TS_bell));
198 fflush (tty->output);
202 /* Set up termcap modes for Emacs. */
204 void
205 tty_set_terminal_modes (struct terminal *terminal)
207 struct tty_display_info *tty = terminal->display_info.tty;
209 if (tty->output)
211 if (tty->TS_termcap_modes)
212 OUTPUT (tty, tty->TS_termcap_modes);
213 else
215 /* Output enough newlines to scroll all the old screen contents
216 off the screen, so it won't be overwritten and lost. */
217 int i;
218 current_tty = tty;
219 for (i = 0; i < FRAME_LINES (XFRAME (selected_frame)); i++)
220 cmputc ('\n');
223 OUTPUT_IF (tty, tty->TS_termcap_modes);
224 OUTPUT_IF (tty, visible_cursor ? tty->TS_cursor_visible : tty->TS_cursor_normal);
225 OUTPUT_IF (tty, tty->TS_keypad_mode);
226 losecursor (tty);
227 fflush (tty->output);
231 /* Reset termcap modes before exiting Emacs. */
233 void
234 tty_reset_terminal_modes (struct terminal *terminal)
236 struct tty_display_info *tty = terminal->display_info.tty;
238 if (tty->output)
240 tty_turn_off_highlight (tty);
241 tty_turn_off_insert (tty);
242 OUTPUT_IF (tty, tty->TS_end_keypad_mode);
243 OUTPUT_IF (tty, tty->TS_cursor_normal);
244 OUTPUT_IF (tty, tty->TS_end_termcap_modes);
245 OUTPUT_IF (tty, tty->TS_orig_pair);
246 /* Output raw CR so kernel can track the cursor hpos. */
247 current_tty = tty;
248 cmputc ('\r');
249 fflush (tty->output);
253 /* Flag the end of a display update on a termcap terminal. */
255 static void
256 tty_update_end (struct frame *f)
258 struct tty_display_info *tty = FRAME_TTY (f);
260 if (!XWINDOW (selected_window)->cursor_off_p)
261 tty_show_cursor (tty);
262 tty_turn_off_insert (tty);
263 tty_background_highlight (tty);
266 /* The implementation of set_terminal_window for termcap frames. */
268 static void
269 tty_set_terminal_window (struct frame *f, int size)
271 struct tty_display_info *tty = FRAME_TTY (f);
273 tty->specified_window = size ? size : FRAME_LINES (f);
274 if (FRAME_SCROLL_REGION_OK (f))
275 tty_set_scroll_region (f, 0, tty->specified_window);
278 static void
279 tty_set_scroll_region (struct frame *f, int start, int stop)
281 char *buf;
282 struct tty_display_info *tty = FRAME_TTY (f);
284 if (tty->TS_set_scroll_region)
285 buf = tparam (tty->TS_set_scroll_region, 0, 0, start, stop - 1);
286 else if (tty->TS_set_scroll_region_1)
287 buf = tparam (tty->TS_set_scroll_region_1, 0, 0,
288 FRAME_LINES (f), start,
289 FRAME_LINES (f) - stop,
290 FRAME_LINES (f));
291 else
292 buf = tparam (tty->TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (f));
294 OUTPUT (tty, buf);
295 xfree (buf);
296 losecursor (tty);
300 static void
301 tty_turn_on_insert (struct tty_display_info *tty)
303 if (!tty->insert_mode)
304 OUTPUT (tty, tty->TS_insert_mode);
305 tty->insert_mode = 1;
308 void
309 tty_turn_off_insert (struct tty_display_info *tty)
311 if (tty->insert_mode)
312 OUTPUT (tty, tty->TS_end_insert_mode);
313 tty->insert_mode = 0;
316 /* Handle highlighting. */
318 void
319 tty_turn_off_highlight (struct tty_display_info *tty)
321 if (tty->standout_mode)
322 OUTPUT_IF (tty, tty->TS_end_standout_mode);
323 tty->standout_mode = 0;
326 static void
327 tty_turn_on_highlight (struct tty_display_info *tty)
329 if (!tty->standout_mode)
330 OUTPUT_IF (tty, tty->TS_standout_mode);
331 tty->standout_mode = 1;
334 static void
335 tty_toggle_highlight (struct tty_display_info *tty)
337 if (tty->standout_mode)
338 tty_turn_off_highlight (tty);
339 else
340 tty_turn_on_highlight (tty);
344 /* Make cursor invisible. */
346 static void
347 tty_hide_cursor (struct tty_display_info *tty)
349 if (tty->cursor_hidden == 0)
351 tty->cursor_hidden = 1;
352 OUTPUT_IF (tty, tty->TS_cursor_invisible);
357 /* Ensure that cursor is visible. */
359 static void
360 tty_show_cursor (struct tty_display_info *tty)
362 if (tty->cursor_hidden)
364 tty->cursor_hidden = 0;
365 OUTPUT_IF (tty, tty->TS_cursor_normal);
366 if (visible_cursor)
367 OUTPUT_IF (tty, tty->TS_cursor_visible);
372 /* Set standout mode to the state it should be in for
373 empty space inside windows. What this is,
374 depends on the user option inverse-video. */
376 static void
377 tty_background_highlight (struct tty_display_info *tty)
379 if (inverse_video)
380 tty_turn_on_highlight (tty);
381 else
382 tty_turn_off_highlight (tty);
385 /* Set standout mode to the mode specified for the text to be output. */
387 static void
388 tty_highlight_if_desired (struct tty_display_info *tty)
390 if (inverse_video)
391 tty_turn_on_highlight (tty);
392 else
393 tty_turn_off_highlight (tty);
397 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
398 frame-relative coordinates. */
400 static void
401 tty_cursor_to (struct frame *f, int vpos, int hpos)
403 struct tty_display_info *tty = FRAME_TTY (f);
405 /* Detect the case where we are called from reset_sys_modes
406 and the costs have never been calculated. Do nothing. */
407 if (! tty->costs_set)
408 return;
410 if (curY (tty) == vpos
411 && curX (tty) == hpos)
412 return;
413 if (!tty->TF_standout_motion)
414 tty_background_highlight (tty);
415 if (!tty->TF_insmode_motion)
416 tty_turn_off_insert (tty);
417 cmgoto (tty, vpos, hpos);
420 /* Similar but don't take any account of the wasted characters. */
422 static void
423 tty_raw_cursor_to (struct frame *f, int row, int col)
425 struct tty_display_info *tty = FRAME_TTY (f);
427 if (curY (tty) == row
428 && curX (tty) == col)
429 return;
430 if (!tty->TF_standout_motion)
431 tty_background_highlight (tty);
432 if (!tty->TF_insmode_motion)
433 tty_turn_off_insert (tty);
434 cmgoto (tty, row, col);
437 /* Erase operations */
439 /* Clear from cursor to end of frame on a termcap device. */
441 static void
442 tty_clear_to_end (struct frame *f)
444 register int i;
445 struct tty_display_info *tty = FRAME_TTY (f);
447 if (tty->TS_clr_to_bottom)
449 tty_background_highlight (tty);
450 OUTPUT (tty, tty->TS_clr_to_bottom);
452 else
454 for (i = curY (tty); i < FRAME_LINES (f); i++)
456 cursor_to (f, i, 0);
457 clear_end_of_line (f, FRAME_COLS (f));
462 /* Clear an entire termcap frame. */
464 static void
465 tty_clear_frame (struct frame *f)
467 struct tty_display_info *tty = FRAME_TTY (f);
469 if (tty->TS_clr_frame)
471 tty_background_highlight (tty);
472 OUTPUT (tty, tty->TS_clr_frame);
473 cmat (tty, 0, 0);
475 else
477 cursor_to (f, 0, 0);
478 clear_to_end (f);
482 /* An implementation of clear_end_of_line for termcap frames.
484 Note that the cursor may be moved, on terminals lacking a `ce' string. */
486 static void
487 tty_clear_end_of_line (struct frame *f, int first_unused_hpos)
489 register int i;
490 struct tty_display_info *tty = FRAME_TTY (f);
492 /* Detect the case where we are called from reset_sys_modes
493 and the costs have never been calculated. Do nothing. */
494 if (! tty->costs_set)
495 return;
497 if (curX (tty) >= first_unused_hpos)
498 return;
499 tty_background_highlight (tty);
500 if (tty->TS_clr_line)
502 OUTPUT1 (tty, tty->TS_clr_line);
504 else
505 { /* have to do it the hard way */
506 tty_turn_off_insert (tty);
508 /* Do not write in last row last col with Auto-wrap on. */
509 if (AutoWrap (tty)
510 && curY (tty) == FrameRows (tty) - 1
511 && first_unused_hpos == FrameCols (tty))
512 first_unused_hpos--;
514 for (i = curX (tty); i < first_unused_hpos; i++)
516 if (tty->termscript)
517 fputc (' ', tty->termscript);
518 fputc (' ', tty->output);
520 cmplus (tty, first_unused_hpos - curX (tty));
524 /* Buffer to store the source and result of code conversion for terminal. */
525 static unsigned char *encode_terminal_buf;
526 /* Allocated size of the above buffer. */
527 static int encode_terminal_bufsize;
529 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes.
530 Set CODING->produced to the byte-length of the resulting byte
531 sequence, and return a pointer to that byte sequence. */
533 unsigned char *
534 encode_terminal_code (src, src_len, coding)
535 struct glyph *src;
536 int src_len;
537 struct coding_system *coding;
539 struct glyph *src_end = src + src_len;
540 register GLYPH g;
541 unsigned char *buf;
542 int nchars, nbytes, required;
543 register int tlen = GLYPH_TABLE_LENGTH;
544 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
546 /* Allocate sufficient size of buffer to store all characters in
547 multibyte-form. But, it may be enlarged on demand if
548 Vglyph_table contains a string. */
549 required = MAX_MULTIBYTE_LENGTH * src_len;
550 if (encode_terminal_bufsize < required)
552 if (encode_terminal_bufsize == 0)
553 encode_terminal_buf = xmalloc (required);
554 else
555 encode_terminal_buf = xrealloc (encode_terminal_buf, required);
556 encode_terminal_bufsize = required;
559 buf = encode_terminal_buf;
560 nchars = 0;
561 while (src < src_end)
563 /* We must skip glyphs to be padded for a wide character. */
564 if (! CHAR_GLYPH_PADDING_P (*src))
566 g = GLYPH_FROM_CHAR_GLYPH (src[0]);
568 if (g < 0 || g >= tlen)
570 /* This glyph doesn't has an entry in Vglyph_table. */
571 if (CHAR_VALID_P (src->u.ch, 0))
572 buf += CHAR_STRING (src->u.ch, buf);
573 else
574 *buf++ = SPACEGLYPH;
575 nchars++;
577 else
579 /* This glyph has an entry in Vglyph_table,
580 so process any alias before testing for simpleness. */
581 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
583 if (GLYPH_SIMPLE_P (tbase, tlen, g))
585 int c = FAST_GLYPH_CHAR (g);
587 if (CHAR_VALID_P (c, 0))
588 buf += CHAR_STRING (c, buf);
589 else
590 *buf++ = SPACEGLYPH;
591 nchars++;
593 else
595 /* We have a string in Vglyph_table. */
596 Lisp_Object string;
598 string = tbase[g];
599 if (! STRING_MULTIBYTE (string))
600 string = string_to_multibyte (string);
601 nbytes = buf - encode_terminal_buf;
602 if (encode_terminal_bufsize < nbytes + SBYTES (string))
604 encode_terminal_bufsize = nbytes + SBYTES (string);
605 encode_terminal_buf = xrealloc (encode_terminal_buf,
606 encode_terminal_bufsize);
607 buf = encode_terminal_buf + nbytes;
609 bcopy (SDATA (string), buf, SBYTES (string));
610 buf += SBYTES (string);
611 nchars += SCHARS (string);
615 src++;
618 nbytes = buf - encode_terminal_buf;
619 coding->src_multibyte = 1;
620 coding->dst_multibyte = 0;
621 if (SYMBOLP (coding->pre_write_conversion)
622 && ! NILP (Ffboundp (coding->pre_write_conversion)))
624 run_pre_write_conversin_on_c_str (&encode_terminal_buf,
625 &encode_terminal_bufsize,
626 nchars, nbytes, coding);
627 nchars = coding->produced_char;
628 nbytes = coding->produced;
630 required = nbytes + encoding_buffer_size (coding, nbytes);
631 if (encode_terminal_bufsize < required)
633 encode_terminal_bufsize = required;
634 encode_terminal_buf = xrealloc (encode_terminal_buf, required);
637 encode_coding (coding, encode_terminal_buf, encode_terminal_buf + nbytes,
638 nbytes, encode_terminal_bufsize - nbytes);
639 return encode_terminal_buf + nbytes;
643 /* An implementation of write_glyphs for termcap frames. */
645 static void
646 tty_write_glyphs (struct frame *f, struct glyph *string, int len)
648 unsigned char *conversion_buffer;
649 struct coding_system *coding;
651 struct tty_display_info *tty = FRAME_TTY (f);
653 tty_turn_off_insert (tty);
654 tty_hide_cursor (tty);
656 /* Don't dare write in last column of bottom line, if Auto-Wrap,
657 since that would scroll the whole frame on some terminals. */
659 if (AutoWrap (tty)
660 && curY (tty) + 1 == FRAME_LINES (f)
661 && (curX (tty) + len) == FRAME_COLS (f))
662 len --;
663 if (len <= 0)
664 return;
666 cmplus (tty, len);
668 /* If terminal_coding does any conversion, use it, otherwise use
669 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
670 because it always return 1 if the member src_multibyte is 1. */
671 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
672 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
673 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
674 the tail. */
675 coding->mode &= ~CODING_MODE_LAST_BLOCK;
677 while (len > 0)
679 /* Identify a run of glyphs with the same face. */
680 int face_id = string->face_id;
681 int n;
683 for (n = 1; n < len; ++n)
684 if (string[n].face_id != face_id)
685 break;
687 /* Turn appearance modes of the face of the run on. */
688 tty_highlight_if_desired (tty);
689 turn_on_face (f, face_id);
691 if (n == len)
692 /* This is the last run. */
693 coding->mode |= CODING_MODE_LAST_BLOCK;
694 conversion_buffer = encode_terminal_code (string, n, coding);
695 if (coding->produced > 0)
697 fwrite (conversion_buffer, 1, coding->produced, tty->output);
698 if (ferror (tty->output))
699 clearerr (tty->output);
700 if (tty->termscript)
701 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
703 len -= n;
704 string += n;
706 /* Turn appearance modes off. */
707 turn_off_face (f, face_id);
708 tty_turn_off_highlight (tty);
711 cmcheckmagic (tty);
714 /* An implementation of insert_glyphs for termcap frames. */
716 static void
717 tty_insert_glyphs (struct frame *f, struct glyph *start, int len)
719 char *buf;
720 struct glyph *glyph = NULL;
721 unsigned char *conversion_buffer;
722 unsigned char space[1];
723 struct coding_system *coding;
725 struct tty_display_info *tty = FRAME_TTY (f);
727 if (tty->TS_ins_multi_chars)
729 buf = tparam (tty->TS_ins_multi_chars, 0, 0, len);
730 OUTPUT1 (tty, buf);
731 xfree (buf);
732 if (start)
733 write_glyphs (f, start, len);
734 return;
737 tty_turn_on_insert (tty);
738 cmplus (tty, len);
740 if (! start)
741 space[0] = SPACEGLYPH;
743 /* If terminal_coding does any conversion, use it, otherwise use
744 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
745 because it always return 1 if the member src_multibyte is 1. */
746 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
747 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
748 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
749 the tail. */
750 coding->mode &= ~CODING_MODE_LAST_BLOCK;
752 while (len-- > 0)
754 OUTPUT1_IF (tty, tty->TS_ins_char);
755 if (!start)
757 conversion_buffer = space;
758 coding->produced = 1;
760 else
762 tty_highlight_if_desired (tty);
763 turn_on_face (f, start->face_id);
764 glyph = start;
765 ++start;
766 /* We must open sufficient space for a character which
767 occupies more than one column. */
768 while (len && CHAR_GLYPH_PADDING_P (*start))
770 OUTPUT1_IF (tty, tty->TS_ins_char);
771 start++, len--;
774 if (len <= 0)
775 /* This is the last glyph. */
776 coding->mode |= CODING_MODE_LAST_BLOCK;
778 conversion_buffer = encode_terminal_code (glyph, 1, coding);
781 if (coding->produced > 0)
783 fwrite (conversion_buffer, 1, coding->produced, tty->output);
784 if (ferror (tty->output))
785 clearerr (tty->output);
786 if (tty->termscript)
787 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
790 OUTPUT1_IF (tty, tty->TS_pad_inserted_char);
791 if (start)
793 turn_off_face (f, glyph->face_id);
794 tty_turn_off_highlight (tty);
798 cmcheckmagic (tty);
801 /* An implementation of delete_glyphs for termcap frames. */
803 static void
804 tty_delete_glyphs (struct frame *f, int n)
806 char *buf;
807 register int i;
809 struct tty_display_info *tty = FRAME_TTY (f);
811 if (tty->delete_in_insert_mode)
813 tty_turn_on_insert (tty);
815 else
817 tty_turn_off_insert (tty);
818 OUTPUT_IF (tty, tty->TS_delete_mode);
821 if (tty->TS_del_multi_chars)
823 buf = tparam (tty->TS_del_multi_chars, 0, 0, n);
824 OUTPUT1 (tty, buf);
825 xfree (buf);
827 else
828 for (i = 0; i < n; i++)
829 OUTPUT1 (tty, tty->TS_del_char);
830 if (!tty->delete_in_insert_mode)
831 OUTPUT_IF (tty, tty->TS_end_delete_mode);
834 /* An implementation of ins_del_lines for termcap frames. */
836 static void
837 tty_ins_del_lines (struct frame *f, int vpos, int n)
839 struct tty_display_info *tty = FRAME_TTY (f);
840 char *multi = n > 0 ? tty->TS_ins_multi_lines : tty->TS_del_multi_lines;
841 char *single = n > 0 ? tty->TS_ins_line : tty->TS_del_line;
842 char *scroll = n > 0 ? tty->TS_rev_scroll : tty->TS_fwd_scroll;
844 register int i = n > 0 ? n : -n;
845 register char *buf;
847 /* If the lines below the insertion are being pushed
848 into the end of the window, this is the same as clearing;
849 and we know the lines are already clear, since the matching
850 deletion has already been done. So can ignore this. */
851 /* If the lines below the deletion are blank lines coming
852 out of the end of the window, don't bother,
853 as there will be a matching inslines later that will flush them. */
854 if (FRAME_SCROLL_REGION_OK (f)
855 && vpos + i >= tty->specified_window)
856 return;
857 if (!FRAME_MEMORY_BELOW_FRAME (f)
858 && vpos + i >= FRAME_LINES (f))
859 return;
861 if (multi)
863 raw_cursor_to (f, vpos, 0);
864 tty_background_highlight (tty);
865 buf = tparam (multi, 0, 0, i);
866 OUTPUT (tty, buf);
867 xfree (buf);
869 else if (single)
871 raw_cursor_to (f, vpos, 0);
872 tty_background_highlight (tty);
873 while (--i >= 0)
874 OUTPUT (tty, single);
875 if (tty->TF_teleray)
876 curX (tty) = 0;
878 else
880 tty_set_scroll_region (f, vpos, tty->specified_window);
881 if (n < 0)
882 raw_cursor_to (f, tty->specified_window - 1, 0);
883 else
884 raw_cursor_to (f, vpos, 0);
885 tty_background_highlight (tty);
886 while (--i >= 0)
887 OUTPUTL (tty, scroll, tty->specified_window - vpos);
888 tty_set_scroll_region (f, 0, tty->specified_window);
891 if (!FRAME_SCROLL_REGION_OK (f)
892 && FRAME_MEMORY_BELOW_FRAME (f)
893 && n < 0)
895 cursor_to (f, FRAME_LINES (f) + n, 0);
896 clear_to_end (f);
900 /* Compute cost of sending "str", in characters,
901 not counting any line-dependent padding. */
904 string_cost (char *str)
906 cost = 0;
907 if (str)
908 tputs (str, 0, evalcost);
909 return cost;
912 /* Compute cost of sending "str", in characters,
913 counting any line-dependent padding at one line. */
915 static int
916 string_cost_one_line (char *str)
918 cost = 0;
919 if (str)
920 tputs (str, 1, evalcost);
921 return cost;
924 /* Compute per line amount of line-dependent padding,
925 in tenths of characters. */
928 per_line_cost (char *str)
930 cost = 0;
931 if (str)
932 tputs (str, 0, evalcost);
933 cost = - cost;
934 if (str)
935 tputs (str, 10, evalcost);
936 return cost;
939 #ifndef old
940 /* char_ins_del_cost[n] is cost of inserting N characters.
941 char_ins_del_cost[-n] is cost of deleting N characters.
942 The length of this vector is based on max_frame_cols. */
944 int *char_ins_del_vector;
946 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
947 #endif
949 /* ARGSUSED */
950 static void
951 calculate_ins_del_char_costs (struct frame *f)
953 struct tty_display_info *tty = FRAME_TTY (f);
954 int ins_startup_cost, del_startup_cost;
955 int ins_cost_per_char, del_cost_per_char;
956 register int i;
957 register int *p;
959 if (tty->TS_ins_multi_chars)
961 ins_cost_per_char = 0;
962 ins_startup_cost = string_cost_one_line (tty->TS_ins_multi_chars);
964 else if (tty->TS_ins_char || tty->TS_pad_inserted_char
965 || (tty->TS_insert_mode && tty->TS_end_insert_mode))
967 ins_startup_cost = (30 * (string_cost (tty->TS_insert_mode)
968 + string_cost (tty->TS_end_insert_mode))) / 100;
969 ins_cost_per_char = (string_cost_one_line (tty->TS_ins_char)
970 + string_cost_one_line (tty->TS_pad_inserted_char));
972 else
974 ins_startup_cost = 9999;
975 ins_cost_per_char = 0;
978 if (tty->TS_del_multi_chars)
980 del_cost_per_char = 0;
981 del_startup_cost = string_cost_one_line (tty->TS_del_multi_chars);
983 else if (tty->TS_del_char)
985 del_startup_cost = (string_cost (tty->TS_delete_mode)
986 + string_cost (tty->TS_end_delete_mode));
987 if (tty->delete_in_insert_mode)
988 del_startup_cost /= 2;
989 del_cost_per_char = string_cost_one_line (tty->TS_del_char);
991 else
993 del_startup_cost = 9999;
994 del_cost_per_char = 0;
997 /* Delete costs are at negative offsets */
998 p = &char_ins_del_cost (f)[0];
999 for (i = FRAME_COLS (f); --i >= 0;)
1000 *--p = (del_startup_cost += del_cost_per_char);
1002 /* Doing nothing is free */
1003 p = &char_ins_del_cost (f)[0];
1004 *p++ = 0;
1006 /* Insert costs are at positive offsets */
1007 for (i = FRAME_COLS (f); --i >= 0;)
1008 *p++ = (ins_startup_cost += ins_cost_per_char);
1011 void
1012 calculate_costs (struct frame *frame)
1014 FRAME_COST_BAUD_RATE (frame) = baud_rate;
1016 if (FRAME_TERMCAP_P (frame))
1018 struct tty_display_info *tty = FRAME_TTY (frame);
1019 register char *f = (tty->TS_set_scroll_region
1020 ? tty->TS_set_scroll_region
1021 : tty->TS_set_scroll_region_1);
1023 FRAME_SCROLL_REGION_COST (frame) = string_cost (f);
1025 tty->costs_set = 1;
1027 /* These variables are only used for terminal stuff. They are
1028 allocated once for the terminal frame of X-windows emacs, but not
1029 used afterwards.
1031 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1032 X turns off char_ins_del_ok. */
1034 max_frame_lines = max (max_frame_lines, FRAME_LINES (frame));
1035 max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
1037 if (char_ins_del_vector != 0)
1038 char_ins_del_vector
1039 = (int *) xrealloc (char_ins_del_vector,
1040 (sizeof (int)
1041 + 2 * max_frame_cols * sizeof (int)));
1042 else
1043 char_ins_del_vector
1044 = (int *) xmalloc (sizeof (int)
1045 + 2 * max_frame_cols * sizeof (int));
1047 bzero (char_ins_del_vector, (sizeof (int)
1048 + 2 * max_frame_cols * sizeof (int)));
1051 if (f && (!tty->TS_ins_line && !tty->TS_del_line))
1052 do_line_insertion_deletion_costs (frame,
1053 tty->TS_rev_scroll, tty->TS_ins_multi_lines,
1054 tty->TS_fwd_scroll, tty->TS_del_multi_lines,
1055 f, f, 1);
1056 else
1057 do_line_insertion_deletion_costs (frame,
1058 tty->TS_ins_line, tty->TS_ins_multi_lines,
1059 tty->TS_del_line, tty->TS_del_multi_lines,
1060 0, 0, 1);
1062 calculate_ins_del_char_costs (frame);
1064 /* Don't use TS_repeat if its padding is worse than sending the chars */
1065 if (tty->TS_repeat && per_line_cost (tty->TS_repeat) * baud_rate < 9000)
1066 tty->RPov = string_cost (tty->TS_repeat);
1067 else
1068 tty->RPov = FRAME_COLS (frame) * 2;
1070 cmcostinit (FRAME_TTY (frame)); /* set up cursor motion costs */
1074 struct fkey_table {
1075 char *cap, *name;
1078 /* Termcap capability names that correspond directly to X keysyms.
1079 Some of these (marked "terminfo") aren't supplied by old-style
1080 (Berkeley) termcap entries. They're listed in X keysym order;
1081 except we put the keypad keys first, so that if they clash with
1082 other keys (as on the IBM PC keyboard) they get overridden.
1085 static struct fkey_table keys[] =
1087 {"kh", "home"}, /* termcap */
1088 {"kl", "left"}, /* termcap */
1089 {"ku", "up"}, /* termcap */
1090 {"kr", "right"}, /* termcap */
1091 {"kd", "down"}, /* termcap */
1092 {"%8", "prior"}, /* terminfo */
1093 {"%5", "next"}, /* terminfo */
1094 {"@7", "end"}, /* terminfo */
1095 {"@1", "begin"}, /* terminfo */
1096 {"*6", "select"}, /* terminfo */
1097 {"%9", "print"}, /* terminfo */
1098 {"@4", "execute"}, /* terminfo --- actually the `command' key */
1100 * "insert" --- see below
1102 {"&8", "undo"}, /* terminfo */
1103 {"%0", "redo"}, /* terminfo */
1104 {"%7", "menu"}, /* terminfo --- actually the `options' key */
1105 {"@0", "find"}, /* terminfo */
1106 {"@2", "cancel"}, /* terminfo */
1107 {"%1", "help"}, /* terminfo */
1109 * "break" goes here, but can't be reliably intercepted with termcap
1111 {"&4", "reset"}, /* terminfo --- actually `restart' */
1113 * "system" and "user" --- no termcaps
1115 {"kE", "clearline"}, /* terminfo */
1116 {"kA", "insertline"}, /* terminfo */
1117 {"kL", "deleteline"}, /* terminfo */
1118 {"kI", "insertchar"}, /* terminfo */
1119 {"kD", "deletechar"}, /* terminfo */
1120 {"kB", "backtab"}, /* terminfo */
1122 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1124 {"@8", "kp-enter"}, /* terminfo */
1126 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1127 * "kp-multiply", "kp-add", "kp-separator",
1128 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1129 * --- no termcaps for any of these.
1131 {"K4", "kp-1"}, /* terminfo */
1133 * "kp-2" --- no termcap
1135 {"K5", "kp-3"}, /* terminfo */
1137 * "kp-4" --- no termcap
1139 {"K2", "kp-5"}, /* terminfo */
1141 * "kp-6" --- no termcap
1143 {"K1", "kp-7"}, /* terminfo */
1145 * "kp-8" --- no termcap
1147 {"K3", "kp-9"}, /* terminfo */
1149 * "kp-equal" --- no termcap
1151 {"k1", "f1"},
1152 {"k2", "f2"},
1153 {"k3", "f3"},
1154 {"k4", "f4"},
1155 {"k5", "f5"},
1156 {"k6", "f6"},
1157 {"k7", "f7"},
1158 {"k8", "f8"},
1159 {"k9", "f9"},
1161 {"&0", "S-cancel"}, /*shifted cancel key*/
1162 {"&9", "S-begin"}, /*shifted begin key*/
1163 {"*0", "S-find"}, /*shifted find key*/
1164 {"*1", "S-execute"}, /*shifted execute? actually shifted command key*/
1165 {"*4", "S-delete"}, /*shifted delete-character key*/
1166 {"*7", "S-end"}, /*shifted end key*/
1167 {"*8", "S-clearline"}, /*shifted clear-to end-of-line key*/
1168 {"#1", "S-help"}, /*shifted help key*/
1169 {"#2", "S-home"}, /*shifted home key*/
1170 {"#3", "S-insert"}, /*shifted insert-character key*/
1171 {"#4", "S-left"}, /*shifted left-arrow key*/
1172 {"%d", "S-menu"}, /*shifted menu? actually shifted options key*/
1173 {"%c", "S-next"}, /*shifted next key*/
1174 {"%e", "S-prior"}, /*shifted previous key*/
1175 {"%f", "S-print"}, /*shifted print key*/
1176 {"%g", "S-redo"}, /*shifted redo key*/
1177 {"%i", "S-right"}, /*shifted right-arrow key*/
1178 {"!3", "S-undo"} /*shifted undo key*/
1181 static char **term_get_fkeys_address;
1182 static KBOARD *term_get_fkeys_kboard;
1183 static Lisp_Object term_get_fkeys_1 ();
1185 /* Find the escape codes sent by the function keys for Vfunction_key_map.
1186 This function scans the termcap function key sequence entries, and
1187 adds entries to Vfunction_key_map for each function key it finds. */
1189 static void
1190 term_get_fkeys (address, kboard)
1191 char **address;
1192 KBOARD *kboard;
1194 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1195 errors during the call. The only errors should be from Fdefine_key
1196 when given a key sequence containing an invalid prefix key. If the
1197 termcap defines function keys which use a prefix that is already bound
1198 to a command by the default bindings, we should silently ignore that
1199 function key specification, rather than giving the user an error and
1200 refusing to run at all on such a terminal. */
1202 extern Lisp_Object Fidentity ();
1203 term_get_fkeys_address = address;
1204 term_get_fkeys_kboard = kboard;
1205 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1208 static Lisp_Object
1209 term_get_fkeys_1 ()
1211 int i;
1213 char **address = term_get_fkeys_address;
1214 KBOARD *kboard = term_get_fkeys_kboard;
1216 /* This can happen if CANNOT_DUMP or with strange options. */
1217 if (!initialized)
1218 kboard->Vlocal_function_key_map = Fmake_sparse_keymap (Qnil);
1220 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1222 char *sequence = tgetstr (keys[i].cap, address);
1223 if (sequence)
1224 Fdefine_key (kboard->Vlocal_function_key_map, build_string (sequence),
1225 Fmake_vector (make_number (1),
1226 intern (keys[i].name)));
1229 /* The uses of the "k0" capability are inconsistent; sometimes it
1230 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1231 We will attempt to politely accommodate both systems by testing for
1232 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1235 char *k_semi = tgetstr ("k;", address);
1236 char *k0 = tgetstr ("k0", address);
1237 char *k0_name = "f10";
1239 if (k_semi)
1241 if (k0)
1242 /* Define f0 first, so that f10 takes precedence in case the
1243 key sequences happens to be the same. */
1244 Fdefine_key (kboard->Vlocal_function_key_map, build_string (k0),
1245 Fmake_vector (make_number (1), intern ("f0")));
1246 Fdefine_key (kboard->Vlocal_function_key_map, build_string (k_semi),
1247 Fmake_vector (make_number (1), intern ("f10")));
1249 else if (k0)
1250 Fdefine_key (kboard->Vlocal_function_key_map, build_string (k0),
1251 Fmake_vector (make_number (1), intern (k0_name)));
1254 /* Set up cookies for numbered function keys above f10. */
1256 char fcap[3], fkey[4];
1258 fcap[0] = 'F'; fcap[2] = '\0';
1259 for (i = 11; i < 64; i++)
1261 if (i <= 19)
1262 fcap[1] = '1' + i - 11;
1263 else if (i <= 45)
1264 fcap[1] = 'A' + i - 20;
1265 else
1266 fcap[1] = 'a' + i - 46;
1269 char *sequence = tgetstr (fcap, address);
1270 if (sequence)
1272 sprintf (fkey, "f%d", i);
1273 Fdefine_key (kboard->Vlocal_function_key_map, build_string (sequence),
1274 Fmake_vector (make_number (1),
1275 intern (fkey)));
1282 * Various mappings to try and get a better fit.
1285 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1286 if (!tgetstr (cap1, address)) \
1288 char *sequence = tgetstr (cap2, address); \
1289 if (sequence) \
1290 Fdefine_key (kboard->Vlocal_function_key_map, build_string (sequence), \
1291 Fmake_vector (make_number (1), \
1292 intern (sym))); \
1295 /* if there's no key_next keycap, map key_npage to `next' keysym */
1296 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1297 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1298 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1299 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1300 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1301 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1302 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1304 /* IBM has their own non-standard dialect of terminfo.
1305 If the standard name isn't found, try the IBM name. */
1306 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1307 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1308 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1309 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1310 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1311 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1312 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1313 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1314 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1315 #undef CONDITIONAL_REASSIGN
1318 return Qnil;
1322 /***********************************************************************
1323 Character Display Information
1324 ***********************************************************************/
1326 static void append_glyph P_ ((struct it *));
1327 static void produce_stretch_glyph P_ ((struct it *));
1330 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1331 terminal frames if IT->glyph_row != NULL. IT->c is the character
1332 for which to produce glyphs; IT->face_id contains the character's
1333 face. Padding glyphs are appended if IT->c has a IT->pixel_width >
1334 1. */
1336 static void
1337 append_glyph (it)
1338 struct it *it;
1340 struct glyph *glyph, *end;
1341 int i;
1343 xassert (it->glyph_row);
1344 glyph = (it->glyph_row->glyphs[it->area]
1345 + it->glyph_row->used[it->area]);
1346 end = it->glyph_row->glyphs[1 + it->area];
1348 for (i = 0;
1349 i < it->pixel_width && glyph < end;
1350 ++i)
1352 glyph->type = CHAR_GLYPH;
1353 glyph->pixel_width = 1;
1354 glyph->u.ch = it->c;
1355 glyph->face_id = it->face_id;
1356 glyph->padding_p = i > 0;
1357 glyph->charpos = CHARPOS (it->position);
1358 glyph->object = it->object;
1360 ++it->glyph_row->used[it->area];
1361 ++glyph;
1366 /* Produce glyphs for the display element described by IT. *IT
1367 specifies what we want to produce a glyph for (character, image, ...),
1368 and where in the glyph matrix we currently are (glyph row and hpos).
1369 produce_glyphs fills in output fields of *IT with information such as the
1370 pixel width and height of a character, and maybe output actual glyphs at
1371 the same time if IT->glyph_row is non-null. See the explanation of
1372 struct display_iterator in dispextern.h for an overview.
1374 produce_glyphs also stores the result of glyph width, ascent
1375 etc. computations in *IT.
1377 IT->glyph_row may be null, in which case produce_glyphs does not
1378 actually fill in the glyphs. This is used in the move_* functions
1379 in xdisp.c for text width and height computations.
1381 Callers usually don't call produce_glyphs directly;
1382 instead they use the macro PRODUCE_GLYPHS. */
1384 void
1385 produce_glyphs (it)
1386 struct it *it;
1388 /* If a hook is installed, let it do the work. */
1389 xassert (it->what == IT_CHARACTER
1390 || it->what == IT_COMPOSITION
1391 || it->what == IT_STRETCH);
1393 if (it->what == IT_STRETCH)
1395 produce_stretch_glyph (it);
1396 goto done;
1399 /* Nothing but characters are supported on terminal frames. For a
1400 composition sequence, it->c is the first character of the
1401 sequence. */
1402 xassert (it->what == IT_CHARACTER
1403 || it->what == IT_COMPOSITION);
1405 if (it->c >= 040 && it->c < 0177)
1407 it->pixel_width = it->nglyphs = 1;
1408 if (it->glyph_row)
1409 append_glyph (it);
1411 else if (it->c == '\n')
1412 it->pixel_width = it->nglyphs = 0;
1413 else if (it->c == '\t')
1415 int absolute_x = (it->current_x
1416 + it->continuation_lines_width);
1417 int next_tab_x
1418 = (((1 + absolute_x + it->tab_width - 1)
1419 / it->tab_width)
1420 * it->tab_width);
1421 int nspaces;
1423 /* If part of the TAB has been displayed on the previous line
1424 which is continued now, continuation_lines_width will have
1425 been incremented already by the part that fitted on the
1426 continued line. So, we will get the right number of spaces
1427 here. */
1428 nspaces = next_tab_x - absolute_x;
1430 if (it->glyph_row)
1432 int n = nspaces;
1434 it->c = ' ';
1435 it->pixel_width = it->len = 1;
1437 while (n--)
1438 append_glyph (it);
1440 it->c = '\t';
1443 it->pixel_width = nspaces;
1444 it->nglyphs = nspaces;
1446 else if (SINGLE_BYTE_CHAR_P (it->c))
1448 /* Coming here means that it->c is from display table, thus we
1449 must send the code as is to the terminal. Although there's
1450 no way to know how many columns it occupies on a screen, it
1451 is a good assumption that a single byte code has 1-column
1452 width. */
1453 it->pixel_width = it->nglyphs = 1;
1454 if (it->glyph_row)
1455 append_glyph (it);
1457 else
1459 /* A multi-byte character. The display width is fixed for all
1460 characters of the set. Some of the glyphs may have to be
1461 ignored because they are already displayed in a continued
1462 line. */
1463 int charset = CHAR_CHARSET (it->c);
1465 it->pixel_width = CHARSET_WIDTH (charset);
1466 it->nglyphs = it->pixel_width;
1468 if (it->glyph_row)
1469 append_glyph (it);
1472 done:
1473 /* Advance current_x by the pixel width as a convenience for
1474 the caller. */
1475 if (it->area == TEXT_AREA)
1476 it->current_x += it->pixel_width;
1477 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1478 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
1482 /* Produce a stretch glyph for iterator IT. IT->object is the value
1483 of the glyph property displayed. The value must be a list
1484 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1485 being recognized:
1487 1. `:width WIDTH' specifies that the space should be WIDTH *
1488 canonical char width wide. WIDTH may be an integer or floating
1489 point number.
1491 2. `:align-to HPOS' specifies that the space should be wide enough
1492 to reach HPOS, a value in canonical character units. */
1494 static void
1495 produce_stretch_glyph (it)
1496 struct it *it;
1498 /* (space :width WIDTH ...) */
1499 Lisp_Object prop, plist;
1500 int width = 0, align_to = -1;
1501 int zero_width_ok_p = 0;
1502 double tem;
1504 /* List should start with `space'. */
1505 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1506 plist = XCDR (it->object);
1508 /* Compute the width of the stretch. */
1509 if ((prop = Fplist_get (plist, QCwidth), !NILP (prop))
1510 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, 0))
1512 /* Absolute width `:width WIDTH' specified and valid. */
1513 zero_width_ok_p = 1;
1514 width = (int)(tem + 0.5);
1516 else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
1517 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, &align_to))
1519 if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
1520 align_to = (align_to < 0
1522 : align_to - window_box_left_offset (it->w, TEXT_AREA));
1523 else if (align_to < 0)
1524 align_to = window_box_left_offset (it->w, TEXT_AREA);
1525 width = max (0, (int)(tem + 0.5) + align_to - it->current_x);
1526 zero_width_ok_p = 1;
1528 else
1529 /* Nothing specified -> width defaults to canonical char width. */
1530 width = FRAME_COLUMN_WIDTH (it->f);
1532 if (width <= 0 && (width < 0 || !zero_width_ok_p))
1533 width = 1;
1535 if (width > 0 && it->glyph_row)
1537 Lisp_Object o_object = it->object;
1538 Lisp_Object object = it->stack[it->sp - 1].string;
1539 int n = width;
1540 int c = it->c;
1542 if (!STRINGP (object))
1543 object = it->w->buffer;
1544 it->object = object;
1545 it->c = ' ';
1546 it->pixel_width = it->len = 1;
1547 while (n--)
1548 append_glyph (it);
1549 it->object = o_object;
1550 it->c = c;
1552 it->pixel_width = width;
1553 it->nglyphs = width;
1557 /* Get information about special display element WHAT in an
1558 environment described by IT. WHAT is one of IT_TRUNCATION or
1559 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1560 non-null glyph_row member. This function ensures that fields like
1561 face_id, c, len of IT are left untouched. */
1563 void
1564 produce_special_glyphs (it, what)
1565 struct it *it;
1566 enum display_element_type what;
1568 struct it temp_it;
1569 GLYPH glyph;
1571 temp_it = *it;
1572 temp_it.dp = NULL;
1573 temp_it.what = IT_CHARACTER;
1574 temp_it.len = 1;
1575 temp_it.object = make_number (0);
1576 bzero (&temp_it.current, sizeof temp_it.current);
1578 if (what == IT_CONTINUATION)
1580 /* Continuation glyph. */
1581 if (it->dp
1582 && INTEGERP (DISP_CONTINUE_GLYPH (it->dp))
1583 && GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (it->dp))))
1585 glyph = XINT (DISP_CONTINUE_GLYPH (it->dp));
1586 glyph = spec_glyph_lookup_face (XWINDOW (it->window), glyph);
1588 else
1589 glyph = '\\';
1591 else if (what == IT_TRUNCATION)
1593 /* Truncation glyph. */
1594 if (it->dp
1595 && INTEGERP (DISP_TRUNC_GLYPH (it->dp))
1596 && GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (it->dp))))
1598 glyph = XINT (DISP_TRUNC_GLYPH (it->dp));
1599 glyph = spec_glyph_lookup_face (XWINDOW (it->window), glyph);
1601 else
1602 glyph = '$';
1604 else
1605 abort ();
1607 temp_it.c = FAST_GLYPH_CHAR (glyph);
1608 temp_it.face_id = FAST_GLYPH_FACE (glyph);
1609 temp_it.len = CHAR_BYTES (temp_it.c);
1611 produce_glyphs (&temp_it);
1612 it->pixel_width = temp_it.pixel_width;
1613 it->nglyphs = temp_it.pixel_width;
1618 /***********************************************************************
1619 Faces
1620 ***********************************************************************/
1622 /* Value is non-zero if attribute ATTR may be used. ATTR should be
1623 one of the enumerators from enum no_color_bit, or a bit set built
1624 from them. Some display attributes may not be used together with
1625 color; the termcap capability `NC' specifies which ones. */
1627 #define MAY_USE_WITH_COLORS_P(tty, ATTR) \
1628 (tty->TN_max_colors > 0 \
1629 ? (tty->TN_no_color_video & (ATTR)) == 0 \
1630 : 1)
1632 /* Turn appearances of face FACE_ID on tty frame F on.
1633 FACE_ID is a realized face ID number, in the face cache. */
1635 static void
1636 turn_on_face (f, face_id)
1637 struct frame *f;
1638 int face_id;
1640 struct face *face = FACE_FROM_ID (f, face_id);
1641 long fg = face->foreground;
1642 long bg = face->background;
1643 struct tty_display_info *tty = FRAME_TTY (f);
1645 /* Do this first because TS_end_standout_mode may be the same
1646 as TS_exit_attribute_mode, which turns all appearances off. */
1647 if (MAY_USE_WITH_COLORS_P (tty, NC_REVERSE))
1649 if (tty->TN_max_colors > 0)
1651 if (fg >= 0 && bg >= 0)
1653 /* If the terminal supports colors, we can set them
1654 below without using reverse video. The face's fg
1655 and bg colors are set as they should appear on
1656 the screen, i.e. they take the inverse-video'ness
1657 of the face already into account. */
1659 else if (inverse_video)
1661 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1662 || bg == FACE_TTY_DEFAULT_BG_COLOR)
1663 tty_toggle_highlight (tty);
1665 else
1667 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1668 || bg == FACE_TTY_DEFAULT_FG_COLOR)
1669 tty_toggle_highlight (tty);
1672 else
1674 /* If we can't display colors, use reverse video
1675 if the face specifies that. */
1676 if (inverse_video)
1678 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1679 || bg == FACE_TTY_DEFAULT_BG_COLOR)
1680 tty_toggle_highlight (tty);
1682 else
1684 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1685 || bg == FACE_TTY_DEFAULT_FG_COLOR)
1686 tty_toggle_highlight (tty);
1691 if (face->tty_bold_p)
1693 if (MAY_USE_WITH_COLORS_P (tty, NC_BOLD))
1694 OUTPUT1_IF (tty, tty->TS_enter_bold_mode);
1696 else if (face->tty_dim_p)
1697 if (MAY_USE_WITH_COLORS_P (tty, NC_DIM))
1698 OUTPUT1_IF (tty, tty->TS_enter_dim_mode);
1700 /* Alternate charset and blinking not yet used. */
1701 if (face->tty_alt_charset_p
1702 && MAY_USE_WITH_COLORS_P (tty, NC_ALT_CHARSET))
1703 OUTPUT1_IF (tty, tty->TS_enter_alt_charset_mode);
1705 if (face->tty_blinking_p
1706 && MAY_USE_WITH_COLORS_P (tty, NC_BLINK))
1707 OUTPUT1_IF (tty, tty->TS_enter_blink_mode);
1709 if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (tty, NC_UNDERLINE))
1710 OUTPUT1_IF (tty, tty->TS_enter_underline_mode);
1712 if (tty->TN_max_colors > 0)
1714 char *ts, *p;
1716 ts = tty->standout_mode ? tty->TS_set_background : tty->TS_set_foreground;
1717 if (fg >= 0 && ts)
1719 p = tparam (ts, NULL, 0, (int) fg);
1720 OUTPUT (tty, p);
1721 xfree (p);
1724 ts = tty->standout_mode ? tty->TS_set_foreground : tty->TS_set_background;
1725 if (bg >= 0 && ts)
1727 p = tparam (ts, NULL, 0, (int) bg);
1728 OUTPUT (tty, p);
1729 xfree (p);
1735 /* Turn off appearances of face FACE_ID on tty frame F. */
1737 static void
1738 turn_off_face (f, face_id)
1739 struct frame *f;
1740 int face_id;
1742 struct face *face = FACE_FROM_ID (f, face_id);
1743 struct tty_display_info *tty = FRAME_TTY (f);
1745 xassert (face != NULL);
1747 if (tty->TS_exit_attribute_mode)
1749 /* Capability "me" will turn off appearance modes double-bright,
1750 half-bright, reverse-video, standout, underline. It may or
1751 may not turn off alt-char-mode. */
1752 if (face->tty_bold_p
1753 || face->tty_dim_p
1754 || face->tty_reverse_p
1755 || face->tty_alt_charset_p
1756 || face->tty_blinking_p
1757 || face->tty_underline_p)
1759 OUTPUT1_IF (tty, tty->TS_exit_attribute_mode);
1760 if (strcmp (tty->TS_exit_attribute_mode, tty->TS_end_standout_mode) == 0)
1761 tty->standout_mode = 0;
1764 if (face->tty_alt_charset_p)
1765 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
1767 else
1769 /* If we don't have "me" we can only have those appearances
1770 that have exit sequences defined. */
1771 if (face->tty_alt_charset_p)
1772 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
1774 if (face->tty_underline_p)
1775 OUTPUT_IF (tty, tty->TS_exit_underline_mode);
1778 /* Switch back to default colors. */
1779 if (tty->TN_max_colors > 0
1780 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
1781 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
1782 || (face->background != FACE_TTY_DEFAULT_COLOR
1783 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
1784 OUTPUT1_IF (tty, tty->TS_orig_pair);
1788 /* Return non-zero if the terminal on frame F supports all of the
1789 capabilities in CAPS simultaneously, with foreground and background
1790 colors FG and BG. */
1793 tty_capable_p (tty, caps, fg, bg)
1794 struct tty_display_info *tty;
1795 unsigned caps;
1796 unsigned long fg, bg;
1798 #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
1799 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
1800 return 0;
1802 TTY_CAPABLE_P_TRY (tty, TTY_CAP_INVERSE, tty->TS_standout_mode, NC_REVERSE);
1803 TTY_CAPABLE_P_TRY (tty, TTY_CAP_UNDERLINE, tty->TS_enter_underline_mode, NC_UNDERLINE);
1804 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BOLD, tty->TS_enter_bold_mode, NC_BOLD);
1805 TTY_CAPABLE_P_TRY (tty, TTY_CAP_DIM, tty->TS_enter_dim_mode, NC_DIM);
1806 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BLINK, tty->TS_enter_blink_mode, NC_BLINK);
1807 TTY_CAPABLE_P_TRY (tty, TTY_CAP_ALT_CHARSET, tty->TS_enter_alt_charset_mode, NC_ALT_CHARSET);
1809 /* We can do it! */
1810 return 1;
1813 /* Return non-zero if the terminal is capable to display colors. */
1815 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
1816 0, 1, 0,
1817 doc: /* Return non-nil if the tty device TERMINAL can display colors.
1819 TERMINAL can be a terminal id, a frame or nil (meaning the selected
1820 frame's terminal). This function always returns nil if TERMINAL
1821 is not on a tty device. */)
1822 (terminal)
1823 Lisp_Object terminal;
1825 struct terminal *t = get_tty_terminal (terminal);
1826 if (!t)
1827 return Qnil;
1828 else
1829 return t->display_info.tty->TN_max_colors > 0 ? Qt : Qnil;
1832 /* Return the number of supported colors. */
1833 DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
1834 Stty_display_color_cells, 0, 1, 0,
1835 doc: /* Return the number of colors supported by the tty device TERMINAL.
1837 TERMINAL can be a terminal id, a frame or nil (meaning the selected
1838 frame's terminal). This function always returns nil if TERMINAL
1839 is not on a tty device. */)
1840 (terminal)
1841 Lisp_Object terminal;
1843 struct terminal *t = get_tty_terminal (terminal);
1844 if (!t)
1845 return make_number (0);
1846 else
1847 return make_number (t->display_info.tty->TN_max_colors);
1850 #ifndef WINDOWSNT
1852 /* Save or restore the default color-related capabilities of this
1853 terminal. */
1854 static void
1855 tty_default_color_capabilities (struct tty_display_info *tty, int save)
1857 static char
1858 *default_orig_pair, *default_set_foreground, *default_set_background;
1859 static int default_max_colors, default_max_pairs, default_no_color_video;
1861 if (save)
1863 if (default_orig_pair)
1864 xfree (default_orig_pair);
1865 default_orig_pair = tty->TS_orig_pair ? xstrdup (tty->TS_orig_pair) : NULL;
1867 if (default_set_foreground)
1868 xfree (default_set_foreground);
1869 default_set_foreground = tty->TS_set_foreground ? xstrdup (tty->TS_set_foreground)
1870 : NULL;
1872 if (default_set_background)
1873 xfree (default_set_background);
1874 default_set_background = tty->TS_set_background ? xstrdup (tty->TS_set_background)
1875 : NULL;
1877 default_max_colors = tty->TN_max_colors;
1878 default_max_pairs = tty->TN_max_pairs;
1879 default_no_color_video = tty->TN_no_color_video;
1881 else
1883 tty->TS_orig_pair = default_orig_pair;
1884 tty->TS_set_foreground = default_set_foreground;
1885 tty->TS_set_background = default_set_background;
1886 tty->TN_max_colors = default_max_colors;
1887 tty->TN_max_pairs = default_max_pairs;
1888 tty->TN_no_color_video = default_no_color_video;
1892 /* Setup one of the standard tty color schemes according to MODE.
1893 MODE's value is generally the number of colors which we want to
1894 support; zero means set up for the default capabilities, the ones
1895 we saw at init_tty time; -1 means turn off color support. */
1896 static void
1897 tty_setup_colors (struct tty_display_info *tty, int mode)
1899 /* Canonicalize all negative values of MODE. */
1900 if (mode < -1)
1901 mode = -1;
1903 switch (mode)
1905 case -1: /* no colors at all */
1906 tty->TN_max_colors = 0;
1907 tty->TN_max_pairs = 0;
1908 tty->TN_no_color_video = 0;
1909 tty->TS_set_foreground = tty->TS_set_background = tty->TS_orig_pair = NULL;
1910 break;
1911 case 0: /* default colors, if any */
1912 default:
1913 tty_default_color_capabilities (tty, 0);
1914 break;
1915 case 8: /* 8 standard ANSI colors */
1916 tty->TS_orig_pair = "\033[0m";
1917 #ifdef TERMINFO
1918 tty->TS_set_foreground = "\033[3%p1%dm";
1919 tty->TS_set_background = "\033[4%p1%dm";
1920 #else
1921 tty->TS_set_foreground = "\033[3%dm";
1922 tty->TS_set_background = "\033[4%dm";
1923 #endif
1924 tty->TN_max_colors = 8;
1925 tty->TN_max_pairs = 64;
1926 tty->TN_no_color_video = 0;
1927 break;
1931 void
1932 set_tty_color_mode (f, val)
1933 struct frame *f;
1934 Lisp_Object val;
1936 Lisp_Object color_mode_spec, current_mode_spec;
1937 Lisp_Object color_mode, current_mode;
1938 int mode, old_mode;
1939 extern Lisp_Object Qtty_color_mode;
1940 Lisp_Object tty_color_mode_alist;
1942 tty_color_mode_alist = Fintern_soft (build_string ("tty-color-mode-alist"),
1943 Qnil);
1945 if (INTEGERP (val))
1946 color_mode = val;
1947 else
1949 if (NILP (tty_color_mode_alist))
1950 color_mode_spec = Qnil;
1951 else
1952 color_mode_spec = Fassq (val, XSYMBOL (tty_color_mode_alist)->value);
1954 if (CONSP (color_mode_spec))
1955 color_mode = XCDR (color_mode_spec);
1956 else
1957 color_mode = Qnil;
1960 current_mode_spec = assq_no_quit (Qtty_color_mode, f->param_alist);
1962 if (CONSP (current_mode_spec))
1963 current_mode = XCDR (current_mode_spec);
1964 else
1965 current_mode = Qnil;
1966 if (INTEGERP (color_mode))
1967 mode = XINT (color_mode);
1968 else
1969 mode = 0; /* meaning default */
1970 if (INTEGERP (current_mode))
1971 old_mode = XINT (current_mode);
1972 else
1973 old_mode = 0;
1975 if (mode != old_mode)
1977 tty_setup_colors (FRAME_TTY (f), mode);
1978 /* This recomputes all the faces given the new color
1979 definitions. */
1980 call0 (intern ("tty-set-up-initial-frame-faces"));
1981 redraw_frame (f);
1985 #endif /* !WINDOWSNT */
1989 /* Return the tty display object specified by TERMINAL. */
1991 struct terminal *
1992 get_tty_terminal (Lisp_Object terminal)
1994 struct terminal *t = get_terminal (terminal, 0);
1996 if (t && t->type == output_initial)
1997 t = NULL;
1999 if (t && t->type != output_termcap)
2000 error ("Device %d is not a termcap terminal device", t->id);
2002 return t;
2005 /* Return the active termcap device that uses the tty device with the
2006 given name. If NAME is NULL, return the device corresponding to
2007 our controlling terminal.
2009 This function ignores suspended devices.
2011 Returns NULL if the named terminal device is not opened. */
2013 struct terminal *
2014 get_named_tty (name)
2015 char *name;
2017 struct terminal *t;
2019 for (t = terminal_list; t; t = t->next_terminal) {
2020 if (t->type == output_termcap
2021 && ((t->display_info.tty->name == 0 && name == 0)
2022 || (name && t->display_info.tty->name
2023 && !strcmp (t->display_info.tty->name, name)))
2024 && TERMINAL_ACTIVE_P (t))
2025 return t;
2028 return 0;
2032 DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0,
2033 doc: /* Return the type of the tty device that TERMINAL uses.
2035 TERMINAL can be a terminal id, a frame or nil (meaning the selected
2036 frame's terminal). */)
2037 (terminal)
2038 Lisp_Object terminal;
2040 struct terminal *t = get_terminal (terminal, 1);
2042 if (t->type != output_termcap)
2043 error ("Terminal %d is not a termcap terminal", t->id);
2045 if (t->display_info.tty->type)
2046 return build_string (t->display_info.tty->type);
2047 else
2048 return Qnil;
2051 DEFUN ("controlling-tty-p", Fcontrolling_tty_p, Scontrolling_tty_p, 0, 1, 0,
2052 doc: /* Return non-nil if TERMINAL is on the controlling tty of the Emacs process.
2054 TERMINAL can be a terminal id, a frame or nil (meaning the selected
2055 frame's terminal). This function always returns nil if TERMINAL
2056 is not on a tty device. */)
2057 (terminal)
2058 Lisp_Object terminal;
2060 struct terminal *t = get_terminal (terminal, 1);
2062 if (t->type != output_termcap || t->display_info.tty->name)
2063 return Qnil;
2064 else
2065 return Qt;
2068 DEFUN ("tty-no-underline", Ftty_no_underline, Stty_no_underline, 0, 1, 0,
2069 doc: /* Declare that the tty used by TERMINAL does not handle underlining.
2070 This is used to override the terminfo data, for certain terminals that
2071 do not really do underlining, but say that they do. This function has
2072 no effect if used on a non-tty terminal.
2074 TERMINAL can be a terminal id, a frame or nil (meaning the selected
2075 frame's terminal). This function always returns nil if TERMINAL
2076 is not on a tty device. */)
2077 (terminal)
2078 Lisp_Object terminal;
2080 struct terminal *t = get_terminal (terminal, 1);
2082 if (t->type == output_termcap)
2083 t->display_info.tty->TS_enter_underline_mode = 0;
2084 return Qnil;
2089 DEFUN ("suspend-tty", Fsuspend_tty, Ssuspend_tty, 0, 1, 0,
2090 doc: /* Suspend the terminal device TTY.
2092 The device is restored to its default state, and Emacs ceases all
2093 access to the tty device. Frames that use the device are not deleted,
2094 but input is not read from them and if they change, their display is
2095 not updated.
2097 TTY may be a terminal id, a frame, or nil for the terminal device of
2098 the currently selected frame.
2100 This function runs `suspend-tty-functions' after suspending the
2101 device. The functions are run with one arg, the id of the suspended
2102 terminal device.
2104 `suspend-tty' does nothing if it is called on a device that is already
2105 suspended.
2107 A suspended tty may be resumed by calling `resume-tty' on it. */)
2108 (tty)
2109 Lisp_Object tty;
2111 struct terminal *t = get_tty_terminal (tty);
2112 FILE *f;
2114 if (!t)
2115 error ("Unknown tty device");
2117 f = t->display_info.tty->input;
2119 if (f)
2121 reset_sys_modes (t->display_info.tty);
2123 delete_keyboard_wait_descriptor (fileno (f));
2125 fclose (f);
2126 if (f != t->display_info.tty->output)
2127 fclose (t->display_info.tty->output);
2129 t->display_info.tty->input = 0;
2130 t->display_info.tty->output = 0;
2132 if (FRAMEP (t->display_info.tty->top_frame))
2133 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0);
2135 /* Run `suspend-tty-functions'. */
2136 if (!NILP (Vrun_hooks))
2138 Lisp_Object args[2];
2139 args[0] = intern ("suspend-tty-functions");
2140 args[1] = make_number (t->id);
2141 Frun_hook_with_args (2, args);
2145 return Qnil;
2148 DEFUN ("resume-tty", Fresume_tty, Sresume_tty, 0, 1, 0,
2149 doc: /* Resume the previously suspended terminal device TTY.
2150 The terminal is opened and reinitialized. Frames that are on the
2151 suspended terminal are revived.
2153 It is an error to resume a terminal while another terminal is active
2154 on the same device.
2156 This function runs `resume-tty-functions' after resuming the terminal.
2157 The functions are run with one arg, the id of the resumed terminal
2158 device.
2160 `resume-tty' does nothing if it is called on a device that is not
2161 suspended.
2163 TTY may be a terminal id, a frame, or nil for the terminal device of
2164 the currently selected frame. */)
2165 (tty)
2166 Lisp_Object tty;
2168 struct terminal *t = get_tty_terminal (tty);
2169 int fd;
2171 if (!t)
2172 error ("Unknown tty device");
2174 if (!t->display_info.tty->input)
2176 if (get_named_tty (t->display_info.tty->name))
2177 error ("Cannot resume display while another display is active on the same device");
2179 fd = emacs_open (t->display_info.tty->name, O_RDWR | O_NOCTTY, 0);
2181 /* XXX What if open fails? */
2183 dissociate_if_controlling_tty (fd);
2185 t->display_info.tty->output = fdopen (fd, "w+");
2186 t->display_info.tty->input = t->display_info.tty->output;
2188 add_keyboard_wait_descriptor (fd);
2190 if (FRAMEP (t->display_info.tty->top_frame))
2191 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
2193 init_sys_modes (t->display_info.tty);
2195 /* Run `suspend-tty-functions'. */
2196 if (!NILP (Vrun_hooks))
2198 Lisp_Object args[2];
2199 args[0] = intern ("resume-tty-functions");
2200 args[1] = make_number (t->id);
2201 Frun_hook_with_args (2, args);
2205 return Qnil;
2209 /***********************************************************************
2210 Initialization
2211 ***********************************************************************/
2213 /* Initialize the tty-dependent part of frame F. The frame must
2214 already have its device initialized. */
2216 void
2217 create_tty_output (struct frame *f)
2219 struct tty_output *t;
2221 if (! FRAME_TERMCAP_P (f))
2222 abort ();
2224 t = xmalloc (sizeof (struct tty_output));
2225 bzero (t, sizeof (struct tty_output));
2227 t->display_info = FRAME_TERMINAL (f)->display_info.tty;
2229 f->output_data.tty = t;
2232 /* Delete the tty-dependent part of frame F. */
2234 static void
2235 delete_tty_output (struct frame *f)
2237 if (! FRAME_TERMCAP_P (f))
2238 abort ();
2240 xfree (f->output_data.tty);
2245 /* Drop the controlling terminal if fd is the same device. */
2246 static void
2247 dissociate_if_controlling_tty (int fd)
2249 int pgid;
2250 EMACS_GET_TTY_PGRP (fd, &pgid); /* If tcgetpgrp succeeds, fd is the ctty. */
2251 if (pgid != -1)
2253 #if defined (USG) && !defined (BSD_PGRPS)
2254 setpgrp ();
2255 no_controlling_tty = 1;
2256 #else
2257 #ifdef TIOCNOTTY /* Try BSD ioctls. */
2258 sigblock (sigmask (SIGTTOU));
2259 fd = emacs_open ("/dev/tty", O_RDWR, 0);
2260 if (fd != -1 && ioctl (fd, TIOCNOTTY, 0) != -1)
2262 no_controlling_tty = 1;
2264 if (fd != -1)
2265 emacs_close (fd);
2266 sigunblock (sigmask (SIGTTOU));
2267 #else
2268 /* Unknown system. */
2269 croak ();
2270 #endif /* ! TIOCNOTTY */
2271 #endif /* ! USG */
2275 static void maybe_fatal();
2277 /* Create a termcap display on the tty device with the given name and
2278 type.
2280 If NAME is NULL, then use the controlling tty, i.e., stdin/stdout.
2281 Otherwise NAME should be a path to the tty device file,
2282 e.g. "/dev/pts/7".
2284 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
2286 If MUST_SUCCEED is true, then all errors are fatal. */
2288 struct terminal *
2289 init_tty (char *name, char *terminal_type, int must_succeed)
2291 char *area;
2292 char **address = &area;
2293 char *buffer = NULL;
2294 int buffer_size = 4096;
2295 register char *p;
2296 int status;
2297 struct tty_display_info *tty;
2298 struct terminal *terminal;
2300 if (!terminal_type)
2301 maybe_fatal (must_succeed, 0, 0,
2302 "Unknown terminal type",
2303 "Unknown terminal type");
2305 /* If we already have a terminal on the given device, use that. If
2306 all such terminals are suspended, create a new one instead. */
2307 /* XXX Perhaps this should be made explicit by having init_tty
2308 always create a new terminal and separating terminal and frame
2309 creation on Lisp level. */
2310 terminal = get_named_tty (name);
2311 if (terminal)
2312 return terminal;
2314 terminal = create_terminal ();
2315 tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info));
2316 bzero (tty, sizeof (struct tty_display_info));
2317 tty->next = tty_list;
2318 tty_list = tty;
2320 terminal->type = output_termcap;
2321 terminal->display_info.tty = tty;
2322 tty->terminal = terminal;
2324 tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
2325 Wcm_clear (tty);
2327 terminal->rif = 0; /* ttys don't support window-based redisplay. */
2329 terminal->cursor_to_hook = &tty_cursor_to;
2330 terminal->raw_cursor_to_hook = &tty_raw_cursor_to;
2332 terminal->clear_to_end_hook = &tty_clear_to_end;
2333 terminal->clear_frame_hook = &tty_clear_frame;
2334 terminal->clear_end_of_line_hook = &tty_clear_end_of_line;
2336 terminal->ins_del_lines_hook = &tty_ins_del_lines;
2338 terminal->insert_glyphs_hook = &tty_insert_glyphs;
2339 terminal->write_glyphs_hook = &tty_write_glyphs;
2340 terminal->delete_glyphs_hook = &tty_delete_glyphs;
2342 terminal->ring_bell_hook = &tty_ring_bell;
2344 terminal->reset_terminal_modes_hook = &tty_reset_terminal_modes;
2345 terminal->set_terminal_modes_hook = &tty_set_terminal_modes;
2346 terminal->update_begin_hook = 0; /* Not needed. */
2347 terminal->update_end_hook = &tty_update_end;
2348 terminal->set_terminal_window_hook = &tty_set_terminal_window;
2350 terminal->mouse_position_hook = 0; /* Not needed. */
2351 terminal->frame_rehighlight_hook = 0; /* Not needed. */
2352 terminal->frame_raise_lower_hook = 0; /* Not needed. */
2354 terminal->set_vertical_scroll_bar_hook = 0; /* Not needed. */
2355 terminal->condemn_scroll_bars_hook = 0; /* Not needed. */
2356 terminal->redeem_scroll_bar_hook = 0; /* Not needed. */
2357 terminal->judge_scroll_bars_hook = 0; /* Not needed. */
2359 terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */
2360 terminal->frame_up_to_date_hook = 0; /* Not needed. */
2362 terminal->delete_frame_hook = &delete_tty_output;
2363 terminal->delete_terminal_hook = &delete_tty;
2365 if (name)
2367 int fd;
2368 FILE *file;
2370 #ifdef O_IGNORE_CTTY
2371 /* Open the terminal device. Don't recognize it as our
2372 controlling terminal, and don't make it the controlling tty
2373 if we don't have one at the moment. */
2374 fd = emacs_open (name, O_RDWR | O_IGNORE_CTTY | O_NOCTTY, 0);
2375 #else
2376 /* Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
2377 defined on Hurd. On other systems, we need to dissociate
2378 ourselves from the controlling tty when we want to open a
2379 frame on the same terminal. */
2381 fd = emacs_open (name, O_RDWR | O_NOCTTY, 0);
2383 #endif /* O_IGNORE_CTTY */
2385 if (fd < 0)
2387 delete_tty (terminal);
2388 error ("Could not open file: %s", name);
2390 if (!isatty (fd))
2392 close (fd);
2393 error ("Not a tty device: %s", name);
2396 dissociate_if_controlling_tty (fd);
2398 file = fdopen (fd, "w+");
2399 tty->name = xstrdup (name);
2400 terminal->name = xstrdup (name);
2401 tty->input = file;
2402 tty->output = file;
2404 else
2406 if (no_controlling_tty)
2408 /* Opening a frame on stdout is unsafe if we have
2409 disconnected our controlling terminal. */
2410 error ("There is no controlling terminal any more");
2412 tty->name = 0;
2413 terminal->name = xstrdup (ttyname (0));
2414 tty->input = stdin;
2415 tty->output = stdout;
2418 tty->type = xstrdup (terminal_type);
2420 add_keyboard_wait_descriptor (fileno (tty->input));
2422 encode_terminal_bufsize = 0;
2424 #ifdef WINDOWSNT
2425 initialize_w32_display ();
2427 Wcm_clear (tty);
2429 area = (char *) xmalloc (2044);
2431 FrameRows (tty) = FRAME_LINES (f); /* XXX */
2432 FrameCols (tty) = FRAME_COLS (f); /* XXX */
2433 tty->specified_window = FRAME_LINES (f); /* XXX */
2435 tty->terminal->delete_in_insert_mode = 1;
2437 UseTabs (tty) = 0;
2438 terminal->scroll_region_ok = 0;
2440 /* Seems to insert lines when it's not supposed to, messing up the
2441 display. In doing a trace, it didn't seem to be called much, so I
2442 don't think we're losing anything by turning it off. */
2443 terminal->line_ins_del_ok = 0;
2444 terminal->char_ins_del_ok = 1;
2446 baud_rate = 19200;
2448 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0; /* XXX */
2449 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none; /* XXX */
2450 TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
2452 return terminal;
2453 #else /* not WINDOWSNT */
2455 Wcm_clear (tty);
2457 buffer = (char *) xmalloc (buffer_size);
2459 /* On some systems, tgetent tries to access the controlling
2460 terminal. */
2461 sigblock (sigmask (SIGTTOU));
2462 status = tgetent (buffer, terminal_type);
2463 sigunblock (sigmask (SIGTTOU));
2465 if (status < 0)
2467 #ifdef TERMINFO
2468 maybe_fatal (must_succeed, buffer, terminal,
2469 "Cannot open terminfo database file",
2470 "Cannot open terminfo database file");
2471 #else
2472 maybe_fatal (must_succeed, buffer, terminal,
2473 "Cannot open termcap database file",
2474 "Cannot open termcap database file");
2475 #endif
2477 if (status == 0)
2479 #ifdef TERMINFO
2480 maybe_fatal (must_succeed, buffer, terminal,
2481 "Terminal type %s is not defined",
2482 "Terminal type %s is not defined.\n\
2483 If that is not the actual type of terminal you have,\n\
2484 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2485 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2486 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
2487 terminal_type);
2488 #else
2489 maybe_fatal (must_succeed, buffer, terminal,
2490 "Terminal type %s is not defined",
2491 "Terminal type %s is not defined.\n\
2492 If that is not the actual type of terminal you have,\n\
2493 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2494 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2495 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
2496 terminal_type);
2497 #endif
2500 #ifndef TERMINFO
2501 if (strlen (buffer) >= buffer_size)
2502 abort ();
2503 buffer_size = strlen (buffer);
2504 #endif
2505 area = (char *) xmalloc (buffer_size);
2507 tty->TS_ins_line = tgetstr ("al", address);
2508 tty->TS_ins_multi_lines = tgetstr ("AL", address);
2509 tty->TS_bell = tgetstr ("bl", address);
2510 BackTab (tty) = tgetstr ("bt", address);
2511 tty->TS_clr_to_bottom = tgetstr ("cd", address);
2512 tty->TS_clr_line = tgetstr ("ce", address);
2513 tty->TS_clr_frame = tgetstr ("cl", address);
2514 ColPosition (tty) = NULL; /* tgetstr ("ch", address); */
2515 AbsPosition (tty) = tgetstr ("cm", address);
2516 CR (tty) = tgetstr ("cr", address);
2517 tty->TS_set_scroll_region = tgetstr ("cs", address);
2518 tty->TS_set_scroll_region_1 = tgetstr ("cS", address);
2519 RowPosition (tty) = tgetstr ("cv", address);
2520 tty->TS_del_char = tgetstr ("dc", address);
2521 tty->TS_del_multi_chars = tgetstr ("DC", address);
2522 tty->TS_del_line = tgetstr ("dl", address);
2523 tty->TS_del_multi_lines = tgetstr ("DL", address);
2524 tty->TS_delete_mode = tgetstr ("dm", address);
2525 tty->TS_end_delete_mode = tgetstr ("ed", address);
2526 tty->TS_end_insert_mode = tgetstr ("ei", address);
2527 Home (tty) = tgetstr ("ho", address);
2528 tty->TS_ins_char = tgetstr ("ic", address);
2529 tty->TS_ins_multi_chars = tgetstr ("IC", address);
2530 tty->TS_insert_mode = tgetstr ("im", address);
2531 tty->TS_pad_inserted_char = tgetstr ("ip", address);
2532 tty->TS_end_keypad_mode = tgetstr ("ke", address);
2533 tty->TS_keypad_mode = tgetstr ("ks", address);
2534 LastLine (tty) = tgetstr ("ll", address);
2535 Right (tty) = tgetstr ("nd", address);
2536 Down (tty) = tgetstr ("do", address);
2537 if (!Down (tty))
2538 Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do" */
2539 #ifdef VMS
2540 /* VMS puts a carriage return before each linefeed,
2541 so it is not safe to use linefeeds. */
2542 if (Down (tty) && Down (tty)[0] == '\n' && Down (tty)[1] == '\0')
2543 Down (tty) = 0;
2544 #endif /* VMS */
2545 if (tgetflag ("bs"))
2546 Left (tty) = "\b"; /* can't possibly be longer! */
2547 else /* (Actually, "bs" is obsolete...) */
2548 Left (tty) = tgetstr ("le", address);
2549 if (!Left (tty))
2550 Left (tty) = tgetstr ("bc", address); /* Obsolete name for "le" */
2551 tty->TS_pad_char = tgetstr ("pc", address);
2552 tty->TS_repeat = tgetstr ("rp", address);
2553 tty->TS_end_standout_mode = tgetstr ("se", address);
2554 tty->TS_fwd_scroll = tgetstr ("sf", address);
2555 tty->TS_standout_mode = tgetstr ("so", address);
2556 tty->TS_rev_scroll = tgetstr ("sr", address);
2557 tty->Wcm->cm_tab = tgetstr ("ta", address);
2558 tty->TS_end_termcap_modes = tgetstr ("te", address);
2559 tty->TS_termcap_modes = tgetstr ("ti", address);
2560 Up (tty) = tgetstr ("up", address);
2561 tty->TS_visible_bell = tgetstr ("vb", address);
2562 tty->TS_cursor_normal = tgetstr ("ve", address);
2563 tty->TS_cursor_visible = tgetstr ("vs", address);
2564 tty->TS_cursor_invisible = tgetstr ("vi", address);
2565 tty->TS_set_window = tgetstr ("wi", address);
2567 tty->TS_enter_underline_mode = tgetstr ("us", address);
2568 tty->TS_exit_underline_mode = tgetstr ("ue", address);
2569 tty->TS_enter_bold_mode = tgetstr ("md", address);
2570 tty->TS_enter_dim_mode = tgetstr ("mh", address);
2571 tty->TS_enter_blink_mode = tgetstr ("mb", address);
2572 tty->TS_enter_reverse_mode = tgetstr ("mr", address);
2573 tty->TS_enter_alt_charset_mode = tgetstr ("as", address);
2574 tty->TS_exit_alt_charset_mode = tgetstr ("ae", address);
2575 tty->TS_exit_attribute_mode = tgetstr ("me", address);
2577 MultiUp (tty) = tgetstr ("UP", address);
2578 MultiDown (tty) = tgetstr ("DO", address);
2579 MultiLeft (tty) = tgetstr ("LE", address);
2580 MultiRight (tty) = tgetstr ("RI", address);
2582 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
2583 color because we can't switch back to the default foreground and
2584 background. */
2585 tty->TS_orig_pair = tgetstr ("op", address);
2586 if (tty->TS_orig_pair)
2588 tty->TS_set_foreground = tgetstr ("AF", address);
2589 tty->TS_set_background = tgetstr ("AB", address);
2590 if (!tty->TS_set_foreground)
2592 /* SVr4. */
2593 tty->TS_set_foreground = tgetstr ("Sf", address);
2594 tty->TS_set_background = tgetstr ("Sb", address);
2597 tty->TN_max_colors = tgetnum ("Co");
2598 tty->TN_max_pairs = tgetnum ("pa");
2600 tty->TN_no_color_video = tgetnum ("NC");
2601 if (tty->TN_no_color_video == -1)
2602 tty->TN_no_color_video = 0;
2605 tty_default_color_capabilities (tty, 1);
2607 MagicWrap (tty) = tgetflag ("xn");
2608 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
2609 the former flag imply the latter. */
2610 AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
2611 terminal->memory_below_frame = tgetflag ("db");
2612 tty->TF_hazeltine = tgetflag ("hz");
2613 terminal->must_write_spaces = tgetflag ("in");
2614 tty->meta_key = tgetflag ("km") || tgetflag ("MT");
2615 tty->TF_insmode_motion = tgetflag ("mi");
2616 tty->TF_standout_motion = tgetflag ("ms");
2617 tty->TF_underscore = tgetflag ("ul");
2618 tty->TF_teleray = tgetflag ("xt");
2620 #ifdef MULTI_KBOARD
2621 terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
2622 init_kboard (terminal->kboard);
2623 terminal->kboard->next_kboard = all_kboards;
2624 all_kboards = terminal->kboard;
2625 terminal->kboard->reference_count++;
2626 /* Don't let the initial kboard remain current longer than necessary.
2627 That would cause problems if a file loaded on startup tries to
2628 prompt in the mini-buffer. */
2629 if (current_kboard == initial_kboard)
2630 current_kboard = terminal->kboard;
2631 #endif
2633 term_get_fkeys (address, terminal->kboard);
2635 /* Get frame size from system, or else from termcap. */
2637 int height, width;
2638 get_tty_size (fileno (tty->input), &width, &height);
2639 FrameCols (tty) = width;
2640 FrameRows (tty) = height;
2643 if (FrameCols (tty) <= 0)
2644 FrameCols (tty) = tgetnum ("co");
2645 if (FrameRows (tty) <= 0)
2646 FrameRows (tty) = tgetnum ("li");
2648 if (FrameRows (tty) < 3 || FrameCols (tty) < 3)
2649 maybe_fatal (must_succeed, NULL, terminal,
2650 "Screen size %dx%d is too small"
2651 "Screen size %dx%d is too small",
2652 FrameCols (tty), FrameRows (tty));
2654 #if 0 /* This is not used anywhere. */
2655 tty->terminal->min_padding_speed = tgetnum ("pb");
2656 #endif
2658 TabWidth (tty) = tgetnum ("tw");
2660 #ifdef VMS
2661 /* These capabilities commonly use ^J.
2662 I don't know why, but sending them on VMS does not work;
2663 it causes following spaces to be lost, sometimes.
2664 For now, the simplest fix is to avoid using these capabilities ever. */
2665 if (Down (tty) && Down (tty)[0] == '\n')
2666 Down (tty) = 0;
2667 #endif /* VMS */
2669 if (!tty->TS_bell)
2670 tty->TS_bell = "\07";
2672 if (!tty->TS_fwd_scroll)
2673 tty->TS_fwd_scroll = Down (tty);
2675 PC = tty->TS_pad_char ? *tty->TS_pad_char : 0;
2677 if (TabWidth (tty) < 0)
2678 TabWidth (tty) = 8;
2680 /* Turned off since /etc/termcap seems to have :ta= for most terminals
2681 and newer termcap doc does not seem to say there is a default.
2682 if (!tty->Wcm->cm_tab)
2683 tty->Wcm->cm_tab = "\t";
2686 /* We don't support standout modes that use `magic cookies', so
2687 turn off any that do. */
2688 if (tty->TS_standout_mode && tgetnum ("sg") >= 0)
2690 tty->TS_standout_mode = 0;
2691 tty->TS_end_standout_mode = 0;
2693 if (tty->TS_enter_underline_mode && tgetnum ("ug") >= 0)
2695 tty->TS_enter_underline_mode = 0;
2696 tty->TS_exit_underline_mode = 0;
2699 /* If there's no standout mode, try to use underlining instead. */
2700 if (tty->TS_standout_mode == 0)
2702 tty->TS_standout_mode = tty->TS_enter_underline_mode;
2703 tty->TS_end_standout_mode = tty->TS_exit_underline_mode;
2706 /* If no `se' string, try using a `me' string instead.
2707 If that fails, we can't use standout mode at all. */
2708 if (tty->TS_end_standout_mode == 0)
2710 char *s = tgetstr ("me", address);
2711 if (s != 0)
2712 tty->TS_end_standout_mode = s;
2713 else
2714 tty->TS_standout_mode = 0;
2717 if (tty->TF_teleray)
2719 tty->Wcm->cm_tab = 0;
2720 /* We can't support standout mode, because it uses magic cookies. */
2721 tty->TS_standout_mode = 0;
2722 /* But that means we cannot rely on ^M to go to column zero! */
2723 CR (tty) = 0;
2724 /* LF can't be trusted either -- can alter hpos */
2725 /* if move at column 0 thru a line with TS_standout_mode */
2726 Down (tty) = 0;
2729 /* Special handling for certain terminal types known to need it */
2731 if (!strcmp (terminal_type, "supdup"))
2733 terminal->memory_below_frame = 1;
2734 tty->Wcm->cm_losewrap = 1;
2736 if (!strncmp (terminal_type, "c10", 3)
2737 || !strcmp (terminal_type, "perq"))
2739 /* Supply a makeshift :wi string.
2740 This string is not valid in general since it works only
2741 for windows starting at the upper left corner;
2742 but that is all Emacs uses.
2744 This string works only if the frame is using
2745 the top of the video memory, because addressing is memory-relative.
2746 So first check the :ti string to see if that is true.
2748 It would be simpler if the :wi string could go in the termcap
2749 entry, but it can't because it is not fully valid.
2750 If it were in the termcap entry, it would confuse other programs. */
2751 if (!tty->TS_set_window)
2753 p = tty->TS_termcap_modes;
2754 while (*p && strcmp (p, "\033v "))
2755 p++;
2756 if (*p)
2757 tty->TS_set_window = "\033v%C %C %C %C ";
2759 /* Termcap entry often fails to have :in: flag */
2760 terminal->must_write_spaces = 1;
2761 /* :ti string typically fails to have \E^G! in it */
2762 /* This limits scope of insert-char to one line. */
2763 strcpy (area, tty->TS_termcap_modes);
2764 strcat (area, "\033\007!");
2765 tty->TS_termcap_modes = area;
2766 area += strlen (area) + 1;
2767 p = AbsPosition (tty);
2768 /* Change all %+ parameters to %C, to handle
2769 values above 96 correctly for the C100. */
2770 while (*p)
2772 if (p[0] == '%' && p[1] == '+')
2773 p[1] = 'C';
2774 p++;
2778 tty->specified_window = FrameRows (tty);
2780 if (Wcm_init (tty) == -1) /* can't do cursor motion */
2782 maybe_fatal (must_succeed, NULL, terminal,
2783 "Terminal type \"%s\" is not powerful enough to run Emacs",
2784 #ifdef VMS
2785 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2786 It lacks the ability to position the cursor.\n\
2787 If that is not the actual type of terminal you have, use either the\n\
2788 DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
2789 or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
2790 #else /* not VMS */
2791 # ifdef TERMINFO
2792 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2793 It lacks the ability to position the cursor.\n\
2794 If that is not the actual type of terminal you have,\n\
2795 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2796 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2797 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
2798 # else /* TERMCAP */
2799 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2800 It lacks the ability to position the cursor.\n\
2801 If that is not the actual type of terminal you have,\n\
2802 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2803 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2804 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
2805 # endif /* TERMINFO */
2806 #endif /*VMS */
2807 terminal_type);
2810 if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
2811 maybe_fatal (must_succeed, NULL, terminal,
2812 "Could not determine the frame size",
2813 "Could not determine the frame size");
2815 tty->delete_in_insert_mode
2816 = tty->TS_delete_mode && tty->TS_insert_mode
2817 && !strcmp (tty->TS_delete_mode, tty->TS_insert_mode);
2819 tty->se_is_so = (tty->TS_standout_mode
2820 && tty->TS_end_standout_mode
2821 && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode));
2823 UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8;
2825 terminal->scroll_region_ok
2826 = (tty->Wcm->cm_abs
2827 && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
2829 terminal->line_ins_del_ok
2830 = (((tty->TS_ins_line || tty->TS_ins_multi_lines)
2831 && (tty->TS_del_line || tty->TS_del_multi_lines))
2832 || (terminal->scroll_region_ok
2833 && tty->TS_fwd_scroll && tty->TS_rev_scroll));
2835 terminal->char_ins_del_ok
2836 = ((tty->TS_ins_char || tty->TS_insert_mode
2837 || tty->TS_pad_inserted_char || tty->TS_ins_multi_chars)
2838 && (tty->TS_del_char || tty->TS_del_multi_chars));
2840 terminal->fast_clear_end_of_line = tty->TS_clr_line != 0;
2842 init_baud_rate (fileno (tty->input));
2844 #ifdef AIXHFT
2845 /* The HFT system on AIX doesn't optimize for scrolling, so it's
2846 really ugly at times. */
2847 terminal->line_ins_del_ok = 0;
2848 terminal->char_ins_del_ok = 0;
2849 #endif
2851 /* Don't do this. I think termcap may still need the buffer. */
2852 /* xfree (buffer); */
2854 /* Init system terminal modes (RAW or CBREAK, etc.). */
2855 init_sys_modes (tty);
2857 return terminal;
2858 #endif /* not WINDOWSNT */
2861 /* Auxiliary error-handling function for init_tty.
2862 Free BUFFER and delete TERMINAL, then call error or fatal
2863 with str1 or str2, respectively, according to MUST_SUCCEED. */
2865 static void
2866 maybe_fatal (must_succeed, buffer, terminal, str1, str2, arg1, arg2)
2867 int must_succeed;
2868 char *buffer;
2869 struct terminal *terminal;
2870 char *str1, *str2, *arg1, *arg2;
2872 if (buffer)
2873 xfree (buffer);
2875 if (terminal)
2876 delete_tty (terminal);
2878 if (must_succeed)
2879 fatal (str2, arg1, arg2);
2880 else
2881 error (str1, arg1, arg2);
2883 abort ();
2886 /* VARARGS 1 */
2887 void
2888 fatal (str, arg1, arg2)
2889 char *str, *arg1, *arg2;
2891 fprintf (stderr, "emacs: ");
2892 fprintf (stderr, str, arg1, arg2);
2893 fprintf (stderr, "\n");
2894 fflush (stderr);
2895 exit (1);
2900 static int deleting_tty = 0;
2903 /* Delete the given tty terminal, closing all frames on it. */
2905 static void
2906 delete_tty (struct terminal *terminal)
2908 struct tty_display_info *tty;
2909 Lisp_Object tail, frame;
2910 char *tty_name;
2911 int last_terminal;
2913 if (deleting_tty)
2914 /* We get a recursive call when we delete the last frame on this
2915 terminal. */
2916 return;
2918 if (terminal->type != output_termcap)
2919 abort ();
2921 tty = terminal->display_info.tty;
2923 last_terminal = 1;
2924 FOR_EACH_FRAME (tail, frame)
2926 struct frame *f = XFRAME (frame);
2927 if (FRAME_LIVE_P (f) && (!FRAME_TERMCAP_P (f) || FRAME_TTY (f) != tty))
2929 last_terminal = 0;
2930 break;
2933 if (last_terminal)
2934 error ("Attempt to delete the sole terminal device with live frames");
2936 if (tty == tty_list)
2937 tty_list = tty->next;
2938 else
2940 struct tty_display_info *p;
2941 for (p = tty_list; p && p->next != tty; p = p->next)
2944 if (! p)
2945 /* This should not happen. */
2946 abort ();
2948 p->next = tty->next;
2949 tty->next = 0;
2952 deleting_tty = 1;
2954 FOR_EACH_FRAME (tail, frame)
2956 struct frame *f = XFRAME (frame);
2957 if (FRAME_TERMCAP_P (f) && FRAME_LIVE_P (f) && FRAME_TTY (f) == tty)
2959 Fdelete_frame (frame, Qt);
2963 /* reset_sys_modes needs a valid device, so this call needs to be
2964 before delete_terminal. */
2965 reset_sys_modes (tty);
2967 delete_terminal (terminal);
2969 tty_name = tty->name;
2970 if (tty->type)
2971 xfree (tty->type);
2973 if (tty->input)
2975 delete_keyboard_wait_descriptor (fileno (tty->input));
2976 if (tty->input != stdin)
2977 fclose (tty->input);
2979 if (tty->output && tty->output != stdout && tty->output != tty->input)
2980 fclose (tty->output);
2981 if (tty->termscript)
2982 fclose (tty->termscript);
2984 if (tty->old_tty)
2985 xfree (tty->old_tty);
2987 if (tty->Wcm)
2988 xfree (tty->Wcm);
2990 bzero (tty, sizeof (struct tty_display_info));
2991 xfree (tty);
2992 deleting_tty = 0;
2997 /* Mark the pointers in the tty_display_info objects.
2998 Called by the Fgarbage_collector. */
3000 void
3001 mark_ttys (void)
3003 struct tty_display_info *tty;
3005 for (tty = tty_list; tty; tty = tty->next)
3007 if (tty->top_frame)
3008 mark_object (tty->top_frame);
3014 void
3015 syms_of_term ()
3017 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
3018 doc: /* Non-nil means the system uses terminfo rather than termcap.
3019 This variable can be used by terminal emulator packages. */);
3020 #ifdef TERMINFO
3021 system_uses_terminfo = 1;
3022 #else
3023 system_uses_terminfo = 0;
3024 #endif
3026 DEFVAR_LISP ("suspend-tty-functions", &Vsuspend_tty_functions,
3027 doc: /* Functions to be run after suspending a tty.
3028 The functions are run with one argument, the name of the tty to be suspended.
3029 See `suspend-tty'. */);
3030 Vsuspend_tty_functions = Qnil;
3033 DEFVAR_LISP ("resume-tty-functions", &Vresume_tty_functions,
3034 doc: /* Functions to be run after resuming a tty.
3035 The functions are run with one argument, the name of the tty that was revived.
3036 See `resume-tty'. */);
3037 Vresume_tty_functions = Qnil;
3039 DEFVAR_BOOL ("visible-cursor", &visible_cursor,
3040 doc: /* Non-nil means to make the cursor very visible.
3041 This only has an effect when running in a text terminal.
3042 What means \"very visible\" is up to your terminal. It may make the cursor
3043 bigger, or it may make it blink, or it may do nothing at all. */);
3044 visible_cursor = 1;
3046 defsubr (&Stty_display_color_p);
3047 defsubr (&Stty_display_color_cells);
3048 defsubr (&Stty_no_underline);
3049 defsubr (&Stty_type);
3050 defsubr (&Scontrolling_tty_p);
3051 defsubr (&Ssuspend_tty);
3052 defsubr (&Sresume_tty);
3057 /* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193
3058 (do not change this comment) */