Fix ediff problems. (Reported by Dan Nicolaescu.)
[emacs.git] / src / term.c
blobb1183ed9e2aab8aaa95e6308dfacaa0f9222d190
1 /* Terminal control module for terminals described by TERMCAP
2 Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1998, 2000, 2001,
3 2002, 2003, 2004, 2005, 2006 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->char_to_display is
1332 the character for which to produce glyphs; IT->face_id contains the
1333 character's face. Padding glyphs are appended if IT->c has a
1334 IT->pixel_width > 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->char_to_display;
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 /* Maybe translate single-byte characters to multibyte. */
1406 it->char_to_display = it->c;
1408 if (it->c >= 040 && it->c < 0177)
1410 it->pixel_width = it->nglyphs = 1;
1411 if (it->glyph_row)
1412 append_glyph (it);
1414 else if (it->c == '\n')
1415 it->pixel_width = it->nglyphs = 0;
1416 else if (it->c == '\t')
1418 int absolute_x = (it->current_x
1419 + it->continuation_lines_width);
1420 int next_tab_x
1421 = (((1 + absolute_x + it->tab_width - 1)
1422 / it->tab_width)
1423 * it->tab_width);
1424 int nspaces;
1426 /* If part of the TAB has been displayed on the previous line
1427 which is continued now, continuation_lines_width will have
1428 been incremented already by the part that fitted on the
1429 continued line. So, we will get the right number of spaces
1430 here. */
1431 nspaces = next_tab_x - absolute_x;
1433 if (it->glyph_row)
1435 int n = nspaces;
1437 it->char_to_display = ' ';
1438 it->pixel_width = it->len = 1;
1440 while (n--)
1441 append_glyph (it);
1444 it->pixel_width = nspaces;
1445 it->nglyphs = nspaces;
1447 else if (SINGLE_BYTE_CHAR_P (it->c))
1449 if (unibyte_display_via_language_environment
1450 && (it->c >= 0240
1451 || !NILP (Vnonascii_translation_table)))
1453 int charset;
1455 it->char_to_display = unibyte_char_to_multibyte (it->c);
1456 charset = CHAR_CHARSET (it->char_to_display);
1457 it->pixel_width = CHARSET_WIDTH (charset);
1458 it->nglyphs = it->pixel_width;
1459 if (it->glyph_row)
1460 append_glyph (it);
1462 else
1464 /* Coming here means that it->c is from display table, thus we
1465 must send the code as is to the terminal. Although there's
1466 no way to know how many columns it occupies on a screen, it
1467 is a good assumption that a single byte code has 1-column
1468 width. */
1469 it->pixel_width = it->nglyphs = 1;
1470 if (it->glyph_row)
1471 append_glyph (it);
1474 else
1476 /* A multi-byte character. The display width is fixed for all
1477 characters of the set. Some of the glyphs may have to be
1478 ignored because they are already displayed in a continued
1479 line. */
1480 int charset = CHAR_CHARSET (it->c);
1482 it->pixel_width = CHARSET_WIDTH (charset);
1483 it->nglyphs = it->pixel_width;
1485 if (it->glyph_row)
1486 append_glyph (it);
1489 done:
1490 /* Advance current_x by the pixel width as a convenience for
1491 the caller. */
1492 if (it->area == TEXT_AREA)
1493 it->current_x += it->pixel_width;
1494 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1495 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
1499 /* Produce a stretch glyph for iterator IT. IT->object is the value
1500 of the glyph property displayed. The value must be a list
1501 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1502 being recognized:
1504 1. `:width WIDTH' specifies that the space should be WIDTH *
1505 canonical char width wide. WIDTH may be an integer or floating
1506 point number.
1508 2. `:align-to HPOS' specifies that the space should be wide enough
1509 to reach HPOS, a value in canonical character units. */
1511 static void
1512 produce_stretch_glyph (it)
1513 struct it *it;
1515 /* (space :width WIDTH ...) */
1516 Lisp_Object prop, plist;
1517 int width = 0, align_to = -1;
1518 int zero_width_ok_p = 0;
1519 double tem;
1521 /* List should start with `space'. */
1522 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1523 plist = XCDR (it->object);
1525 /* Compute the width of the stretch. */
1526 if ((prop = Fplist_get (plist, QCwidth), !NILP (prop))
1527 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, 0))
1529 /* Absolute width `:width WIDTH' specified and valid. */
1530 zero_width_ok_p = 1;
1531 width = (int)(tem + 0.5);
1533 else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
1534 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, &align_to))
1536 if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
1537 align_to = (align_to < 0
1539 : align_to - window_box_left_offset (it->w, TEXT_AREA));
1540 else if (align_to < 0)
1541 align_to = window_box_left_offset (it->w, TEXT_AREA);
1542 width = max (0, (int)(tem + 0.5) + align_to - it->current_x);
1543 zero_width_ok_p = 1;
1545 else
1546 /* Nothing specified -> width defaults to canonical char width. */
1547 width = FRAME_COLUMN_WIDTH (it->f);
1549 if (width <= 0 && (width < 0 || !zero_width_ok_p))
1550 width = 1;
1552 if (width > 0 && it->glyph_row)
1554 Lisp_Object o_object = it->object;
1555 Lisp_Object object = it->stack[it->sp - 1].string;
1556 int n = width;
1558 if (!STRINGP (object))
1559 object = it->w->buffer;
1560 it->object = object;
1561 it->char_to_display = ' ';
1562 it->pixel_width = it->len = 1;
1563 while (n--)
1564 append_glyph (it);
1565 it->object = o_object;
1567 it->pixel_width = width;
1568 it->nglyphs = width;
1572 /* Get information about special display element WHAT in an
1573 environment described by IT. WHAT is one of IT_TRUNCATION or
1574 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1575 non-null glyph_row member. This function ensures that fields like
1576 face_id, c, len of IT are left untouched. */
1578 void
1579 produce_special_glyphs (it, what)
1580 struct it *it;
1581 enum display_element_type what;
1583 struct it temp_it;
1584 GLYPH glyph;
1586 temp_it = *it;
1587 temp_it.dp = NULL;
1588 temp_it.what = IT_CHARACTER;
1589 temp_it.len = 1;
1590 temp_it.object = make_number (0);
1591 bzero (&temp_it.current, sizeof temp_it.current);
1593 if (what == IT_CONTINUATION)
1595 /* Continuation glyph. */
1596 if (it->dp
1597 && INTEGERP (DISP_CONTINUE_GLYPH (it->dp))
1598 && GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (it->dp))))
1600 glyph = XINT (DISP_CONTINUE_GLYPH (it->dp));
1601 glyph = spec_glyph_lookup_face (XWINDOW (it->window), glyph);
1603 else
1604 glyph = '\\';
1606 else if (what == IT_TRUNCATION)
1608 /* Truncation glyph. */
1609 if (it->dp
1610 && INTEGERP (DISP_TRUNC_GLYPH (it->dp))
1611 && GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (it->dp))))
1613 glyph = XINT (DISP_TRUNC_GLYPH (it->dp));
1614 glyph = spec_glyph_lookup_face (XWINDOW (it->window), glyph);
1616 else
1617 glyph = '$';
1619 else
1620 abort ();
1622 temp_it.c = FAST_GLYPH_CHAR (glyph);
1623 temp_it.face_id = FAST_GLYPH_FACE (glyph);
1624 temp_it.len = CHAR_BYTES (temp_it.c);
1626 produce_glyphs (&temp_it);
1627 it->pixel_width = temp_it.pixel_width;
1628 it->nglyphs = temp_it.pixel_width;
1633 /***********************************************************************
1634 Faces
1635 ***********************************************************************/
1637 /* Value is non-zero if attribute ATTR may be used. ATTR should be
1638 one of the enumerators from enum no_color_bit, or a bit set built
1639 from them. Some display attributes may not be used together with
1640 color; the termcap capability `NC' specifies which ones. */
1642 #define MAY_USE_WITH_COLORS_P(tty, ATTR) \
1643 (tty->TN_max_colors > 0 \
1644 ? (tty->TN_no_color_video & (ATTR)) == 0 \
1645 : 1)
1647 /* Turn appearances of face FACE_ID on tty frame F on.
1648 FACE_ID is a realized face ID number, in the face cache. */
1650 static void
1651 turn_on_face (f, face_id)
1652 struct frame *f;
1653 int face_id;
1655 struct face *face = FACE_FROM_ID (f, face_id);
1656 long fg = face->foreground;
1657 long bg = face->background;
1658 struct tty_display_info *tty = FRAME_TTY (f);
1660 /* Do this first because TS_end_standout_mode may be the same
1661 as TS_exit_attribute_mode, which turns all appearances off. */
1662 if (MAY_USE_WITH_COLORS_P (tty, NC_REVERSE))
1664 if (tty->TN_max_colors > 0)
1666 if (fg >= 0 && bg >= 0)
1668 /* If the terminal supports colors, we can set them
1669 below without using reverse video. The face's fg
1670 and bg colors are set as they should appear on
1671 the screen, i.e. they take the inverse-video'ness
1672 of the face already into account. */
1674 else if (inverse_video)
1676 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1677 || bg == FACE_TTY_DEFAULT_BG_COLOR)
1678 tty_toggle_highlight (tty);
1680 else
1682 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1683 || bg == FACE_TTY_DEFAULT_FG_COLOR)
1684 tty_toggle_highlight (tty);
1687 else
1689 /* If we can't display colors, use reverse video
1690 if the face specifies that. */
1691 if (inverse_video)
1693 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1694 || bg == FACE_TTY_DEFAULT_BG_COLOR)
1695 tty_toggle_highlight (tty);
1697 else
1699 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1700 || bg == FACE_TTY_DEFAULT_FG_COLOR)
1701 tty_toggle_highlight (tty);
1706 if (face->tty_bold_p)
1708 if (MAY_USE_WITH_COLORS_P (tty, NC_BOLD))
1709 OUTPUT1_IF (tty, tty->TS_enter_bold_mode);
1711 else if (face->tty_dim_p)
1712 if (MAY_USE_WITH_COLORS_P (tty, NC_DIM))
1713 OUTPUT1_IF (tty, tty->TS_enter_dim_mode);
1715 /* Alternate charset and blinking not yet used. */
1716 if (face->tty_alt_charset_p
1717 && MAY_USE_WITH_COLORS_P (tty, NC_ALT_CHARSET))
1718 OUTPUT1_IF (tty, tty->TS_enter_alt_charset_mode);
1720 if (face->tty_blinking_p
1721 && MAY_USE_WITH_COLORS_P (tty, NC_BLINK))
1722 OUTPUT1_IF (tty, tty->TS_enter_blink_mode);
1724 if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (tty, NC_UNDERLINE))
1725 OUTPUT1_IF (tty, tty->TS_enter_underline_mode);
1727 if (tty->TN_max_colors > 0)
1729 char *ts, *p;
1731 ts = tty->standout_mode ? tty->TS_set_background : tty->TS_set_foreground;
1732 if (fg >= 0 && ts)
1734 p = tparam (ts, NULL, 0, (int) fg);
1735 OUTPUT (tty, p);
1736 xfree (p);
1739 ts = tty->standout_mode ? tty->TS_set_foreground : tty->TS_set_background;
1740 if (bg >= 0 && ts)
1742 p = tparam (ts, NULL, 0, (int) bg);
1743 OUTPUT (tty, p);
1744 xfree (p);
1750 /* Turn off appearances of face FACE_ID on tty frame F. */
1752 static void
1753 turn_off_face (f, face_id)
1754 struct frame *f;
1755 int face_id;
1757 struct face *face = FACE_FROM_ID (f, face_id);
1758 struct tty_display_info *tty = FRAME_TTY (f);
1760 xassert (face != NULL);
1762 if (tty->TS_exit_attribute_mode)
1764 /* Capability "me" will turn off appearance modes double-bright,
1765 half-bright, reverse-video, standout, underline. It may or
1766 may not turn off alt-char-mode. */
1767 if (face->tty_bold_p
1768 || face->tty_dim_p
1769 || face->tty_reverse_p
1770 || face->tty_alt_charset_p
1771 || face->tty_blinking_p
1772 || face->tty_underline_p)
1774 OUTPUT1_IF (tty, tty->TS_exit_attribute_mode);
1775 if (strcmp (tty->TS_exit_attribute_mode, tty->TS_end_standout_mode) == 0)
1776 tty->standout_mode = 0;
1779 if (face->tty_alt_charset_p)
1780 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
1782 else
1784 /* If we don't have "me" we can only have those appearances
1785 that have exit sequences defined. */
1786 if (face->tty_alt_charset_p)
1787 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
1789 if (face->tty_underline_p)
1790 OUTPUT_IF (tty, tty->TS_exit_underline_mode);
1793 /* Switch back to default colors. */
1794 if (tty->TN_max_colors > 0
1795 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
1796 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
1797 || (face->background != FACE_TTY_DEFAULT_COLOR
1798 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
1799 OUTPUT1_IF (tty, tty->TS_orig_pair);
1803 /* Return non-zero if the terminal on frame F supports all of the
1804 capabilities in CAPS simultaneously, with foreground and background
1805 colors FG and BG. */
1808 tty_capable_p (tty, caps, fg, bg)
1809 struct tty_display_info *tty;
1810 unsigned caps;
1811 unsigned long fg, bg;
1813 #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
1814 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
1815 return 0;
1817 TTY_CAPABLE_P_TRY (tty, TTY_CAP_INVERSE, tty->TS_standout_mode, NC_REVERSE);
1818 TTY_CAPABLE_P_TRY (tty, TTY_CAP_UNDERLINE, tty->TS_enter_underline_mode, NC_UNDERLINE);
1819 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BOLD, tty->TS_enter_bold_mode, NC_BOLD);
1820 TTY_CAPABLE_P_TRY (tty, TTY_CAP_DIM, tty->TS_enter_dim_mode, NC_DIM);
1821 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BLINK, tty->TS_enter_blink_mode, NC_BLINK);
1822 TTY_CAPABLE_P_TRY (tty, TTY_CAP_ALT_CHARSET, tty->TS_enter_alt_charset_mode, NC_ALT_CHARSET);
1824 /* We can do it! */
1825 return 1;
1828 /* Return non-zero if the terminal is capable to display colors. */
1830 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
1831 0, 1, 0,
1832 doc: /* Return non-nil if the tty device TERMINAL can display colors.
1834 TERMINAL can be a terminal id, a frame or nil (meaning the selected
1835 frame's terminal). This function always returns nil if TERMINAL
1836 is not on a tty device. */)
1837 (terminal)
1838 Lisp_Object terminal;
1840 struct terminal *t = get_tty_terminal (terminal);
1841 if (!t)
1842 return Qnil;
1843 else
1844 return t->display_info.tty->TN_max_colors > 0 ? Qt : Qnil;
1847 /* Return the number of supported colors. */
1848 DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
1849 Stty_display_color_cells, 0, 1, 0,
1850 doc: /* Return the number of colors supported by the tty device TERMINAL.
1852 TERMINAL can be a terminal id, a frame or nil (meaning the selected
1853 frame's terminal). This function always returns nil if TERMINAL
1854 is not on a tty device. */)
1855 (terminal)
1856 Lisp_Object terminal;
1858 struct terminal *t = get_tty_terminal (terminal);
1859 if (!t)
1860 return make_number (0);
1861 else
1862 return make_number (t->display_info.tty->TN_max_colors);
1865 #ifndef WINDOWSNT
1867 /* Save or restore the default color-related capabilities of this
1868 terminal. */
1869 static void
1870 tty_default_color_capabilities (struct tty_display_info *tty, int save)
1872 static char
1873 *default_orig_pair, *default_set_foreground, *default_set_background;
1874 static int default_max_colors, default_max_pairs, default_no_color_video;
1876 if (save)
1878 if (default_orig_pair)
1879 xfree (default_orig_pair);
1880 default_orig_pair = tty->TS_orig_pair ? xstrdup (tty->TS_orig_pair) : NULL;
1882 if (default_set_foreground)
1883 xfree (default_set_foreground);
1884 default_set_foreground = tty->TS_set_foreground ? xstrdup (tty->TS_set_foreground)
1885 : NULL;
1887 if (default_set_background)
1888 xfree (default_set_background);
1889 default_set_background = tty->TS_set_background ? xstrdup (tty->TS_set_background)
1890 : NULL;
1892 default_max_colors = tty->TN_max_colors;
1893 default_max_pairs = tty->TN_max_pairs;
1894 default_no_color_video = tty->TN_no_color_video;
1896 else
1898 tty->TS_orig_pair = default_orig_pair;
1899 tty->TS_set_foreground = default_set_foreground;
1900 tty->TS_set_background = default_set_background;
1901 tty->TN_max_colors = default_max_colors;
1902 tty->TN_max_pairs = default_max_pairs;
1903 tty->TN_no_color_video = default_no_color_video;
1907 /* Setup one of the standard tty color schemes according to MODE.
1908 MODE's value is generally the number of colors which we want to
1909 support; zero means set up for the default capabilities, the ones
1910 we saw at init_tty time; -1 means turn off color support. */
1911 static void
1912 tty_setup_colors (struct tty_display_info *tty, int mode)
1914 /* Canonicalize all negative values of MODE. */
1915 if (mode < -1)
1916 mode = -1;
1918 switch (mode)
1920 case -1: /* no colors at all */
1921 tty->TN_max_colors = 0;
1922 tty->TN_max_pairs = 0;
1923 tty->TN_no_color_video = 0;
1924 tty->TS_set_foreground = tty->TS_set_background = tty->TS_orig_pair = NULL;
1925 break;
1926 case 0: /* default colors, if any */
1927 default:
1928 tty_default_color_capabilities (tty, 0);
1929 break;
1930 case 8: /* 8 standard ANSI colors */
1931 tty->TS_orig_pair = "\033[0m";
1932 #ifdef TERMINFO
1933 tty->TS_set_foreground = "\033[3%p1%dm";
1934 tty->TS_set_background = "\033[4%p1%dm";
1935 #else
1936 tty->TS_set_foreground = "\033[3%dm";
1937 tty->TS_set_background = "\033[4%dm";
1938 #endif
1939 tty->TN_max_colors = 8;
1940 tty->TN_max_pairs = 64;
1941 tty->TN_no_color_video = 0;
1942 break;
1946 void
1947 set_tty_color_mode (f, val)
1948 struct frame *f;
1949 Lisp_Object val;
1951 Lisp_Object color_mode_spec, current_mode_spec;
1952 Lisp_Object color_mode, current_mode;
1953 int mode, old_mode;
1954 extern Lisp_Object Qtty_color_mode;
1955 Lisp_Object tty_color_mode_alist;
1957 tty_color_mode_alist = Fintern_soft (build_string ("tty-color-mode-alist"),
1958 Qnil);
1960 if (INTEGERP (val))
1961 color_mode = val;
1962 else
1964 if (NILP (tty_color_mode_alist))
1965 color_mode_spec = Qnil;
1966 else
1967 color_mode_spec = Fassq (val, XSYMBOL (tty_color_mode_alist)->value);
1969 if (CONSP (color_mode_spec))
1970 color_mode = XCDR (color_mode_spec);
1971 else
1972 color_mode = Qnil;
1975 current_mode_spec = assq_no_quit (Qtty_color_mode, f->param_alist);
1977 if (CONSP (current_mode_spec))
1978 current_mode = XCDR (current_mode_spec);
1979 else
1980 current_mode = Qnil;
1981 if (INTEGERP (color_mode))
1982 mode = XINT (color_mode);
1983 else
1984 mode = 0; /* meaning default */
1985 if (INTEGERP (current_mode))
1986 old_mode = XINT (current_mode);
1987 else
1988 old_mode = 0;
1990 if (mode != old_mode)
1992 tty_setup_colors (FRAME_TTY (f), mode);
1993 /* This recomputes all the faces given the new color
1994 definitions. */
1995 call0 (intern ("tty-set-up-initial-frame-faces"));
1996 redraw_frame (f);
2000 #endif /* !WINDOWSNT */
2004 /* Return the tty display object specified by TERMINAL. */
2006 struct terminal *
2007 get_tty_terminal (Lisp_Object terminal)
2009 struct terminal *t = get_terminal (terminal, 0);
2011 if (t && t->type == output_initial)
2012 t = NULL;
2014 if (t && t->type != output_termcap)
2015 error ("Device %d is not a termcap terminal device", t->id);
2017 return t;
2020 /* Return the active termcap device that uses the tty device with the
2021 given name. If NAME is NULL, return the device corresponding to
2022 our controlling terminal.
2024 This function ignores suspended devices.
2026 Returns NULL if the named terminal device is not opened. */
2028 struct terminal *
2029 get_named_tty (name)
2030 char *name;
2032 struct terminal *t;
2034 for (t = terminal_list; t; t = t->next_terminal) {
2035 if (t->type == output_termcap
2036 && ((t->display_info.tty->name == 0 && name == 0)
2037 || (name && t->display_info.tty->name
2038 && !strcmp (t->display_info.tty->name, name)))
2039 && TERMINAL_ACTIVE_P (t))
2040 return t;
2043 return 0;
2047 DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0,
2048 doc: /* Return the type of the tty device that TERMINAL uses.
2050 TERMINAL can be a terminal id, a frame or nil (meaning the selected
2051 frame's terminal). */)
2052 (terminal)
2053 Lisp_Object terminal;
2055 struct terminal *t = get_terminal (terminal, 1);
2057 if (t->type != output_termcap)
2058 error ("Terminal %d is not a termcap terminal", t->id);
2060 if (t->display_info.tty->type)
2061 return build_string (t->display_info.tty->type);
2062 else
2063 return Qnil;
2066 DEFUN ("controlling-tty-p", Fcontrolling_tty_p, Scontrolling_tty_p, 0, 1, 0,
2067 doc: /* Return non-nil if TERMINAL is on the controlling tty of the Emacs process.
2069 TERMINAL can be a terminal id, a frame or nil (meaning the selected
2070 frame's terminal). This function always returns nil if TERMINAL
2071 is not on a tty device. */)
2072 (terminal)
2073 Lisp_Object terminal;
2075 struct terminal *t = get_terminal (terminal, 1);
2077 if (t->type != output_termcap || t->display_info.tty->name)
2078 return Qnil;
2079 else
2080 return Qt;
2083 DEFUN ("tty-no-underline", Ftty_no_underline, Stty_no_underline, 0, 1, 0,
2084 doc: /* Declare that the tty used by TERMINAL does not handle underlining.
2085 This is used to override the terminfo data, for certain terminals that
2086 do not really do underlining, but say that they do. This function has
2087 no effect if used on a non-tty terminal.
2089 TERMINAL can be a terminal id, a frame or nil (meaning the selected
2090 frame's terminal). This function always returns nil if TERMINAL
2091 is not on a tty device. */)
2092 (terminal)
2093 Lisp_Object terminal;
2095 struct terminal *t = get_terminal (terminal, 1);
2097 if (t->type == output_termcap)
2098 t->display_info.tty->TS_enter_underline_mode = 0;
2099 return Qnil;
2104 DEFUN ("suspend-tty", Fsuspend_tty, Ssuspend_tty, 0, 1, 0,
2105 doc: /* Suspend the terminal device TTY.
2107 The device is restored to its default state, and Emacs ceases all
2108 access to the tty device. Frames that use the device are not deleted,
2109 but input is not read from them and if they change, their display is
2110 not updated.
2112 TTY may be a terminal id, a frame, or nil for the terminal device of
2113 the currently selected frame.
2115 This function runs `suspend-tty-functions' after suspending the
2116 device. The functions are run with one arg, the id of the suspended
2117 terminal device.
2119 `suspend-tty' does nothing if it is called on a device that is already
2120 suspended.
2122 A suspended tty may be resumed by calling `resume-tty' on it. */)
2123 (tty)
2124 Lisp_Object tty;
2126 struct terminal *t = get_tty_terminal (tty);
2127 FILE *f;
2129 if (!t)
2130 error ("Unknown tty device");
2132 f = t->display_info.tty->input;
2134 if (f)
2136 reset_sys_modes (t->display_info.tty);
2138 delete_keyboard_wait_descriptor (fileno (f));
2140 fclose (f);
2141 if (f != t->display_info.tty->output)
2142 fclose (t->display_info.tty->output);
2144 t->display_info.tty->input = 0;
2145 t->display_info.tty->output = 0;
2147 if (FRAMEP (t->display_info.tty->top_frame))
2148 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0);
2150 /* Run `suspend-tty-functions'. */
2151 if (!NILP (Vrun_hooks))
2153 Lisp_Object args[2];
2154 args[0] = intern ("suspend-tty-functions");
2155 args[1] = make_number (t->id);
2156 Frun_hook_with_args (2, args);
2160 return Qnil;
2163 DEFUN ("resume-tty", Fresume_tty, Sresume_tty, 0, 1, 0,
2164 doc: /* Resume the previously suspended terminal device TTY.
2165 The terminal is opened and reinitialized. Frames that are on the
2166 suspended terminal are revived.
2168 It is an error to resume a terminal while another terminal is active
2169 on the same device.
2171 This function runs `resume-tty-functions' after resuming the terminal.
2172 The functions are run with one arg, the id of the resumed terminal
2173 device.
2175 `resume-tty' does nothing if it is called on a device that is not
2176 suspended.
2178 TTY may be a terminal id, a frame, or nil for the terminal device of
2179 the currently selected frame. */)
2180 (tty)
2181 Lisp_Object tty;
2183 struct terminal *t = get_tty_terminal (tty);
2184 int fd;
2186 if (!t)
2187 error ("Unknown tty device");
2189 if (!t->display_info.tty->input)
2191 if (get_named_tty (t->display_info.tty->name))
2192 error ("Cannot resume display while another display is active on the same device");
2194 fd = emacs_open (t->display_info.tty->name, O_RDWR | O_NOCTTY, 0);
2196 /* XXX What if open fails? */
2198 dissociate_if_controlling_tty (fd);
2200 t->display_info.tty->output = fdopen (fd, "w+");
2201 t->display_info.tty->input = t->display_info.tty->output;
2203 add_keyboard_wait_descriptor (fd);
2205 if (FRAMEP (t->display_info.tty->top_frame))
2206 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
2208 init_sys_modes (t->display_info.tty);
2210 /* Run `suspend-tty-functions'. */
2211 if (!NILP (Vrun_hooks))
2213 Lisp_Object args[2];
2214 args[0] = intern ("resume-tty-functions");
2215 args[1] = make_number (t->id);
2216 Frun_hook_with_args (2, args);
2220 return Qnil;
2224 /***********************************************************************
2225 Initialization
2226 ***********************************************************************/
2228 /* Initialize the tty-dependent part of frame F. The frame must
2229 already have its device initialized. */
2231 void
2232 create_tty_output (struct frame *f)
2234 struct tty_output *t;
2236 if (! FRAME_TERMCAP_P (f))
2237 abort ();
2239 t = xmalloc (sizeof (struct tty_output));
2240 bzero (t, sizeof (struct tty_output));
2242 t->display_info = FRAME_TERMINAL (f)->display_info.tty;
2244 f->output_data.tty = t;
2247 /* Delete the tty-dependent part of frame F. */
2249 static void
2250 delete_tty_output (struct frame *f)
2252 if (! FRAME_TERMCAP_P (f))
2253 abort ();
2255 xfree (f->output_data.tty);
2260 /* Drop the controlling terminal if fd is the same device. */
2261 static void
2262 dissociate_if_controlling_tty (int fd)
2264 int pgid;
2265 EMACS_GET_TTY_PGRP (fd, &pgid); /* If tcgetpgrp succeeds, fd is the ctty. */
2266 if (pgid != -1)
2268 #if defined (USG) && !defined (BSD_PGRPS)
2269 setpgrp ();
2270 no_controlling_tty = 1;
2271 #else
2272 #ifdef TIOCNOTTY /* Try BSD ioctls. */
2273 sigblock (sigmask (SIGTTOU));
2274 fd = emacs_open ("/dev/tty", O_RDWR, 0);
2275 if (fd != -1 && ioctl (fd, TIOCNOTTY, 0) != -1)
2277 no_controlling_tty = 1;
2279 if (fd != -1)
2280 emacs_close (fd);
2281 sigunblock (sigmask (SIGTTOU));
2282 #else
2283 /* Unknown system. */
2284 croak ();
2285 #endif /* ! TIOCNOTTY */
2286 #endif /* ! USG */
2290 static void maybe_fatal();
2292 /* Create a termcap display on the tty device with the given name and
2293 type.
2295 If NAME is NULL, then use the controlling tty, i.e., stdin/stdout.
2296 Otherwise NAME should be a path to the tty device file,
2297 e.g. "/dev/pts/7".
2299 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
2301 If MUST_SUCCEED is true, then all errors are fatal. */
2303 struct terminal *
2304 init_tty (char *name, char *terminal_type, int must_succeed)
2306 char *area;
2307 char **address = &area;
2308 char *buffer = NULL;
2309 int buffer_size = 4096;
2310 register char *p;
2311 int status;
2312 struct tty_display_info *tty;
2313 struct terminal *terminal;
2315 if (!terminal_type)
2316 maybe_fatal (must_succeed, 0, 0,
2317 "Unknown terminal type",
2318 "Unknown terminal type");
2320 /* If we already have a terminal on the given device, use that. If
2321 all such terminals are suspended, create a new one instead. */
2322 /* XXX Perhaps this should be made explicit by having init_tty
2323 always create a new terminal and separating terminal and frame
2324 creation on Lisp level. */
2325 terminal = get_named_tty (name);
2326 if (terminal)
2327 return terminal;
2329 terminal = create_terminal ();
2330 tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info));
2331 bzero (tty, sizeof (struct tty_display_info));
2332 tty->next = tty_list;
2333 tty_list = tty;
2335 terminal->type = output_termcap;
2336 terminal->display_info.tty = tty;
2337 tty->terminal = terminal;
2339 tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
2340 Wcm_clear (tty);
2342 terminal->rif = 0; /* ttys don't support window-based redisplay. */
2344 terminal->cursor_to_hook = &tty_cursor_to;
2345 terminal->raw_cursor_to_hook = &tty_raw_cursor_to;
2347 terminal->clear_to_end_hook = &tty_clear_to_end;
2348 terminal->clear_frame_hook = &tty_clear_frame;
2349 terminal->clear_end_of_line_hook = &tty_clear_end_of_line;
2351 terminal->ins_del_lines_hook = &tty_ins_del_lines;
2353 terminal->insert_glyphs_hook = &tty_insert_glyphs;
2354 terminal->write_glyphs_hook = &tty_write_glyphs;
2355 terminal->delete_glyphs_hook = &tty_delete_glyphs;
2357 terminal->ring_bell_hook = &tty_ring_bell;
2359 terminal->reset_terminal_modes_hook = &tty_reset_terminal_modes;
2360 terminal->set_terminal_modes_hook = &tty_set_terminal_modes;
2361 terminal->update_begin_hook = 0; /* Not needed. */
2362 terminal->update_end_hook = &tty_update_end;
2363 terminal->set_terminal_window_hook = &tty_set_terminal_window;
2365 terminal->mouse_position_hook = 0; /* Not needed. */
2366 terminal->frame_rehighlight_hook = 0; /* Not needed. */
2367 terminal->frame_raise_lower_hook = 0; /* Not needed. */
2369 terminal->set_vertical_scroll_bar_hook = 0; /* Not needed. */
2370 terminal->condemn_scroll_bars_hook = 0; /* Not needed. */
2371 terminal->redeem_scroll_bar_hook = 0; /* Not needed. */
2372 terminal->judge_scroll_bars_hook = 0; /* Not needed. */
2374 terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */
2375 terminal->frame_up_to_date_hook = 0; /* Not needed. */
2377 terminal->delete_frame_hook = &delete_tty_output;
2378 terminal->delete_terminal_hook = &delete_tty;
2380 if (name)
2382 int fd;
2383 FILE *file;
2385 #ifdef O_IGNORE_CTTY
2386 /* Open the terminal device. Don't recognize it as our
2387 controlling terminal, and don't make it the controlling tty
2388 if we don't have one at the moment. */
2389 fd = emacs_open (name, O_RDWR | O_IGNORE_CTTY | O_NOCTTY, 0);
2390 #else
2391 /* Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
2392 defined on Hurd. On other systems, we need to dissociate
2393 ourselves from the controlling tty when we want to open a
2394 frame on the same terminal. */
2396 fd = emacs_open (name, O_RDWR | O_NOCTTY, 0);
2398 #endif /* O_IGNORE_CTTY */
2400 if (fd < 0)
2402 delete_tty (terminal);
2403 error ("Could not open file: %s", name);
2405 if (!isatty (fd))
2407 close (fd);
2408 error ("Not a tty device: %s", name);
2411 dissociate_if_controlling_tty (fd);
2413 file = fdopen (fd, "w+");
2414 tty->name = xstrdup (name);
2415 terminal->name = xstrdup (name);
2416 tty->input = file;
2417 tty->output = file;
2419 else
2421 if (no_controlling_tty)
2423 /* Opening a frame on stdout is unsafe if we have
2424 disconnected our controlling terminal. */
2425 error ("There is no controlling terminal any more");
2427 tty->name = 0;
2428 terminal->name = xstrdup (ttyname (0));
2429 tty->input = stdin;
2430 tty->output = stdout;
2433 tty->type = xstrdup (terminal_type);
2435 add_keyboard_wait_descriptor (fileno (tty->input));
2437 encode_terminal_bufsize = 0;
2439 #ifdef WINDOWSNT
2440 initialize_w32_display ();
2442 Wcm_clear (tty);
2444 area = (char *) xmalloc (2044);
2446 FrameRows (tty) = FRAME_LINES (f); /* XXX */
2447 FrameCols (tty) = FRAME_COLS (f); /* XXX */
2448 tty->specified_window = FRAME_LINES (f); /* XXX */
2450 tty->terminal->delete_in_insert_mode = 1;
2452 UseTabs (tty) = 0;
2453 terminal->scroll_region_ok = 0;
2455 /* Seems to insert lines when it's not supposed to, messing up the
2456 display. In doing a trace, it didn't seem to be called much, so I
2457 don't think we're losing anything by turning it off. */
2458 terminal->line_ins_del_ok = 0;
2459 terminal->char_ins_del_ok = 1;
2461 baud_rate = 19200;
2463 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0; /* XXX */
2464 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none; /* XXX */
2465 TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
2467 return terminal;
2468 #else /* not WINDOWSNT */
2470 Wcm_clear (tty);
2472 buffer = (char *) xmalloc (buffer_size);
2474 /* On some systems, tgetent tries to access the controlling
2475 terminal. */
2476 sigblock (sigmask (SIGTTOU));
2477 status = tgetent (buffer, terminal_type);
2478 sigunblock (sigmask (SIGTTOU));
2480 if (status < 0)
2482 #ifdef TERMINFO
2483 maybe_fatal (must_succeed, buffer, terminal,
2484 "Cannot open terminfo database file",
2485 "Cannot open terminfo database file");
2486 #else
2487 maybe_fatal (must_succeed, buffer, terminal,
2488 "Cannot open termcap database file",
2489 "Cannot open termcap database file");
2490 #endif
2492 if (status == 0)
2494 #ifdef TERMINFO
2495 maybe_fatal (must_succeed, buffer, terminal,
2496 "Terminal type %s is not defined",
2497 "Terminal type %s is not defined.\n\
2498 If that is not the actual type of terminal you have,\n\
2499 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2500 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2501 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
2502 terminal_type);
2503 #else
2504 maybe_fatal (must_succeed, buffer, terminal,
2505 "Terminal type %s is not defined",
2506 "Terminal type %s is not defined.\n\
2507 If that is not the actual type of terminal you have,\n\
2508 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2509 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2510 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
2511 terminal_type);
2512 #endif
2515 #ifndef TERMINFO
2516 if (strlen (buffer) >= buffer_size)
2517 abort ();
2518 buffer_size = strlen (buffer);
2519 #endif
2520 area = (char *) xmalloc (buffer_size);
2522 tty->TS_ins_line = tgetstr ("al", address);
2523 tty->TS_ins_multi_lines = tgetstr ("AL", address);
2524 tty->TS_bell = tgetstr ("bl", address);
2525 BackTab (tty) = tgetstr ("bt", address);
2526 tty->TS_clr_to_bottom = tgetstr ("cd", address);
2527 tty->TS_clr_line = tgetstr ("ce", address);
2528 tty->TS_clr_frame = tgetstr ("cl", address);
2529 ColPosition (tty) = NULL; /* tgetstr ("ch", address); */
2530 AbsPosition (tty) = tgetstr ("cm", address);
2531 CR (tty) = tgetstr ("cr", address);
2532 tty->TS_set_scroll_region = tgetstr ("cs", address);
2533 tty->TS_set_scroll_region_1 = tgetstr ("cS", address);
2534 RowPosition (tty) = tgetstr ("cv", address);
2535 tty->TS_del_char = tgetstr ("dc", address);
2536 tty->TS_del_multi_chars = tgetstr ("DC", address);
2537 tty->TS_del_line = tgetstr ("dl", address);
2538 tty->TS_del_multi_lines = tgetstr ("DL", address);
2539 tty->TS_delete_mode = tgetstr ("dm", address);
2540 tty->TS_end_delete_mode = tgetstr ("ed", address);
2541 tty->TS_end_insert_mode = tgetstr ("ei", address);
2542 Home (tty) = tgetstr ("ho", address);
2543 tty->TS_ins_char = tgetstr ("ic", address);
2544 tty->TS_ins_multi_chars = tgetstr ("IC", address);
2545 tty->TS_insert_mode = tgetstr ("im", address);
2546 tty->TS_pad_inserted_char = tgetstr ("ip", address);
2547 tty->TS_end_keypad_mode = tgetstr ("ke", address);
2548 tty->TS_keypad_mode = tgetstr ("ks", address);
2549 LastLine (tty) = tgetstr ("ll", address);
2550 Right (tty) = tgetstr ("nd", address);
2551 Down (tty) = tgetstr ("do", address);
2552 if (!Down (tty))
2553 Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do" */
2554 #ifdef VMS
2555 /* VMS puts a carriage return before each linefeed,
2556 so it is not safe to use linefeeds. */
2557 if (Down (tty) && Down (tty)[0] == '\n' && Down (tty)[1] == '\0')
2558 Down (tty) = 0;
2559 #endif /* VMS */
2560 if (tgetflag ("bs"))
2561 Left (tty) = "\b"; /* can't possibly be longer! */
2562 else /* (Actually, "bs" is obsolete...) */
2563 Left (tty) = tgetstr ("le", address);
2564 if (!Left (tty))
2565 Left (tty) = tgetstr ("bc", address); /* Obsolete name for "le" */
2566 tty->TS_pad_char = tgetstr ("pc", address);
2567 tty->TS_repeat = tgetstr ("rp", address);
2568 tty->TS_end_standout_mode = tgetstr ("se", address);
2569 tty->TS_fwd_scroll = tgetstr ("sf", address);
2570 tty->TS_standout_mode = tgetstr ("so", address);
2571 tty->TS_rev_scroll = tgetstr ("sr", address);
2572 tty->Wcm->cm_tab = tgetstr ("ta", address);
2573 tty->TS_end_termcap_modes = tgetstr ("te", address);
2574 tty->TS_termcap_modes = tgetstr ("ti", address);
2575 Up (tty) = tgetstr ("up", address);
2576 tty->TS_visible_bell = tgetstr ("vb", address);
2577 tty->TS_cursor_normal = tgetstr ("ve", address);
2578 tty->TS_cursor_visible = tgetstr ("vs", address);
2579 tty->TS_cursor_invisible = tgetstr ("vi", address);
2580 tty->TS_set_window = tgetstr ("wi", address);
2582 tty->TS_enter_underline_mode = tgetstr ("us", address);
2583 tty->TS_exit_underline_mode = tgetstr ("ue", address);
2584 tty->TS_enter_bold_mode = tgetstr ("md", address);
2585 tty->TS_enter_dim_mode = tgetstr ("mh", address);
2586 tty->TS_enter_blink_mode = tgetstr ("mb", address);
2587 tty->TS_enter_reverse_mode = tgetstr ("mr", address);
2588 tty->TS_enter_alt_charset_mode = tgetstr ("as", address);
2589 tty->TS_exit_alt_charset_mode = tgetstr ("ae", address);
2590 tty->TS_exit_attribute_mode = tgetstr ("me", address);
2592 MultiUp (tty) = tgetstr ("UP", address);
2593 MultiDown (tty) = tgetstr ("DO", address);
2594 MultiLeft (tty) = tgetstr ("LE", address);
2595 MultiRight (tty) = tgetstr ("RI", address);
2597 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
2598 color because we can't switch back to the default foreground and
2599 background. */
2600 tty->TS_orig_pair = tgetstr ("op", address);
2601 if (tty->TS_orig_pair)
2603 tty->TS_set_foreground = tgetstr ("AF", address);
2604 tty->TS_set_background = tgetstr ("AB", address);
2605 if (!tty->TS_set_foreground)
2607 /* SVr4. */
2608 tty->TS_set_foreground = tgetstr ("Sf", address);
2609 tty->TS_set_background = tgetstr ("Sb", address);
2612 tty->TN_max_colors = tgetnum ("Co");
2613 tty->TN_max_pairs = tgetnum ("pa");
2615 tty->TN_no_color_video = tgetnum ("NC");
2616 if (tty->TN_no_color_video == -1)
2617 tty->TN_no_color_video = 0;
2620 tty_default_color_capabilities (tty, 1);
2622 MagicWrap (tty) = tgetflag ("xn");
2623 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
2624 the former flag imply the latter. */
2625 AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
2626 terminal->memory_below_frame = tgetflag ("db");
2627 tty->TF_hazeltine = tgetflag ("hz");
2628 terminal->must_write_spaces = tgetflag ("in");
2629 tty->meta_key = tgetflag ("km") || tgetflag ("MT");
2630 tty->TF_insmode_motion = tgetflag ("mi");
2631 tty->TF_standout_motion = tgetflag ("ms");
2632 tty->TF_underscore = tgetflag ("ul");
2633 tty->TF_teleray = tgetflag ("xt");
2635 #ifdef MULTI_KBOARD
2636 terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
2637 init_kboard (terminal->kboard);
2638 terminal->kboard->next_kboard = all_kboards;
2639 all_kboards = terminal->kboard;
2640 terminal->kboard->reference_count++;
2641 /* Don't let the initial kboard remain current longer than necessary.
2642 That would cause problems if a file loaded on startup tries to
2643 prompt in the mini-buffer. */
2644 if (current_kboard == initial_kboard)
2645 current_kboard = terminal->kboard;
2646 #endif
2648 term_get_fkeys (address, terminal->kboard);
2650 /* Get frame size from system, or else from termcap. */
2652 int height, width;
2653 get_tty_size (fileno (tty->input), &width, &height);
2654 FrameCols (tty) = width;
2655 FrameRows (tty) = height;
2658 if (FrameCols (tty) <= 0)
2659 FrameCols (tty) = tgetnum ("co");
2660 if (FrameRows (tty) <= 0)
2661 FrameRows (tty) = tgetnum ("li");
2663 if (FrameRows (tty) < 3 || FrameCols (tty) < 3)
2664 maybe_fatal (must_succeed, NULL, terminal,
2665 "Screen size %dx%d is too small"
2666 "Screen size %dx%d is too small",
2667 FrameCols (tty), FrameRows (tty));
2669 #if 0 /* This is not used anywhere. */
2670 tty->terminal->min_padding_speed = tgetnum ("pb");
2671 #endif
2673 TabWidth (tty) = tgetnum ("tw");
2675 #ifdef VMS
2676 /* These capabilities commonly use ^J.
2677 I don't know why, but sending them on VMS does not work;
2678 it causes following spaces to be lost, sometimes.
2679 For now, the simplest fix is to avoid using these capabilities ever. */
2680 if (Down (tty) && Down (tty)[0] == '\n')
2681 Down (tty) = 0;
2682 #endif /* VMS */
2684 if (!tty->TS_bell)
2685 tty->TS_bell = "\07";
2687 if (!tty->TS_fwd_scroll)
2688 tty->TS_fwd_scroll = Down (tty);
2690 PC = tty->TS_pad_char ? *tty->TS_pad_char : 0;
2692 if (TabWidth (tty) < 0)
2693 TabWidth (tty) = 8;
2695 /* Turned off since /etc/termcap seems to have :ta= for most terminals
2696 and newer termcap doc does not seem to say there is a default.
2697 if (!tty->Wcm->cm_tab)
2698 tty->Wcm->cm_tab = "\t";
2701 /* We don't support standout modes that use `magic cookies', so
2702 turn off any that do. */
2703 if (tty->TS_standout_mode && tgetnum ("sg") >= 0)
2705 tty->TS_standout_mode = 0;
2706 tty->TS_end_standout_mode = 0;
2708 if (tty->TS_enter_underline_mode && tgetnum ("ug") >= 0)
2710 tty->TS_enter_underline_mode = 0;
2711 tty->TS_exit_underline_mode = 0;
2714 /* If there's no standout mode, try to use underlining instead. */
2715 if (tty->TS_standout_mode == 0)
2717 tty->TS_standout_mode = tty->TS_enter_underline_mode;
2718 tty->TS_end_standout_mode = tty->TS_exit_underline_mode;
2721 /* If no `se' string, try using a `me' string instead.
2722 If that fails, we can't use standout mode at all. */
2723 if (tty->TS_end_standout_mode == 0)
2725 char *s = tgetstr ("me", address);
2726 if (s != 0)
2727 tty->TS_end_standout_mode = s;
2728 else
2729 tty->TS_standout_mode = 0;
2732 if (tty->TF_teleray)
2734 tty->Wcm->cm_tab = 0;
2735 /* We can't support standout mode, because it uses magic cookies. */
2736 tty->TS_standout_mode = 0;
2737 /* But that means we cannot rely on ^M to go to column zero! */
2738 CR (tty) = 0;
2739 /* LF can't be trusted either -- can alter hpos */
2740 /* if move at column 0 thru a line with TS_standout_mode */
2741 Down (tty) = 0;
2744 /* Special handling for certain terminal types known to need it */
2746 if (!strcmp (terminal_type, "supdup"))
2748 terminal->memory_below_frame = 1;
2749 tty->Wcm->cm_losewrap = 1;
2751 if (!strncmp (terminal_type, "c10", 3)
2752 || !strcmp (terminal_type, "perq"))
2754 /* Supply a makeshift :wi string.
2755 This string is not valid in general since it works only
2756 for windows starting at the upper left corner;
2757 but that is all Emacs uses.
2759 This string works only if the frame is using
2760 the top of the video memory, because addressing is memory-relative.
2761 So first check the :ti string to see if that is true.
2763 It would be simpler if the :wi string could go in the termcap
2764 entry, but it can't because it is not fully valid.
2765 If it were in the termcap entry, it would confuse other programs. */
2766 if (!tty->TS_set_window)
2768 p = tty->TS_termcap_modes;
2769 while (*p && strcmp (p, "\033v "))
2770 p++;
2771 if (*p)
2772 tty->TS_set_window = "\033v%C %C %C %C ";
2774 /* Termcap entry often fails to have :in: flag */
2775 terminal->must_write_spaces = 1;
2776 /* :ti string typically fails to have \E^G! in it */
2777 /* This limits scope of insert-char to one line. */
2778 strcpy (area, tty->TS_termcap_modes);
2779 strcat (area, "\033\007!");
2780 tty->TS_termcap_modes = area;
2781 area += strlen (area) + 1;
2782 p = AbsPosition (tty);
2783 /* Change all %+ parameters to %C, to handle
2784 values above 96 correctly for the C100. */
2785 while (*p)
2787 if (p[0] == '%' && p[1] == '+')
2788 p[1] = 'C';
2789 p++;
2793 tty->specified_window = FrameRows (tty);
2795 if (Wcm_init (tty) == -1) /* can't do cursor motion */
2797 maybe_fatal (must_succeed, NULL, terminal,
2798 "Terminal type \"%s\" is not powerful enough to run Emacs",
2799 #ifdef VMS
2800 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2801 It lacks the ability to position the cursor.\n\
2802 If that is not the actual type of terminal you have, use either the\n\
2803 DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
2804 or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
2805 #else /* not VMS */
2806 # ifdef TERMINFO
2807 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2808 It lacks the ability to position the cursor.\n\
2809 If that is not the actual type of terminal you have,\n\
2810 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2811 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2812 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
2813 # else /* TERMCAP */
2814 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2815 It lacks the ability to position the cursor.\n\
2816 If that is not the actual type of terminal you have,\n\
2817 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2818 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2819 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
2820 # endif /* TERMINFO */
2821 #endif /*VMS */
2822 terminal_type);
2825 if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
2826 maybe_fatal (must_succeed, NULL, terminal,
2827 "Could not determine the frame size",
2828 "Could not determine the frame size");
2830 tty->delete_in_insert_mode
2831 = tty->TS_delete_mode && tty->TS_insert_mode
2832 && !strcmp (tty->TS_delete_mode, tty->TS_insert_mode);
2834 tty->se_is_so = (tty->TS_standout_mode
2835 && tty->TS_end_standout_mode
2836 && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode));
2838 UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8;
2840 terminal->scroll_region_ok
2841 = (tty->Wcm->cm_abs
2842 && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
2844 terminal->line_ins_del_ok
2845 = (((tty->TS_ins_line || tty->TS_ins_multi_lines)
2846 && (tty->TS_del_line || tty->TS_del_multi_lines))
2847 || (terminal->scroll_region_ok
2848 && tty->TS_fwd_scroll && tty->TS_rev_scroll));
2850 terminal->char_ins_del_ok
2851 = ((tty->TS_ins_char || tty->TS_insert_mode
2852 || tty->TS_pad_inserted_char || tty->TS_ins_multi_chars)
2853 && (tty->TS_del_char || tty->TS_del_multi_chars));
2855 terminal->fast_clear_end_of_line = tty->TS_clr_line != 0;
2857 init_baud_rate (fileno (tty->input));
2859 #ifdef AIXHFT
2860 /* The HFT system on AIX doesn't optimize for scrolling, so it's
2861 really ugly at times. */
2862 terminal->line_ins_del_ok = 0;
2863 terminal->char_ins_del_ok = 0;
2864 #endif
2866 /* Don't do this. I think termcap may still need the buffer. */
2867 /* xfree (buffer); */
2869 /* Init system terminal modes (RAW or CBREAK, etc.). */
2870 init_sys_modes (tty);
2872 return terminal;
2873 #endif /* not WINDOWSNT */
2876 /* Auxiliary error-handling function for init_tty.
2877 Free BUFFER and delete TERMINAL, then call error or fatal
2878 with str1 or str2, respectively, according to MUST_SUCCEED. */
2880 static void
2881 maybe_fatal (must_succeed, buffer, terminal, str1, str2, arg1, arg2)
2882 int must_succeed;
2883 char *buffer;
2884 struct terminal *terminal;
2885 char *str1, *str2, *arg1, *arg2;
2887 if (buffer)
2888 xfree (buffer);
2890 if (terminal)
2891 delete_tty (terminal);
2893 if (must_succeed)
2894 fatal (str2, arg1, arg2);
2895 else
2896 error (str1, arg1, arg2);
2898 abort ();
2901 /* VARARGS 1 */
2902 void
2903 fatal (str, arg1, arg2)
2904 char *str, *arg1, *arg2;
2906 fprintf (stderr, "emacs: ");
2907 fprintf (stderr, str, arg1, arg2);
2908 fprintf (stderr, "\n");
2909 fflush (stderr);
2910 exit (1);
2915 static int deleting_tty = 0;
2918 /* Delete the given tty terminal, closing all frames on it. */
2920 static void
2921 delete_tty (struct terminal *terminal)
2923 struct tty_display_info *tty;
2924 Lisp_Object tail, frame;
2925 char *tty_name;
2926 int last_terminal;
2928 if (deleting_tty)
2929 /* We get a recursive call when we delete the last frame on this
2930 terminal. */
2931 return;
2933 if (terminal->type != output_termcap)
2934 abort ();
2936 tty = terminal->display_info.tty;
2938 last_terminal = 1;
2939 FOR_EACH_FRAME (tail, frame)
2941 struct frame *f = XFRAME (frame);
2942 if (FRAME_LIVE_P (f) && (!FRAME_TERMCAP_P (f) || FRAME_TTY (f) != tty))
2944 last_terminal = 0;
2945 break;
2948 if (last_terminal)
2949 error ("Attempt to delete the sole terminal device with live frames");
2951 if (tty == tty_list)
2952 tty_list = tty->next;
2953 else
2955 struct tty_display_info *p;
2956 for (p = tty_list; p && p->next != tty; p = p->next)
2959 if (! p)
2960 /* This should not happen. */
2961 abort ();
2963 p->next = tty->next;
2964 tty->next = 0;
2967 deleting_tty = 1;
2969 FOR_EACH_FRAME (tail, frame)
2971 struct frame *f = XFRAME (frame);
2972 if (FRAME_TERMCAP_P (f) && FRAME_LIVE_P (f) && FRAME_TTY (f) == tty)
2974 Fdelete_frame (frame, Qt);
2978 /* reset_sys_modes needs a valid device, so this call needs to be
2979 before delete_terminal. */
2980 reset_sys_modes (tty);
2982 delete_terminal (terminal);
2984 tty_name = tty->name;
2985 if (tty->type)
2986 xfree (tty->type);
2988 if (tty->input)
2990 delete_keyboard_wait_descriptor (fileno (tty->input));
2991 if (tty->input != stdin)
2992 fclose (tty->input);
2994 if (tty->output && tty->output != stdout && tty->output != tty->input)
2995 fclose (tty->output);
2996 if (tty->termscript)
2997 fclose (tty->termscript);
2999 if (tty->old_tty)
3000 xfree (tty->old_tty);
3002 if (tty->Wcm)
3003 xfree (tty->Wcm);
3005 bzero (tty, sizeof (struct tty_display_info));
3006 xfree (tty);
3007 deleting_tty = 0;
3012 /* Mark the pointers in the tty_display_info objects.
3013 Called by the Fgarbage_collector. */
3015 void
3016 mark_ttys (void)
3018 struct tty_display_info *tty;
3020 for (tty = tty_list; tty; tty = tty->next)
3022 if (tty->top_frame)
3023 mark_object (tty->top_frame);
3029 void
3030 syms_of_term ()
3032 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
3033 doc: /* Non-nil means the system uses terminfo rather than termcap.
3034 This variable can be used by terminal emulator packages. */);
3035 #ifdef TERMINFO
3036 system_uses_terminfo = 1;
3037 #else
3038 system_uses_terminfo = 0;
3039 #endif
3041 DEFVAR_LISP ("suspend-tty-functions", &Vsuspend_tty_functions,
3042 doc: /* Functions to be run after suspending a tty.
3043 The functions are run with one argument, the name of the tty to be suspended.
3044 See `suspend-tty'. */);
3045 Vsuspend_tty_functions = Qnil;
3048 DEFVAR_LISP ("resume-tty-functions", &Vresume_tty_functions,
3049 doc: /* Functions to be run after resuming a tty.
3050 The functions are run with one argument, the name of the tty that was revived.
3051 See `resume-tty'. */);
3052 Vresume_tty_functions = Qnil;
3054 DEFVAR_BOOL ("visible-cursor", &visible_cursor,
3055 doc: /* Non-nil means to make the cursor very visible.
3056 This only has an effect when running in a text terminal.
3057 What means \"very visible\" is up to your terminal. It may make the cursor
3058 bigger, or it may make it blink, or it may do nothing at all. */);
3059 visible_cursor = 1;
3061 defsubr (&Stty_display_color_p);
3062 defsubr (&Stty_display_color_cells);
3063 defsubr (&Stty_no_underline);
3064 defsubr (&Stty_type);
3065 defsubr (&Scontrolling_tty_p);
3066 defsubr (&Ssuspend_tty);
3067 defsubr (&Sresume_tty);
3072 /* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193
3073 (do not change this comment) */