* lisp/obsolete/spell.el: Fix header comment.
[emacs.git] / src / term.c
blob1aefe02421f9335ab46d03130192496bd8b0af7a
1 /* Terminal control module for terminals described by TERMCAP
2 Copyright (C) 1985-1987, 1993-1995, 1998, 2000-2011
3 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 3 of the License, or
10 (at your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20 /* New redisplay, TTY faces by Gerd Moellmann <gerd@gnu.org>. */
22 #include <config.h>
23 #include <stdio.h>
24 #include <ctype.h>
25 #include <errno.h>
26 #include <sys/file.h>
27 #include <unistd.h>
28 #include <signal.h>
29 #include <stdarg.h>
30 #include <setjmp.h>
32 #include "lisp.h"
33 #include "termchar.h"
34 #include "termopts.h"
35 #include "buffer.h"
36 #include "character.h"
37 #include "charset.h"
38 #include "coding.h"
39 #include "composite.h"
40 #include "keyboard.h"
41 #include "frame.h"
42 #include "disptab.h"
43 #include "termhooks.h"
44 #include "dispextern.h"
45 #include "window.h"
46 #include "keymap.h"
47 #include "blockinput.h"
48 #include "syssignal.h"
49 #include "systty.h"
50 #include "intervals.h"
51 #ifdef MSDOS
52 #include "msdos.h"
53 static int been_here = -1;
54 #endif
56 /* For now, don't try to include termcap.h. On some systems,
57 configure finds a non-standard termcap.h that the main build
58 won't find. */
59 extern void tputs (const char *, int, int (*)(int));
60 extern int tgetent (char *, const char *);
61 extern int tgetflag (char *id);
62 extern int tgetnum (char *id);
64 char *tparam (char *, char *, int, int, ...);
66 extern char *tgetstr (char *, char **);
68 #include "cm.h"
69 #ifdef HAVE_X_WINDOWS
70 #include "xterm.h"
71 #endif
73 #ifndef O_RDWR
74 #define O_RDWR 2
75 #endif
77 #ifndef O_NOCTTY
78 #define O_NOCTTY 0
79 #endif
81 /* The name of the default console device. */
82 #ifdef WINDOWSNT
83 #define DEV_TTY "CONOUT$"
84 #else
85 #define DEV_TTY "/dev/tty"
86 #endif
88 static void tty_set_scroll_region (struct frame *f, int start, int stop);
89 static void turn_on_face (struct frame *, int face_id);
90 static void turn_off_face (struct frame *, int face_id);
91 static void tty_show_cursor (struct tty_display_info *);
92 static void tty_hide_cursor (struct tty_display_info *);
93 static void tty_background_highlight (struct tty_display_info *tty);
94 static void clear_tty_hooks (struct terminal *terminal);
95 static void set_tty_hooks (struct terminal *terminal);
96 static void dissociate_if_controlling_tty (int fd);
97 static void delete_tty (struct terminal *);
98 static void maybe_fatal (int must_succeed, struct terminal *terminal,
99 const char *str1, const char *str2, ...) NO_RETURN;
100 static void vfatal (const char *str, va_list ap) NO_RETURN;
103 #define OUTPUT(tty, a) \
104 emacs_tputs ((tty), a, \
105 (int) (FRAME_LINES (XFRAME (selected_frame)) \
106 - curY (tty)), \
107 cmputc)
109 #define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
110 #define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
112 #define OUTPUT_IF(tty, a) \
113 do { \
114 if (a) \
115 emacs_tputs ((tty), a, \
116 (int) (FRAME_LINES (XFRAME (selected_frame)) \
117 - curY (tty) ), \
118 cmputc); \
119 } while (0)
121 #define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
123 /* Display space properties */
125 /* Chain of all tty device parameters. */
126 struct tty_display_info *tty_list;
128 /* Meaning of bits in no_color_video. Each bit set means that the
129 corresponding attribute cannot be combined with colors. */
131 enum no_color_bit
133 NC_STANDOUT = 1 << 0,
134 NC_UNDERLINE = 1 << 1,
135 NC_REVERSE = 1 << 2,
136 NC_BLINK = 1 << 3,
137 NC_DIM = 1 << 4,
138 NC_BOLD = 1 << 5,
139 NC_INVIS = 1 << 6,
140 NC_PROTECT = 1 << 7,
141 NC_ALT_CHARSET = 1 << 8
144 /* internal state */
146 /* The largest frame width in any call to calculate_costs. */
148 int max_frame_cols;
150 /* The largest frame height in any call to calculate_costs. */
152 int max_frame_lines;
154 /* Non-zero if we have dropped our controlling tty and therefore
155 should not open a frame on stdout. */
156 static int no_controlling_tty;
160 #ifdef HAVE_GPM
161 #include <sys/fcntl.h>
163 /* The device for which we have enabled gpm support (or NULL). */
164 struct tty_display_info *gpm_tty = NULL;
166 /* Last recorded mouse coordinates. */
167 static int last_mouse_x, last_mouse_y;
168 #endif /* HAVE_GPM */
170 /* Ring the bell on a tty. */
172 static void
173 tty_ring_bell (struct frame *f)
175 struct tty_display_info *tty = FRAME_TTY (f);
177 if (tty->output)
179 OUTPUT (tty, (tty->TS_visible_bell && visible_bell
180 ? tty->TS_visible_bell
181 : tty->TS_bell));
182 fflush (tty->output);
186 /* Set up termcap modes for Emacs. */
188 void
189 tty_set_terminal_modes (struct terminal *terminal)
191 struct tty_display_info *tty = terminal->display_info.tty;
193 if (tty->output)
195 if (tty->TS_termcap_modes)
196 OUTPUT (tty, tty->TS_termcap_modes);
197 else
199 /* Output enough newlines to scroll all the old screen contents
200 off the screen, so it won't be overwritten and lost. */
201 int i;
202 current_tty = tty;
203 for (i = 0; i < FRAME_LINES (XFRAME (selected_frame)); i++)
204 cmputc ('\n');
207 OUTPUT_IF (tty, visible_cursor ? tty->TS_cursor_visible : tty->TS_cursor_normal);
208 OUTPUT_IF (tty, tty->TS_keypad_mode);
209 losecursor (tty);
210 fflush (tty->output);
214 /* Reset termcap modes before exiting Emacs. */
216 void
217 tty_reset_terminal_modes (struct terminal *terminal)
219 struct tty_display_info *tty = terminal->display_info.tty;
221 if (tty->output)
223 tty_turn_off_highlight (tty);
224 tty_turn_off_insert (tty);
225 OUTPUT_IF (tty, tty->TS_end_keypad_mode);
226 OUTPUT_IF (tty, tty->TS_cursor_normal);
227 OUTPUT_IF (tty, tty->TS_end_termcap_modes);
228 OUTPUT_IF (tty, tty->TS_orig_pair);
229 /* Output raw CR so kernel can track the cursor hpos. */
230 current_tty = tty;
231 cmputc ('\r');
232 fflush (tty->output);
236 /* Flag the end of a display update on a termcap terminal. */
238 static void
239 tty_update_end (struct frame *f)
241 struct tty_display_info *tty = FRAME_TTY (f);
243 if (!XWINDOW (selected_window)->cursor_off_p)
244 tty_show_cursor (tty);
245 tty_turn_off_insert (tty);
246 tty_background_highlight (tty);
249 /* The implementation of set_terminal_window for termcap frames. */
251 static void
252 tty_set_terminal_window (struct frame *f, int size)
254 struct tty_display_info *tty = FRAME_TTY (f);
256 tty->specified_window = size ? size : FRAME_LINES (f);
257 if (FRAME_SCROLL_REGION_OK (f))
258 tty_set_scroll_region (f, 0, tty->specified_window);
261 static void
262 tty_set_scroll_region (struct frame *f, int start, int stop)
264 char *buf;
265 struct tty_display_info *tty = FRAME_TTY (f);
267 if (tty->TS_set_scroll_region)
268 buf = tparam (tty->TS_set_scroll_region, 0, 0, start, stop - 1);
269 else if (tty->TS_set_scroll_region_1)
270 buf = tparam (tty->TS_set_scroll_region_1, 0, 0,
271 FRAME_LINES (f), start,
272 FRAME_LINES (f) - stop,
273 FRAME_LINES (f));
274 else
275 buf = tparam (tty->TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (f));
277 OUTPUT (tty, buf);
278 xfree (buf);
279 losecursor (tty);
283 static void
284 tty_turn_on_insert (struct tty_display_info *tty)
286 if (!tty->insert_mode)
287 OUTPUT (tty, tty->TS_insert_mode);
288 tty->insert_mode = 1;
291 void
292 tty_turn_off_insert (struct tty_display_info *tty)
294 if (tty->insert_mode)
295 OUTPUT (tty, tty->TS_end_insert_mode);
296 tty->insert_mode = 0;
299 /* Handle highlighting. */
301 void
302 tty_turn_off_highlight (struct tty_display_info *tty)
304 if (tty->standout_mode)
305 OUTPUT_IF (tty, tty->TS_end_standout_mode);
306 tty->standout_mode = 0;
309 static void
310 tty_turn_on_highlight (struct tty_display_info *tty)
312 if (!tty->standout_mode)
313 OUTPUT_IF (tty, tty->TS_standout_mode);
314 tty->standout_mode = 1;
317 static void
318 tty_toggle_highlight (struct tty_display_info *tty)
320 if (tty->standout_mode)
321 tty_turn_off_highlight (tty);
322 else
323 tty_turn_on_highlight (tty);
327 /* Make cursor invisible. */
329 static void
330 tty_hide_cursor (struct tty_display_info *tty)
332 if (tty->cursor_hidden == 0)
334 tty->cursor_hidden = 1;
335 OUTPUT_IF (tty, tty->TS_cursor_invisible);
340 /* Ensure that cursor is visible. */
342 static void
343 tty_show_cursor (struct tty_display_info *tty)
345 if (tty->cursor_hidden)
347 tty->cursor_hidden = 0;
348 OUTPUT_IF (tty, tty->TS_cursor_normal);
349 if (visible_cursor)
350 OUTPUT_IF (tty, tty->TS_cursor_visible);
355 /* Set standout mode to the state it should be in for
356 empty space inside windows. What this is,
357 depends on the user option inverse-video. */
359 static void
360 tty_background_highlight (struct tty_display_info *tty)
362 if (inverse_video)
363 tty_turn_on_highlight (tty);
364 else
365 tty_turn_off_highlight (tty);
368 /* Set standout mode to the mode specified for the text to be output. */
370 static void
371 tty_highlight_if_desired (struct tty_display_info *tty)
373 if (inverse_video)
374 tty_turn_on_highlight (tty);
375 else
376 tty_turn_off_highlight (tty);
380 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
381 frame-relative coordinates. */
383 static void
384 tty_cursor_to (struct frame *f, int vpos, int hpos)
386 struct tty_display_info *tty = FRAME_TTY (f);
388 /* Detect the case where we are called from reset_sys_modes
389 and the costs have never been calculated. Do nothing. */
390 if (! tty->costs_set)
391 return;
393 if (curY (tty) == vpos
394 && curX (tty) == hpos)
395 return;
396 if (!tty->TF_standout_motion)
397 tty_background_highlight (tty);
398 if (!tty->TF_insmode_motion)
399 tty_turn_off_insert (tty);
400 cmgoto (tty, vpos, hpos);
403 /* Similar but don't take any account of the wasted characters. */
405 static void
406 tty_raw_cursor_to (struct frame *f, int row, int col)
408 struct tty_display_info *tty = FRAME_TTY (f);
410 if (curY (tty) == row
411 && curX (tty) == col)
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, row, col);
420 /* Erase operations */
422 /* Clear from cursor to end of frame on a termcap device. */
424 static void
425 tty_clear_to_end (struct frame *f)
427 register int i;
428 struct tty_display_info *tty = FRAME_TTY (f);
430 if (tty->TS_clr_to_bottom)
432 tty_background_highlight (tty);
433 OUTPUT (tty, tty->TS_clr_to_bottom);
435 else
437 for (i = curY (tty); i < FRAME_LINES (f); i++)
439 cursor_to (f, i, 0);
440 clear_end_of_line (f, FRAME_COLS (f));
445 /* Clear an entire termcap frame. */
447 static void
448 tty_clear_frame (struct frame *f)
450 struct tty_display_info *tty = FRAME_TTY (f);
452 if (tty->TS_clr_frame)
454 tty_background_highlight (tty);
455 OUTPUT (tty, tty->TS_clr_frame);
456 cmat (tty, 0, 0);
458 else
460 cursor_to (f, 0, 0);
461 clear_to_end (f);
465 /* An implementation of clear_end_of_line for termcap frames.
467 Note that the cursor may be moved, on terminals lacking a `ce' string. */
469 static void
470 tty_clear_end_of_line (struct frame *f, int first_unused_hpos)
472 register int i;
473 struct tty_display_info *tty = FRAME_TTY (f);
475 /* Detect the case where we are called from reset_sys_modes
476 and the costs have never been calculated. Do nothing. */
477 if (! tty->costs_set)
478 return;
480 if (curX (tty) >= first_unused_hpos)
481 return;
482 tty_background_highlight (tty);
483 if (tty->TS_clr_line)
485 OUTPUT1 (tty, tty->TS_clr_line);
487 else
488 { /* have to do it the hard way */
489 tty_turn_off_insert (tty);
491 /* Do not write in last row last col with Auto-wrap on. */
492 if (AutoWrap (tty)
493 && curY (tty) == FrameRows (tty) - 1
494 && first_unused_hpos == FrameCols (tty))
495 first_unused_hpos--;
497 for (i = curX (tty); i < first_unused_hpos; i++)
499 if (tty->termscript)
500 fputc (' ', tty->termscript);
501 fputc (' ', tty->output);
503 cmplus (tty, first_unused_hpos - curX (tty));
507 /* Buffers to store the source and result of code conversion for terminal. */
508 static unsigned char *encode_terminal_src;
509 static unsigned char *encode_terminal_dst;
510 /* Allocated sizes of the above buffers. */
511 static int encode_terminal_src_size;
512 static int encode_terminal_dst_size;
514 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes.
515 Set CODING->produced to the byte-length of the resulting byte
516 sequence, and return a pointer to that byte sequence. */
518 unsigned char *
519 encode_terminal_code (struct glyph *src, int src_len, struct coding_system *coding)
521 struct glyph *src_end = src + src_len;
522 unsigned char *buf;
523 int nchars, nbytes, required;
524 register int tlen = GLYPH_TABLE_LENGTH;
525 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
526 Lisp_Object charset_list;
528 /* Allocate sufficient size of buffer to store all characters in
529 multibyte-form. But, it may be enlarged on demand if
530 Vglyph_table contains a string or a composite glyph is
531 encountered. */
532 required = MAX_MULTIBYTE_LENGTH * src_len;
533 if (encode_terminal_src_size < required)
535 if (encode_terminal_src)
536 encode_terminal_src = xrealloc (encode_terminal_src, required);
537 else
538 encode_terminal_src = xmalloc (required);
539 encode_terminal_src_size = required;
542 charset_list = coding_charset_list (coding);
544 buf = encode_terminal_src;
545 nchars = 0;
546 while (src < src_end)
548 if (src->type == COMPOSITE_GLYPH)
550 struct composition *cmp;
551 Lisp_Object gstring;
552 int i;
554 nbytes = buf - encode_terminal_src;
555 if (src->u.cmp.automatic)
557 gstring = composition_gstring_from_id (src->u.cmp.id);
558 required = src->slice.cmp.to + 1 - src->slice.cmp.from;
560 else
562 cmp = composition_table[src->u.cmp.id];
563 required = MAX_MULTIBYTE_LENGTH * cmp->glyph_len;
566 if (encode_terminal_src_size < nbytes + required)
568 encode_terminal_src_size = nbytes + required;
569 encode_terminal_src = xrealloc (encode_terminal_src,
570 encode_terminal_src_size);
571 buf = encode_terminal_src + nbytes;
574 if (src->u.cmp.automatic)
575 for (i = src->slice.cmp.from; i <= src->slice.cmp.to; i++)
577 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
578 int c = LGLYPH_CHAR (g);
580 if (! char_charset (c, charset_list, NULL))
581 c = '?';
582 buf += CHAR_STRING (c, buf);
583 nchars++;
585 else
586 for (i = 0; i < cmp->glyph_len; i++)
588 int c = COMPOSITION_GLYPH (cmp, i);
590 if (c == '\t')
591 continue;
592 if (char_charset (c, charset_list, NULL))
594 if (CHAR_WIDTH (c) == 0
595 && i > 0 && COMPOSITION_GLYPH (cmp, i - 1) == '\t')
596 /* Should be left-padded */
598 buf += CHAR_STRING (' ', buf);
599 nchars++;
602 else
603 c = '?';
604 buf += CHAR_STRING (c, buf);
605 nchars++;
608 /* We must skip glyphs to be padded for a wide character. */
609 else if (! CHAR_GLYPH_PADDING_P (*src))
611 GLYPH g;
612 int c;
613 Lisp_Object string;
615 string = Qnil;
616 SET_GLYPH_FROM_CHAR_GLYPH (g, src[0]);
618 if (GLYPH_INVALID_P (g) || GLYPH_SIMPLE_P (tbase, tlen, g))
620 /* This glyph doesn't have an entry in Vglyph_table. */
621 c = src->u.ch;
623 else
625 /* This glyph has an entry in Vglyph_table,
626 so process any alias before testing for simpleness. */
627 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
629 if (GLYPH_SIMPLE_P (tbase, tlen, g))
630 /* We set the multi-byte form of a character in G
631 (that should be an ASCII character) at WORKBUF. */
632 c = GLYPH_CHAR (g);
633 else
634 /* We have a string in Vglyph_table. */
635 string = tbase[GLYPH_CHAR (g)];
638 if (NILP (string))
640 nbytes = buf - encode_terminal_src;
641 if (encode_terminal_src_size < nbytes + MAX_MULTIBYTE_LENGTH)
643 encode_terminal_src_size = nbytes + MAX_MULTIBYTE_LENGTH;
644 encode_terminal_src = xrealloc (encode_terminal_src,
645 encode_terminal_src_size);
646 buf = encode_terminal_src + nbytes;
648 if (CHAR_BYTE8_P (c)
649 || char_charset (c, charset_list, NULL))
651 /* Store the multibyte form of C at BUF. */
652 buf += CHAR_STRING (c, buf);
653 nchars++;
655 else
657 /* C is not encodable. */
658 *buf++ = '?';
659 nchars++;
660 while (src + 1 < src_end && CHAR_GLYPH_PADDING_P (src[1]))
662 *buf++ = '?';
663 nchars++;
664 src++;
668 else
670 unsigned char *p = SDATA (string);
672 if (! STRING_MULTIBYTE (string))
673 string = string_to_multibyte (string);
674 nbytes = buf - encode_terminal_src;
675 if (encode_terminal_src_size < nbytes + SBYTES (string))
677 encode_terminal_src_size = nbytes + SBYTES (string);
678 encode_terminal_src = xrealloc (encode_terminal_src,
679 encode_terminal_src_size);
680 buf = encode_terminal_src + nbytes;
682 memcpy (buf, SDATA (string), SBYTES (string));
683 buf += SBYTES (string);
684 nchars += SCHARS (string);
687 src++;
690 if (nchars == 0)
692 coding->produced = 0;
693 return NULL;
696 nbytes = buf - encode_terminal_src;
697 coding->source = encode_terminal_src;
698 if (encode_terminal_dst_size == 0)
700 encode_terminal_dst_size = encode_terminal_src_size;
701 if (encode_terminal_dst)
702 encode_terminal_dst = xrealloc (encode_terminal_dst,
703 encode_terminal_dst_size);
704 else
705 encode_terminal_dst = xmalloc (encode_terminal_dst_size);
707 coding->destination = encode_terminal_dst;
708 coding->dst_bytes = encode_terminal_dst_size;
709 encode_coding_object (coding, Qnil, 0, 0, nchars, nbytes, Qnil);
710 /* coding->destination may have been reallocated. */
711 encode_terminal_dst = coding->destination;
712 encode_terminal_dst_size = coding->dst_bytes;
714 return (encode_terminal_dst);
719 /* An implementation of write_glyphs for termcap frames. */
721 static void
722 tty_write_glyphs (struct frame *f, struct glyph *string, int len)
724 unsigned char *conversion_buffer;
725 struct coding_system *coding;
727 struct tty_display_info *tty = FRAME_TTY (f);
729 tty_turn_off_insert (tty);
730 tty_hide_cursor (tty);
732 /* Don't dare write in last column of bottom line, if Auto-Wrap,
733 since that would scroll the whole frame on some terminals. */
735 if (AutoWrap (tty)
736 && curY (tty) + 1 == FRAME_LINES (f)
737 && (curX (tty) + len) == FRAME_COLS (f))
738 len --;
739 if (len <= 0)
740 return;
742 cmplus (tty, len);
744 /* If terminal_coding does any conversion, use it, otherwise use
745 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
746 because it always return 1 if the member src_multibyte is 1. */
747 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
748 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
749 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
750 the tail. */
751 coding->mode &= ~CODING_MODE_LAST_BLOCK;
753 while (len > 0)
755 /* Identify a run of glyphs with the same face. */
756 int face_id = string->face_id;
757 int n;
759 for (n = 1; n < len; ++n)
760 if (string[n].face_id != face_id)
761 break;
763 /* Turn appearance modes of the face of the run on. */
764 tty_highlight_if_desired (tty);
765 turn_on_face (f, face_id);
767 if (n == len)
768 /* This is the last run. */
769 coding->mode |= CODING_MODE_LAST_BLOCK;
770 conversion_buffer = encode_terminal_code (string, n, coding);
771 if (coding->produced > 0)
773 BLOCK_INPUT;
774 fwrite (conversion_buffer, 1, coding->produced, tty->output);
775 if (ferror (tty->output))
776 clearerr (tty->output);
777 if (tty->termscript)
778 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
779 UNBLOCK_INPUT;
781 len -= n;
782 string += n;
784 /* Turn appearance modes off. */
785 turn_off_face (f, face_id);
786 tty_turn_off_highlight (tty);
789 cmcheckmagic (tty);
792 #ifdef HAVE_GPM /* Only used by GPM code. */
794 static void
795 tty_write_glyphs_with_face (register struct frame *f, register struct glyph *string,
796 register int len, register int face_id)
798 unsigned char *conversion_buffer;
799 struct coding_system *coding;
801 struct tty_display_info *tty = FRAME_TTY (f);
803 tty_turn_off_insert (tty);
804 tty_hide_cursor (tty);
806 /* Don't dare write in last column of bottom line, if Auto-Wrap,
807 since that would scroll the whole frame on some terminals. */
809 if (AutoWrap (tty)
810 && curY (tty) + 1 == FRAME_LINES (f)
811 && (curX (tty) + len) == FRAME_COLS (f))
812 len --;
813 if (len <= 0)
814 return;
816 cmplus (tty, len);
818 /* If terminal_coding does any conversion, use it, otherwise use
819 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
820 because it always return 1 if the member src_multibyte is 1. */
821 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
822 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
823 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
824 the tail. */
825 coding->mode &= ~CODING_MODE_LAST_BLOCK;
827 /* Turn appearance modes of the face. */
828 tty_highlight_if_desired (tty);
829 turn_on_face (f, face_id);
831 coding->mode |= CODING_MODE_LAST_BLOCK;
832 conversion_buffer = encode_terminal_code (string, len, coding);
833 if (coding->produced > 0)
835 BLOCK_INPUT;
836 fwrite (conversion_buffer, 1, coding->produced, tty->output);
837 if (ferror (tty->output))
838 clearerr (tty->output);
839 if (tty->termscript)
840 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
841 UNBLOCK_INPUT;
844 /* Turn appearance modes off. */
845 turn_off_face (f, face_id);
846 tty_turn_off_highlight (tty);
848 cmcheckmagic (tty);
850 #endif
852 /* An implementation of insert_glyphs for termcap frames. */
854 static void
855 tty_insert_glyphs (struct frame *f, struct glyph *start, int len)
857 char *buf;
858 struct glyph *glyph = NULL;
859 unsigned char *conversion_buffer;
860 unsigned char space[1];
861 struct coding_system *coding;
863 struct tty_display_info *tty = FRAME_TTY (f);
865 if (tty->TS_ins_multi_chars)
867 buf = tparam (tty->TS_ins_multi_chars, 0, 0, len);
868 OUTPUT1 (tty, buf);
869 xfree (buf);
870 if (start)
871 write_glyphs (f, start, len);
872 return;
875 tty_turn_on_insert (tty);
876 cmplus (tty, len);
878 if (! start)
879 space[0] = SPACEGLYPH;
881 /* If terminal_coding does any conversion, use it, otherwise use
882 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
883 because it always return 1 if the member src_multibyte is 1. */
884 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
885 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
886 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
887 the tail. */
888 coding->mode &= ~CODING_MODE_LAST_BLOCK;
890 while (len-- > 0)
892 OUTPUT1_IF (tty, tty->TS_ins_char);
893 if (!start)
895 conversion_buffer = space;
896 coding->produced = 1;
898 else
900 tty_highlight_if_desired (tty);
901 turn_on_face (f, start->face_id);
902 glyph = start;
903 ++start;
904 /* We must open sufficient space for a character which
905 occupies more than one column. */
906 while (len && CHAR_GLYPH_PADDING_P (*start))
908 OUTPUT1_IF (tty, tty->TS_ins_char);
909 start++, len--;
912 if (len <= 0)
913 /* This is the last glyph. */
914 coding->mode |= CODING_MODE_LAST_BLOCK;
916 conversion_buffer = encode_terminal_code (glyph, 1, coding);
919 if (coding->produced > 0)
921 BLOCK_INPUT;
922 fwrite (conversion_buffer, 1, coding->produced, tty->output);
923 if (ferror (tty->output))
924 clearerr (tty->output);
925 if (tty->termscript)
926 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
927 UNBLOCK_INPUT;
930 OUTPUT1_IF (tty, tty->TS_pad_inserted_char);
931 if (start)
933 turn_off_face (f, glyph->face_id);
934 tty_turn_off_highlight (tty);
938 cmcheckmagic (tty);
941 /* An implementation of delete_glyphs for termcap frames. */
943 static void
944 tty_delete_glyphs (struct frame *f, int n)
946 char *buf;
947 register int i;
949 struct tty_display_info *tty = FRAME_TTY (f);
951 if (tty->delete_in_insert_mode)
953 tty_turn_on_insert (tty);
955 else
957 tty_turn_off_insert (tty);
958 OUTPUT_IF (tty, tty->TS_delete_mode);
961 if (tty->TS_del_multi_chars)
963 buf = tparam (tty->TS_del_multi_chars, 0, 0, n);
964 OUTPUT1 (tty, buf);
965 xfree (buf);
967 else
968 for (i = 0; i < n; i++)
969 OUTPUT1 (tty, tty->TS_del_char);
970 if (!tty->delete_in_insert_mode)
971 OUTPUT_IF (tty, tty->TS_end_delete_mode);
974 /* An implementation of ins_del_lines for termcap frames. */
976 static void
977 tty_ins_del_lines (struct frame *f, int vpos, int n)
979 struct tty_display_info *tty = FRAME_TTY (f);
980 char *multi = n > 0 ? tty->TS_ins_multi_lines : tty->TS_del_multi_lines;
981 char *single = n > 0 ? tty->TS_ins_line : tty->TS_del_line;
982 char *scroll = n > 0 ? tty->TS_rev_scroll : tty->TS_fwd_scroll;
984 register int i = n > 0 ? n : -n;
985 register char *buf;
987 /* If the lines below the insertion are being pushed
988 into the end of the window, this is the same as clearing;
989 and we know the lines are already clear, since the matching
990 deletion has already been done. So can ignore this. */
991 /* If the lines below the deletion are blank lines coming
992 out of the end of the window, don't bother,
993 as there will be a matching inslines later that will flush them. */
994 if (FRAME_SCROLL_REGION_OK (f)
995 && vpos + i >= tty->specified_window)
996 return;
997 if (!FRAME_MEMORY_BELOW_FRAME (f)
998 && vpos + i >= FRAME_LINES (f))
999 return;
1001 if (multi)
1003 raw_cursor_to (f, vpos, 0);
1004 tty_background_highlight (tty);
1005 buf = tparam (multi, 0, 0, i);
1006 OUTPUT (tty, buf);
1007 xfree (buf);
1009 else if (single)
1011 raw_cursor_to (f, vpos, 0);
1012 tty_background_highlight (tty);
1013 while (--i >= 0)
1014 OUTPUT (tty, single);
1015 if (tty->TF_teleray)
1016 curX (tty) = 0;
1018 else
1020 tty_set_scroll_region (f, vpos, tty->specified_window);
1021 if (n < 0)
1022 raw_cursor_to (f, tty->specified_window - 1, 0);
1023 else
1024 raw_cursor_to (f, vpos, 0);
1025 tty_background_highlight (tty);
1026 while (--i >= 0)
1027 OUTPUTL (tty, scroll, tty->specified_window - vpos);
1028 tty_set_scroll_region (f, 0, tty->specified_window);
1031 if (!FRAME_SCROLL_REGION_OK (f)
1032 && FRAME_MEMORY_BELOW_FRAME (f)
1033 && n < 0)
1035 cursor_to (f, FRAME_LINES (f) + n, 0);
1036 clear_to_end (f);
1040 /* Compute cost of sending "str", in characters,
1041 not counting any line-dependent padding. */
1044 string_cost (const char *str)
1046 cost = 0;
1047 if (str)
1048 tputs (str, 0, evalcost);
1049 return cost;
1052 /* Compute cost of sending "str", in characters,
1053 counting any line-dependent padding at one line. */
1055 static int
1056 string_cost_one_line (const char *str)
1058 cost = 0;
1059 if (str)
1060 tputs (str, 1, evalcost);
1061 return cost;
1064 /* Compute per line amount of line-dependent padding,
1065 in tenths of characters. */
1068 per_line_cost (const char *str)
1070 cost = 0;
1071 if (str)
1072 tputs (str, 0, evalcost);
1073 cost = - cost;
1074 if (str)
1075 tputs (str, 10, evalcost);
1076 return cost;
1079 /* char_ins_del_cost[n] is cost of inserting N characters.
1080 char_ins_del_cost[-n] is cost of deleting N characters.
1081 The length of this vector is based on max_frame_cols. */
1083 int *char_ins_del_vector;
1085 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
1087 /* ARGSUSED */
1088 static void
1089 calculate_ins_del_char_costs (struct frame *f)
1091 struct tty_display_info *tty = FRAME_TTY (f);
1092 int ins_startup_cost, del_startup_cost;
1093 int ins_cost_per_char, del_cost_per_char;
1094 register int i;
1095 register int *p;
1097 if (tty->TS_ins_multi_chars)
1099 ins_cost_per_char = 0;
1100 ins_startup_cost = string_cost_one_line (tty->TS_ins_multi_chars);
1102 else if (tty->TS_ins_char || tty->TS_pad_inserted_char
1103 || (tty->TS_insert_mode && tty->TS_end_insert_mode))
1105 ins_startup_cost = (30 * (string_cost (tty->TS_insert_mode)
1106 + string_cost (tty->TS_end_insert_mode))) / 100;
1107 ins_cost_per_char = (string_cost_one_line (tty->TS_ins_char)
1108 + string_cost_one_line (tty->TS_pad_inserted_char));
1110 else
1112 ins_startup_cost = 9999;
1113 ins_cost_per_char = 0;
1116 if (tty->TS_del_multi_chars)
1118 del_cost_per_char = 0;
1119 del_startup_cost = string_cost_one_line (tty->TS_del_multi_chars);
1121 else if (tty->TS_del_char)
1123 del_startup_cost = (string_cost (tty->TS_delete_mode)
1124 + string_cost (tty->TS_end_delete_mode));
1125 if (tty->delete_in_insert_mode)
1126 del_startup_cost /= 2;
1127 del_cost_per_char = string_cost_one_line (tty->TS_del_char);
1129 else
1131 del_startup_cost = 9999;
1132 del_cost_per_char = 0;
1135 /* Delete costs are at negative offsets */
1136 p = &char_ins_del_cost (f)[0];
1137 for (i = FRAME_COLS (f); --i >= 0;)
1138 *--p = (del_startup_cost += del_cost_per_char);
1140 /* Doing nothing is free */
1141 p = &char_ins_del_cost (f)[0];
1142 *p++ = 0;
1144 /* Insert costs are at positive offsets */
1145 for (i = FRAME_COLS (f); --i >= 0;)
1146 *p++ = (ins_startup_cost += ins_cost_per_char);
1149 void
1150 calculate_costs (struct frame *frame)
1152 FRAME_COST_BAUD_RATE (frame) = baud_rate;
1154 if (FRAME_TERMCAP_P (frame))
1156 struct tty_display_info *tty = FRAME_TTY (frame);
1157 register char *f = (tty->TS_set_scroll_region
1158 ? tty->TS_set_scroll_region
1159 : tty->TS_set_scroll_region_1);
1161 FRAME_SCROLL_REGION_COST (frame) = string_cost (f);
1163 tty->costs_set = 1;
1165 /* These variables are only used for terminal stuff. They are
1166 allocated once for the terminal frame of X-windows emacs, but not
1167 used afterwards.
1169 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1170 X turns off char_ins_del_ok. */
1172 max_frame_lines = max (max_frame_lines, FRAME_LINES (frame));
1173 max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
1175 if (char_ins_del_vector != 0)
1176 char_ins_del_vector
1177 = (int *) xrealloc (char_ins_del_vector,
1178 (sizeof (int)
1179 + 2 * max_frame_cols * sizeof (int)));
1180 else
1181 char_ins_del_vector
1182 = (int *) xmalloc (sizeof (int)
1183 + 2 * max_frame_cols * sizeof (int));
1185 memset (char_ins_del_vector, 0,
1186 (sizeof (int) + 2 * max_frame_cols * sizeof (int)));
1189 if (f && (!tty->TS_ins_line && !tty->TS_del_line))
1190 do_line_insertion_deletion_costs (frame,
1191 tty->TS_rev_scroll, tty->TS_ins_multi_lines,
1192 tty->TS_fwd_scroll, tty->TS_del_multi_lines,
1193 f, f, 1);
1194 else
1195 do_line_insertion_deletion_costs (frame,
1196 tty->TS_ins_line, tty->TS_ins_multi_lines,
1197 tty->TS_del_line, tty->TS_del_multi_lines,
1198 0, 0, 1);
1200 calculate_ins_del_char_costs (frame);
1202 /* Don't use TS_repeat if its padding is worse than sending the chars */
1203 if (tty->TS_repeat && per_line_cost (tty->TS_repeat) * baud_rate < 9000)
1204 tty->RPov = string_cost (tty->TS_repeat);
1205 else
1206 tty->RPov = FRAME_COLS (frame) * 2;
1208 cmcostinit (FRAME_TTY (frame)); /* set up cursor motion costs */
1212 struct fkey_table {
1213 char *cap, *name;
1216 /* Termcap capability names that correspond directly to X keysyms.
1217 Some of these (marked "terminfo") aren't supplied by old-style
1218 (Berkeley) termcap entries. They're listed in X keysym order;
1219 except we put the keypad keys first, so that if they clash with
1220 other keys (as on the IBM PC keyboard) they get overridden.
1223 static const struct fkey_table keys[] =
1225 {"kh", "home"}, /* termcap */
1226 {"kl", "left"}, /* termcap */
1227 {"ku", "up"}, /* termcap */
1228 {"kr", "right"}, /* termcap */
1229 {"kd", "down"}, /* termcap */
1230 {"%8", "prior"}, /* terminfo */
1231 {"%5", "next"}, /* terminfo */
1232 {"@7", "end"}, /* terminfo */
1233 {"@1", "begin"}, /* terminfo */
1234 {"*6", "select"}, /* terminfo */
1235 {"%9", "print"}, /* terminfo */
1236 {"@4", "execute"}, /* terminfo --- actually the `command' key */
1238 * "insert" --- see below
1240 {"&8", "undo"}, /* terminfo */
1241 {"%0", "redo"}, /* terminfo */
1242 {"%7", "menu"}, /* terminfo --- actually the `options' key */
1243 {"@0", "find"}, /* terminfo */
1244 {"@2", "cancel"}, /* terminfo */
1245 {"%1", "help"}, /* terminfo */
1247 * "break" goes here, but can't be reliably intercepted with termcap
1249 {"&4", "reset"}, /* terminfo --- actually `restart' */
1251 * "system" and "user" --- no termcaps
1253 {"kE", "clearline"}, /* terminfo */
1254 {"kA", "insertline"}, /* terminfo */
1255 {"kL", "deleteline"}, /* terminfo */
1256 {"kI", "insertchar"}, /* terminfo */
1257 {"kD", "deletechar"}, /* terminfo */
1258 {"kB", "backtab"}, /* terminfo */
1260 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1262 {"@8", "kp-enter"}, /* terminfo */
1264 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1265 * "kp-multiply", "kp-add", "kp-separator",
1266 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1267 * --- no termcaps for any of these.
1269 {"K4", "kp-1"}, /* terminfo */
1271 * "kp-2" --- no termcap
1273 {"K5", "kp-3"}, /* terminfo */
1275 * "kp-4" --- no termcap
1277 {"K2", "kp-5"}, /* terminfo */
1279 * "kp-6" --- no termcap
1281 {"K1", "kp-7"}, /* terminfo */
1283 * "kp-8" --- no termcap
1285 {"K3", "kp-9"}, /* terminfo */
1287 * "kp-equal" --- no termcap
1289 {"k1", "f1"},
1290 {"k2", "f2"},
1291 {"k3", "f3"},
1292 {"k4", "f4"},
1293 {"k5", "f5"},
1294 {"k6", "f6"},
1295 {"k7", "f7"},
1296 {"k8", "f8"},
1297 {"k9", "f9"},
1299 {"&0", "S-cancel"}, /*shifted cancel key*/
1300 {"&9", "S-begin"}, /*shifted begin key*/
1301 {"*0", "S-find"}, /*shifted find key*/
1302 {"*1", "S-execute"}, /*shifted execute? actually shifted command key*/
1303 {"*4", "S-delete"}, /*shifted delete-character key*/
1304 {"*7", "S-end"}, /*shifted end key*/
1305 {"*8", "S-clearline"}, /*shifted clear-to end-of-line key*/
1306 {"#1", "S-help"}, /*shifted help key*/
1307 {"#2", "S-home"}, /*shifted home key*/
1308 {"#3", "S-insert"}, /*shifted insert-character key*/
1309 {"#4", "S-left"}, /*shifted left-arrow key*/
1310 {"%d", "S-menu"}, /*shifted menu? actually shifted options key*/
1311 {"%c", "S-next"}, /*shifted next key*/
1312 {"%e", "S-prior"}, /*shifted previous key*/
1313 {"%f", "S-print"}, /*shifted print key*/
1314 {"%g", "S-redo"}, /*shifted redo key*/
1315 {"%i", "S-right"}, /*shifted right-arrow key*/
1316 {"!3", "S-undo"} /*shifted undo key*/
1319 #ifndef DOS_NT
1320 static char **term_get_fkeys_address;
1321 static KBOARD *term_get_fkeys_kboard;
1322 static Lisp_Object term_get_fkeys_1 (void);
1324 /* Find the escape codes sent by the function keys for Vinput_decode_map.
1325 This function scans the termcap function key sequence entries, and
1326 adds entries to Vinput_decode_map for each function key it finds. */
1328 static void
1329 term_get_fkeys (char **address, KBOARD *kboard)
1331 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1332 errors during the call. The only errors should be from Fdefine_key
1333 when given a key sequence containing an invalid prefix key. If the
1334 termcap defines function keys which use a prefix that is already bound
1335 to a command by the default bindings, we should silently ignore that
1336 function key specification, rather than giving the user an error and
1337 refusing to run at all on such a terminal. */
1339 term_get_fkeys_address = address;
1340 term_get_fkeys_kboard = kboard;
1341 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1344 static Lisp_Object
1345 term_get_fkeys_1 (void)
1347 int i;
1349 char **address = term_get_fkeys_address;
1350 KBOARD *kboard = term_get_fkeys_kboard;
1352 /* This can happen if CANNOT_DUMP or with strange options. */
1353 if (!KEYMAPP (kboard->Vinput_decode_map))
1354 kboard->Vinput_decode_map = Fmake_sparse_keymap (Qnil);
1356 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1358 char *sequence = tgetstr (keys[i].cap, address);
1359 if (sequence)
1360 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence),
1361 Fmake_vector (make_number (1),
1362 intern (keys[i].name)));
1365 /* The uses of the "k0" capability are inconsistent; sometimes it
1366 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1367 We will attempt to politely accommodate both systems by testing for
1368 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1371 char *k_semi = tgetstr ("k;", address);
1372 char *k0 = tgetstr ("k0", address);
1373 char *k0_name = "f10";
1375 if (k_semi)
1377 if (k0)
1378 /* Define f0 first, so that f10 takes precedence in case the
1379 key sequences happens to be the same. */
1380 Fdefine_key (kboard->Vinput_decode_map, build_string (k0),
1381 Fmake_vector (make_number (1), intern ("f0")));
1382 Fdefine_key (kboard->Vinput_decode_map, build_string (k_semi),
1383 Fmake_vector (make_number (1), intern ("f10")));
1385 else if (k0)
1386 Fdefine_key (kboard->Vinput_decode_map, build_string (k0),
1387 Fmake_vector (make_number (1), intern (k0_name)));
1390 /* Set up cookies for numbered function keys above f10. */
1392 char fcap[3], fkey[4];
1394 fcap[0] = 'F'; fcap[2] = '\0';
1395 for (i = 11; i < 64; i++)
1397 if (i <= 19)
1398 fcap[1] = '1' + i - 11;
1399 else if (i <= 45)
1400 fcap[1] = 'A' + i - 20;
1401 else
1402 fcap[1] = 'a' + i - 46;
1405 char *sequence = tgetstr (fcap, address);
1406 if (sequence)
1408 sprintf (fkey, "f%d", i);
1409 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence),
1410 Fmake_vector (make_number (1),
1411 intern (fkey)));
1418 * Various mappings to try and get a better fit.
1421 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1422 if (!tgetstr (cap1, address)) \
1424 char *sequence = tgetstr (cap2, address); \
1425 if (sequence) \
1426 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence), \
1427 Fmake_vector (make_number (1), \
1428 intern (sym))); \
1431 /* if there's no key_next keycap, map key_npage to `next' keysym */
1432 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1433 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1434 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1435 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1436 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1437 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1438 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1440 /* IBM has their own non-standard dialect of terminfo.
1441 If the standard name isn't found, try the IBM name. */
1442 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1443 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1444 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1445 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1446 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1447 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1448 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1449 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1450 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1451 #undef CONDITIONAL_REASSIGN
1454 return Qnil;
1456 #endif /* not DOS_NT */
1459 /***********************************************************************
1460 Character Display Information
1461 ***********************************************************************/
1462 static void append_glyph (struct it *);
1463 static void produce_stretch_glyph (struct it *);
1464 static void append_composite_glyph (struct it *);
1465 static void produce_composite_glyph (struct it *);
1466 static void append_glyphless_glyph (struct it *, int, char *);
1467 static void produce_glyphless_glyph (struct it *, int, Lisp_Object);
1469 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1470 terminal frames if IT->glyph_row != NULL. IT->char_to_display is
1471 the character for which to produce glyphs; IT->face_id contains the
1472 character's face. Padding glyphs are appended if IT->c has a
1473 IT->pixel_width > 1. */
1475 static void
1476 append_glyph (struct it *it)
1478 struct glyph *glyph, *end;
1479 int i;
1481 xassert (it->glyph_row);
1482 glyph = (it->glyph_row->glyphs[it->area]
1483 + it->glyph_row->used[it->area]);
1484 end = it->glyph_row->glyphs[1 + it->area];
1486 /* If the glyph row is reversed, we need to prepend the glyph rather
1487 than append it. */
1488 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1490 struct glyph *g;
1491 int move_by = it->pixel_width;
1493 /* Make room for the new glyphs. */
1494 if (move_by > end - glyph) /* don't overstep end of this area */
1495 move_by = end - glyph;
1496 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1497 g[move_by] = *g;
1498 glyph = it->glyph_row->glyphs[it->area];
1499 end = glyph + move_by;
1502 /* BIDI Note: we put the glyphs of a "multi-pixel" character left to
1503 right, even in the REVERSED_P case, since (a) all of its u.ch are
1504 identical, and (b) the PADDING_P flag needs to be set for the
1505 leftmost one, because we write to the terminal left-to-right. */
1506 for (i = 0;
1507 i < it->pixel_width && glyph < end;
1508 ++i)
1510 glyph->type = CHAR_GLYPH;
1511 glyph->pixel_width = 1;
1512 glyph->u.ch = it->char_to_display;
1513 glyph->face_id = it->face_id;
1514 glyph->padding_p = i > 0;
1515 glyph->charpos = CHARPOS (it->position);
1516 glyph->object = it->object;
1517 if (it->bidi_p)
1519 glyph->resolved_level = it->bidi_it.resolved_level;
1520 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1521 abort ();
1522 glyph->bidi_type = it->bidi_it.type;
1524 else
1526 glyph->resolved_level = 0;
1527 glyph->bidi_type = UNKNOWN_BT;
1530 ++it->glyph_row->used[it->area];
1531 ++glyph;
1535 /* Produce glyphs for the display element described by IT. *IT
1536 specifies what we want to produce a glyph for (character, image, ...),
1537 and where in the glyph matrix we currently are (glyph row and hpos).
1538 produce_glyphs fills in output fields of *IT with information such as the
1539 pixel width and height of a character, and maybe output actual glyphs at
1540 the same time if IT->glyph_row is non-null. For an overview, see
1541 the explanation in dispextern.h, before the definition of the
1542 display_element_type enumeration.
1544 produce_glyphs also stores the result of glyph width, ascent
1545 etc. computations in *IT.
1547 IT->glyph_row may be null, in which case produce_glyphs does not
1548 actually fill in the glyphs. This is used in the move_* functions
1549 in xdisp.c for text width and height computations.
1551 Callers usually don't call produce_glyphs directly;
1552 instead they use the macro PRODUCE_GLYPHS. */
1554 void
1555 produce_glyphs (struct it *it)
1557 /* If a hook is installed, let it do the work. */
1559 /* Nothing but characters are supported on terminal frames. */
1560 xassert (it->what == IT_CHARACTER
1561 || it->what == IT_COMPOSITION
1562 || it->what == IT_STRETCH);
1564 if (it->what == IT_STRETCH)
1566 produce_stretch_glyph (it);
1567 goto done;
1570 if (it->what == IT_COMPOSITION)
1572 produce_composite_glyph (it);
1573 goto done;
1576 if (it->what == IT_GLYPHLESS)
1578 produce_glyphless_glyph (it, 0, Qnil);
1579 goto done;
1582 if (it->char_to_display >= 040 && it->char_to_display < 0177)
1584 it->pixel_width = it->nglyphs = 1;
1585 if (it->glyph_row)
1586 append_glyph (it);
1588 else if (it->char_to_display == '\n')
1589 it->pixel_width = it->nglyphs = 0;
1590 else if (it->char_to_display == '\t')
1592 int absolute_x = (it->current_x
1593 + it->continuation_lines_width);
1594 int next_tab_x
1595 = (((1 + absolute_x + it->tab_width - 1)
1596 / it->tab_width)
1597 * it->tab_width);
1598 int nspaces;
1600 /* If part of the TAB has been displayed on the previous line
1601 which is continued now, continuation_lines_width will have
1602 been incremented already by the part that fitted on the
1603 continued line. So, we will get the right number of spaces
1604 here. */
1605 nspaces = next_tab_x - absolute_x;
1607 if (it->glyph_row)
1609 int n = nspaces;
1611 it->char_to_display = ' ';
1612 it->pixel_width = it->len = 1;
1614 while (n--)
1615 append_glyph (it);
1618 it->pixel_width = nspaces;
1619 it->nglyphs = nspaces;
1621 else if (CHAR_BYTE8_P (it->char_to_display))
1623 /* Coming here means that we must send the raw 8-bit byte as is
1624 to the terminal. Although there's no way to know how many
1625 columns it occupies on a screen, it is a good assumption that
1626 a single byte code has 1-column width. */
1627 it->pixel_width = it->nglyphs = 1;
1628 if (it->glyph_row)
1629 append_glyph (it);
1631 else
1633 Lisp_Object charset_list = FRAME_TERMINAL (it->f)->charset_list;
1635 if (char_charset (it->char_to_display, charset_list, NULL))
1637 it->pixel_width = CHAR_WIDTH (it->char_to_display);
1638 it->nglyphs = it->pixel_width;
1639 if (it->glyph_row)
1640 append_glyph (it);
1642 else
1644 Lisp_Object acronym = lookup_glyphless_char_display (-1, it);
1646 xassert (it->what == IT_GLYPHLESS);
1647 produce_glyphless_glyph (it, 1, acronym);
1651 done:
1652 /* Advance current_x by the pixel width as a convenience for
1653 the caller. */
1654 if (it->area == TEXT_AREA)
1655 it->current_x += it->pixel_width;
1656 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1657 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
1661 /* Produce a stretch glyph for iterator IT. IT->object is the value
1662 of the glyph property displayed. The value must be a list
1663 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1664 being recognized:
1666 1. `:width WIDTH' specifies that the space should be WIDTH *
1667 canonical char width wide. WIDTH may be an integer or floating
1668 point number.
1670 2. `:align-to HPOS' specifies that the space should be wide enough
1671 to reach HPOS, a value in canonical character units. */
1673 static void
1674 produce_stretch_glyph (struct it *it)
1676 /* (space :width WIDTH ...) */
1677 Lisp_Object prop, plist;
1678 int width = 0, align_to = -1;
1679 int zero_width_ok_p = 0;
1680 double tem;
1682 /* List should start with `space'. */
1683 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1684 plist = XCDR (it->object);
1686 /* Compute the width of the stretch. */
1687 if ((prop = Fplist_get (plist, QCwidth), !NILP (prop))
1688 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, 0))
1690 /* Absolute width `:width WIDTH' specified and valid. */
1691 zero_width_ok_p = 1;
1692 width = (int)(tem + 0.5);
1694 else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
1695 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, &align_to))
1697 if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
1698 align_to = (align_to < 0
1700 : align_to - window_box_left_offset (it->w, TEXT_AREA));
1701 else if (align_to < 0)
1702 align_to = window_box_left_offset (it->w, TEXT_AREA);
1703 width = max (0, (int)(tem + 0.5) + align_to - it->current_x);
1704 zero_width_ok_p = 1;
1706 else
1707 /* Nothing specified -> width defaults to canonical char width. */
1708 width = FRAME_COLUMN_WIDTH (it->f);
1710 if (width <= 0 && (width < 0 || !zero_width_ok_p))
1711 width = 1;
1713 if (width > 0 && it->line_wrap != TRUNCATE
1714 && it->current_x + width > it->last_visible_x)
1715 width = it->last_visible_x - it->current_x - 1;
1717 if (width > 0 && it->glyph_row)
1719 Lisp_Object o_object = it->object;
1720 Lisp_Object object = it->stack[it->sp - 1].string;
1721 int n = width;
1723 if (!STRINGP (object))
1724 object = it->w->buffer;
1725 it->object = object;
1726 it->char_to_display = ' ';
1727 it->pixel_width = it->len = 1;
1728 while (n--)
1729 append_glyph (it);
1730 it->object = o_object;
1732 it->pixel_width = width;
1733 it->nglyphs = width;
1737 /* Append glyphs to IT's glyph_row for the composition IT->cmp_id.
1738 Called from produce_composite_glyph for terminal frames if
1739 IT->glyph_row != NULL. IT->face_id contains the character's
1740 face. */
1742 static void
1743 append_composite_glyph (struct it *it)
1745 struct glyph *glyph;
1747 xassert (it->glyph_row);
1748 glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
1749 if (glyph < it->glyph_row->glyphs[1 + it->area])
1751 /* If the glyph row is reversed, we need to prepend the glyph
1752 rather than append it. */
1753 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1755 struct glyph *g;
1757 /* Make room for the new glyph. */
1758 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1759 g[1] = *g;
1760 glyph = it->glyph_row->glyphs[it->area];
1762 glyph->type = COMPOSITE_GLYPH;
1763 glyph->pixel_width = it->pixel_width;
1764 glyph->u.cmp.id = it->cmp_it.id;
1765 if (it->cmp_it.ch < 0)
1767 glyph->u.cmp.automatic = 0;
1768 glyph->u.cmp.id = it->cmp_it.id;
1770 else
1772 glyph->u.cmp.automatic = 1;
1773 glyph->u.cmp.id = it->cmp_it.id;
1774 glyph->slice.cmp.from = it->cmp_it.from;
1775 glyph->slice.cmp.to = it->cmp_it.to - 1;
1778 glyph->face_id = it->face_id;
1779 glyph->padding_p = 0;
1780 glyph->charpos = CHARPOS (it->position);
1781 glyph->object = it->object;
1782 if (it->bidi_p)
1784 glyph->resolved_level = it->bidi_it.resolved_level;
1785 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1786 abort ();
1787 glyph->bidi_type = it->bidi_it.type;
1789 else
1791 glyph->resolved_level = 0;
1792 glyph->bidi_type = UNKNOWN_BT;
1795 ++it->glyph_row->used[it->area];
1796 ++glyph;
1801 /* Produce a composite glyph for iterator IT. IT->cmp_id is the ID of
1802 the composition. We simply produces components of the composition
1803 assuming that the terminal has a capability to layout/render it
1804 correctly. */
1806 static void
1807 produce_composite_glyph (struct it *it)
1809 if (it->cmp_it.ch < 0)
1811 struct composition *cmp = composition_table[it->cmp_it.id];
1813 it->pixel_width = cmp->width;
1815 else
1817 Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id);
1819 it->pixel_width = composition_gstring_width (gstring, it->cmp_it.from,
1820 it->cmp_it.to, NULL);
1822 it->nglyphs = 1;
1823 if (it->glyph_row)
1824 append_composite_glyph (it);
1828 /* Append a glyph for a glyphless character to IT->glyph_row. FACE_ID
1829 is a face ID to be used for the glyph. What is actually appended
1830 are glyphs of type CHAR_GLYPH whose characters are in STR (which
1831 comes from it->nglyphs bytes). */
1833 static void
1834 append_glyphless_glyph (struct it *it, int face_id, char *str)
1836 struct glyph *glyph, *end;
1837 int i;
1839 xassert (it->glyph_row);
1840 glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
1841 end = it->glyph_row->glyphs[1 + it->area];
1843 /* If the glyph row is reversed, we need to prepend the glyph rather
1844 than append it. */
1845 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1847 struct glyph *g;
1848 int move_by = it->pixel_width;
1850 /* Make room for the new glyphs. */
1851 if (move_by > end - glyph) /* don't overstep end of this area */
1852 move_by = end - glyph;
1853 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1854 g[move_by] = *g;
1855 glyph = it->glyph_row->glyphs[it->area];
1856 end = glyph + move_by;
1859 if (glyph >= end)
1860 return;
1861 glyph->type = CHAR_GLYPH;
1862 glyph->pixel_width = 1;
1863 glyph->face_id = face_id;
1864 glyph->padding_p = 0;
1865 glyph->charpos = CHARPOS (it->position);
1866 glyph->object = it->object;
1867 if (it->bidi_p)
1869 glyph->resolved_level = it->bidi_it.resolved_level;
1870 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1871 abort ();
1872 glyph->bidi_type = it->bidi_it.type;
1874 else
1876 glyph->resolved_level = 0;
1877 glyph->bidi_type = UNKNOWN_BT;
1880 /* BIDI Note: we put the glyphs of characters left to right, even in
1881 the REVERSED_P case because we write to the terminal
1882 left-to-right. */
1883 for (i = 0; i < it->nglyphs && glyph < end; ++i)
1885 if (i > 0)
1886 glyph[0] = glyph[-1];
1887 glyph->u.ch = str[i];
1888 ++it->glyph_row->used[it->area];
1889 ++glyph;
1893 /* Produce glyphs for a glyphless character for iterator IT.
1894 IT->glyphless_method specifies which method to use for displaying
1895 the character. See the description of enum
1896 glyphless_display_method in dispextern.h for the details.
1898 FOR_NO_FONT is nonzero if and only if this is for a character that
1899 is not supproted by the coding system of the terminal. ACRONYM, if
1900 non-nil, is an acronym string for the character.
1902 The glyphs actually produced are of type CHAR_GLYPH. */
1904 static void
1905 produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym)
1907 int face_id;
1908 int len;
1909 char buf[9], *str = " ";
1911 /* Get a face ID for the glyph by utilizing a cache (the same way as
1912 done for `escape-glyph' in get_next_display_element). */
1913 if (it->f == last_glyphless_glyph_frame
1914 && it->face_id == last_glyphless_glyph_face_id)
1916 face_id = last_glyphless_glyph_merged_face_id;
1918 else
1920 /* Merge the `glyphless-char' face into the current face. */
1921 face_id = merge_faces (it->f, Qglyphless_char, 0, it->face_id);
1922 last_glyphless_glyph_frame = it->f;
1923 last_glyphless_glyph_face_id = it->face_id;
1924 last_glyphless_glyph_merged_face_id = face_id;
1927 if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE)
1929 /* As there's no way to produce a thin space, we produce a space
1930 of canonical width. */
1931 len = 1;
1933 else if (it->glyphless_method == GLYPHLESS_DISPLAY_EMPTY_BOX)
1935 len = CHAR_WIDTH (it->c);
1936 if (len == 0)
1937 len = 1;
1938 else if (len > 4)
1939 len = 4;
1940 sprintf (buf, "[%.*s]", len, str);
1941 len += 2;
1942 str = buf;
1944 else
1946 if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM)
1948 if (! STRINGP (acronym) && CHAR_TABLE_P (Vglyphless_char_display))
1949 acronym = CHAR_TABLE_REF (Vglyphless_char_display, it->c);
1950 buf[0] = '[';
1951 str = STRINGP (acronym) ? SSDATA (acronym) : "";
1952 for (len = 0; len < 6 && str[len] && ASCII_BYTE_P (str[len]); len++)
1953 buf[1 + len] = str[len];
1954 buf[1 + len] = ']';
1955 len += 2;
1957 else
1959 xassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEX_CODE);
1960 len = (it->c < 0x10000 ? sprintf (buf, "\\u%04X", it->c)
1961 : it->c <= MAX_UNICODE_CHAR ? sprintf (buf, "\\U%06X", it->c)
1962 : sprintf (buf, "\\x%06X", it->c));
1964 str = buf;
1967 it->pixel_width = len;
1968 it->nglyphs = len;
1969 if (len > 0 && it->glyph_row)
1970 append_glyphless_glyph (it, face_id, str);
1974 /* Get information about special display element WHAT in an
1975 environment described by IT. WHAT is one of IT_TRUNCATION or
1976 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1977 non-null glyph_row member. This function ensures that fields like
1978 face_id, c, len of IT are left untouched. */
1980 void
1981 produce_special_glyphs (struct it *it, enum display_element_type what)
1983 struct it temp_it;
1984 Lisp_Object gc;
1985 GLYPH glyph;
1987 temp_it = *it;
1988 temp_it.dp = NULL;
1989 temp_it.what = IT_CHARACTER;
1990 temp_it.len = 1;
1991 temp_it.object = make_number (0);
1992 memset (&temp_it.current, 0, sizeof temp_it.current);
1994 if (what == IT_CONTINUATION)
1996 /* Continuation glyph. For R2L lines, we mirror it by hand. */
1997 if (it->bidi_it.paragraph_dir == R2L)
1998 SET_GLYPH_FROM_CHAR (glyph, '/');
1999 else
2000 SET_GLYPH_FROM_CHAR (glyph, '\\');
2001 if (it->dp
2002 && (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc))
2003 && GLYPH_CODE_CHAR_VALID_P (gc))
2005 /* FIXME: Should we mirror GC for R2L lines? */
2006 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
2007 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
2010 else if (what == IT_TRUNCATION)
2012 /* Truncation glyph. */
2013 SET_GLYPH_FROM_CHAR (glyph, '$');
2014 if (it->dp
2015 && (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc))
2016 && GLYPH_CODE_CHAR_VALID_P (gc))
2018 /* FIXME: Should we mirror GC for R2L lines? */
2019 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
2020 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
2023 else
2024 abort ();
2026 temp_it.c = temp_it.char_to_display = GLYPH_CHAR (glyph);
2027 temp_it.face_id = GLYPH_FACE (glyph);
2028 temp_it.len = CHAR_BYTES (temp_it.c);
2030 produce_glyphs (&temp_it);
2031 it->pixel_width = temp_it.pixel_width;
2032 it->nglyphs = temp_it.pixel_width;
2037 /***********************************************************************
2038 Faces
2039 ***********************************************************************/
2041 /* Value is non-zero if attribute ATTR may be used. ATTR should be
2042 one of the enumerators from enum no_color_bit, or a bit set built
2043 from them. Some display attributes may not be used together with
2044 color; the termcap capability `NC' specifies which ones. */
2046 #define MAY_USE_WITH_COLORS_P(tty, ATTR) \
2047 (tty->TN_max_colors > 0 \
2048 ? (tty->TN_no_color_video & (ATTR)) == 0 \
2049 : 1)
2051 /* Turn appearances of face FACE_ID on tty frame F on.
2052 FACE_ID is a realized face ID number, in the face cache. */
2054 static void
2055 turn_on_face (struct frame *f, int face_id)
2057 struct face *face = FACE_FROM_ID (f, face_id);
2058 long fg = face->foreground;
2059 long bg = face->background;
2060 struct tty_display_info *tty = FRAME_TTY (f);
2062 /* Do this first because TS_end_standout_mode may be the same
2063 as TS_exit_attribute_mode, which turns all appearances off. */
2064 if (MAY_USE_WITH_COLORS_P (tty, NC_REVERSE))
2066 if (tty->TN_max_colors > 0)
2068 if (fg >= 0 && bg >= 0)
2070 /* If the terminal supports colors, we can set them
2071 below without using reverse video. The face's fg
2072 and bg colors are set as they should appear on
2073 the screen, i.e. they take the inverse-video'ness
2074 of the face already into account. */
2076 else if (inverse_video)
2078 if (fg == FACE_TTY_DEFAULT_FG_COLOR
2079 || bg == FACE_TTY_DEFAULT_BG_COLOR)
2080 tty_toggle_highlight (tty);
2082 else
2084 if (fg == FACE_TTY_DEFAULT_BG_COLOR
2085 || bg == FACE_TTY_DEFAULT_FG_COLOR)
2086 tty_toggle_highlight (tty);
2089 else
2091 /* If we can't display colors, use reverse video
2092 if the face specifies that. */
2093 if (inverse_video)
2095 if (fg == FACE_TTY_DEFAULT_FG_COLOR
2096 || bg == FACE_TTY_DEFAULT_BG_COLOR)
2097 tty_toggle_highlight (tty);
2099 else
2101 if (fg == FACE_TTY_DEFAULT_BG_COLOR
2102 || bg == FACE_TTY_DEFAULT_FG_COLOR)
2103 tty_toggle_highlight (tty);
2108 if (face->tty_bold_p && MAY_USE_WITH_COLORS_P (tty, NC_BOLD))
2109 OUTPUT1_IF (tty, tty->TS_enter_bold_mode);
2111 if (face->tty_dim_p && MAY_USE_WITH_COLORS_P (tty, NC_DIM))
2112 OUTPUT1_IF (tty, tty->TS_enter_dim_mode);
2114 /* Alternate charset and blinking not yet used. */
2115 if (face->tty_alt_charset_p
2116 && MAY_USE_WITH_COLORS_P (tty, NC_ALT_CHARSET))
2117 OUTPUT1_IF (tty, tty->TS_enter_alt_charset_mode);
2119 if (face->tty_blinking_p
2120 && MAY_USE_WITH_COLORS_P (tty, NC_BLINK))
2121 OUTPUT1_IF (tty, tty->TS_enter_blink_mode);
2123 if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (tty, NC_UNDERLINE))
2124 OUTPUT1_IF (tty, tty->TS_enter_underline_mode);
2126 if (tty->TN_max_colors > 0)
2128 char *ts, *p;
2130 ts = tty->standout_mode ? tty->TS_set_background : tty->TS_set_foreground;
2131 if (fg >= 0 && ts)
2133 p = tparam (ts, NULL, 0, (int) fg);
2134 OUTPUT (tty, p);
2135 xfree (p);
2138 ts = tty->standout_mode ? tty->TS_set_foreground : tty->TS_set_background;
2139 if (bg >= 0 && ts)
2141 p = tparam (ts, NULL, 0, (int) bg);
2142 OUTPUT (tty, p);
2143 xfree (p);
2149 /* Turn off appearances of face FACE_ID on tty frame F. */
2151 static void
2152 turn_off_face (struct frame *f, int face_id)
2154 struct face *face = FACE_FROM_ID (f, face_id);
2155 struct tty_display_info *tty = FRAME_TTY (f);
2157 xassert (face != NULL);
2159 if (tty->TS_exit_attribute_mode)
2161 /* Capability "me" will turn off appearance modes double-bright,
2162 half-bright, reverse-video, standout, underline. It may or
2163 may not turn off alt-char-mode. */
2164 if (face->tty_bold_p
2165 || face->tty_dim_p
2166 || face->tty_reverse_p
2167 || face->tty_alt_charset_p
2168 || face->tty_blinking_p
2169 || face->tty_underline_p)
2171 OUTPUT1_IF (tty, tty->TS_exit_attribute_mode);
2172 if (strcmp (tty->TS_exit_attribute_mode, tty->TS_end_standout_mode) == 0)
2173 tty->standout_mode = 0;
2176 if (face->tty_alt_charset_p)
2177 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
2179 else
2181 /* If we don't have "me" we can only have those appearances
2182 that have exit sequences defined. */
2183 if (face->tty_alt_charset_p)
2184 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
2186 if (face->tty_underline_p)
2187 OUTPUT_IF (tty, tty->TS_exit_underline_mode);
2190 /* Switch back to default colors. */
2191 if (tty->TN_max_colors > 0
2192 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
2193 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
2194 || (face->background != FACE_TTY_DEFAULT_COLOR
2195 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
2196 OUTPUT1_IF (tty, tty->TS_orig_pair);
2200 /* Return non-zero if the terminal on frame F supports all of the
2201 capabilities in CAPS simultaneously, with foreground and background
2202 colors FG and BG. */
2205 tty_capable_p (struct tty_display_info *tty, unsigned int caps,
2206 unsigned long fg, unsigned long bg)
2208 #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
2209 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
2210 return 0;
2212 TTY_CAPABLE_P_TRY (tty, TTY_CAP_INVERSE, tty->TS_standout_mode, NC_REVERSE);
2213 TTY_CAPABLE_P_TRY (tty, TTY_CAP_UNDERLINE, tty->TS_enter_underline_mode, NC_UNDERLINE);
2214 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BOLD, tty->TS_enter_bold_mode, NC_BOLD);
2215 TTY_CAPABLE_P_TRY (tty, TTY_CAP_DIM, tty->TS_enter_dim_mode, NC_DIM);
2216 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BLINK, tty->TS_enter_blink_mode, NC_BLINK);
2217 TTY_CAPABLE_P_TRY (tty, TTY_CAP_ALT_CHARSET, tty->TS_enter_alt_charset_mode, NC_ALT_CHARSET);
2219 /* We can do it! */
2220 return 1;
2223 /* Return non-zero if the terminal is capable to display colors. */
2225 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
2226 0, 1, 0,
2227 doc: /* Return non-nil if the tty device TERMINAL can display colors.
2229 TERMINAL can be a terminal object, a frame, or nil (meaning the
2230 selected frame's terminal). This function always returns nil if
2231 TERMINAL does not refer to a text-only terminal. */)
2232 (Lisp_Object terminal)
2234 struct terminal *t = get_tty_terminal (terminal, 0);
2235 if (!t)
2236 return Qnil;
2237 else
2238 return t->display_info.tty->TN_max_colors > 0 ? Qt : Qnil;
2241 /* Return the number of supported colors. */
2242 DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
2243 Stty_display_color_cells, 0, 1, 0,
2244 doc: /* Return the number of colors supported by the tty device TERMINAL.
2246 TERMINAL can be a terminal object, a frame, or nil (meaning the
2247 selected frame's terminal). This function always returns 0 if
2248 TERMINAL does not refer to a text-only terminal. */)
2249 (Lisp_Object terminal)
2251 struct terminal *t = get_tty_terminal (terminal, 0);
2252 if (!t)
2253 return make_number (0);
2254 else
2255 return make_number (t->display_info.tty->TN_max_colors);
2258 #ifndef DOS_NT
2260 /* Declare here rather than in the function, as in the rest of Emacs,
2261 to work around an HPUX compiler bug (?). See
2262 http://lists.gnu.org/archive/html/emacs-devel/2007-08/msg00410.html */
2263 static int default_max_colors;
2264 static int default_max_pairs;
2265 static int default_no_color_video;
2266 static char *default_orig_pair;
2267 static char *default_set_foreground;
2268 static char *default_set_background;
2270 /* Save or restore the default color-related capabilities of this
2271 terminal. */
2272 static void
2273 tty_default_color_capabilities (struct tty_display_info *tty, int save)
2276 if (save)
2278 xfree (default_orig_pair);
2279 default_orig_pair = tty->TS_orig_pair ? xstrdup (tty->TS_orig_pair) : NULL;
2281 xfree (default_set_foreground);
2282 default_set_foreground = tty->TS_set_foreground ? xstrdup (tty->TS_set_foreground)
2283 : NULL;
2285 xfree (default_set_background);
2286 default_set_background = tty->TS_set_background ? xstrdup (tty->TS_set_background)
2287 : NULL;
2289 default_max_colors = tty->TN_max_colors;
2290 default_max_pairs = tty->TN_max_pairs;
2291 default_no_color_video = tty->TN_no_color_video;
2293 else
2295 tty->TS_orig_pair = default_orig_pair;
2296 tty->TS_set_foreground = default_set_foreground;
2297 tty->TS_set_background = default_set_background;
2298 tty->TN_max_colors = default_max_colors;
2299 tty->TN_max_pairs = default_max_pairs;
2300 tty->TN_no_color_video = default_no_color_video;
2304 /* Setup one of the standard tty color schemes according to MODE.
2305 MODE's value is generally the number of colors which we want to
2306 support; zero means set up for the default capabilities, the ones
2307 we saw at init_tty time; -1 means turn off color support. */
2308 static void
2309 tty_setup_colors (struct tty_display_info *tty, int mode)
2311 /* Canonicalize all negative values of MODE. */
2312 if (mode < -1)
2313 mode = -1;
2315 switch (mode)
2317 case -1: /* no colors at all */
2318 tty->TN_max_colors = 0;
2319 tty->TN_max_pairs = 0;
2320 tty->TN_no_color_video = 0;
2321 tty->TS_set_foreground = tty->TS_set_background = tty->TS_orig_pair = NULL;
2322 break;
2323 case 0: /* default colors, if any */
2324 default:
2325 tty_default_color_capabilities (tty, 0);
2326 break;
2327 case 8: /* 8 standard ANSI colors */
2328 tty->TS_orig_pair = "\033[0m";
2329 #ifdef TERMINFO
2330 tty->TS_set_foreground = "\033[3%p1%dm";
2331 tty->TS_set_background = "\033[4%p1%dm";
2332 #else
2333 tty->TS_set_foreground = "\033[3%dm";
2334 tty->TS_set_background = "\033[4%dm";
2335 #endif
2336 tty->TN_max_colors = 8;
2337 tty->TN_max_pairs = 64;
2338 tty->TN_no_color_video = 0;
2339 break;
2343 void
2344 set_tty_color_mode (struct tty_display_info *tty, struct frame *f)
2346 Lisp_Object tem, val;
2347 Lisp_Object color_mode;
2348 int mode;
2349 Lisp_Object tty_color_mode_alist
2350 = Fintern_soft (build_string ("tty-color-mode-alist"), Qnil);
2352 tem = assq_no_quit (Qtty_color_mode, f->param_alist);
2353 val = CONSP (tem) ? XCDR (tem) : Qnil;
2355 if (INTEGERP (val))
2356 color_mode = val;
2357 else if (SYMBOLP (tty_color_mode_alist))
2359 tem = Fassq (val, Fsymbol_value (tty_color_mode_alist));
2360 color_mode = CONSP (tem) ? XCDR (tem) : Qnil;
2362 else
2363 color_mode = Qnil;
2365 mode = INTEGERP (color_mode) ? XINT (color_mode) : 0;
2367 if (mode != tty->previous_color_mode)
2369 Lisp_Object funsym = intern ("tty-set-up-initial-frame-faces");
2370 tty->previous_color_mode = mode;
2371 tty_setup_colors (tty , mode);
2372 /* This recomputes all the faces given the new color definitions. */
2373 safe_call (1, &funsym);
2377 #endif /* !DOS_NT */
2381 /* Return the tty display object specified by TERMINAL. */
2383 struct terminal *
2384 get_tty_terminal (Lisp_Object terminal, int throw)
2386 struct terminal *t = get_terminal (terminal, throw);
2388 if (t && t->type != output_termcap && t->type != output_msdos_raw)
2390 if (throw)
2391 error ("Device %d is not a termcap terminal device", t->id);
2392 else
2393 return NULL;
2396 return t;
2399 /* Return an active termcap device that uses the tty device with the
2400 given name.
2402 This function ignores suspended devices.
2404 Returns NULL if the named terminal device is not opened. */
2406 struct terminal *
2407 get_named_tty (const char *name)
2409 struct terminal *t;
2411 if (!name)
2412 abort ();
2414 for (t = terminal_list; t; t = t->next_terminal)
2416 if ((t->type == output_termcap || t->type == output_msdos_raw)
2417 && !strcmp (t->display_info.tty->name, name)
2418 && TERMINAL_ACTIVE_P (t))
2419 return t;
2422 return 0;
2426 DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0,
2427 doc: /* Return the type of the tty device that TERMINAL uses.
2428 Returns nil if TERMINAL is not on a tty device.
2430 TERMINAL can be a terminal object, a frame, or nil (meaning the
2431 selected frame's terminal). */)
2432 (Lisp_Object terminal)
2434 struct terminal *t = get_terminal (terminal, 1);
2436 if (t->type != output_termcap && t->type != output_msdos_raw)
2437 return Qnil;
2439 if (t->display_info.tty->type)
2440 return build_string (t->display_info.tty->type);
2441 else
2442 return Qnil;
2445 DEFUN ("controlling-tty-p", Fcontrolling_tty_p, Scontrolling_tty_p, 0, 1, 0,
2446 doc: /* Return non-nil if TERMINAL is the controlling tty of the Emacs process.
2448 TERMINAL can be a terminal object, a frame, or nil (meaning the
2449 selected frame's terminal). This function always returns nil if
2450 TERMINAL is not on a tty device. */)
2451 (Lisp_Object terminal)
2453 struct terminal *t = get_terminal (terminal, 1);
2455 if ((t->type != output_termcap && t->type != output_msdos_raw)
2456 || strcmp (t->display_info.tty->name, DEV_TTY) != 0)
2457 return Qnil;
2458 else
2459 return Qt;
2462 DEFUN ("tty-no-underline", Ftty_no_underline, Stty_no_underline, 0, 1, 0,
2463 doc: /* Declare that the tty used by TERMINAL does not handle underlining.
2464 This is used to override the terminfo data, for certain terminals that
2465 do not really do underlining, but say that they do. This function has
2466 no effect if used on a non-tty terminal.
2468 TERMINAL can be a terminal object, a frame or nil (meaning the
2469 selected frame's terminal). This function always returns nil if
2470 TERMINAL does not refer to a text-only terminal. */)
2471 (Lisp_Object terminal)
2473 struct terminal *t = get_terminal (terminal, 1);
2475 if (t->type == output_termcap)
2476 t->display_info.tty->TS_enter_underline_mode = 0;
2477 return Qnil;
2482 DEFUN ("suspend-tty", Fsuspend_tty, Ssuspend_tty, 0, 1, 0,
2483 doc: /* Suspend the terminal device TTY.
2485 The device is restored to its default state, and Emacs ceases all
2486 access to the tty device. Frames that use the device are not deleted,
2487 but input is not read from them and if they change, their display is
2488 not updated.
2490 TTY may be a terminal object, a frame, or nil for the terminal device
2491 of the currently selected frame.
2493 This function runs `suspend-tty-functions' after suspending the
2494 device. The functions are run with one arg, the id of the suspended
2495 terminal device.
2497 `suspend-tty' does nothing if it is called on a device that is already
2498 suspended.
2500 A suspended tty may be resumed by calling `resume-tty' on it. */)
2501 (Lisp_Object tty)
2503 struct terminal *t = get_tty_terminal (tty, 1);
2504 FILE *f;
2506 if (!t)
2507 error ("Unknown tty device");
2509 f = t->display_info.tty->input;
2511 if (f)
2513 /* First run `suspend-tty-functions' and then clean up the tty
2514 state because `suspend-tty-functions' might need to change
2515 the tty state. */
2516 if (!NILP (Vrun_hooks))
2518 Lisp_Object args[2];
2519 args[0] = intern ("suspend-tty-functions");
2520 XSETTERMINAL (args[1], t);
2521 Frun_hook_with_args (2, args);
2524 reset_sys_modes (t->display_info.tty);
2525 delete_keyboard_wait_descriptor (fileno (f));
2527 #ifndef MSDOS
2528 fclose (f);
2529 if (f != t->display_info.tty->output)
2530 fclose (t->display_info.tty->output);
2531 #endif
2533 t->display_info.tty->input = 0;
2534 t->display_info.tty->output = 0;
2536 if (FRAMEP (t->display_info.tty->top_frame))
2537 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0);
2541 /* Clear display hooks to prevent further output. */
2542 clear_tty_hooks (t);
2544 return Qnil;
2547 DEFUN ("resume-tty", Fresume_tty, Sresume_tty, 0, 1, 0,
2548 doc: /* Resume the previously suspended terminal device TTY.
2549 The terminal is opened and reinitialized. Frames that are on the
2550 suspended terminal are revived.
2552 It is an error to resume a terminal while another terminal is active
2553 on the same device.
2555 This function runs `resume-tty-functions' after resuming the terminal.
2556 The functions are run with one arg, the id of the resumed terminal
2557 device.
2559 `resume-tty' does nothing if it is called on a device that is not
2560 suspended.
2562 TTY may be a terminal object, a frame, or nil (meaning the selected
2563 frame's terminal). */)
2564 (Lisp_Object tty)
2566 struct terminal *t = get_tty_terminal (tty, 1);
2567 int fd;
2569 if (!t)
2570 error ("Unknown tty device");
2572 if (!t->display_info.tty->input)
2574 if (get_named_tty (t->display_info.tty->name))
2575 error ("Cannot resume display while another display is active on the same device");
2577 #ifdef MSDOS
2578 t->display_info.tty->output = stdout;
2579 t->display_info.tty->input = stdin;
2580 #else /* !MSDOS */
2581 fd = emacs_open (t->display_info.tty->name, O_RDWR | O_NOCTTY, 0);
2583 if (fd == -1)
2584 error ("Can not reopen tty device %s: %s", t->display_info.tty->name, strerror (errno));
2586 if (strcmp (t->display_info.tty->name, DEV_TTY))
2587 dissociate_if_controlling_tty (fd);
2589 t->display_info.tty->output = fdopen (fd, "w+");
2590 t->display_info.tty->input = t->display_info.tty->output;
2591 #endif
2593 add_keyboard_wait_descriptor (fd);
2595 if (FRAMEP (t->display_info.tty->top_frame))
2597 struct frame *f = XFRAME (t->display_info.tty->top_frame);
2598 int width, height;
2599 int old_height = FRAME_COLS (f);
2600 int old_width = FRAME_LINES (f);
2602 /* Check if terminal/window size has changed while the frame
2603 was suspended. */
2604 get_tty_size (fileno (t->display_info.tty->input), &width, &height);
2605 if (width != old_width || height != old_height)
2606 change_frame_size (f, height, width, 0, 0, 0);
2607 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
2610 init_sys_modes (t->display_info.tty);
2612 /* Run `resume-tty-functions'. */
2613 if (!NILP (Vrun_hooks))
2615 Lisp_Object args[2];
2616 args[0] = intern ("resume-tty-functions");
2617 XSETTERMINAL (args[1], t);
2618 Frun_hook_with_args (2, args);
2622 set_tty_hooks (t);
2624 return Qnil;
2628 /***********************************************************************
2629 Mouse
2630 ***********************************************************************/
2632 #ifdef HAVE_GPM
2633 void
2634 term_mouse_moveto (int x, int y)
2636 /* TODO: how to set mouse position?
2637 const char *name;
2638 int fd;
2639 name = (const char *) ttyname (0);
2640 fd = open (name, O_WRONLY);
2641 SOME_FUNCTION (x, y, fd);
2642 close (fd);
2643 last_mouse_x = x;
2644 last_mouse_y = y; */
2647 /* Implementation of draw_row_with_mouse_face for TTY/GPM. */
2648 void
2649 tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *row,
2650 int start_hpos, int end_hpos,
2651 enum draw_glyphs_face draw)
2653 int nglyphs = end_hpos - start_hpos;
2654 struct frame *f = XFRAME (WINDOW_FRAME (w));
2655 struct tty_display_info *tty = FRAME_TTY (f);
2656 int face_id = tty->mouse_highlight.mouse_face_face_id;
2657 int save_x, save_y, pos_x, pos_y;
2659 if (end_hpos >= row->used[TEXT_AREA])
2660 nglyphs = row->used[TEXT_AREA] - start_hpos;
2662 pos_y = row->y + WINDOW_TOP_EDGE_Y (w);
2663 pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos + WINDOW_LEFT_EDGE_X (w);
2665 /* Save current cursor co-ordinates. */
2666 save_y = curY (tty);
2667 save_x = curX (tty);
2668 cursor_to (f, pos_y, pos_x);
2670 if (draw == DRAW_MOUSE_FACE)
2671 tty_write_glyphs_with_face (f, row->glyphs[TEXT_AREA] + start_hpos,
2672 nglyphs, face_id);
2673 else if (draw == DRAW_NORMAL_TEXT)
2674 write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
2676 cursor_to (f, save_y, save_x);
2679 static int
2680 term_mouse_movement (FRAME_PTR frame, Gpm_Event *event)
2682 /* Has the mouse moved off the glyph it was on at the last sighting? */
2683 if (event->x != last_mouse_x || event->y != last_mouse_y)
2685 frame->mouse_moved = 1;
2686 note_mouse_highlight (frame, event->x, event->y);
2687 /* Remember which glyph we're now on. */
2688 last_mouse_x = event->x;
2689 last_mouse_y = event->y;
2690 return 1;
2692 return 0;
2695 /* Return the current position of the mouse.
2697 Set *f to the frame the mouse is in, or zero if the mouse is in no
2698 Emacs frame. If it is set to zero, all the other arguments are
2699 garbage.
2701 Set *bar_window to Qnil, and *x and *y to the column and
2702 row of the character cell the mouse is over.
2704 Set *time to the time the mouse was at the returned position.
2706 This clears mouse_moved until the next motion
2707 event arrives. */
2708 static void
2709 term_mouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
2710 enum scroll_bar_part *part, Lisp_Object *x,
2711 Lisp_Object *y, unsigned long *time)
2713 struct timeval now;
2715 *fp = SELECTED_FRAME ();
2716 (*fp)->mouse_moved = 0;
2718 *bar_window = Qnil;
2719 *part = 0;
2721 XSETINT (*x, last_mouse_x);
2722 XSETINT (*y, last_mouse_y);
2723 gettimeofday(&now, 0);
2724 *time = (now.tv_sec * 1000) + (now.tv_usec / 1000);
2727 /* Prepare a mouse-event in *RESULT for placement in the input queue.
2729 If the event is a button press, then note that we have grabbed
2730 the mouse. */
2732 static Lisp_Object
2733 term_mouse_click (struct input_event *result, Gpm_Event *event,
2734 struct frame *f)
2736 struct timeval now;
2737 int i, j;
2739 result->kind = GPM_CLICK_EVENT;
2740 for (i = 0, j = GPM_B_LEFT; i < 3; i++, j >>= 1 )
2742 if (event->buttons & j) {
2743 result->code = i; /* button number */
2744 break;
2747 gettimeofday(&now, 0);
2748 result->timestamp = (now.tv_sec * 1000) + (now.tv_usec / 1000);
2750 if (event->type & GPM_UP)
2751 result->modifiers = up_modifier;
2752 else if (event->type & GPM_DOWN)
2753 result->modifiers = down_modifier;
2754 else
2755 result->modifiers = 0;
2757 if (event->type & GPM_SINGLE)
2758 result->modifiers |= click_modifier;
2760 if (event->type & GPM_DOUBLE)
2761 result->modifiers |= double_modifier;
2763 if (event->type & GPM_TRIPLE)
2764 result->modifiers |= triple_modifier;
2766 if (event->type & GPM_DRAG)
2767 result->modifiers |= drag_modifier;
2769 if (!(event->type & (GPM_MOVE | GPM_DRAG))) {
2771 /* 1 << KG_SHIFT */
2772 if (event->modifiers & (1 << 0))
2773 result->modifiers |= shift_modifier;
2775 /* 1 << KG_CTRL */
2776 if (event->modifiers & (1 << 2))
2777 result->modifiers |= ctrl_modifier;
2779 /* 1 << KG_ALT || KG_ALTGR */
2780 if (event->modifiers & (1 << 3)
2781 || event->modifiers & (1 << 1))
2782 result->modifiers |= meta_modifier;
2785 XSETINT (result->x, event->x);
2786 XSETINT (result->y, event->y);
2787 XSETFRAME (result->frame_or_window, f);
2788 result->arg = Qnil;
2789 return Qnil;
2793 handle_one_term_event (struct tty_display_info *tty, Gpm_Event *event, struct input_event* hold_quit)
2795 struct frame *f = XFRAME (tty->top_frame);
2796 struct input_event ie;
2797 int do_help = 0;
2798 int count = 0;
2800 EVENT_INIT (ie);
2801 ie.kind = NO_EVENT;
2802 ie.arg = Qnil;
2804 if (event->type & (GPM_MOVE | GPM_DRAG)) {
2805 previous_help_echo_string = help_echo_string;
2806 help_echo_string = Qnil;
2808 Gpm_DrawPointer (event->x, event->y, fileno (tty->output));
2810 if (!term_mouse_movement (f, event))
2811 help_echo_string = previous_help_echo_string;
2813 /* If the contents of the global variable help_echo_string
2814 has changed, generate a HELP_EVENT. */
2815 if (!NILP (help_echo_string)
2816 || !NILP (previous_help_echo_string))
2817 do_help = 1;
2819 goto done;
2821 else {
2822 f->mouse_moved = 0;
2823 term_mouse_click (&ie, event, f);
2826 done:
2827 if (ie.kind != NO_EVENT)
2829 kbd_buffer_store_event_hold (&ie, hold_quit);
2830 count++;
2833 if (do_help
2834 && !(hold_quit && hold_quit->kind != NO_EVENT))
2836 Lisp_Object frame;
2838 if (f)
2839 XSETFRAME (frame, f);
2840 else
2841 frame = Qnil;
2843 gen_help_event (help_echo_string, frame, help_echo_window,
2844 help_echo_object, help_echo_pos);
2845 count++;
2848 return count;
2851 DEFUN ("gpm-mouse-start", Fgpm_mouse_start, Sgpm_mouse_start,
2852 0, 0, 0,
2853 doc: /* Open a connection to Gpm.
2854 Gpm-mouse can only be activated for one tty at a time. */)
2855 (void)
2857 struct frame *f = SELECTED_FRAME ();
2858 struct tty_display_info *tty
2859 = ((f)->output_method == output_termcap
2860 ? (f)->terminal->display_info.tty : NULL);
2861 Gpm_Connect connection;
2863 if (!tty)
2864 error ("Gpm-mouse only works in the GNU/Linux console");
2865 if (gpm_tty == tty)
2866 return Qnil; /* Already activated, nothing to do. */
2867 if (gpm_tty)
2868 error ("Gpm-mouse can only be activated for one tty at a time");
2870 connection.eventMask = ~0;
2871 connection.defaultMask = ~GPM_HARD;
2872 connection.maxMod = ~0;
2873 connection.minMod = 0;
2874 gpm_zerobased = 1;
2876 if (Gpm_Open (&connection, 0) < 0)
2877 error ("Gpm-mouse failed to connect to the gpm daemon");
2878 else
2880 gpm_tty = tty;
2881 /* `init_sys_modes' arranges for mouse movements sent through gpm_fd
2882 to generate SIGIOs. Apparently we need to call reset_sys_modes
2883 before calling init_sys_modes. */
2884 reset_sys_modes (tty);
2885 init_sys_modes (tty);
2886 add_gpm_wait_descriptor (gpm_fd);
2887 return Qnil;
2891 void
2892 close_gpm (int fd)
2894 if (fd >= 0)
2895 delete_gpm_wait_descriptor (fd);
2896 while (Gpm_Close()); /* close all the stack */
2897 gpm_tty = NULL;
2900 DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop, Sgpm_mouse_stop,
2901 0, 0, 0,
2902 doc: /* Close a connection to Gpm. */)
2903 (void)
2905 struct frame *f = SELECTED_FRAME ();
2906 struct tty_display_info *tty
2907 = ((f)->output_method == output_termcap
2908 ? (f)->terminal->display_info.tty : NULL);
2910 if (!tty || gpm_tty != tty)
2911 return Qnil; /* Not activated on this terminal, nothing to do. */
2913 close_gpm (gpm_fd);
2914 return Qnil;
2916 #endif /* HAVE_GPM */
2919 #ifndef MSDOS
2920 /***********************************************************************
2921 Initialization
2922 ***********************************************************************/
2924 /* Initialize the tty-dependent part of frame F. The frame must
2925 already have its device initialized. */
2927 void
2928 create_tty_output (struct frame *f)
2930 struct tty_output *t;
2932 if (! FRAME_TERMCAP_P (f))
2933 abort ();
2935 t = xmalloc (sizeof (struct tty_output));
2936 memset (t, 0, sizeof (struct tty_output));
2938 t->display_info = FRAME_TERMINAL (f)->display_info.tty;
2940 f->output_data.tty = t;
2943 /* Delete frame F's face cache, and its tty-dependent part. */
2945 static void
2946 tty_free_frame_resources (struct frame *f)
2948 if (! FRAME_TERMCAP_P (f))
2949 abort ();
2951 if (FRAME_FACE_CACHE (f))
2952 free_frame_faces (f);
2954 xfree (f->output_data.tty);
2957 #else /* MSDOS */
2959 /* Delete frame F's face cache. */
2961 static void
2962 tty_free_frame_resources (struct frame *f)
2964 if (! FRAME_TERMCAP_P (f) && ! FRAME_MSDOS_P (f))
2965 abort ();
2967 if (FRAME_FACE_CACHE (f))
2968 free_frame_faces (f);
2970 #endif /* MSDOS */
2972 /* Reset the hooks in TERMINAL. */
2974 static void
2975 clear_tty_hooks (struct terminal *terminal)
2977 terminal->rif = 0;
2978 terminal->cursor_to_hook = 0;
2979 terminal->raw_cursor_to_hook = 0;
2980 terminal->clear_to_end_hook = 0;
2981 terminal->clear_frame_hook = 0;
2982 terminal->clear_end_of_line_hook = 0;
2983 terminal->ins_del_lines_hook = 0;
2984 terminal->insert_glyphs_hook = 0;
2985 terminal->write_glyphs_hook = 0;
2986 terminal->delete_glyphs_hook = 0;
2987 terminal->ring_bell_hook = 0;
2988 terminal->reset_terminal_modes_hook = 0;
2989 terminal->set_terminal_modes_hook = 0;
2990 terminal->update_begin_hook = 0;
2991 terminal->update_end_hook = 0;
2992 terminal->set_terminal_window_hook = 0;
2993 terminal->mouse_position_hook = 0;
2994 terminal->frame_rehighlight_hook = 0;
2995 terminal->frame_raise_lower_hook = 0;
2996 terminal->fullscreen_hook = 0;
2997 terminal->set_vertical_scroll_bar_hook = 0;
2998 terminal->condemn_scroll_bars_hook = 0;
2999 terminal->redeem_scroll_bar_hook = 0;
3000 terminal->judge_scroll_bars_hook = 0;
3001 terminal->read_socket_hook = 0;
3002 terminal->frame_up_to_date_hook = 0;
3004 /* Leave these two set, or suspended frames are not deleted
3005 correctly. */
3006 terminal->delete_frame_hook = &tty_free_frame_resources;
3007 terminal->delete_terminal_hook = &delete_tty;
3010 /* Initialize hooks in TERMINAL with the values needed for a tty. */
3012 static void
3013 set_tty_hooks (struct terminal *terminal)
3015 terminal->rif = 0; /* ttys don't support window-based redisplay. */
3017 terminal->cursor_to_hook = &tty_cursor_to;
3018 terminal->raw_cursor_to_hook = &tty_raw_cursor_to;
3020 terminal->clear_to_end_hook = &tty_clear_to_end;
3021 terminal->clear_frame_hook = &tty_clear_frame;
3022 terminal->clear_end_of_line_hook = &tty_clear_end_of_line;
3024 terminal->ins_del_lines_hook = &tty_ins_del_lines;
3026 terminal->insert_glyphs_hook = &tty_insert_glyphs;
3027 terminal->write_glyphs_hook = &tty_write_glyphs;
3028 terminal->delete_glyphs_hook = &tty_delete_glyphs;
3030 terminal->ring_bell_hook = &tty_ring_bell;
3032 terminal->reset_terminal_modes_hook = &tty_reset_terminal_modes;
3033 terminal->set_terminal_modes_hook = &tty_set_terminal_modes;
3034 terminal->update_begin_hook = 0; /* Not needed. */
3035 terminal->update_end_hook = &tty_update_end;
3036 terminal->set_terminal_window_hook = &tty_set_terminal_window;
3038 terminal->mouse_position_hook = 0; /* Not needed. */
3039 terminal->frame_rehighlight_hook = 0; /* Not needed. */
3040 terminal->frame_raise_lower_hook = 0; /* Not needed. */
3042 terminal->set_vertical_scroll_bar_hook = 0; /* Not needed. */
3043 terminal->condemn_scroll_bars_hook = 0; /* Not needed. */
3044 terminal->redeem_scroll_bar_hook = 0; /* Not needed. */
3045 terminal->judge_scroll_bars_hook = 0; /* Not needed. */
3047 terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */
3048 terminal->frame_up_to_date_hook = 0; /* Not needed. */
3050 terminal->delete_frame_hook = &tty_free_frame_resources;
3051 terminal->delete_terminal_hook = &delete_tty;
3054 /* Drop the controlling terminal if fd is the same device. */
3055 static void
3056 dissociate_if_controlling_tty (int fd)
3058 #ifndef DOS_NT
3059 int pgid = tcgetpgrp (fd); /* If tcgetpgrp succeeds, fd is the ctty. */
3060 if (pgid != -1)
3062 #if defined (USG5)
3063 setpgrp ();
3064 no_controlling_tty = 1;
3065 #elif defined (CYGWIN)
3066 setsid ();
3067 no_controlling_tty = 1;
3068 #else
3069 #ifdef TIOCNOTTY /* Try BSD ioctls. */
3070 sigblock (sigmask (SIGTTOU));
3071 fd = emacs_open (DEV_TTY, O_RDWR, 0);
3072 if (fd != -1 && ioctl (fd, TIOCNOTTY, 0) != -1)
3074 no_controlling_tty = 1;
3076 if (fd != -1)
3077 emacs_close (fd);
3078 sigunblock (sigmask (SIGTTOU));
3079 #else
3080 /* Unknown system. */
3081 croak ();
3082 #endif /* ! TIOCNOTTY */
3083 #endif /* ! USG */
3085 #endif /* !DOS_NT */
3088 /* Create a termcap display on the tty device with the given name and
3089 type.
3091 If NAME is NULL, then use the controlling tty, i.e., "/dev/tty".
3092 Otherwise NAME should be a path to the tty device file,
3093 e.g. "/dev/pts/7".
3095 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
3097 If MUST_SUCCEED is true, then all errors are fatal. */
3099 struct terminal *
3100 init_tty (const char *name, const char *terminal_type, int must_succeed)
3102 char *area = NULL;
3103 char **address = &area;
3104 int buffer_size = 4096;
3105 register char *p = NULL;
3106 int status;
3107 struct tty_display_info *tty = NULL;
3108 struct terminal *terminal = NULL;
3109 int ctty = 0; /* 1 if asked to open controlling tty. */
3111 if (!terminal_type)
3112 maybe_fatal (must_succeed, 0,
3113 "Unknown terminal type",
3114 "Unknown terminal type");
3116 if (name == NULL)
3117 name = DEV_TTY;
3118 if (!strcmp (name, DEV_TTY))
3119 ctty = 1;
3121 /* If we already have a terminal on the given device, use that. If
3122 all such terminals are suspended, create a new one instead. */
3123 /* XXX Perhaps this should be made explicit by having init_tty
3124 always create a new terminal and separating terminal and frame
3125 creation on Lisp level. */
3126 terminal = get_named_tty (name);
3127 if (terminal)
3128 return terminal;
3130 terminal = create_terminal ();
3131 #ifdef MSDOS
3132 if (been_here > 0)
3133 maybe_fatal (1, 0, "Attempt to create another terminal %s", "",
3134 name, "");
3135 been_here = 1;
3136 tty = &the_only_display_info;
3137 #else
3138 tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info));
3139 #endif
3140 memset (tty, 0, sizeof (struct tty_display_info));
3141 tty->next = tty_list;
3142 tty_list = tty;
3144 terminal->type = output_termcap;
3145 terminal->display_info.tty = tty;
3146 tty->terminal = terminal;
3148 tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
3149 Wcm_clear (tty);
3151 encode_terminal_src_size = 0;
3152 encode_terminal_dst_size = 0;
3154 #ifdef HAVE_GPM
3155 terminal->mouse_position_hook = term_mouse_position;
3156 tty->mouse_highlight.mouse_face_window = Qnil;
3157 #endif
3160 #ifndef DOS_NT
3161 set_tty_hooks (terminal);
3164 int fd;
3165 FILE *file;
3167 #ifdef O_IGNORE_CTTY
3168 if (!ctty)
3169 /* Open the terminal device. Don't recognize it as our
3170 controlling terminal, and don't make it the controlling tty
3171 if we don't have one at the moment. */
3172 fd = emacs_open (name, O_RDWR | O_IGNORE_CTTY | O_NOCTTY, 0);
3173 else
3174 #else
3175 /* Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
3176 defined on Hurd. On other systems, we need to explicitly
3177 dissociate ourselves from the controlling tty when we want to
3178 open a frame on the same terminal. */
3179 fd = emacs_open (name, O_RDWR | O_NOCTTY, 0);
3180 #endif /* O_IGNORE_CTTY */
3182 tty->name = xstrdup (name);
3183 terminal->name = xstrdup (name);
3185 if (fd < 0)
3186 maybe_fatal (must_succeed, terminal,
3187 "Could not open file: %s",
3188 "Could not open file: %s",
3189 name);
3190 if (!isatty (fd))
3192 close (fd);
3193 maybe_fatal (must_succeed, terminal,
3194 "Not a tty device: %s",
3195 "Not a tty device: %s",
3196 name);
3199 #ifndef O_IGNORE_CTTY
3200 if (!ctty)
3201 dissociate_if_controlling_tty (fd);
3202 #endif
3204 file = fdopen (fd, "w+");
3205 tty->input = file;
3206 tty->output = file;
3209 tty->type = xstrdup (terminal_type);
3211 add_keyboard_wait_descriptor (fileno (tty->input));
3213 Wcm_clear (tty);
3215 tty->termcap_term_buffer = (char *) xmalloc (buffer_size);
3217 /* On some systems, tgetent tries to access the controlling
3218 terminal. */
3219 sigblock (sigmask (SIGTTOU));
3220 status = tgetent (tty->termcap_term_buffer, terminal_type);
3221 sigunblock (sigmask (SIGTTOU));
3223 if (status < 0)
3225 #ifdef TERMINFO
3226 maybe_fatal (must_succeed, terminal,
3227 "Cannot open terminfo database file",
3228 "Cannot open terminfo database file");
3229 #else
3230 maybe_fatal (must_succeed, terminal,
3231 "Cannot open termcap database file",
3232 "Cannot open termcap database file");
3233 #endif
3235 if (status == 0)
3237 maybe_fatal (must_succeed, terminal,
3238 "Terminal type %s is not defined",
3239 "Terminal type %s is not defined.\n\
3240 If that is not the actual type of terminal you have,\n\
3241 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3242 `setenv TERM ...') to specify the correct type. It may be necessary\n"
3243 #ifdef TERMINFO
3244 "to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3245 #else
3246 "to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3247 #endif
3248 terminal_type);
3251 #ifndef TERMINFO
3252 if (strlen (tty->termcap_term_buffer) >= buffer_size)
3253 abort ();
3254 buffer_size = strlen (tty->termcap_term_buffer);
3255 #endif
3256 tty->termcap_strings_buffer = area = (char *) xmalloc (buffer_size);
3257 tty->TS_ins_line = tgetstr ("al", address);
3258 tty->TS_ins_multi_lines = tgetstr ("AL", address);
3259 tty->TS_bell = tgetstr ("bl", address);
3260 BackTab (tty) = tgetstr ("bt", address);
3261 tty->TS_clr_to_bottom = tgetstr ("cd", address);
3262 tty->TS_clr_line = tgetstr ("ce", address);
3263 tty->TS_clr_frame = tgetstr ("cl", address);
3264 ColPosition (tty) = NULL; /* tgetstr ("ch", address); */
3265 AbsPosition (tty) = tgetstr ("cm", address);
3266 CR (tty) = tgetstr ("cr", address);
3267 tty->TS_set_scroll_region = tgetstr ("cs", address);
3268 tty->TS_set_scroll_region_1 = tgetstr ("cS", address);
3269 RowPosition (tty) = tgetstr ("cv", address);
3270 tty->TS_del_char = tgetstr ("dc", address);
3271 tty->TS_del_multi_chars = tgetstr ("DC", address);
3272 tty->TS_del_line = tgetstr ("dl", address);
3273 tty->TS_del_multi_lines = tgetstr ("DL", address);
3274 tty->TS_delete_mode = tgetstr ("dm", address);
3275 tty->TS_end_delete_mode = tgetstr ("ed", address);
3276 tty->TS_end_insert_mode = tgetstr ("ei", address);
3277 Home (tty) = tgetstr ("ho", address);
3278 tty->TS_ins_char = tgetstr ("ic", address);
3279 tty->TS_ins_multi_chars = tgetstr ("IC", address);
3280 tty->TS_insert_mode = tgetstr ("im", address);
3281 tty->TS_pad_inserted_char = tgetstr ("ip", address);
3282 tty->TS_end_keypad_mode = tgetstr ("ke", address);
3283 tty->TS_keypad_mode = tgetstr ("ks", address);
3284 LastLine (tty) = tgetstr ("ll", address);
3285 Right (tty) = tgetstr ("nd", address);
3286 Down (tty) = tgetstr ("do", address);
3287 if (!Down (tty))
3288 Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do" */
3289 if (tgetflag ("bs"))
3290 Left (tty) = "\b"; /* can't possibly be longer! */
3291 else /* (Actually, "bs" is obsolete...) */
3292 Left (tty) = tgetstr ("le", address);
3293 if (!Left (tty))
3294 Left (tty) = tgetstr ("bc", address); /* Obsolete name for "le" */
3295 tty->TS_pad_char = tgetstr ("pc", address);
3296 tty->TS_repeat = tgetstr ("rp", address);
3297 tty->TS_end_standout_mode = tgetstr ("se", address);
3298 tty->TS_fwd_scroll = tgetstr ("sf", address);
3299 tty->TS_standout_mode = tgetstr ("so", address);
3300 tty->TS_rev_scroll = tgetstr ("sr", address);
3301 tty->Wcm->cm_tab = tgetstr ("ta", address);
3302 tty->TS_end_termcap_modes = tgetstr ("te", address);
3303 tty->TS_termcap_modes = tgetstr ("ti", address);
3304 Up (tty) = tgetstr ("up", address);
3305 tty->TS_visible_bell = tgetstr ("vb", address);
3306 tty->TS_cursor_normal = tgetstr ("ve", address);
3307 tty->TS_cursor_visible = tgetstr ("vs", address);
3308 tty->TS_cursor_invisible = tgetstr ("vi", address);
3309 tty->TS_set_window = tgetstr ("wi", address);
3311 tty->TS_enter_underline_mode = tgetstr ("us", address);
3312 tty->TS_exit_underline_mode = tgetstr ("ue", address);
3313 tty->TS_enter_bold_mode = tgetstr ("md", address);
3314 tty->TS_enter_dim_mode = tgetstr ("mh", address);
3315 tty->TS_enter_blink_mode = tgetstr ("mb", address);
3316 tty->TS_enter_reverse_mode = tgetstr ("mr", address);
3317 tty->TS_enter_alt_charset_mode = tgetstr ("as", address);
3318 tty->TS_exit_alt_charset_mode = tgetstr ("ae", address);
3319 tty->TS_exit_attribute_mode = tgetstr ("me", address);
3321 MultiUp (tty) = tgetstr ("UP", address);
3322 MultiDown (tty) = tgetstr ("DO", address);
3323 MultiLeft (tty) = tgetstr ("LE", address);
3324 MultiRight (tty) = tgetstr ("RI", address);
3326 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
3327 color because we can't switch back to the default foreground and
3328 background. */
3329 tty->TS_orig_pair = tgetstr ("op", address);
3330 if (tty->TS_orig_pair)
3332 tty->TS_set_foreground = tgetstr ("AF", address);
3333 tty->TS_set_background = tgetstr ("AB", address);
3334 if (!tty->TS_set_foreground)
3336 /* SVr4. */
3337 tty->TS_set_foreground = tgetstr ("Sf", address);
3338 tty->TS_set_background = tgetstr ("Sb", address);
3341 tty->TN_max_colors = tgetnum ("Co");
3342 tty->TN_max_pairs = tgetnum ("pa");
3344 tty->TN_no_color_video = tgetnum ("NC");
3345 if (tty->TN_no_color_video == -1)
3346 tty->TN_no_color_video = 0;
3349 tty_default_color_capabilities (tty, 1);
3351 MagicWrap (tty) = tgetflag ("xn");
3352 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
3353 the former flag imply the latter. */
3354 AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
3355 terminal->memory_below_frame = tgetflag ("db");
3356 tty->TF_hazeltine = tgetflag ("hz");
3357 terminal->must_write_spaces = tgetflag ("in");
3358 tty->meta_key = tgetflag ("km") || tgetflag ("MT");
3359 tty->TF_insmode_motion = tgetflag ("mi");
3360 tty->TF_standout_motion = tgetflag ("ms");
3361 tty->TF_underscore = tgetflag ("ul");
3362 tty->TF_teleray = tgetflag ("xt");
3364 #else /* DOS_NT */
3365 #ifdef WINDOWSNT
3367 struct frame *f = XFRAME (selected_frame);
3369 initialize_w32_display (terminal);
3371 FrameRows (tty) = FRAME_LINES (f);
3372 FrameCols (tty) = FRAME_COLS (f);
3373 tty->specified_window = FRAME_LINES (f);
3375 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
3376 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
3377 terminal->char_ins_del_ok = 1;
3378 baud_rate = 19200;
3380 #else /* MSDOS */
3382 int height, width;
3383 if (strcmp (terminal_type, "internal") == 0)
3384 terminal->type = output_msdos_raw;
3385 initialize_msdos_display (terminal);
3387 get_tty_size (fileno (tty->input), &width, &height);
3388 FrameCols (tty) = width;
3389 FrameRows (tty) = height;
3390 terminal->char_ins_del_ok = 0;
3391 init_baud_rate (fileno (tty->input));
3393 #endif /* MSDOS */
3394 tty->output = stdout;
3395 tty->input = stdin;
3396 /* The following two are inaccessible from w32console.c. */
3397 terminal->delete_frame_hook = &tty_free_frame_resources;
3398 terminal->delete_terminal_hook = &delete_tty;
3400 tty->name = xstrdup (name);
3401 terminal->name = xstrdup (name);
3402 tty->type = xstrdup (terminal_type);
3404 add_keyboard_wait_descriptor (0);
3406 tty->delete_in_insert_mode = 1;
3408 UseTabs (tty) = 0;
3409 terminal->scroll_region_ok = 0;
3411 /* Seems to insert lines when it's not supposed to, messing up the
3412 display. In doing a trace, it didn't seem to be called much, so I
3413 don't think we're losing anything by turning it off. */
3414 terminal->line_ins_del_ok = 0;
3416 tty->TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
3417 #endif /* DOS_NT */
3419 terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
3420 init_kboard (terminal->kboard);
3421 terminal->kboard->Vwindow_system = Qnil;
3422 terminal->kboard->next_kboard = all_kboards;
3423 all_kboards = terminal->kboard;
3424 terminal->kboard->reference_count++;
3425 /* Don't let the initial kboard remain current longer than necessary.
3426 That would cause problems if a file loaded on startup tries to
3427 prompt in the mini-buffer. */
3428 if (current_kboard == initial_kboard)
3429 current_kboard = terminal->kboard;
3430 #ifndef DOS_NT
3431 term_get_fkeys (address, terminal->kboard);
3433 /* Get frame size from system, or else from termcap. */
3435 int height, width;
3436 get_tty_size (fileno (tty->input), &width, &height);
3437 FrameCols (tty) = width;
3438 FrameRows (tty) = height;
3441 if (FrameCols (tty) <= 0)
3442 FrameCols (tty) = tgetnum ("co");
3443 if (FrameRows (tty) <= 0)
3444 FrameRows (tty) = tgetnum ("li");
3446 if (FrameRows (tty) < 3 || FrameCols (tty) < 3)
3447 maybe_fatal (must_succeed, terminal,
3448 "Screen size %dx%d is too small",
3449 "Screen size %dx%d is too small",
3450 FrameCols (tty), FrameRows (tty));
3452 TabWidth (tty) = tgetnum ("tw");
3454 if (!tty->TS_bell)
3455 tty->TS_bell = "\07";
3457 if (!tty->TS_fwd_scroll)
3458 tty->TS_fwd_scroll = Down (tty);
3460 PC = tty->TS_pad_char ? *tty->TS_pad_char : 0;
3462 if (TabWidth (tty) < 0)
3463 TabWidth (tty) = 8;
3465 /* Turned off since /etc/termcap seems to have :ta= for most terminals
3466 and newer termcap doc does not seem to say there is a default.
3467 if (!tty->Wcm->cm_tab)
3468 tty->Wcm->cm_tab = "\t";
3471 /* We don't support standout modes that use `magic cookies', so
3472 turn off any that do. */
3473 if (tty->TS_standout_mode && tgetnum ("sg") >= 0)
3475 tty->TS_standout_mode = 0;
3476 tty->TS_end_standout_mode = 0;
3478 if (tty->TS_enter_underline_mode && tgetnum ("ug") >= 0)
3480 tty->TS_enter_underline_mode = 0;
3481 tty->TS_exit_underline_mode = 0;
3484 /* If there's no standout mode, try to use underlining instead. */
3485 if (tty->TS_standout_mode == 0)
3487 tty->TS_standout_mode = tty->TS_enter_underline_mode;
3488 tty->TS_end_standout_mode = tty->TS_exit_underline_mode;
3491 /* If no `se' string, try using a `me' string instead.
3492 If that fails, we can't use standout mode at all. */
3493 if (tty->TS_end_standout_mode == 0)
3495 char *s = tgetstr ("me", address);
3496 if (s != 0)
3497 tty->TS_end_standout_mode = s;
3498 else
3499 tty->TS_standout_mode = 0;
3502 if (tty->TF_teleray)
3504 tty->Wcm->cm_tab = 0;
3505 /* We can't support standout mode, because it uses magic cookies. */
3506 tty->TS_standout_mode = 0;
3507 /* But that means we cannot rely on ^M to go to column zero! */
3508 CR (tty) = 0;
3509 /* LF can't be trusted either -- can alter hpos */
3510 /* if move at column 0 thru a line with TS_standout_mode */
3511 Down (tty) = 0;
3514 /* Special handling for certain terminal types known to need it */
3516 if (!strcmp (terminal_type, "supdup"))
3518 terminal->memory_below_frame = 1;
3519 tty->Wcm->cm_losewrap = 1;
3521 if (!strncmp (terminal_type, "c10", 3)
3522 || !strcmp (terminal_type, "perq"))
3524 /* Supply a makeshift :wi string.
3525 This string is not valid in general since it works only
3526 for windows starting at the upper left corner;
3527 but that is all Emacs uses.
3529 This string works only if the frame is using
3530 the top of the video memory, because addressing is memory-relative.
3531 So first check the :ti string to see if that is true.
3533 It would be simpler if the :wi string could go in the termcap
3534 entry, but it can't because it is not fully valid.
3535 If it were in the termcap entry, it would confuse other programs. */
3536 if (!tty->TS_set_window)
3538 p = tty->TS_termcap_modes;
3539 while (*p && strcmp (p, "\033v "))
3540 p++;
3541 if (*p)
3542 tty->TS_set_window = "\033v%C %C %C %C ";
3544 /* Termcap entry often fails to have :in: flag */
3545 terminal->must_write_spaces = 1;
3546 /* :ti string typically fails to have \E^G! in it */
3547 /* This limits scope of insert-char to one line. */
3548 strcpy (area, tty->TS_termcap_modes);
3549 strcat (area, "\033\007!");
3550 tty->TS_termcap_modes = area;
3551 area += strlen (area) + 1;
3552 p = AbsPosition (tty);
3553 /* Change all %+ parameters to %C, to handle
3554 values above 96 correctly for the C100. */
3555 while (*p)
3557 if (p[0] == '%' && p[1] == '+')
3558 p[1] = 'C';
3559 p++;
3563 tty->specified_window = FrameRows (tty);
3565 if (Wcm_init (tty) == -1) /* can't do cursor motion */
3567 maybe_fatal (must_succeed, terminal,
3568 "Terminal type \"%s\" is not powerful enough to run Emacs",
3569 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3570 It lacks the ability to position the cursor.\n\
3571 If that is not the actual type of terminal you have,\n\
3572 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3573 `setenv TERM ...') to specify the correct type. It may be necessary\n"
3574 # ifdef TERMINFO
3575 "to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3576 # else /* TERMCAP */
3577 "to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3578 # endif /* TERMINFO */
3579 terminal_type);
3582 if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
3583 maybe_fatal (must_succeed, terminal,
3584 "Could not determine the frame size",
3585 "Could not determine the frame size");
3587 tty->delete_in_insert_mode
3588 = tty->TS_delete_mode && tty->TS_insert_mode
3589 && !strcmp (tty->TS_delete_mode, tty->TS_insert_mode);
3591 tty->se_is_so = (tty->TS_standout_mode
3592 && tty->TS_end_standout_mode
3593 && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode));
3595 UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8;
3597 terminal->scroll_region_ok
3598 = (tty->Wcm->cm_abs
3599 && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
3601 terminal->line_ins_del_ok
3602 = (((tty->TS_ins_line || tty->TS_ins_multi_lines)
3603 && (tty->TS_del_line || tty->TS_del_multi_lines))
3604 || (terminal->scroll_region_ok
3605 && tty->TS_fwd_scroll && tty->TS_rev_scroll));
3607 terminal->char_ins_del_ok
3608 = ((tty->TS_ins_char || tty->TS_insert_mode
3609 || tty->TS_pad_inserted_char || tty->TS_ins_multi_chars)
3610 && (tty->TS_del_char || tty->TS_del_multi_chars));
3612 terminal->fast_clear_end_of_line = tty->TS_clr_line != 0;
3614 init_baud_rate (fileno (tty->input));
3616 #endif /* not DOS_NT */
3618 /* Init system terminal modes (RAW or CBREAK, etc.). */
3619 init_sys_modes (tty);
3621 return terminal;
3625 static void
3626 vfatal (const char *str, va_list ap)
3628 fprintf (stderr, "emacs: ");
3629 vfprintf (stderr, str, ap);
3630 if (!(strlen (str) > 0 && str[strlen (str) - 1] == '\n'))
3631 fprintf (stderr, "\n");
3632 va_end (ap);
3633 fflush (stderr);
3634 exit (1);
3638 /* Auxiliary error-handling function for init_tty.
3639 Delete TERMINAL, then call error or fatal with str1 or str2,
3640 respectively, according to MUST_SUCCEED. */
3642 static void
3643 maybe_fatal (int must_succeed, struct terminal *terminal,
3644 const char *str1, const char *str2, ...)
3646 va_list ap;
3647 va_start (ap, str2);
3648 if (terminal)
3649 delete_tty (terminal);
3651 if (must_succeed)
3652 vfatal (str2, ap);
3653 else
3654 verror (str1, ap);
3656 va_end (ap);
3657 abort ();
3660 void
3661 fatal (const char *str, ...)
3663 va_list ap;
3664 va_start (ap, str);
3665 vfatal (str, ap);
3666 va_end (ap);
3671 /* Delete the given tty terminal, closing all frames on it. */
3673 static void
3674 delete_tty (struct terminal *terminal)
3676 struct tty_display_info *tty;
3678 /* Protect against recursive calls. delete_frame in
3679 delete_terminal calls us back when it deletes our last frame. */
3680 if (!terminal->name)
3681 return;
3683 if (terminal->type != output_termcap)
3684 abort ();
3686 tty = terminal->display_info.tty;
3688 if (tty == tty_list)
3689 tty_list = tty->next;
3690 else
3692 struct tty_display_info *p;
3693 for (p = tty_list; p && p->next != tty; p = p->next)
3696 if (! p)
3697 /* This should not happen. */
3698 abort ();
3700 p->next = tty->next;
3701 tty->next = 0;
3704 /* reset_sys_modes needs a valid device, so this call needs to be
3705 before delete_terminal. */
3706 reset_sys_modes (tty);
3708 delete_terminal (terminal);
3710 xfree (tty->name);
3711 xfree (tty->type);
3713 if (tty->input)
3715 delete_keyboard_wait_descriptor (fileno (tty->input));
3716 if (tty->input != stdin)
3717 fclose (tty->input);
3719 if (tty->output && tty->output != stdout && tty->output != tty->input)
3720 fclose (tty->output);
3721 if (tty->termscript)
3722 fclose (tty->termscript);
3724 xfree (tty->old_tty);
3725 xfree (tty->Wcm);
3726 xfree (tty->termcap_strings_buffer);
3727 xfree (tty->termcap_term_buffer);
3729 memset (tty, 0, sizeof (struct tty_display_info));
3730 xfree (tty);
3735 /* Mark the pointers in the tty_display_info objects.
3736 Called by the Fgarbage_collector. */
3738 void
3739 mark_ttys (void)
3741 struct tty_display_info *tty;
3743 for (tty = tty_list; tty; tty = tty->next)
3744 mark_object (tty->top_frame);
3749 void
3750 syms_of_term (void)
3752 DEFVAR_BOOL ("system-uses-terminfo", system_uses_terminfo,
3753 doc: /* Non-nil means the system uses terminfo rather than termcap.
3754 This variable can be used by terminal emulator packages. */);
3755 #ifdef TERMINFO
3756 system_uses_terminfo = 1;
3757 #else
3758 system_uses_terminfo = 0;
3759 #endif
3761 DEFVAR_LISP ("suspend-tty-functions", Vsuspend_tty_functions,
3762 doc: /* Functions to be run after suspending a tty.
3763 The functions are run with one argument, the terminal object to be suspended.
3764 See `suspend-tty'. */);
3765 Vsuspend_tty_functions = Qnil;
3768 DEFVAR_LISP ("resume-tty-functions", Vresume_tty_functions,
3769 doc: /* Functions to be run after resuming a tty.
3770 The functions are run with one argument, the terminal object that was revived.
3771 See `resume-tty'. */);
3772 Vresume_tty_functions = Qnil;
3774 DEFVAR_BOOL ("visible-cursor", visible_cursor,
3775 doc: /* Non-nil means to make the cursor very visible.
3776 This only has an effect when running in a text terminal.
3777 What means \"very visible\" is up to your terminal. It may make the cursor
3778 bigger, or it may make it blink, or it may do nothing at all. */);
3779 visible_cursor = 1;
3781 defsubr (&Stty_display_color_p);
3782 defsubr (&Stty_display_color_cells);
3783 defsubr (&Stty_no_underline);
3784 defsubr (&Stty_type);
3785 defsubr (&Scontrolling_tty_p);
3786 defsubr (&Ssuspend_tty);
3787 defsubr (&Sresume_tty);
3788 #ifdef HAVE_GPM
3789 defsubr (&Sgpm_mouse_start);
3790 defsubr (&Sgpm_mouse_stop);
3791 #endif /* HAVE_GPM */
3793 #ifndef DOS_NT
3794 default_orig_pair = NULL;
3795 default_set_foreground = NULL;
3796 default_set_background = NULL;
3797 #endif /* !DOS_NT */
3799 encode_terminal_src = NULL;
3800 encode_terminal_dst = NULL;