Merge from mainline.
[emacs.git] / src / term.c
blobce3b26d21dfe3265b70d8dc6207852a35901f20f
1 /* Terminal control module for terminals described by TERMCAP
2 Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1998, 2000, 2001,
3 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
4 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
21 /* New redisplay, TTY faces by Gerd Moellmann <gerd@gnu.org>. */
23 #include <config.h>
24 #include <stdio.h>
25 #include <ctype.h>
26 #include <errno.h>
27 #include <sys/file.h>
28 #include <unistd.h>
29 #include <signal.h>
30 #include <stdarg.h>
31 #include <setjmp.h>
33 #include "lisp.h"
34 #include "termchar.h"
35 #include "termopts.h"
36 #include "buffer.h"
37 #include "character.h"
38 #include "charset.h"
39 #include "coding.h"
40 #include "composite.h"
41 #include "keyboard.h"
42 #include "frame.h"
43 #include "disptab.h"
44 #include "termhooks.h"
45 #include "dispextern.h"
46 #include "window.h"
47 #include "keymap.h"
48 #include "blockinput.h"
49 #include "syssignal.h"
50 #include "systty.h"
51 #include "intervals.h"
52 #ifdef MSDOS
53 #include "msdos.h"
54 static int been_here = -1;
55 #endif
57 /* For now, don't try to include termcap.h. On some systems,
58 configure finds a non-standard termcap.h that the main build
59 won't find. */
60 extern void tputs (const char *, int, int (*)(int));
61 extern int tgetent (char *, const char *);
62 extern int tgetflag (char *id);
63 extern int tgetnum (char *id);
65 char *tparam (char *, char *, int, int, ...);
67 extern char *tgetstr (char *, char **);
69 #include "cm.h"
70 #ifdef HAVE_X_WINDOWS
71 #include "xterm.h"
72 #endif
74 #ifndef O_RDWR
75 #define O_RDWR 2
76 #endif
78 #ifndef O_NOCTTY
79 #define O_NOCTTY 0
80 #endif
82 /* The name of the default console device. */
83 #ifdef WINDOWSNT
84 #define DEV_TTY "CONOUT$"
85 #else
86 #define DEV_TTY "/dev/tty"
87 #endif
89 static void tty_set_scroll_region (struct frame *f, int start, int stop);
90 static void turn_on_face (struct frame *, int face_id);
91 static void turn_off_face (struct frame *, int face_id);
92 static void tty_show_cursor (struct tty_display_info *);
93 static void tty_hide_cursor (struct tty_display_info *);
94 static void tty_background_highlight (struct tty_display_info *tty);
95 static void clear_tty_hooks (struct terminal *terminal);
96 static void set_tty_hooks (struct terminal *terminal);
97 static void dissociate_if_controlling_tty (int fd);
98 static void delete_tty (struct terminal *);
99 static void maybe_fatal (int must_succeed, struct terminal *terminal,
100 const char *str1, const char *str2, ...) NO_RETURN;
101 static void vfatal (const char *str, va_list ap) NO_RETURN;
104 #define OUTPUT(tty, a) \
105 emacs_tputs ((tty), a, \
106 (int) (FRAME_LINES (XFRAME (selected_frame)) \
107 - curY (tty)), \
108 cmputc)
110 #define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
111 #define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
113 #define OUTPUT_IF(tty, a) \
114 do { \
115 if (a) \
116 emacs_tputs ((tty), a, \
117 (int) (FRAME_LINES (XFRAME (selected_frame)) \
118 - curY (tty) ), \
119 cmputc); \
120 } while (0)
122 #define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
124 /* If true, use "vs", otherwise use "ve" to make the cursor visible. */
126 static int visible_cursor;
128 /* Display space properties */
130 /* Functions to call after suspending a tty. */
131 Lisp_Object Vsuspend_tty_functions;
133 /* Functions to call after resuming a tty. */
134 Lisp_Object Vresume_tty_functions;
136 /* Chain of all tty device parameters. */
137 struct tty_display_info *tty_list;
139 /* Nonzero means no need to redraw the entire frame on resuming a
140 suspended Emacs. This is useful on terminals with multiple
141 pages, where one page is used for Emacs and another for all
142 else. */
143 int no_redraw_on_reenter;
145 /* Meaning of bits in no_color_video. Each bit set means that the
146 corresponding attribute cannot be combined with colors. */
148 enum no_color_bit
150 NC_STANDOUT = 1 << 0,
151 NC_UNDERLINE = 1 << 1,
152 NC_REVERSE = 1 << 2,
153 NC_BLINK = 1 << 3,
154 NC_DIM = 1 << 4,
155 NC_BOLD = 1 << 5,
156 NC_INVIS = 1 << 6,
157 NC_PROTECT = 1 << 7,
158 NC_ALT_CHARSET = 1 << 8
161 /* internal state */
163 /* The largest frame width in any call to calculate_costs. */
165 int max_frame_cols;
167 /* The largest frame height in any call to calculate_costs. */
169 int max_frame_lines;
171 /* Non-zero if we have dropped our controlling tty and therefore
172 should not open a frame on stdout. */
173 static int no_controlling_tty;
175 /* Provided for lisp packages. */
177 static int system_uses_terminfo;
181 #ifdef HAVE_GPM
182 #include <sys/fcntl.h>
184 /* The device for which we have enabled gpm support (or NULL). */
185 struct tty_display_info *gpm_tty = NULL;
187 /* Last recorded mouse coordinates. */
188 static int last_mouse_x, last_mouse_y;
189 #endif /* HAVE_GPM */
191 /* Ring the bell on a tty. */
193 static void
194 tty_ring_bell (struct frame *f)
196 struct tty_display_info *tty = FRAME_TTY (f);
198 if (tty->output)
200 OUTPUT (tty, (tty->TS_visible_bell && visible_bell
201 ? tty->TS_visible_bell
202 : tty->TS_bell));
203 fflush (tty->output);
207 /* Set up termcap modes for Emacs. */
209 void
210 tty_set_terminal_modes (struct terminal *terminal)
212 struct tty_display_info *tty = terminal->display_info.tty;
214 if (tty->output)
216 if (tty->TS_termcap_modes)
217 OUTPUT (tty, tty->TS_termcap_modes);
218 else
220 /* Output enough newlines to scroll all the old screen contents
221 off the screen, so it won't be overwritten and lost. */
222 int i;
223 current_tty = tty;
224 for (i = 0; i < FRAME_LINES (XFRAME (selected_frame)); i++)
225 cmputc ('\n');
228 OUTPUT_IF (tty, visible_cursor ? tty->TS_cursor_visible : tty->TS_cursor_normal);
229 OUTPUT_IF (tty, tty->TS_keypad_mode);
230 losecursor (tty);
231 fflush (tty->output);
235 /* Reset termcap modes before exiting Emacs. */
237 void
238 tty_reset_terminal_modes (struct terminal *terminal)
240 struct tty_display_info *tty = terminal->display_info.tty;
242 if (tty->output)
244 tty_turn_off_highlight (tty);
245 tty_turn_off_insert (tty);
246 OUTPUT_IF (tty, tty->TS_end_keypad_mode);
247 OUTPUT_IF (tty, tty->TS_cursor_normal);
248 OUTPUT_IF (tty, tty->TS_end_termcap_modes);
249 OUTPUT_IF (tty, tty->TS_orig_pair);
250 /* Output raw CR so kernel can track the cursor hpos. */
251 current_tty = tty;
252 cmputc ('\r');
253 fflush (tty->output);
257 /* Flag the end of a display update on a termcap terminal. */
259 static void
260 tty_update_end (struct frame *f)
262 struct tty_display_info *tty = FRAME_TTY (f);
264 if (!XWINDOW (selected_window)->cursor_off_p)
265 tty_show_cursor (tty);
266 tty_turn_off_insert (tty);
267 tty_background_highlight (tty);
270 /* The implementation of set_terminal_window for termcap frames. */
272 static void
273 tty_set_terminal_window (struct frame *f, int size)
275 struct tty_display_info *tty = FRAME_TTY (f);
277 tty->specified_window = size ? size : FRAME_LINES (f);
278 if (FRAME_SCROLL_REGION_OK (f))
279 tty_set_scroll_region (f, 0, tty->specified_window);
282 static void
283 tty_set_scroll_region (struct frame *f, int start, int stop)
285 char *buf;
286 struct tty_display_info *tty = FRAME_TTY (f);
288 if (tty->TS_set_scroll_region)
289 buf = tparam (tty->TS_set_scroll_region, 0, 0, start, stop - 1);
290 else if (tty->TS_set_scroll_region_1)
291 buf = tparam (tty->TS_set_scroll_region_1, 0, 0,
292 FRAME_LINES (f), start,
293 FRAME_LINES (f) - stop,
294 FRAME_LINES (f));
295 else
296 buf = tparam (tty->TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (f));
298 OUTPUT (tty, buf);
299 xfree (buf);
300 losecursor (tty);
304 static void
305 tty_turn_on_insert (struct tty_display_info *tty)
307 if (!tty->insert_mode)
308 OUTPUT (tty, tty->TS_insert_mode);
309 tty->insert_mode = 1;
312 void
313 tty_turn_off_insert (struct tty_display_info *tty)
315 if (tty->insert_mode)
316 OUTPUT (tty, tty->TS_end_insert_mode);
317 tty->insert_mode = 0;
320 /* Handle highlighting. */
322 void
323 tty_turn_off_highlight (struct tty_display_info *tty)
325 if (tty->standout_mode)
326 OUTPUT_IF (tty, tty->TS_end_standout_mode);
327 tty->standout_mode = 0;
330 static void
331 tty_turn_on_highlight (struct tty_display_info *tty)
333 if (!tty->standout_mode)
334 OUTPUT_IF (tty, tty->TS_standout_mode);
335 tty->standout_mode = 1;
338 static void
339 tty_toggle_highlight (struct tty_display_info *tty)
341 if (tty->standout_mode)
342 tty_turn_off_highlight (tty);
343 else
344 tty_turn_on_highlight (tty);
348 /* Make cursor invisible. */
350 static void
351 tty_hide_cursor (struct tty_display_info *tty)
353 if (tty->cursor_hidden == 0)
355 tty->cursor_hidden = 1;
356 OUTPUT_IF (tty, tty->TS_cursor_invisible);
361 /* Ensure that cursor is visible. */
363 static void
364 tty_show_cursor (struct tty_display_info *tty)
366 if (tty->cursor_hidden)
368 tty->cursor_hidden = 0;
369 OUTPUT_IF (tty, tty->TS_cursor_normal);
370 if (visible_cursor)
371 OUTPUT_IF (tty, tty->TS_cursor_visible);
376 /* Set standout mode to the state it should be in for
377 empty space inside windows. What this is,
378 depends on the user option inverse-video. */
380 static void
381 tty_background_highlight (struct tty_display_info *tty)
383 if (inverse_video)
384 tty_turn_on_highlight (tty);
385 else
386 tty_turn_off_highlight (tty);
389 /* Set standout mode to the mode specified for the text to be output. */
391 static void
392 tty_highlight_if_desired (struct tty_display_info *tty)
394 if (inverse_video)
395 tty_turn_on_highlight (tty);
396 else
397 tty_turn_off_highlight (tty);
401 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
402 frame-relative coordinates. */
404 static void
405 tty_cursor_to (struct frame *f, int vpos, int hpos)
407 struct tty_display_info *tty = FRAME_TTY (f);
409 /* Detect the case where we are called from reset_sys_modes
410 and the costs have never been calculated. Do nothing. */
411 if (! tty->costs_set)
412 return;
414 if (curY (tty) == vpos
415 && curX (tty) == hpos)
416 return;
417 if (!tty->TF_standout_motion)
418 tty_background_highlight (tty);
419 if (!tty->TF_insmode_motion)
420 tty_turn_off_insert (tty);
421 cmgoto (tty, vpos, hpos);
424 /* Similar but don't take any account of the wasted characters. */
426 static void
427 tty_raw_cursor_to (struct frame *f, int row, int col)
429 struct tty_display_info *tty = FRAME_TTY (f);
431 if (curY (tty) == row
432 && curX (tty) == col)
433 return;
434 if (!tty->TF_standout_motion)
435 tty_background_highlight (tty);
436 if (!tty->TF_insmode_motion)
437 tty_turn_off_insert (tty);
438 cmgoto (tty, row, col);
441 /* Erase operations */
443 /* Clear from cursor to end of frame on a termcap device. */
445 static void
446 tty_clear_to_end (struct frame *f)
448 register int i;
449 struct tty_display_info *tty = FRAME_TTY (f);
451 if (tty->TS_clr_to_bottom)
453 tty_background_highlight (tty);
454 OUTPUT (tty, tty->TS_clr_to_bottom);
456 else
458 for (i = curY (tty); i < FRAME_LINES (f); i++)
460 cursor_to (f, i, 0);
461 clear_end_of_line (f, FRAME_COLS (f));
466 /* Clear an entire termcap frame. */
468 static void
469 tty_clear_frame (struct frame *f)
471 struct tty_display_info *tty = FRAME_TTY (f);
473 if (tty->TS_clr_frame)
475 tty_background_highlight (tty);
476 OUTPUT (tty, tty->TS_clr_frame);
477 cmat (tty, 0, 0);
479 else
481 cursor_to (f, 0, 0);
482 clear_to_end (f);
486 /* An implementation of clear_end_of_line for termcap frames.
488 Note that the cursor may be moved, on terminals lacking a `ce' string. */
490 static void
491 tty_clear_end_of_line (struct frame *f, int first_unused_hpos)
493 register int i;
494 struct tty_display_info *tty = FRAME_TTY (f);
496 /* Detect the case where we are called from reset_sys_modes
497 and the costs have never been calculated. Do nothing. */
498 if (! tty->costs_set)
499 return;
501 if (curX (tty) >= first_unused_hpos)
502 return;
503 tty_background_highlight (tty);
504 if (tty->TS_clr_line)
506 OUTPUT1 (tty, tty->TS_clr_line);
508 else
509 { /* have to do it the hard way */
510 tty_turn_off_insert (tty);
512 /* Do not write in last row last col with Auto-wrap on. */
513 if (AutoWrap (tty)
514 && curY (tty) == FrameRows (tty) - 1
515 && first_unused_hpos == FrameCols (tty))
516 first_unused_hpos--;
518 for (i = curX (tty); i < first_unused_hpos; i++)
520 if (tty->termscript)
521 fputc (' ', tty->termscript);
522 fputc (' ', tty->output);
524 cmplus (tty, first_unused_hpos - curX (tty));
528 /* Buffers to store the source and result of code conversion for terminal. */
529 static unsigned char *encode_terminal_src;
530 static unsigned char *encode_terminal_dst;
531 /* Allocated sizes of the above buffers. */
532 static int encode_terminal_src_size;
533 static int encode_terminal_dst_size;
535 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes.
536 Set CODING->produced to the byte-length of the resulting byte
537 sequence, and return a pointer to that byte sequence. */
539 unsigned char *
540 encode_terminal_code (struct glyph *src, int src_len, struct coding_system *coding)
542 struct glyph *src_end = src + src_len;
543 unsigned char *buf;
544 int nchars, nbytes, required;
545 register int tlen = GLYPH_TABLE_LENGTH;
546 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
547 Lisp_Object charset_list;
549 /* Allocate sufficient size of buffer to store all characters in
550 multibyte-form. But, it may be enlarged on demand if
551 Vglyph_table contains a string or a composite glyph is
552 encountered. */
553 required = MAX_MULTIBYTE_LENGTH * src_len;
554 if (encode_terminal_src_size < required)
556 if (encode_terminal_src)
557 encode_terminal_src = xrealloc (encode_terminal_src, required);
558 else
559 encode_terminal_src = xmalloc (required);
560 encode_terminal_src_size = required;
563 charset_list = coding_charset_list (coding);
565 buf = encode_terminal_src;
566 nchars = 0;
567 while (src < src_end)
569 if (src->type == COMPOSITE_GLYPH)
571 struct composition *cmp;
572 Lisp_Object gstring;
573 int i;
575 nbytes = buf - encode_terminal_src;
576 if (src->u.cmp.automatic)
578 gstring = composition_gstring_from_id (src->u.cmp.id);
579 required = src->slice.cmp.to + 1 - src->slice.cmp.from;
581 else
583 cmp = composition_table[src->u.cmp.id];
584 required = MAX_MULTIBYTE_LENGTH * cmp->glyph_len;
587 if (encode_terminal_src_size < nbytes + required)
589 encode_terminal_src_size = nbytes + required;
590 encode_terminal_src = xrealloc (encode_terminal_src,
591 encode_terminal_src_size);
592 buf = encode_terminal_src + nbytes;
595 if (src->u.cmp.automatic)
596 for (i = src->slice.cmp.from; i <= src->slice.cmp.to; i++)
598 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
599 int c = LGLYPH_CHAR (g);
601 if (! char_charset (c, charset_list, NULL))
602 c = '?';
603 buf += CHAR_STRING (c, buf);
604 nchars++;
606 else
607 for (i = 0; i < cmp->glyph_len; i++)
609 int c = COMPOSITION_GLYPH (cmp, i);
611 if (c == '\t')
612 continue;
613 if (char_charset (c, charset_list, NULL))
615 if (CHAR_WIDTH (c) == 0
616 && i > 0 && COMPOSITION_GLYPH (cmp, i - 1) == '\t')
617 /* Should be left-padded */
619 buf += CHAR_STRING (' ', buf);
620 nchars++;
623 else
624 c = '?';
625 buf += CHAR_STRING (c, buf);
626 nchars++;
629 /* We must skip glyphs to be padded for a wide character. */
630 else if (! CHAR_GLYPH_PADDING_P (*src))
632 GLYPH g;
633 int c;
634 Lisp_Object string;
636 string = Qnil;
637 SET_GLYPH_FROM_CHAR_GLYPH (g, src[0]);
639 if (GLYPH_INVALID_P (g) || GLYPH_SIMPLE_P (tbase, tlen, g))
641 /* This glyph doesn't have an entry in Vglyph_table. */
642 c = src->u.ch;
644 else
646 /* This glyph has an entry in Vglyph_table,
647 so process any alias before testing for simpleness. */
648 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
650 if (GLYPH_SIMPLE_P (tbase, tlen, g))
651 /* We set the multi-byte form of a character in G
652 (that should be an ASCII character) at WORKBUF. */
653 c = GLYPH_CHAR (g);
654 else
655 /* We have a string in Vglyph_table. */
656 string = tbase[GLYPH_CHAR (g)];
659 if (NILP (string))
661 nbytes = buf - encode_terminal_src;
662 if (encode_terminal_src_size < nbytes + MAX_MULTIBYTE_LENGTH)
664 encode_terminal_src_size = nbytes + MAX_MULTIBYTE_LENGTH;
665 encode_terminal_src = xrealloc (encode_terminal_src,
666 encode_terminal_src_size);
667 buf = encode_terminal_src + nbytes;
669 if (CHAR_BYTE8_P (c)
670 || char_charset (c, charset_list, NULL))
672 /* Store the multibyte form of C at BUF. */
673 buf += CHAR_STRING (c, buf);
674 nchars++;
676 else
678 /* C is not encodable. */
679 *buf++ = '?';
680 nchars++;
681 while (src + 1 < src_end && CHAR_GLYPH_PADDING_P (src[1]))
683 *buf++ = '?';
684 nchars++;
685 src++;
689 else
691 unsigned char *p = SDATA (string);
693 if (! STRING_MULTIBYTE (string))
694 string = string_to_multibyte (string);
695 nbytes = buf - encode_terminal_src;
696 if (encode_terminal_src_size < nbytes + SBYTES (string))
698 encode_terminal_src_size = nbytes + SBYTES (string);
699 encode_terminal_src = xrealloc (encode_terminal_src,
700 encode_terminal_src_size);
701 buf = encode_terminal_src + nbytes;
703 memcpy (buf, SDATA (string), SBYTES (string));
704 buf += SBYTES (string);
705 nchars += SCHARS (string);
708 src++;
711 if (nchars == 0)
713 coding->produced = 0;
714 return NULL;
717 nbytes = buf - encode_terminal_src;
718 coding->source = encode_terminal_src;
719 if (encode_terminal_dst_size == 0)
721 encode_terminal_dst_size = encode_terminal_src_size;
722 if (encode_terminal_dst)
723 encode_terminal_dst = xrealloc (encode_terminal_dst,
724 encode_terminal_dst_size);
725 else
726 encode_terminal_dst = xmalloc (encode_terminal_dst_size);
728 coding->destination = encode_terminal_dst;
729 coding->dst_bytes = encode_terminal_dst_size;
730 encode_coding_object (coding, Qnil, 0, 0, nchars, nbytes, Qnil);
731 /* coding->destination may have been reallocated. */
732 encode_terminal_dst = coding->destination;
733 encode_terminal_dst_size = coding->dst_bytes;
735 return (encode_terminal_dst);
740 /* An implementation of write_glyphs for termcap frames. */
742 static void
743 tty_write_glyphs (struct frame *f, struct glyph *string, int len)
745 unsigned char *conversion_buffer;
746 struct coding_system *coding;
748 struct tty_display_info *tty = FRAME_TTY (f);
750 tty_turn_off_insert (tty);
751 tty_hide_cursor (tty);
753 /* Don't dare write in last column of bottom line, if Auto-Wrap,
754 since that would scroll the whole frame on some terminals. */
756 if (AutoWrap (tty)
757 && curY (tty) + 1 == FRAME_LINES (f)
758 && (curX (tty) + len) == FRAME_COLS (f))
759 len --;
760 if (len <= 0)
761 return;
763 cmplus (tty, len);
765 /* If terminal_coding does any conversion, use it, otherwise use
766 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
767 because it always return 1 if the member src_multibyte is 1. */
768 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
769 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
770 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
771 the tail. */
772 coding->mode &= ~CODING_MODE_LAST_BLOCK;
774 while (len > 0)
776 /* Identify a run of glyphs with the same face. */
777 int face_id = string->face_id;
778 int n;
780 for (n = 1; n < len; ++n)
781 if (string[n].face_id != face_id)
782 break;
784 /* Turn appearance modes of the face of the run on. */
785 tty_highlight_if_desired (tty);
786 turn_on_face (f, face_id);
788 if (n == len)
789 /* This is the last run. */
790 coding->mode |= CODING_MODE_LAST_BLOCK;
791 conversion_buffer = encode_terminal_code (string, n, coding);
792 if (coding->produced > 0)
794 BLOCK_INPUT;
795 fwrite (conversion_buffer, 1, coding->produced, tty->output);
796 if (ferror (tty->output))
797 clearerr (tty->output);
798 if (tty->termscript)
799 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
800 UNBLOCK_INPUT;
802 len -= n;
803 string += n;
805 /* Turn appearance modes off. */
806 turn_off_face (f, face_id);
807 tty_turn_off_highlight (tty);
810 cmcheckmagic (tty);
813 #ifdef HAVE_GPM /* Only used by GPM code. */
815 static void
816 tty_write_glyphs_with_face (register struct frame *f, register struct glyph *string,
817 register int len, register int face_id)
819 unsigned char *conversion_buffer;
820 struct coding_system *coding;
822 struct tty_display_info *tty = FRAME_TTY (f);
824 tty_turn_off_insert (tty);
825 tty_hide_cursor (tty);
827 /* Don't dare write in last column of bottom line, if Auto-Wrap,
828 since that would scroll the whole frame on some terminals. */
830 if (AutoWrap (tty)
831 && curY (tty) + 1 == FRAME_LINES (f)
832 && (curX (tty) + len) == FRAME_COLS (f))
833 len --;
834 if (len <= 0)
835 return;
837 cmplus (tty, len);
839 /* If terminal_coding does any conversion, use it, otherwise use
840 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
841 because it always return 1 if the member src_multibyte is 1. */
842 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
843 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
844 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
845 the tail. */
846 coding->mode &= ~CODING_MODE_LAST_BLOCK;
848 /* Turn appearance modes of the face. */
849 tty_highlight_if_desired (tty);
850 turn_on_face (f, face_id);
852 coding->mode |= CODING_MODE_LAST_BLOCK;
853 conversion_buffer = encode_terminal_code (string, len, coding);
854 if (coding->produced > 0)
856 BLOCK_INPUT;
857 fwrite (conversion_buffer, 1, coding->produced, tty->output);
858 if (ferror (tty->output))
859 clearerr (tty->output);
860 if (tty->termscript)
861 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
862 UNBLOCK_INPUT;
865 /* Turn appearance modes off. */
866 turn_off_face (f, face_id);
867 tty_turn_off_highlight (tty);
869 cmcheckmagic (tty);
871 #endif
873 /* An implementation of insert_glyphs for termcap frames. */
875 static void
876 tty_insert_glyphs (struct frame *f, struct glyph *start, int len)
878 char *buf;
879 struct glyph *glyph = NULL;
880 unsigned char *conversion_buffer;
881 unsigned char space[1];
882 struct coding_system *coding;
884 struct tty_display_info *tty = FRAME_TTY (f);
886 if (tty->TS_ins_multi_chars)
888 buf = tparam (tty->TS_ins_multi_chars, 0, 0, len);
889 OUTPUT1 (tty, buf);
890 xfree (buf);
891 if (start)
892 write_glyphs (f, start, len);
893 return;
896 tty_turn_on_insert (tty);
897 cmplus (tty, len);
899 if (! start)
900 space[0] = SPACEGLYPH;
902 /* If terminal_coding does any conversion, use it, otherwise use
903 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
904 because it always return 1 if the member src_multibyte is 1. */
905 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
906 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
907 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
908 the tail. */
909 coding->mode &= ~CODING_MODE_LAST_BLOCK;
911 while (len-- > 0)
913 OUTPUT1_IF (tty, tty->TS_ins_char);
914 if (!start)
916 conversion_buffer = space;
917 coding->produced = 1;
919 else
921 tty_highlight_if_desired (tty);
922 turn_on_face (f, start->face_id);
923 glyph = start;
924 ++start;
925 /* We must open sufficient space for a character which
926 occupies more than one column. */
927 while (len && CHAR_GLYPH_PADDING_P (*start))
929 OUTPUT1_IF (tty, tty->TS_ins_char);
930 start++, len--;
933 if (len <= 0)
934 /* This is the last glyph. */
935 coding->mode |= CODING_MODE_LAST_BLOCK;
937 conversion_buffer = encode_terminal_code (glyph, 1, coding);
940 if (coding->produced > 0)
942 BLOCK_INPUT;
943 fwrite (conversion_buffer, 1, coding->produced, tty->output);
944 if (ferror (tty->output))
945 clearerr (tty->output);
946 if (tty->termscript)
947 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
948 UNBLOCK_INPUT;
951 OUTPUT1_IF (tty, tty->TS_pad_inserted_char);
952 if (start)
954 turn_off_face (f, glyph->face_id);
955 tty_turn_off_highlight (tty);
959 cmcheckmagic (tty);
962 /* An implementation of delete_glyphs for termcap frames. */
964 static void
965 tty_delete_glyphs (struct frame *f, int n)
967 char *buf;
968 register int i;
970 struct tty_display_info *tty = FRAME_TTY (f);
972 if (tty->delete_in_insert_mode)
974 tty_turn_on_insert (tty);
976 else
978 tty_turn_off_insert (tty);
979 OUTPUT_IF (tty, tty->TS_delete_mode);
982 if (tty->TS_del_multi_chars)
984 buf = tparam (tty->TS_del_multi_chars, 0, 0, n);
985 OUTPUT1 (tty, buf);
986 xfree (buf);
988 else
989 for (i = 0; i < n; i++)
990 OUTPUT1 (tty, tty->TS_del_char);
991 if (!tty->delete_in_insert_mode)
992 OUTPUT_IF (tty, tty->TS_end_delete_mode);
995 /* An implementation of ins_del_lines for termcap frames. */
997 static void
998 tty_ins_del_lines (struct frame *f, int vpos, int n)
1000 struct tty_display_info *tty = FRAME_TTY (f);
1001 char *multi = n > 0 ? tty->TS_ins_multi_lines : tty->TS_del_multi_lines;
1002 char *single = n > 0 ? tty->TS_ins_line : tty->TS_del_line;
1003 char *scroll = n > 0 ? tty->TS_rev_scroll : tty->TS_fwd_scroll;
1005 register int i = n > 0 ? n : -n;
1006 register char *buf;
1008 /* If the lines below the insertion are being pushed
1009 into the end of the window, this is the same as clearing;
1010 and we know the lines are already clear, since the matching
1011 deletion has already been done. So can ignore this. */
1012 /* If the lines below the deletion are blank lines coming
1013 out of the end of the window, don't bother,
1014 as there will be a matching inslines later that will flush them. */
1015 if (FRAME_SCROLL_REGION_OK (f)
1016 && vpos + i >= tty->specified_window)
1017 return;
1018 if (!FRAME_MEMORY_BELOW_FRAME (f)
1019 && vpos + i >= FRAME_LINES (f))
1020 return;
1022 if (multi)
1024 raw_cursor_to (f, vpos, 0);
1025 tty_background_highlight (tty);
1026 buf = tparam (multi, 0, 0, i);
1027 OUTPUT (tty, buf);
1028 xfree (buf);
1030 else if (single)
1032 raw_cursor_to (f, vpos, 0);
1033 tty_background_highlight (tty);
1034 while (--i >= 0)
1035 OUTPUT (tty, single);
1036 if (tty->TF_teleray)
1037 curX (tty) = 0;
1039 else
1041 tty_set_scroll_region (f, vpos, tty->specified_window);
1042 if (n < 0)
1043 raw_cursor_to (f, tty->specified_window - 1, 0);
1044 else
1045 raw_cursor_to (f, vpos, 0);
1046 tty_background_highlight (tty);
1047 while (--i >= 0)
1048 OUTPUTL (tty, scroll, tty->specified_window - vpos);
1049 tty_set_scroll_region (f, 0, tty->specified_window);
1052 if (!FRAME_SCROLL_REGION_OK (f)
1053 && FRAME_MEMORY_BELOW_FRAME (f)
1054 && n < 0)
1056 cursor_to (f, FRAME_LINES (f) + n, 0);
1057 clear_to_end (f);
1061 /* Compute cost of sending "str", in characters,
1062 not counting any line-dependent padding. */
1065 string_cost (const char *str)
1067 cost = 0;
1068 if (str)
1069 tputs (str, 0, evalcost);
1070 return cost;
1073 /* Compute cost of sending "str", in characters,
1074 counting any line-dependent padding at one line. */
1076 static int
1077 string_cost_one_line (const char *str)
1079 cost = 0;
1080 if (str)
1081 tputs (str, 1, evalcost);
1082 return cost;
1085 /* Compute per line amount of line-dependent padding,
1086 in tenths of characters. */
1089 per_line_cost (const char *str)
1091 cost = 0;
1092 if (str)
1093 tputs (str, 0, evalcost);
1094 cost = - cost;
1095 if (str)
1096 tputs (str, 10, evalcost);
1097 return cost;
1100 /* char_ins_del_cost[n] is cost of inserting N characters.
1101 char_ins_del_cost[-n] is cost of deleting N characters.
1102 The length of this vector is based on max_frame_cols. */
1104 int *char_ins_del_vector;
1106 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
1108 /* ARGSUSED */
1109 static void
1110 calculate_ins_del_char_costs (struct frame *f)
1112 struct tty_display_info *tty = FRAME_TTY (f);
1113 int ins_startup_cost, del_startup_cost;
1114 int ins_cost_per_char, del_cost_per_char;
1115 register int i;
1116 register int *p;
1118 if (tty->TS_ins_multi_chars)
1120 ins_cost_per_char = 0;
1121 ins_startup_cost = string_cost_one_line (tty->TS_ins_multi_chars);
1123 else if (tty->TS_ins_char || tty->TS_pad_inserted_char
1124 || (tty->TS_insert_mode && tty->TS_end_insert_mode))
1126 ins_startup_cost = (30 * (string_cost (tty->TS_insert_mode)
1127 + string_cost (tty->TS_end_insert_mode))) / 100;
1128 ins_cost_per_char = (string_cost_one_line (tty->TS_ins_char)
1129 + string_cost_one_line (tty->TS_pad_inserted_char));
1131 else
1133 ins_startup_cost = 9999;
1134 ins_cost_per_char = 0;
1137 if (tty->TS_del_multi_chars)
1139 del_cost_per_char = 0;
1140 del_startup_cost = string_cost_one_line (tty->TS_del_multi_chars);
1142 else if (tty->TS_del_char)
1144 del_startup_cost = (string_cost (tty->TS_delete_mode)
1145 + string_cost (tty->TS_end_delete_mode));
1146 if (tty->delete_in_insert_mode)
1147 del_startup_cost /= 2;
1148 del_cost_per_char = string_cost_one_line (tty->TS_del_char);
1150 else
1152 del_startup_cost = 9999;
1153 del_cost_per_char = 0;
1156 /* Delete costs are at negative offsets */
1157 p = &char_ins_del_cost (f)[0];
1158 for (i = FRAME_COLS (f); --i >= 0;)
1159 *--p = (del_startup_cost += del_cost_per_char);
1161 /* Doing nothing is free */
1162 p = &char_ins_del_cost (f)[0];
1163 *p++ = 0;
1165 /* Insert costs are at positive offsets */
1166 for (i = FRAME_COLS (f); --i >= 0;)
1167 *p++ = (ins_startup_cost += ins_cost_per_char);
1170 void
1171 calculate_costs (struct frame *frame)
1173 FRAME_COST_BAUD_RATE (frame) = baud_rate;
1175 if (FRAME_TERMCAP_P (frame))
1177 struct tty_display_info *tty = FRAME_TTY (frame);
1178 register char *f = (tty->TS_set_scroll_region
1179 ? tty->TS_set_scroll_region
1180 : tty->TS_set_scroll_region_1);
1182 FRAME_SCROLL_REGION_COST (frame) = string_cost (f);
1184 tty->costs_set = 1;
1186 /* These variables are only used for terminal stuff. They are
1187 allocated once for the terminal frame of X-windows emacs, but not
1188 used afterwards.
1190 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1191 X turns off char_ins_del_ok. */
1193 max_frame_lines = max (max_frame_lines, FRAME_LINES (frame));
1194 max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
1196 if (char_ins_del_vector != 0)
1197 char_ins_del_vector
1198 = (int *) xrealloc (char_ins_del_vector,
1199 (sizeof (int)
1200 + 2 * max_frame_cols * sizeof (int)));
1201 else
1202 char_ins_del_vector
1203 = (int *) xmalloc (sizeof (int)
1204 + 2 * max_frame_cols * sizeof (int));
1206 memset (char_ins_del_vector, 0,
1207 (sizeof (int) + 2 * max_frame_cols * sizeof (int)));
1210 if (f && (!tty->TS_ins_line && !tty->TS_del_line))
1211 do_line_insertion_deletion_costs (frame,
1212 tty->TS_rev_scroll, tty->TS_ins_multi_lines,
1213 tty->TS_fwd_scroll, tty->TS_del_multi_lines,
1214 f, f, 1);
1215 else
1216 do_line_insertion_deletion_costs (frame,
1217 tty->TS_ins_line, tty->TS_ins_multi_lines,
1218 tty->TS_del_line, tty->TS_del_multi_lines,
1219 0, 0, 1);
1221 calculate_ins_del_char_costs (frame);
1223 /* Don't use TS_repeat if its padding is worse than sending the chars */
1224 if (tty->TS_repeat && per_line_cost (tty->TS_repeat) * baud_rate < 9000)
1225 tty->RPov = string_cost (tty->TS_repeat);
1226 else
1227 tty->RPov = FRAME_COLS (frame) * 2;
1229 cmcostinit (FRAME_TTY (frame)); /* set up cursor motion costs */
1233 struct fkey_table {
1234 char *cap, *name;
1237 /* Termcap capability names that correspond directly to X keysyms.
1238 Some of these (marked "terminfo") aren't supplied by old-style
1239 (Berkeley) termcap entries. They're listed in X keysym order;
1240 except we put the keypad keys first, so that if they clash with
1241 other keys (as on the IBM PC keyboard) they get overridden.
1244 static const struct fkey_table keys[] =
1246 {"kh", "home"}, /* termcap */
1247 {"kl", "left"}, /* termcap */
1248 {"ku", "up"}, /* termcap */
1249 {"kr", "right"}, /* termcap */
1250 {"kd", "down"}, /* termcap */
1251 {"%8", "prior"}, /* terminfo */
1252 {"%5", "next"}, /* terminfo */
1253 {"@7", "end"}, /* terminfo */
1254 {"@1", "begin"}, /* terminfo */
1255 {"*6", "select"}, /* terminfo */
1256 {"%9", "print"}, /* terminfo */
1257 {"@4", "execute"}, /* terminfo --- actually the `command' key */
1259 * "insert" --- see below
1261 {"&8", "undo"}, /* terminfo */
1262 {"%0", "redo"}, /* terminfo */
1263 {"%7", "menu"}, /* terminfo --- actually the `options' key */
1264 {"@0", "find"}, /* terminfo */
1265 {"@2", "cancel"}, /* terminfo */
1266 {"%1", "help"}, /* terminfo */
1268 * "break" goes here, but can't be reliably intercepted with termcap
1270 {"&4", "reset"}, /* terminfo --- actually `restart' */
1272 * "system" and "user" --- no termcaps
1274 {"kE", "clearline"}, /* terminfo */
1275 {"kA", "insertline"}, /* terminfo */
1276 {"kL", "deleteline"}, /* terminfo */
1277 {"kI", "insertchar"}, /* terminfo */
1278 {"kD", "deletechar"}, /* terminfo */
1279 {"kB", "backtab"}, /* terminfo */
1281 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1283 {"@8", "kp-enter"}, /* terminfo */
1285 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1286 * "kp-multiply", "kp-add", "kp-separator",
1287 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1288 * --- no termcaps for any of these.
1290 {"K4", "kp-1"}, /* terminfo */
1292 * "kp-2" --- no termcap
1294 {"K5", "kp-3"}, /* terminfo */
1296 * "kp-4" --- no termcap
1298 {"K2", "kp-5"}, /* terminfo */
1300 * "kp-6" --- no termcap
1302 {"K1", "kp-7"}, /* terminfo */
1304 * "kp-8" --- no termcap
1306 {"K3", "kp-9"}, /* terminfo */
1308 * "kp-equal" --- no termcap
1310 {"k1", "f1"},
1311 {"k2", "f2"},
1312 {"k3", "f3"},
1313 {"k4", "f4"},
1314 {"k5", "f5"},
1315 {"k6", "f6"},
1316 {"k7", "f7"},
1317 {"k8", "f8"},
1318 {"k9", "f9"},
1320 {"&0", "S-cancel"}, /*shifted cancel key*/
1321 {"&9", "S-begin"}, /*shifted begin key*/
1322 {"*0", "S-find"}, /*shifted find key*/
1323 {"*1", "S-execute"}, /*shifted execute? actually shifted command key*/
1324 {"*4", "S-delete"}, /*shifted delete-character key*/
1325 {"*7", "S-end"}, /*shifted end key*/
1326 {"*8", "S-clearline"}, /*shifted clear-to end-of-line key*/
1327 {"#1", "S-help"}, /*shifted help key*/
1328 {"#2", "S-home"}, /*shifted home key*/
1329 {"#3", "S-insert"}, /*shifted insert-character key*/
1330 {"#4", "S-left"}, /*shifted left-arrow key*/
1331 {"%d", "S-menu"}, /*shifted menu? actually shifted options key*/
1332 {"%c", "S-next"}, /*shifted next key*/
1333 {"%e", "S-prior"}, /*shifted previous key*/
1334 {"%f", "S-print"}, /*shifted print key*/
1335 {"%g", "S-redo"}, /*shifted redo key*/
1336 {"%i", "S-right"}, /*shifted right-arrow key*/
1337 {"!3", "S-undo"} /*shifted undo key*/
1340 #ifndef DOS_NT
1341 static char **term_get_fkeys_address;
1342 static KBOARD *term_get_fkeys_kboard;
1343 static Lisp_Object term_get_fkeys_1 (void);
1345 /* Find the escape codes sent by the function keys for Vinput_decode_map.
1346 This function scans the termcap function key sequence entries, and
1347 adds entries to Vinput_decode_map for each function key it finds. */
1349 static void
1350 term_get_fkeys (char **address, KBOARD *kboard)
1352 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1353 errors during the call. The only errors should be from Fdefine_key
1354 when given a key sequence containing an invalid prefix key. If the
1355 termcap defines function keys which use a prefix that is already bound
1356 to a command by the default bindings, we should silently ignore that
1357 function key specification, rather than giving the user an error and
1358 refusing to run at all on such a terminal. */
1360 term_get_fkeys_address = address;
1361 term_get_fkeys_kboard = kboard;
1362 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1365 static Lisp_Object
1366 term_get_fkeys_1 (void)
1368 int i;
1370 char **address = term_get_fkeys_address;
1371 KBOARD *kboard = term_get_fkeys_kboard;
1373 /* This can happen if CANNOT_DUMP or with strange options. */
1374 if (!KEYMAPP (kboard->Vinput_decode_map))
1375 kboard->Vinput_decode_map = Fmake_sparse_keymap (Qnil);
1377 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1379 char *sequence = tgetstr (keys[i].cap, address);
1380 if (sequence)
1381 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence),
1382 Fmake_vector (make_number (1),
1383 intern (keys[i].name)));
1386 /* The uses of the "k0" capability are inconsistent; sometimes it
1387 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1388 We will attempt to politely accommodate both systems by testing for
1389 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1392 char *k_semi = tgetstr ("k;", address);
1393 char *k0 = tgetstr ("k0", address);
1394 char *k0_name = "f10";
1396 if (k_semi)
1398 if (k0)
1399 /* Define f0 first, so that f10 takes precedence in case the
1400 key sequences happens to be the same. */
1401 Fdefine_key (kboard->Vinput_decode_map, build_string (k0),
1402 Fmake_vector (make_number (1), intern ("f0")));
1403 Fdefine_key (kboard->Vinput_decode_map, build_string (k_semi),
1404 Fmake_vector (make_number (1), intern ("f10")));
1406 else if (k0)
1407 Fdefine_key (kboard->Vinput_decode_map, build_string (k0),
1408 Fmake_vector (make_number (1), intern (k0_name)));
1411 /* Set up cookies for numbered function keys above f10. */
1413 char fcap[3], fkey[4];
1415 fcap[0] = 'F'; fcap[2] = '\0';
1416 for (i = 11; i < 64; i++)
1418 if (i <= 19)
1419 fcap[1] = '1' + i - 11;
1420 else if (i <= 45)
1421 fcap[1] = 'A' + i - 20;
1422 else
1423 fcap[1] = 'a' + i - 46;
1426 char *sequence = tgetstr (fcap, address);
1427 if (sequence)
1429 sprintf (fkey, "f%d", i);
1430 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence),
1431 Fmake_vector (make_number (1),
1432 intern (fkey)));
1439 * Various mappings to try and get a better fit.
1442 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1443 if (!tgetstr (cap1, address)) \
1445 char *sequence = tgetstr (cap2, address); \
1446 if (sequence) \
1447 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence), \
1448 Fmake_vector (make_number (1), \
1449 intern (sym))); \
1452 /* if there's no key_next keycap, map key_npage to `next' keysym */
1453 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1454 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1455 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1456 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1457 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1458 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1459 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1461 /* IBM has their own non-standard dialect of terminfo.
1462 If the standard name isn't found, try the IBM name. */
1463 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1464 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1465 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1466 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1467 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1468 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1469 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1470 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1471 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1472 #undef CONDITIONAL_REASSIGN
1475 return Qnil;
1477 #endif /* not DOS_NT */
1480 /***********************************************************************
1481 Character Display Information
1482 ***********************************************************************/
1483 static void append_glyph (struct it *);
1484 static void produce_stretch_glyph (struct it *);
1485 static void append_composite_glyph (struct it *);
1486 static void produce_composite_glyph (struct it *);
1487 static void append_glyphless_glyph (struct it *, int, char *);
1488 static void produce_glyphless_glyph (struct it *, int, Lisp_Object);
1490 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1491 terminal frames if IT->glyph_row != NULL. IT->char_to_display is
1492 the character for which to produce glyphs; IT->face_id contains the
1493 character's face. Padding glyphs are appended if IT->c has a
1494 IT->pixel_width > 1. */
1496 static void
1497 append_glyph (struct it *it)
1499 struct glyph *glyph, *end;
1500 int i;
1502 xassert (it->glyph_row);
1503 glyph = (it->glyph_row->glyphs[it->area]
1504 + it->glyph_row->used[it->area]);
1505 end = it->glyph_row->glyphs[1 + it->area];
1507 /* If the glyph row is reversed, we need to prepend the glyph rather
1508 than append it. */
1509 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1511 struct glyph *g;
1512 int move_by = it->pixel_width;
1514 /* Make room for the new glyphs. */
1515 if (move_by > end - glyph) /* don't overstep end of this area */
1516 move_by = end - glyph;
1517 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1518 g[move_by] = *g;
1519 glyph = it->glyph_row->glyphs[it->area];
1520 end = glyph + move_by;
1523 /* BIDI Note: we put the glyphs of a "multi-pixel" character left to
1524 right, even in the REVERSED_P case, since (a) all of its u.ch are
1525 identical, and (b) the PADDING_P flag needs to be set for the
1526 leftmost one, because we write to the terminal left-to-right. */
1527 for (i = 0;
1528 i < it->pixel_width && glyph < end;
1529 ++i)
1531 glyph->type = CHAR_GLYPH;
1532 glyph->pixel_width = 1;
1533 glyph->u.ch = it->char_to_display;
1534 glyph->face_id = it->face_id;
1535 glyph->padding_p = i > 0;
1536 glyph->charpos = CHARPOS (it->position);
1537 glyph->object = it->object;
1538 if (it->bidi_p)
1540 glyph->resolved_level = it->bidi_it.resolved_level;
1541 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1542 abort ();
1543 glyph->bidi_type = it->bidi_it.type;
1545 else
1547 glyph->resolved_level = 0;
1548 glyph->bidi_type = UNKNOWN_BT;
1551 ++it->glyph_row->used[it->area];
1552 ++glyph;
1556 /* Produce glyphs for the display element described by IT. *IT
1557 specifies what we want to produce a glyph for (character, image, ...),
1558 and where in the glyph matrix we currently are (glyph row and hpos).
1559 produce_glyphs fills in output fields of *IT with information such as the
1560 pixel width and height of a character, and maybe output actual glyphs at
1561 the same time if IT->glyph_row is non-null. For an overview, see
1562 the explanation in dispextern.h, before the definition of the
1563 display_element_type enumeration.
1565 produce_glyphs also stores the result of glyph width, ascent
1566 etc. computations in *IT.
1568 IT->glyph_row may be null, in which case produce_glyphs does not
1569 actually fill in the glyphs. This is used in the move_* functions
1570 in xdisp.c for text width and height computations.
1572 Callers usually don't call produce_glyphs directly;
1573 instead they use the macro PRODUCE_GLYPHS. */
1575 void
1576 produce_glyphs (struct it *it)
1578 /* If a hook is installed, let it do the work. */
1580 /* Nothing but characters are supported on terminal frames. */
1581 xassert (it->what == IT_CHARACTER
1582 || it->what == IT_COMPOSITION
1583 || it->what == IT_STRETCH);
1585 if (it->what == IT_STRETCH)
1587 produce_stretch_glyph (it);
1588 goto done;
1591 if (it->what == IT_COMPOSITION)
1593 produce_composite_glyph (it);
1594 goto done;
1597 if (it->what == IT_GLYPHLESS)
1599 produce_glyphless_glyph (it, 0, Qnil);
1600 goto done;
1603 if (it->char_to_display >= 040 && it->char_to_display < 0177)
1605 it->pixel_width = it->nglyphs = 1;
1606 if (it->glyph_row)
1607 append_glyph (it);
1609 else if (it->char_to_display == '\n')
1610 it->pixel_width = it->nglyphs = 0;
1611 else if (it->char_to_display == '\t')
1613 int absolute_x = (it->current_x
1614 + it->continuation_lines_width);
1615 int next_tab_x
1616 = (((1 + absolute_x + it->tab_width - 1)
1617 / it->tab_width)
1618 * it->tab_width);
1619 int nspaces;
1621 /* If part of the TAB has been displayed on the previous line
1622 which is continued now, continuation_lines_width will have
1623 been incremented already by the part that fitted on the
1624 continued line. So, we will get the right number of spaces
1625 here. */
1626 nspaces = next_tab_x - absolute_x;
1628 if (it->glyph_row)
1630 int n = nspaces;
1632 it->char_to_display = ' ';
1633 it->pixel_width = it->len = 1;
1635 while (n--)
1636 append_glyph (it);
1639 it->pixel_width = nspaces;
1640 it->nglyphs = nspaces;
1642 else if (CHAR_BYTE8_P (it->char_to_display))
1644 /* Coming here means that we must send the raw 8-bit byte as is
1645 to the terminal. Although there's no way to know how many
1646 columns it occupies on a screen, it is a good assumption that
1647 a single byte code has 1-column width. */
1648 it->pixel_width = it->nglyphs = 1;
1649 if (it->glyph_row)
1650 append_glyph (it);
1652 else
1654 Lisp_Object charset_list = FRAME_TERMINAL (it->f)->charset_list;
1656 if (char_charset (it->char_to_display, charset_list, NULL))
1658 it->pixel_width = CHAR_WIDTH (it->char_to_display);
1659 it->nglyphs = it->pixel_width;
1660 if (it->glyph_row)
1661 append_glyph (it);
1663 else
1665 Lisp_Object acronym = lookup_glyphless_char_display (-1, it);
1667 xassert (it->what == IT_GLYPHLESS);
1668 produce_glyphless_glyph (it, 1, acronym);
1672 done:
1673 /* Advance current_x by the pixel width as a convenience for
1674 the caller. */
1675 if (it->area == TEXT_AREA)
1676 it->current_x += it->pixel_width;
1677 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1678 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
1682 /* Produce a stretch glyph for iterator IT. IT->object is the value
1683 of the glyph property displayed. The value must be a list
1684 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1685 being recognized:
1687 1. `:width WIDTH' specifies that the space should be WIDTH *
1688 canonical char width wide. WIDTH may be an integer or floating
1689 point number.
1691 2. `:align-to HPOS' specifies that the space should be wide enough
1692 to reach HPOS, a value in canonical character units. */
1694 static void
1695 produce_stretch_glyph (struct it *it)
1697 /* (space :width WIDTH ...) */
1698 Lisp_Object prop, plist;
1699 int width = 0, align_to = -1;
1700 int zero_width_ok_p = 0;
1701 double tem;
1703 /* List should start with `space'. */
1704 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1705 plist = XCDR (it->object);
1707 /* Compute the width of the stretch. */
1708 if ((prop = Fplist_get (plist, QCwidth), !NILP (prop))
1709 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, 0))
1711 /* Absolute width `:width WIDTH' specified and valid. */
1712 zero_width_ok_p = 1;
1713 width = (int)(tem + 0.5);
1715 else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
1716 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, &align_to))
1718 if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
1719 align_to = (align_to < 0
1721 : align_to - window_box_left_offset (it->w, TEXT_AREA));
1722 else if (align_to < 0)
1723 align_to = window_box_left_offset (it->w, TEXT_AREA);
1724 width = max (0, (int)(tem + 0.5) + align_to - it->current_x);
1725 zero_width_ok_p = 1;
1727 else
1728 /* Nothing specified -> width defaults to canonical char width. */
1729 width = FRAME_COLUMN_WIDTH (it->f);
1731 if (width <= 0 && (width < 0 || !zero_width_ok_p))
1732 width = 1;
1734 if (width > 0 && it->line_wrap != TRUNCATE
1735 && it->current_x + width > it->last_visible_x)
1736 width = it->last_visible_x - it->current_x - 1;
1738 if (width > 0 && it->glyph_row)
1740 Lisp_Object o_object = it->object;
1741 Lisp_Object object = it->stack[it->sp - 1].string;
1742 int n = width;
1744 if (!STRINGP (object))
1745 object = it->w->buffer;
1746 it->object = object;
1747 it->char_to_display = ' ';
1748 it->pixel_width = it->len = 1;
1749 while (n--)
1750 append_glyph (it);
1751 it->object = o_object;
1753 it->pixel_width = width;
1754 it->nglyphs = width;
1758 /* Append glyphs to IT's glyph_row for the composition IT->cmp_id.
1759 Called from produce_composite_glyph for terminal frames if
1760 IT->glyph_row != NULL. IT->face_id contains the character's
1761 face. */
1763 static void
1764 append_composite_glyph (struct it *it)
1766 struct glyph *glyph;
1768 xassert (it->glyph_row);
1769 glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
1770 if (glyph < it->glyph_row->glyphs[1 + it->area])
1772 /* If the glyph row is reversed, we need to prepend the glyph
1773 rather than append it. */
1774 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1776 struct glyph *g;
1778 /* Make room for the new glyph. */
1779 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1780 g[1] = *g;
1781 glyph = it->glyph_row->glyphs[it->area];
1783 glyph->type = COMPOSITE_GLYPH;
1784 glyph->pixel_width = it->pixel_width;
1785 glyph->u.cmp.id = it->cmp_it.id;
1786 if (it->cmp_it.ch < 0)
1788 glyph->u.cmp.automatic = 0;
1789 glyph->u.cmp.id = it->cmp_it.id;
1791 else
1793 glyph->u.cmp.automatic = 1;
1794 glyph->u.cmp.id = it->cmp_it.id;
1795 glyph->slice.cmp.from = it->cmp_it.from;
1796 glyph->slice.cmp.to = it->cmp_it.to - 1;
1799 glyph->face_id = it->face_id;
1800 glyph->padding_p = 0;
1801 glyph->charpos = CHARPOS (it->position);
1802 glyph->object = it->object;
1803 if (it->bidi_p)
1805 glyph->resolved_level = it->bidi_it.resolved_level;
1806 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1807 abort ();
1808 glyph->bidi_type = it->bidi_it.type;
1810 else
1812 glyph->resolved_level = 0;
1813 glyph->bidi_type = UNKNOWN_BT;
1816 ++it->glyph_row->used[it->area];
1817 ++glyph;
1822 /* Produce a composite glyph for iterator IT. IT->cmp_id is the ID of
1823 the composition. We simply produces components of the composition
1824 assuming that the terminal has a capability to layout/render it
1825 correctly. */
1827 static void
1828 produce_composite_glyph (struct it *it)
1830 if (it->cmp_it.ch < 0)
1832 struct composition *cmp = composition_table[it->cmp_it.id];
1834 it->pixel_width = cmp->width;
1836 else
1838 Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id);
1840 it->pixel_width = composition_gstring_width (gstring, it->cmp_it.from,
1841 it->cmp_it.to, NULL);
1843 it->nglyphs = 1;
1844 if (it->glyph_row)
1845 append_composite_glyph (it);
1849 /* Append a glyph for a glyphless character to IT->glyph_row. FACE_ID
1850 is a face ID to be used for the glyph. What is actually appended
1851 are glyphs of type CHAR_GLYPH whose characters are in STR (which
1852 comes from it->nglyphs bytes). */
1854 static void
1855 append_glyphless_glyph (struct it *it, int face_id, char *str)
1857 struct glyph *glyph, *end;
1858 int i;
1860 xassert (it->glyph_row);
1861 glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
1862 end = it->glyph_row->glyphs[1 + it->area];
1864 /* If the glyph row is reversed, we need to prepend the glyph rather
1865 than append it. */
1866 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1868 struct glyph *g;
1869 int move_by = it->pixel_width;
1871 /* Make room for the new glyphs. */
1872 if (move_by > end - glyph) /* don't overstep end of this area */
1873 move_by = end - glyph;
1874 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1875 g[move_by] = *g;
1876 glyph = it->glyph_row->glyphs[it->area];
1877 end = glyph + move_by;
1880 if (glyph >= end)
1881 return;
1882 glyph->type = CHAR_GLYPH;
1883 glyph->pixel_width = 1;
1884 glyph->face_id = face_id;
1885 glyph->padding_p = 0;
1886 glyph->charpos = CHARPOS (it->position);
1887 glyph->object = it->object;
1888 if (it->bidi_p)
1890 glyph->resolved_level = it->bidi_it.resolved_level;
1891 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1892 abort ();
1893 glyph->bidi_type = it->bidi_it.type;
1895 else
1897 glyph->resolved_level = 0;
1898 glyph->bidi_type = UNKNOWN_BT;
1901 /* BIDI Note: we put the glyphs of characters left to right, even in
1902 the REVERSED_P case because we write to the terminal
1903 left-to-right. */
1904 for (i = 0; i < it->nglyphs && glyph < end; ++i)
1906 if (i > 0)
1907 glyph[0] = glyph[-1];
1908 glyph->u.ch = str[i];
1909 ++it->glyph_row->used[it->area];
1910 ++glyph;
1914 /* Produce glyphs for a glyphless character for iterator IT.
1915 IT->glyphless_method specifies which method to use for displaying
1916 the character. See the description of enum
1917 glyphless_display_method in dispextern.h for the details.
1919 FOR_NO_FONT is nonzero if and only if this is for a character that
1920 is not supproted by the coding system of the terminal. ACRONYM, if
1921 non-nil, is an acronym string for the character.
1923 The glyphs actually produced are of type CHAR_GLYPH. */
1925 static void
1926 produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym)
1928 int face_id;
1929 int len;
1930 char buf[9], *str = " ";
1932 /* Get a face ID for the glyph by utilizing a cache (the same way as
1933 done for `escape-glyph' in get_next_display_element). */
1934 if (it->f == last_glyphless_glyph_frame
1935 && it->face_id == last_glyphless_glyph_face_id)
1937 face_id = last_glyphless_glyph_merged_face_id;
1939 else
1941 /* Merge the `glyphless-char' face into the current face. */
1942 face_id = merge_faces (it->f, Qglyphless_char, 0, it->face_id);
1943 last_glyphless_glyph_frame = it->f;
1944 last_glyphless_glyph_face_id = it->face_id;
1945 last_glyphless_glyph_merged_face_id = face_id;
1948 if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE)
1950 /* As there's no way to produce a thin space, we produce a space
1951 of canonical width. */
1952 len = 1;
1954 else if (it->glyphless_method == GLYPHLESS_DISPLAY_EMPTY_BOX)
1956 len = CHAR_WIDTH (it->c);
1957 if (len == 0)
1958 len = 1;
1959 else if (len > 4)
1960 len = 4;
1961 sprintf (buf, "[%.*s]", len, str);
1962 len += 2;
1963 str = buf;
1965 else
1967 if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM)
1969 if (! STRINGP (acronym) && CHAR_TABLE_P (Vglyphless_char_display))
1970 acronym = CHAR_TABLE_REF (Vglyphless_char_display, it->c);
1971 buf[0] = '[';
1972 str = STRINGP (acronym) ? (char *) SDATA (acronym) : "";
1973 for (len = 0; len < 6 && str[len] && ASCII_BYTE_P (str[len]); len++)
1974 buf[1 + len] = str[len];
1975 buf[1 + len] = ']';
1976 len += 2;
1978 else
1980 xassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEX_CODE);
1981 len = (it->c < 0x10000 ? sprintf (buf, "\\u%04X", it->c)
1982 : it->c <= MAX_UNICODE_CHAR ? sprintf (buf, "\\U%06X", it->c)
1983 : sprintf (buf, "\\x%06X", it->c));
1985 str = buf;
1988 it->pixel_width = len;
1989 it->nglyphs = len;
1990 if (len > 0 && it->glyph_row)
1991 append_glyphless_glyph (it, face_id, str);
1995 /* Get information about special display element WHAT in an
1996 environment described by IT. WHAT is one of IT_TRUNCATION or
1997 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1998 non-null glyph_row member. This function ensures that fields like
1999 face_id, c, len of IT are left untouched. */
2001 void
2002 produce_special_glyphs (struct it *it, enum display_element_type what)
2004 struct it temp_it;
2005 Lisp_Object gc;
2006 GLYPH glyph;
2008 temp_it = *it;
2009 temp_it.dp = NULL;
2010 temp_it.what = IT_CHARACTER;
2011 temp_it.len = 1;
2012 temp_it.object = make_number (0);
2013 memset (&temp_it.current, 0, sizeof temp_it.current);
2015 if (what == IT_CONTINUATION)
2017 /* Continuation glyph. For R2L lines, we mirror it by hand. */
2018 if (it->bidi_it.paragraph_dir == R2L)
2019 SET_GLYPH_FROM_CHAR (glyph, '/');
2020 else
2021 SET_GLYPH_FROM_CHAR (glyph, '\\');
2022 if (it->dp
2023 && (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc))
2024 && GLYPH_CODE_CHAR_VALID_P (gc))
2026 /* FIXME: Should we mirror GC for R2L lines? */
2027 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
2028 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
2031 else if (what == IT_TRUNCATION)
2033 /* Truncation glyph. */
2034 SET_GLYPH_FROM_CHAR (glyph, '$');
2035 if (it->dp
2036 && (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc))
2037 && GLYPH_CODE_CHAR_VALID_P (gc))
2039 /* FIXME: Should we mirror GC for R2L lines? */
2040 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
2041 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
2044 else
2045 abort ();
2047 temp_it.c = temp_it.char_to_display = GLYPH_CHAR (glyph);
2048 temp_it.face_id = GLYPH_FACE (glyph);
2049 temp_it.len = CHAR_BYTES (temp_it.c);
2051 produce_glyphs (&temp_it);
2052 it->pixel_width = temp_it.pixel_width;
2053 it->nglyphs = temp_it.pixel_width;
2058 /***********************************************************************
2059 Faces
2060 ***********************************************************************/
2062 /* Value is non-zero if attribute ATTR may be used. ATTR should be
2063 one of the enumerators from enum no_color_bit, or a bit set built
2064 from them. Some display attributes may not be used together with
2065 color; the termcap capability `NC' specifies which ones. */
2067 #define MAY_USE_WITH_COLORS_P(tty, ATTR) \
2068 (tty->TN_max_colors > 0 \
2069 ? (tty->TN_no_color_video & (ATTR)) == 0 \
2070 : 1)
2072 /* Turn appearances of face FACE_ID on tty frame F on.
2073 FACE_ID is a realized face ID number, in the face cache. */
2075 static void
2076 turn_on_face (struct frame *f, int face_id)
2078 struct face *face = FACE_FROM_ID (f, face_id);
2079 long fg = face->foreground;
2080 long bg = face->background;
2081 struct tty_display_info *tty = FRAME_TTY (f);
2083 /* Do this first because TS_end_standout_mode may be the same
2084 as TS_exit_attribute_mode, which turns all appearances off. */
2085 if (MAY_USE_WITH_COLORS_P (tty, NC_REVERSE))
2087 if (tty->TN_max_colors > 0)
2089 if (fg >= 0 && bg >= 0)
2091 /* If the terminal supports colors, we can set them
2092 below without using reverse video. The face's fg
2093 and bg colors are set as they should appear on
2094 the screen, i.e. they take the inverse-video'ness
2095 of the face already into account. */
2097 else if (inverse_video)
2099 if (fg == FACE_TTY_DEFAULT_FG_COLOR
2100 || bg == FACE_TTY_DEFAULT_BG_COLOR)
2101 tty_toggle_highlight (tty);
2103 else
2105 if (fg == FACE_TTY_DEFAULT_BG_COLOR
2106 || bg == FACE_TTY_DEFAULT_FG_COLOR)
2107 tty_toggle_highlight (tty);
2110 else
2112 /* If we can't display colors, use reverse video
2113 if the face specifies that. */
2114 if (inverse_video)
2116 if (fg == FACE_TTY_DEFAULT_FG_COLOR
2117 || bg == FACE_TTY_DEFAULT_BG_COLOR)
2118 tty_toggle_highlight (tty);
2120 else
2122 if (fg == FACE_TTY_DEFAULT_BG_COLOR
2123 || bg == FACE_TTY_DEFAULT_FG_COLOR)
2124 tty_toggle_highlight (tty);
2129 if (face->tty_bold_p && MAY_USE_WITH_COLORS_P (tty, NC_BOLD))
2130 OUTPUT1_IF (tty, tty->TS_enter_bold_mode);
2132 if (face->tty_dim_p && MAY_USE_WITH_COLORS_P (tty, NC_DIM))
2133 OUTPUT1_IF (tty, tty->TS_enter_dim_mode);
2135 /* Alternate charset and blinking not yet used. */
2136 if (face->tty_alt_charset_p
2137 && MAY_USE_WITH_COLORS_P (tty, NC_ALT_CHARSET))
2138 OUTPUT1_IF (tty, tty->TS_enter_alt_charset_mode);
2140 if (face->tty_blinking_p
2141 && MAY_USE_WITH_COLORS_P (tty, NC_BLINK))
2142 OUTPUT1_IF (tty, tty->TS_enter_blink_mode);
2144 if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (tty, NC_UNDERLINE))
2145 OUTPUT1_IF (tty, tty->TS_enter_underline_mode);
2147 if (tty->TN_max_colors > 0)
2149 char *ts, *p;
2151 ts = tty->standout_mode ? tty->TS_set_background : tty->TS_set_foreground;
2152 if (fg >= 0 && ts)
2154 p = tparam (ts, NULL, 0, (int) fg);
2155 OUTPUT (tty, p);
2156 xfree (p);
2159 ts = tty->standout_mode ? tty->TS_set_foreground : tty->TS_set_background;
2160 if (bg >= 0 && ts)
2162 p = tparam (ts, NULL, 0, (int) bg);
2163 OUTPUT (tty, p);
2164 xfree (p);
2170 /* Turn off appearances of face FACE_ID on tty frame F. */
2172 static void
2173 turn_off_face (struct frame *f, int face_id)
2175 struct face *face = FACE_FROM_ID (f, face_id);
2176 struct tty_display_info *tty = FRAME_TTY (f);
2178 xassert (face != NULL);
2180 if (tty->TS_exit_attribute_mode)
2182 /* Capability "me" will turn off appearance modes double-bright,
2183 half-bright, reverse-video, standout, underline. It may or
2184 may not turn off alt-char-mode. */
2185 if (face->tty_bold_p
2186 || face->tty_dim_p
2187 || face->tty_reverse_p
2188 || face->tty_alt_charset_p
2189 || face->tty_blinking_p
2190 || face->tty_underline_p)
2192 OUTPUT1_IF (tty, tty->TS_exit_attribute_mode);
2193 if (strcmp (tty->TS_exit_attribute_mode, tty->TS_end_standout_mode) == 0)
2194 tty->standout_mode = 0;
2197 if (face->tty_alt_charset_p)
2198 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
2200 else
2202 /* If we don't have "me" we can only have those appearances
2203 that have exit sequences defined. */
2204 if (face->tty_alt_charset_p)
2205 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
2207 if (face->tty_underline_p)
2208 OUTPUT_IF (tty, tty->TS_exit_underline_mode);
2211 /* Switch back to default colors. */
2212 if (tty->TN_max_colors > 0
2213 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
2214 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
2215 || (face->background != FACE_TTY_DEFAULT_COLOR
2216 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
2217 OUTPUT1_IF (tty, tty->TS_orig_pair);
2221 /* Return non-zero if the terminal on frame F supports all of the
2222 capabilities in CAPS simultaneously, with foreground and background
2223 colors FG and BG. */
2226 tty_capable_p (struct tty_display_info *tty, unsigned int caps,
2227 unsigned long fg, unsigned long bg)
2229 #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
2230 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
2231 return 0;
2233 TTY_CAPABLE_P_TRY (tty, TTY_CAP_INVERSE, tty->TS_standout_mode, NC_REVERSE);
2234 TTY_CAPABLE_P_TRY (tty, TTY_CAP_UNDERLINE, tty->TS_enter_underline_mode, NC_UNDERLINE);
2235 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BOLD, tty->TS_enter_bold_mode, NC_BOLD);
2236 TTY_CAPABLE_P_TRY (tty, TTY_CAP_DIM, tty->TS_enter_dim_mode, NC_DIM);
2237 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BLINK, tty->TS_enter_blink_mode, NC_BLINK);
2238 TTY_CAPABLE_P_TRY (tty, TTY_CAP_ALT_CHARSET, tty->TS_enter_alt_charset_mode, NC_ALT_CHARSET);
2240 /* We can do it! */
2241 return 1;
2244 /* Return non-zero if the terminal is capable to display colors. */
2246 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
2247 0, 1, 0,
2248 doc: /* Return non-nil if the tty device TERMINAL can display colors.
2250 TERMINAL can be a terminal object, a frame, or nil (meaning the
2251 selected frame's terminal). This function always returns nil if
2252 TERMINAL does not refer to a text-only terminal. */)
2253 (Lisp_Object terminal)
2255 struct terminal *t = get_tty_terminal (terminal, 0);
2256 if (!t)
2257 return Qnil;
2258 else
2259 return t->display_info.tty->TN_max_colors > 0 ? Qt : Qnil;
2262 /* Return the number of supported colors. */
2263 DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
2264 Stty_display_color_cells, 0, 1, 0,
2265 doc: /* Return the number of colors supported by the tty device TERMINAL.
2267 TERMINAL can be a terminal object, a frame, or nil (meaning the
2268 selected frame's terminal). This function always returns 0 if
2269 TERMINAL does not refer to a text-only terminal. */)
2270 (Lisp_Object terminal)
2272 struct terminal *t = get_tty_terminal (terminal, 0);
2273 if (!t)
2274 return make_number (0);
2275 else
2276 return make_number (t->display_info.tty->TN_max_colors);
2279 #ifndef DOS_NT
2281 /* Declare here rather than in the function, as in the rest of Emacs,
2282 to work around an HPUX compiler bug (?). See
2283 http://lists.gnu.org/archive/html/emacs-devel/2007-08/msg00410.html */
2284 static int default_max_colors;
2285 static int default_max_pairs;
2286 static int default_no_color_video;
2287 static char *default_orig_pair;
2288 static char *default_set_foreground;
2289 static char *default_set_background;
2291 /* Save or restore the default color-related capabilities of this
2292 terminal. */
2293 static void
2294 tty_default_color_capabilities (struct tty_display_info *tty, int save)
2297 if (save)
2299 xfree (default_orig_pair);
2300 default_orig_pair = tty->TS_orig_pair ? xstrdup (tty->TS_orig_pair) : NULL;
2302 xfree (default_set_foreground);
2303 default_set_foreground = tty->TS_set_foreground ? xstrdup (tty->TS_set_foreground)
2304 : NULL;
2306 xfree (default_set_background);
2307 default_set_background = tty->TS_set_background ? xstrdup (tty->TS_set_background)
2308 : NULL;
2310 default_max_colors = tty->TN_max_colors;
2311 default_max_pairs = tty->TN_max_pairs;
2312 default_no_color_video = tty->TN_no_color_video;
2314 else
2316 tty->TS_orig_pair = default_orig_pair;
2317 tty->TS_set_foreground = default_set_foreground;
2318 tty->TS_set_background = default_set_background;
2319 tty->TN_max_colors = default_max_colors;
2320 tty->TN_max_pairs = default_max_pairs;
2321 tty->TN_no_color_video = default_no_color_video;
2325 /* Setup one of the standard tty color schemes according to MODE.
2326 MODE's value is generally the number of colors which we want to
2327 support; zero means set up for the default capabilities, the ones
2328 we saw at init_tty time; -1 means turn off color support. */
2329 static void
2330 tty_setup_colors (struct tty_display_info *tty, int mode)
2332 /* Canonicalize all negative values of MODE. */
2333 if (mode < -1)
2334 mode = -1;
2336 switch (mode)
2338 case -1: /* no colors at all */
2339 tty->TN_max_colors = 0;
2340 tty->TN_max_pairs = 0;
2341 tty->TN_no_color_video = 0;
2342 tty->TS_set_foreground = tty->TS_set_background = tty->TS_orig_pair = NULL;
2343 break;
2344 case 0: /* default colors, if any */
2345 default:
2346 tty_default_color_capabilities (tty, 0);
2347 break;
2348 case 8: /* 8 standard ANSI colors */
2349 tty->TS_orig_pair = "\033[0m";
2350 #ifdef TERMINFO
2351 tty->TS_set_foreground = "\033[3%p1%dm";
2352 tty->TS_set_background = "\033[4%p1%dm";
2353 #else
2354 tty->TS_set_foreground = "\033[3%dm";
2355 tty->TS_set_background = "\033[4%dm";
2356 #endif
2357 tty->TN_max_colors = 8;
2358 tty->TN_max_pairs = 64;
2359 tty->TN_no_color_video = 0;
2360 break;
2364 void
2365 set_tty_color_mode (struct tty_display_info *tty, struct frame *f)
2367 Lisp_Object tem, val;
2368 Lisp_Object color_mode;
2369 int mode;
2370 Lisp_Object tty_color_mode_alist
2371 = Fintern_soft (build_string ("tty-color-mode-alist"), Qnil);
2373 tem = assq_no_quit (Qtty_color_mode, f->param_alist);
2374 val = CONSP (tem) ? XCDR (tem) : Qnil;
2376 if (INTEGERP (val))
2377 color_mode = val;
2378 else if (SYMBOLP (tty_color_mode_alist))
2380 tem = Fassq (val, Fsymbol_value (tty_color_mode_alist));
2381 color_mode = CONSP (tem) ? XCDR (tem) : Qnil;
2383 else
2384 color_mode = Qnil;
2386 mode = INTEGERP (color_mode) ? XINT (color_mode) : 0;
2388 if (mode != tty->previous_color_mode)
2390 Lisp_Object funsym = intern ("tty-set-up-initial-frame-faces");
2391 tty->previous_color_mode = mode;
2392 tty_setup_colors (tty , mode);
2393 /* This recomputes all the faces given the new color definitions. */
2394 safe_call (1, &funsym);
2398 #endif /* !DOS_NT */
2402 /* Return the tty display object specified by TERMINAL. */
2404 struct terminal *
2405 get_tty_terminal (Lisp_Object terminal, int throw)
2407 struct terminal *t = get_terminal (terminal, throw);
2409 if (t && t->type != output_termcap && t->type != output_msdos_raw)
2411 if (throw)
2412 error ("Device %d is not a termcap terminal device", t->id);
2413 else
2414 return NULL;
2417 return t;
2420 /* Return an active termcap device that uses the tty device with the
2421 given name.
2423 This function ignores suspended devices.
2425 Returns NULL if the named terminal device is not opened. */
2427 struct terminal *
2428 get_named_tty (const char *name)
2430 struct terminal *t;
2432 if (!name)
2433 abort ();
2435 for (t = terminal_list; t; t = t->next_terminal)
2437 if ((t->type == output_termcap || t->type == output_msdos_raw)
2438 && !strcmp (t->display_info.tty->name, name)
2439 && TERMINAL_ACTIVE_P (t))
2440 return t;
2443 return 0;
2447 DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0,
2448 doc: /* Return the type of the tty device that TERMINAL uses.
2449 Returns nil if TERMINAL is not on a tty device.
2451 TERMINAL can be a terminal object, a frame, or nil (meaning the
2452 selected frame's terminal). */)
2453 (Lisp_Object terminal)
2455 struct terminal *t = get_terminal (terminal, 1);
2457 if (t->type != output_termcap && t->type != output_msdos_raw)
2458 return Qnil;
2460 if (t->display_info.tty->type)
2461 return build_string (t->display_info.tty->type);
2462 else
2463 return Qnil;
2466 DEFUN ("controlling-tty-p", Fcontrolling_tty_p, Scontrolling_tty_p, 0, 1, 0,
2467 doc: /* Return non-nil if TERMINAL is the controlling tty of the Emacs process.
2469 TERMINAL can be a terminal object, a frame, or nil (meaning the
2470 selected frame's terminal). This function always returns nil if
2471 TERMINAL is not on a tty device. */)
2472 (Lisp_Object terminal)
2474 struct terminal *t = get_terminal (terminal, 1);
2476 if ((t->type != output_termcap && t->type != output_msdos_raw)
2477 || strcmp (t->display_info.tty->name, DEV_TTY) != 0)
2478 return Qnil;
2479 else
2480 return Qt;
2483 DEFUN ("tty-no-underline", Ftty_no_underline, Stty_no_underline, 0, 1, 0,
2484 doc: /* Declare that the tty used by TERMINAL does not handle underlining.
2485 This is used to override the terminfo data, for certain terminals that
2486 do not really do underlining, but say that they do. This function has
2487 no effect if used on a non-tty terminal.
2489 TERMINAL can be a terminal object, a frame or nil (meaning the
2490 selected frame's terminal). This function always returns nil if
2491 TERMINAL does not refer to a text-only terminal. */)
2492 (Lisp_Object terminal)
2494 struct terminal *t = get_terminal (terminal, 1);
2496 if (t->type == output_termcap)
2497 t->display_info.tty->TS_enter_underline_mode = 0;
2498 return Qnil;
2503 DEFUN ("suspend-tty", Fsuspend_tty, Ssuspend_tty, 0, 1, 0,
2504 doc: /* Suspend the terminal device TTY.
2506 The device is restored to its default state, and Emacs ceases all
2507 access to the tty device. Frames that use the device are not deleted,
2508 but input is not read from them and if they change, their display is
2509 not updated.
2511 TTY may be a terminal object, a frame, or nil for the terminal device
2512 of the currently selected frame.
2514 This function runs `suspend-tty-functions' after suspending the
2515 device. The functions are run with one arg, the id of the suspended
2516 terminal device.
2518 `suspend-tty' does nothing if it is called on a device that is already
2519 suspended.
2521 A suspended tty may be resumed by calling `resume-tty' on it. */)
2522 (Lisp_Object tty)
2524 struct terminal *t = get_tty_terminal (tty, 1);
2525 FILE *f;
2527 if (!t)
2528 error ("Unknown tty device");
2530 f = t->display_info.tty->input;
2532 if (f)
2534 /* First run `suspend-tty-functions' and then clean up the tty
2535 state because `suspend-tty-functions' might need to change
2536 the tty state. */
2537 if (!NILP (Vrun_hooks))
2539 Lisp_Object args[2];
2540 args[0] = intern ("suspend-tty-functions");
2541 XSETTERMINAL (args[1], t);
2542 Frun_hook_with_args (2, args);
2545 reset_sys_modes (t->display_info.tty);
2546 delete_keyboard_wait_descriptor (fileno (f));
2548 #ifndef MSDOS
2549 fclose (f);
2550 if (f != t->display_info.tty->output)
2551 fclose (t->display_info.tty->output);
2552 #endif
2554 t->display_info.tty->input = 0;
2555 t->display_info.tty->output = 0;
2557 if (FRAMEP (t->display_info.tty->top_frame))
2558 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0);
2562 /* Clear display hooks to prevent further output. */
2563 clear_tty_hooks (t);
2565 return Qnil;
2568 DEFUN ("resume-tty", Fresume_tty, Sresume_tty, 0, 1, 0,
2569 doc: /* Resume the previously suspended terminal device TTY.
2570 The terminal is opened and reinitialized. Frames that are on the
2571 suspended terminal are revived.
2573 It is an error to resume a terminal while another terminal is active
2574 on the same device.
2576 This function runs `resume-tty-functions' after resuming the terminal.
2577 The functions are run with one arg, the id of the resumed terminal
2578 device.
2580 `resume-tty' does nothing if it is called on a device that is not
2581 suspended.
2583 TTY may be a terminal object, a frame, or nil (meaning the selected
2584 frame's terminal). */)
2585 (Lisp_Object tty)
2587 struct terminal *t = get_tty_terminal (tty, 1);
2588 int fd;
2590 if (!t)
2591 error ("Unknown tty device");
2593 if (!t->display_info.tty->input)
2595 if (get_named_tty (t->display_info.tty->name))
2596 error ("Cannot resume display while another display is active on the same device");
2598 #ifdef MSDOS
2599 t->display_info.tty->output = stdout;
2600 t->display_info.tty->input = stdin;
2601 #else /* !MSDOS */
2602 fd = emacs_open (t->display_info.tty->name, O_RDWR | O_NOCTTY, 0);
2604 if (fd == -1)
2605 error ("Can not reopen tty device %s: %s", t->display_info.tty->name, strerror (errno));
2607 if (strcmp (t->display_info.tty->name, DEV_TTY))
2608 dissociate_if_controlling_tty (fd);
2610 t->display_info.tty->output = fdopen (fd, "w+");
2611 t->display_info.tty->input = t->display_info.tty->output;
2612 #endif
2614 add_keyboard_wait_descriptor (fd);
2616 if (FRAMEP (t->display_info.tty->top_frame))
2618 struct frame *f = XFRAME (t->display_info.tty->top_frame);
2619 int width, height;
2620 int old_height = FRAME_COLS (f);
2621 int old_width = FRAME_LINES (f);
2623 /* Check if terminal/window size has changed while the frame
2624 was suspended. */
2625 get_tty_size (fileno (t->display_info.tty->input), &width, &height);
2626 if (width != old_width || height != old_height)
2627 change_frame_size (f, height, width, 0, 0, 0);
2628 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
2631 init_sys_modes (t->display_info.tty);
2633 /* Run `resume-tty-functions'. */
2634 if (!NILP (Vrun_hooks))
2636 Lisp_Object args[2];
2637 args[0] = intern ("resume-tty-functions");
2638 XSETTERMINAL (args[1], t);
2639 Frun_hook_with_args (2, args);
2643 set_tty_hooks (t);
2645 return Qnil;
2649 /***********************************************************************
2650 Mouse
2651 ***********************************************************************/
2653 #ifdef HAVE_GPM
2654 void
2655 term_mouse_moveto (int x, int y)
2657 /* TODO: how to set mouse position?
2658 const char *name;
2659 int fd;
2660 name = (const char *) ttyname (0);
2661 fd = open (name, O_WRONLY);
2662 SOME_FUNCTION (x, y, fd);
2663 close (fd);
2664 last_mouse_x = x;
2665 last_mouse_y = y; */
2668 /* Implementation of draw_row_with_mouse_face for TTY/GPM. */
2669 void
2670 tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *row,
2671 int start_hpos, int end_hpos,
2672 enum draw_glyphs_face draw)
2674 int nglyphs = end_hpos - start_hpos;
2675 struct frame *f = XFRAME (WINDOW_FRAME (w));
2676 struct tty_display_info *tty = FRAME_TTY (f);
2677 int face_id = tty->mouse_highlight.mouse_face_face_id;
2678 int save_x, save_y, pos_x, pos_y;
2680 if (end_hpos >= row->used[TEXT_AREA])
2681 nglyphs = row->used[TEXT_AREA] - start_hpos;
2683 pos_y = row->y + WINDOW_TOP_EDGE_Y (w);
2684 pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos + WINDOW_LEFT_EDGE_X (w);
2686 /* Save current cursor co-ordinates. */
2687 save_y = curY (tty);
2688 save_x = curX (tty);
2689 cursor_to (f, pos_y, pos_x);
2691 if (draw == DRAW_MOUSE_FACE)
2692 tty_write_glyphs_with_face (f, row->glyphs[TEXT_AREA] + start_hpos,
2693 nglyphs, face_id);
2694 else if (draw == DRAW_NORMAL_TEXT)
2695 write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
2697 cursor_to (f, save_y, save_x);
2700 static int
2701 term_mouse_movement (FRAME_PTR frame, Gpm_Event *event)
2703 /* Has the mouse moved off the glyph it was on at the last sighting? */
2704 if (event->x != last_mouse_x || event->y != last_mouse_y)
2706 frame->mouse_moved = 1;
2707 note_mouse_highlight (frame, event->x, event->y);
2708 /* Remember which glyph we're now on. */
2709 last_mouse_x = event->x;
2710 last_mouse_y = event->y;
2711 return 1;
2713 return 0;
2716 /* Return the current position of the mouse.
2718 Set *f to the frame the mouse is in, or zero if the mouse is in no
2719 Emacs frame. If it is set to zero, all the other arguments are
2720 garbage.
2722 Set *bar_window to Qnil, and *x and *y to the column and
2723 row of the character cell the mouse is over.
2725 Set *time to the time the mouse was at the returned position.
2727 This clears mouse_moved until the next motion
2728 event arrives. */
2729 static void
2730 term_mouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
2731 enum scroll_bar_part *part, Lisp_Object *x,
2732 Lisp_Object *y, unsigned long *time)
2734 struct timeval now;
2736 *fp = SELECTED_FRAME ();
2737 (*fp)->mouse_moved = 0;
2739 *bar_window = Qnil;
2740 *part = 0;
2742 XSETINT (*x, last_mouse_x);
2743 XSETINT (*y, last_mouse_y);
2744 gettimeofday(&now, 0);
2745 *time = (now.tv_sec * 1000) + (now.tv_usec / 1000);
2748 /* Prepare a mouse-event in *RESULT for placement in the input queue.
2750 If the event is a button press, then note that we have grabbed
2751 the mouse. */
2753 static Lisp_Object
2754 term_mouse_click (struct input_event *result, Gpm_Event *event,
2755 struct frame *f)
2757 struct timeval now;
2758 int i, j;
2760 result->kind = GPM_CLICK_EVENT;
2761 for (i = 0, j = GPM_B_LEFT; i < 3; i++, j >>= 1 )
2763 if (event->buttons & j) {
2764 result->code = i; /* button number */
2765 break;
2768 gettimeofday(&now, 0);
2769 result->timestamp = (now.tv_sec * 1000) + (now.tv_usec / 1000);
2771 if (event->type & GPM_UP)
2772 result->modifiers = up_modifier;
2773 else if (event->type & GPM_DOWN)
2774 result->modifiers = down_modifier;
2775 else
2776 result->modifiers = 0;
2778 if (event->type & GPM_SINGLE)
2779 result->modifiers |= click_modifier;
2781 if (event->type & GPM_DOUBLE)
2782 result->modifiers |= double_modifier;
2784 if (event->type & GPM_TRIPLE)
2785 result->modifiers |= triple_modifier;
2787 if (event->type & GPM_DRAG)
2788 result->modifiers |= drag_modifier;
2790 if (!(event->type & (GPM_MOVE | GPM_DRAG))) {
2792 /* 1 << KG_SHIFT */
2793 if (event->modifiers & (1 << 0))
2794 result->modifiers |= shift_modifier;
2796 /* 1 << KG_CTRL */
2797 if (event->modifiers & (1 << 2))
2798 result->modifiers |= ctrl_modifier;
2800 /* 1 << KG_ALT || KG_ALTGR */
2801 if (event->modifiers & (1 << 3)
2802 || event->modifiers & (1 << 1))
2803 result->modifiers |= meta_modifier;
2806 XSETINT (result->x, event->x);
2807 XSETINT (result->y, event->y);
2808 XSETFRAME (result->frame_or_window, f);
2809 result->arg = Qnil;
2810 return Qnil;
2814 handle_one_term_event (struct tty_display_info *tty, Gpm_Event *event, struct input_event* hold_quit)
2816 struct frame *f = XFRAME (tty->top_frame);
2817 struct input_event ie;
2818 int do_help = 0;
2819 int count = 0;
2821 EVENT_INIT (ie);
2822 ie.kind = NO_EVENT;
2823 ie.arg = Qnil;
2825 if (event->type & (GPM_MOVE | GPM_DRAG)) {
2826 previous_help_echo_string = help_echo_string;
2827 help_echo_string = Qnil;
2829 Gpm_DrawPointer (event->x, event->y, fileno (tty->output));
2831 if (!term_mouse_movement (f, event))
2832 help_echo_string = previous_help_echo_string;
2834 /* If the contents of the global variable help_echo_string
2835 has changed, generate a HELP_EVENT. */
2836 if (!NILP (help_echo_string)
2837 || !NILP (previous_help_echo_string))
2838 do_help = 1;
2840 goto done;
2842 else {
2843 f->mouse_moved = 0;
2844 term_mouse_click (&ie, event, f);
2847 done:
2848 if (ie.kind != NO_EVENT)
2850 kbd_buffer_store_event_hold (&ie, hold_quit);
2851 count++;
2854 if (do_help
2855 && !(hold_quit && hold_quit->kind != NO_EVENT))
2857 Lisp_Object frame;
2859 if (f)
2860 XSETFRAME (frame, f);
2861 else
2862 frame = Qnil;
2864 gen_help_event (help_echo_string, frame, help_echo_window,
2865 help_echo_object, help_echo_pos);
2866 count++;
2869 return count;
2872 DEFUN ("gpm-mouse-start", Fgpm_mouse_start, Sgpm_mouse_start,
2873 0, 0, 0,
2874 doc: /* Open a connection to Gpm.
2875 Gpm-mouse can only be activated for one tty at a time. */)
2876 (void)
2878 struct frame *f = SELECTED_FRAME ();
2879 struct tty_display_info *tty
2880 = ((f)->output_method == output_termcap
2881 ? (f)->terminal->display_info.tty : NULL);
2882 Gpm_Connect connection;
2884 if (!tty)
2885 error ("Gpm-mouse only works in the GNU/Linux console");
2886 if (gpm_tty == tty)
2887 return Qnil; /* Already activated, nothing to do. */
2888 if (gpm_tty)
2889 error ("Gpm-mouse can only be activated for one tty at a time");
2891 connection.eventMask = ~0;
2892 connection.defaultMask = ~GPM_HARD;
2893 connection.maxMod = ~0;
2894 connection.minMod = 0;
2895 gpm_zerobased = 1;
2897 if (Gpm_Open (&connection, 0) < 0)
2898 error ("Gpm-mouse failed to connect to the gpm daemon");
2899 else
2901 gpm_tty = tty;
2902 /* `init_sys_modes' arranges for mouse movements sent through gpm_fd
2903 to generate SIGIOs. Apparently we need to call reset_sys_modes
2904 before calling init_sys_modes. */
2905 reset_sys_modes (tty);
2906 init_sys_modes (tty);
2907 add_gpm_wait_descriptor (gpm_fd);
2908 return Qnil;
2912 void
2913 close_gpm (int fd)
2915 if (fd >= 0)
2916 delete_gpm_wait_descriptor (fd);
2917 while (Gpm_Close()); /* close all the stack */
2918 gpm_tty = NULL;
2921 DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop, Sgpm_mouse_stop,
2922 0, 0, 0,
2923 doc: /* Close a connection to Gpm. */)
2924 (void)
2926 struct frame *f = SELECTED_FRAME ();
2927 struct tty_display_info *tty
2928 = ((f)->output_method == output_termcap
2929 ? (f)->terminal->display_info.tty : NULL);
2931 if (!tty || gpm_tty != tty)
2932 return Qnil; /* Not activated on this terminal, nothing to do. */
2934 close_gpm (gpm_fd);
2935 return Qnil;
2937 #endif /* HAVE_GPM */
2940 #ifndef MSDOS
2941 /***********************************************************************
2942 Initialization
2943 ***********************************************************************/
2945 /* Initialize the tty-dependent part of frame F. The frame must
2946 already have its device initialized. */
2948 void
2949 create_tty_output (struct frame *f)
2951 struct tty_output *t;
2953 if (! FRAME_TERMCAP_P (f))
2954 abort ();
2956 t = xmalloc (sizeof (struct tty_output));
2957 memset (t, 0, sizeof (struct tty_output));
2959 t->display_info = FRAME_TERMINAL (f)->display_info.tty;
2961 f->output_data.tty = t;
2964 /* Delete frame F's face cache, and its tty-dependent part. */
2966 static void
2967 tty_free_frame_resources (struct frame *f)
2969 if (! FRAME_TERMCAP_P (f))
2970 abort ();
2972 if (FRAME_FACE_CACHE (f))
2973 free_frame_faces (f);
2975 xfree (f->output_data.tty);
2978 #else /* MSDOS */
2980 /* Delete frame F's face cache. */
2982 static void
2983 tty_free_frame_resources (struct frame *f)
2985 if (! FRAME_TERMCAP_P (f) && ! FRAME_MSDOS_P (f))
2986 abort ();
2988 if (FRAME_FACE_CACHE (f))
2989 free_frame_faces (f);
2991 #endif /* MSDOS */
2993 /* Reset the hooks in TERMINAL. */
2995 static void
2996 clear_tty_hooks (struct terminal *terminal)
2998 terminal->rif = 0;
2999 terminal->cursor_to_hook = 0;
3000 terminal->raw_cursor_to_hook = 0;
3001 terminal->clear_to_end_hook = 0;
3002 terminal->clear_frame_hook = 0;
3003 terminal->clear_end_of_line_hook = 0;
3004 terminal->ins_del_lines_hook = 0;
3005 terminal->insert_glyphs_hook = 0;
3006 terminal->write_glyphs_hook = 0;
3007 terminal->delete_glyphs_hook = 0;
3008 terminal->ring_bell_hook = 0;
3009 terminal->reset_terminal_modes_hook = 0;
3010 terminal->set_terminal_modes_hook = 0;
3011 terminal->update_begin_hook = 0;
3012 terminal->update_end_hook = 0;
3013 terminal->set_terminal_window_hook = 0;
3014 terminal->mouse_position_hook = 0;
3015 terminal->frame_rehighlight_hook = 0;
3016 terminal->frame_raise_lower_hook = 0;
3017 terminal->fullscreen_hook = 0;
3018 terminal->set_vertical_scroll_bar_hook = 0;
3019 terminal->condemn_scroll_bars_hook = 0;
3020 terminal->redeem_scroll_bar_hook = 0;
3021 terminal->judge_scroll_bars_hook = 0;
3022 terminal->read_socket_hook = 0;
3023 terminal->frame_up_to_date_hook = 0;
3025 /* Leave these two set, or suspended frames are not deleted
3026 correctly. */
3027 terminal->delete_frame_hook = &tty_free_frame_resources;
3028 terminal->delete_terminal_hook = &delete_tty;
3031 /* Initialize hooks in TERMINAL with the values needed for a tty. */
3033 static void
3034 set_tty_hooks (struct terminal *terminal)
3036 terminal->rif = 0; /* ttys don't support window-based redisplay. */
3038 terminal->cursor_to_hook = &tty_cursor_to;
3039 terminal->raw_cursor_to_hook = &tty_raw_cursor_to;
3041 terminal->clear_to_end_hook = &tty_clear_to_end;
3042 terminal->clear_frame_hook = &tty_clear_frame;
3043 terminal->clear_end_of_line_hook = &tty_clear_end_of_line;
3045 terminal->ins_del_lines_hook = &tty_ins_del_lines;
3047 terminal->insert_glyphs_hook = &tty_insert_glyphs;
3048 terminal->write_glyphs_hook = &tty_write_glyphs;
3049 terminal->delete_glyphs_hook = &tty_delete_glyphs;
3051 terminal->ring_bell_hook = &tty_ring_bell;
3053 terminal->reset_terminal_modes_hook = &tty_reset_terminal_modes;
3054 terminal->set_terminal_modes_hook = &tty_set_terminal_modes;
3055 terminal->update_begin_hook = 0; /* Not needed. */
3056 terminal->update_end_hook = &tty_update_end;
3057 terminal->set_terminal_window_hook = &tty_set_terminal_window;
3059 terminal->mouse_position_hook = 0; /* Not needed. */
3060 terminal->frame_rehighlight_hook = 0; /* Not needed. */
3061 terminal->frame_raise_lower_hook = 0; /* Not needed. */
3063 terminal->set_vertical_scroll_bar_hook = 0; /* Not needed. */
3064 terminal->condemn_scroll_bars_hook = 0; /* Not needed. */
3065 terminal->redeem_scroll_bar_hook = 0; /* Not needed. */
3066 terminal->judge_scroll_bars_hook = 0; /* Not needed. */
3068 terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */
3069 terminal->frame_up_to_date_hook = 0; /* Not needed. */
3071 terminal->delete_frame_hook = &tty_free_frame_resources;
3072 terminal->delete_terminal_hook = &delete_tty;
3075 /* Drop the controlling terminal if fd is the same device. */
3076 static void
3077 dissociate_if_controlling_tty (int fd)
3079 #ifndef DOS_NT
3080 int pgid = tcgetpgrp (fd); /* If tcgetpgrp succeeds, fd is the ctty. */
3081 if (pgid != -1)
3083 #if defined (USG5)
3084 setpgrp ();
3085 no_controlling_tty = 1;
3086 #elif defined (CYGWIN)
3087 setsid ();
3088 no_controlling_tty = 1;
3089 #else
3090 #ifdef TIOCNOTTY /* Try BSD ioctls. */
3091 sigblock (sigmask (SIGTTOU));
3092 fd = emacs_open (DEV_TTY, O_RDWR, 0);
3093 if (fd != -1 && ioctl (fd, TIOCNOTTY, 0) != -1)
3095 no_controlling_tty = 1;
3097 if (fd != -1)
3098 emacs_close (fd);
3099 sigunblock (sigmask (SIGTTOU));
3100 #else
3101 /* Unknown system. */
3102 croak ();
3103 #endif /* ! TIOCNOTTY */
3104 #endif /* ! USG */
3106 #endif /* !DOS_NT */
3109 /* Create a termcap display on the tty device with the given name and
3110 type.
3112 If NAME is NULL, then use the controlling tty, i.e., "/dev/tty".
3113 Otherwise NAME should be a path to the tty device file,
3114 e.g. "/dev/pts/7".
3116 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
3118 If MUST_SUCCEED is true, then all errors are fatal. */
3120 struct terminal *
3121 init_tty (const char *name, const char *terminal_type, int must_succeed)
3123 char *area = NULL;
3124 char **address = &area;
3125 int buffer_size = 4096;
3126 register char *p = NULL;
3127 int status;
3128 struct tty_display_info *tty = NULL;
3129 struct terminal *terminal = NULL;
3130 int ctty = 0; /* 1 if asked to open controlling tty. */
3132 if (!terminal_type)
3133 maybe_fatal (must_succeed, 0,
3134 "Unknown terminal type",
3135 "Unknown terminal type");
3137 if (name == NULL)
3138 name = DEV_TTY;
3139 if (!strcmp (name, DEV_TTY))
3140 ctty = 1;
3142 /* If we already have a terminal on the given device, use that. If
3143 all such terminals are suspended, create a new one instead. */
3144 /* XXX Perhaps this should be made explicit by having init_tty
3145 always create a new terminal and separating terminal and frame
3146 creation on Lisp level. */
3147 terminal = get_named_tty (name);
3148 if (terminal)
3149 return terminal;
3151 terminal = create_terminal ();
3152 #ifdef MSDOS
3153 if (been_here > 0)
3154 maybe_fatal (1, 0, "Attempt to create another terminal %s", "",
3155 name, "");
3156 been_here = 1;
3157 tty = &the_only_display_info;
3158 #else
3159 tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info));
3160 #endif
3161 memset (tty, 0, sizeof (struct tty_display_info));
3162 tty->next = tty_list;
3163 tty_list = tty;
3165 terminal->type = output_termcap;
3166 terminal->display_info.tty = tty;
3167 tty->terminal = terminal;
3169 tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
3170 Wcm_clear (tty);
3172 encode_terminal_src_size = 0;
3173 encode_terminal_dst_size = 0;
3175 #ifdef HAVE_GPM
3176 terminal->mouse_position_hook = term_mouse_position;
3177 tty->mouse_highlight.mouse_face_window = Qnil;
3178 #endif
3181 #ifndef DOS_NT
3182 set_tty_hooks (terminal);
3185 int fd;
3186 FILE *file;
3188 #ifdef O_IGNORE_CTTY
3189 if (!ctty)
3190 /* Open the terminal device. Don't recognize it as our
3191 controlling terminal, and don't make it the controlling tty
3192 if we don't have one at the moment. */
3193 fd = emacs_open (name, O_RDWR | O_IGNORE_CTTY | O_NOCTTY, 0);
3194 else
3195 #else
3196 /* Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
3197 defined on Hurd. On other systems, we need to explicitly
3198 dissociate ourselves from the controlling tty when we want to
3199 open a frame on the same terminal. */
3200 fd = emacs_open (name, O_RDWR | O_NOCTTY, 0);
3201 #endif /* O_IGNORE_CTTY */
3203 tty->name = xstrdup (name);
3204 terminal->name = xstrdup (name);
3206 if (fd < 0)
3207 maybe_fatal (must_succeed, terminal,
3208 "Could not open file: %s",
3209 "Could not open file: %s",
3210 name);
3211 if (!isatty (fd))
3213 close (fd);
3214 maybe_fatal (must_succeed, terminal,
3215 "Not a tty device: %s",
3216 "Not a tty device: %s",
3217 name);
3220 #ifndef O_IGNORE_CTTY
3221 if (!ctty)
3222 dissociate_if_controlling_tty (fd);
3223 #endif
3225 file = fdopen (fd, "w+");
3226 tty->input = file;
3227 tty->output = file;
3230 tty->type = xstrdup (terminal_type);
3232 add_keyboard_wait_descriptor (fileno (tty->input));
3234 Wcm_clear (tty);
3236 tty->termcap_term_buffer = (char *) xmalloc (buffer_size);
3238 /* On some systems, tgetent tries to access the controlling
3239 terminal. */
3240 sigblock (sigmask (SIGTTOU));
3241 status = tgetent (tty->termcap_term_buffer, terminal_type);
3242 sigunblock (sigmask (SIGTTOU));
3244 if (status < 0)
3246 #ifdef TERMINFO
3247 maybe_fatal (must_succeed, terminal,
3248 "Cannot open terminfo database file",
3249 "Cannot open terminfo database file");
3250 #else
3251 maybe_fatal (must_succeed, terminal,
3252 "Cannot open termcap database file",
3253 "Cannot open termcap database file");
3254 #endif
3256 if (status == 0)
3258 maybe_fatal (must_succeed, terminal,
3259 "Terminal type %s is not defined",
3260 "Terminal type %s is not defined.\n\
3261 If that is not the actual type of terminal you have,\n\
3262 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3263 `setenv TERM ...') to specify the correct type. It may be necessary\n"
3264 #ifdef TERMINFO
3265 "to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3266 #else
3267 "to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3268 #endif
3269 terminal_type);
3272 #ifndef TERMINFO
3273 if (strlen (tty->termcap_term_buffer) >= buffer_size)
3274 abort ();
3275 buffer_size = strlen (tty->termcap_term_buffer);
3276 #endif
3277 tty->termcap_strings_buffer = area = (char *) xmalloc (buffer_size);
3278 tty->TS_ins_line = tgetstr ("al", address);
3279 tty->TS_ins_multi_lines = tgetstr ("AL", address);
3280 tty->TS_bell = tgetstr ("bl", address);
3281 BackTab (tty) = tgetstr ("bt", address);
3282 tty->TS_clr_to_bottom = tgetstr ("cd", address);
3283 tty->TS_clr_line = tgetstr ("ce", address);
3284 tty->TS_clr_frame = tgetstr ("cl", address);
3285 ColPosition (tty) = NULL; /* tgetstr ("ch", address); */
3286 AbsPosition (tty) = tgetstr ("cm", address);
3287 CR (tty) = tgetstr ("cr", address);
3288 tty->TS_set_scroll_region = tgetstr ("cs", address);
3289 tty->TS_set_scroll_region_1 = tgetstr ("cS", address);
3290 RowPosition (tty) = tgetstr ("cv", address);
3291 tty->TS_del_char = tgetstr ("dc", address);
3292 tty->TS_del_multi_chars = tgetstr ("DC", address);
3293 tty->TS_del_line = tgetstr ("dl", address);
3294 tty->TS_del_multi_lines = tgetstr ("DL", address);
3295 tty->TS_delete_mode = tgetstr ("dm", address);
3296 tty->TS_end_delete_mode = tgetstr ("ed", address);
3297 tty->TS_end_insert_mode = tgetstr ("ei", address);
3298 Home (tty) = tgetstr ("ho", address);
3299 tty->TS_ins_char = tgetstr ("ic", address);
3300 tty->TS_ins_multi_chars = tgetstr ("IC", address);
3301 tty->TS_insert_mode = tgetstr ("im", address);
3302 tty->TS_pad_inserted_char = tgetstr ("ip", address);
3303 tty->TS_end_keypad_mode = tgetstr ("ke", address);
3304 tty->TS_keypad_mode = tgetstr ("ks", address);
3305 LastLine (tty) = tgetstr ("ll", address);
3306 Right (tty) = tgetstr ("nd", address);
3307 Down (tty) = tgetstr ("do", address);
3308 if (!Down (tty))
3309 Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do" */
3310 if (tgetflag ("bs"))
3311 Left (tty) = "\b"; /* can't possibly be longer! */
3312 else /* (Actually, "bs" is obsolete...) */
3313 Left (tty) = tgetstr ("le", address);
3314 if (!Left (tty))
3315 Left (tty) = tgetstr ("bc", address); /* Obsolete name for "le" */
3316 tty->TS_pad_char = tgetstr ("pc", address);
3317 tty->TS_repeat = tgetstr ("rp", address);
3318 tty->TS_end_standout_mode = tgetstr ("se", address);
3319 tty->TS_fwd_scroll = tgetstr ("sf", address);
3320 tty->TS_standout_mode = tgetstr ("so", address);
3321 tty->TS_rev_scroll = tgetstr ("sr", address);
3322 tty->Wcm->cm_tab = tgetstr ("ta", address);
3323 tty->TS_end_termcap_modes = tgetstr ("te", address);
3324 tty->TS_termcap_modes = tgetstr ("ti", address);
3325 Up (tty) = tgetstr ("up", address);
3326 tty->TS_visible_bell = tgetstr ("vb", address);
3327 tty->TS_cursor_normal = tgetstr ("ve", address);
3328 tty->TS_cursor_visible = tgetstr ("vs", address);
3329 tty->TS_cursor_invisible = tgetstr ("vi", address);
3330 tty->TS_set_window = tgetstr ("wi", address);
3332 tty->TS_enter_underline_mode = tgetstr ("us", address);
3333 tty->TS_exit_underline_mode = tgetstr ("ue", address);
3334 tty->TS_enter_bold_mode = tgetstr ("md", address);
3335 tty->TS_enter_dim_mode = tgetstr ("mh", address);
3336 tty->TS_enter_blink_mode = tgetstr ("mb", address);
3337 tty->TS_enter_reverse_mode = tgetstr ("mr", address);
3338 tty->TS_enter_alt_charset_mode = tgetstr ("as", address);
3339 tty->TS_exit_alt_charset_mode = tgetstr ("ae", address);
3340 tty->TS_exit_attribute_mode = tgetstr ("me", address);
3342 MultiUp (tty) = tgetstr ("UP", address);
3343 MultiDown (tty) = tgetstr ("DO", address);
3344 MultiLeft (tty) = tgetstr ("LE", address);
3345 MultiRight (tty) = tgetstr ("RI", address);
3347 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
3348 color because we can't switch back to the default foreground and
3349 background. */
3350 tty->TS_orig_pair = tgetstr ("op", address);
3351 if (tty->TS_orig_pair)
3353 tty->TS_set_foreground = tgetstr ("AF", address);
3354 tty->TS_set_background = tgetstr ("AB", address);
3355 if (!tty->TS_set_foreground)
3357 /* SVr4. */
3358 tty->TS_set_foreground = tgetstr ("Sf", address);
3359 tty->TS_set_background = tgetstr ("Sb", address);
3362 tty->TN_max_colors = tgetnum ("Co");
3363 tty->TN_max_pairs = tgetnum ("pa");
3365 tty->TN_no_color_video = tgetnum ("NC");
3366 if (tty->TN_no_color_video == -1)
3367 tty->TN_no_color_video = 0;
3370 tty_default_color_capabilities (tty, 1);
3372 MagicWrap (tty) = tgetflag ("xn");
3373 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
3374 the former flag imply the latter. */
3375 AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
3376 terminal->memory_below_frame = tgetflag ("db");
3377 tty->TF_hazeltine = tgetflag ("hz");
3378 terminal->must_write_spaces = tgetflag ("in");
3379 tty->meta_key = tgetflag ("km") || tgetflag ("MT");
3380 tty->TF_insmode_motion = tgetflag ("mi");
3381 tty->TF_standout_motion = tgetflag ("ms");
3382 tty->TF_underscore = tgetflag ("ul");
3383 tty->TF_teleray = tgetflag ("xt");
3385 #else /* DOS_NT */
3386 #ifdef WINDOWSNT
3388 struct frame *f = XFRAME (selected_frame);
3390 initialize_w32_display (terminal);
3392 FrameRows (tty) = FRAME_LINES (f);
3393 FrameCols (tty) = FRAME_COLS (f);
3394 tty->specified_window = FRAME_LINES (f);
3396 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
3397 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
3398 terminal->char_ins_del_ok = 1;
3399 baud_rate = 19200;
3401 #else /* MSDOS */
3403 int height, width;
3404 if (strcmp (terminal_type, "internal") == 0)
3405 terminal->type = output_msdos_raw;
3406 initialize_msdos_display (terminal);
3408 get_tty_size (fileno (tty->input), &width, &height);
3409 FrameCols (tty) = width;
3410 FrameRows (tty) = height;
3411 terminal->char_ins_del_ok = 0;
3412 init_baud_rate (fileno (tty->input));
3414 #endif /* MSDOS */
3415 tty->output = stdout;
3416 tty->input = stdin;
3417 /* The following two are inaccessible from w32console.c. */
3418 terminal->delete_frame_hook = &tty_free_frame_resources;
3419 terminal->delete_terminal_hook = &delete_tty;
3421 tty->name = xstrdup (name);
3422 terminal->name = xstrdup (name);
3423 tty->type = xstrdup (terminal_type);
3425 add_keyboard_wait_descriptor (0);
3427 tty->delete_in_insert_mode = 1;
3429 UseTabs (tty) = 0;
3430 terminal->scroll_region_ok = 0;
3432 /* Seems to insert lines when it's not supposed to, messing up the
3433 display. In doing a trace, it didn't seem to be called much, so I
3434 don't think we're losing anything by turning it off. */
3435 terminal->line_ins_del_ok = 0;
3437 tty->TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
3438 #endif /* DOS_NT */
3440 terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
3441 init_kboard (terminal->kboard);
3442 terminal->kboard->Vwindow_system = Qnil;
3443 terminal->kboard->next_kboard = all_kboards;
3444 all_kboards = terminal->kboard;
3445 terminal->kboard->reference_count++;
3446 /* Don't let the initial kboard remain current longer than necessary.
3447 That would cause problems if a file loaded on startup tries to
3448 prompt in the mini-buffer. */
3449 if (current_kboard == initial_kboard)
3450 current_kboard = terminal->kboard;
3451 #ifndef DOS_NT
3452 term_get_fkeys (address, terminal->kboard);
3454 /* Get frame size from system, or else from termcap. */
3456 int height, width;
3457 get_tty_size (fileno (tty->input), &width, &height);
3458 FrameCols (tty) = width;
3459 FrameRows (tty) = height;
3462 if (FrameCols (tty) <= 0)
3463 FrameCols (tty) = tgetnum ("co");
3464 if (FrameRows (tty) <= 0)
3465 FrameRows (tty) = tgetnum ("li");
3467 if (FrameRows (tty) < 3 || FrameCols (tty) < 3)
3468 maybe_fatal (must_succeed, terminal,
3469 "Screen size %dx%d is too small",
3470 "Screen size %dx%d is too small",
3471 FrameCols (tty), FrameRows (tty));
3473 TabWidth (tty) = tgetnum ("tw");
3475 if (!tty->TS_bell)
3476 tty->TS_bell = "\07";
3478 if (!tty->TS_fwd_scroll)
3479 tty->TS_fwd_scroll = Down (tty);
3481 PC = tty->TS_pad_char ? *tty->TS_pad_char : 0;
3483 if (TabWidth (tty) < 0)
3484 TabWidth (tty) = 8;
3486 /* Turned off since /etc/termcap seems to have :ta= for most terminals
3487 and newer termcap doc does not seem to say there is a default.
3488 if (!tty->Wcm->cm_tab)
3489 tty->Wcm->cm_tab = "\t";
3492 /* We don't support standout modes that use `magic cookies', so
3493 turn off any that do. */
3494 if (tty->TS_standout_mode && tgetnum ("sg") >= 0)
3496 tty->TS_standout_mode = 0;
3497 tty->TS_end_standout_mode = 0;
3499 if (tty->TS_enter_underline_mode && tgetnum ("ug") >= 0)
3501 tty->TS_enter_underline_mode = 0;
3502 tty->TS_exit_underline_mode = 0;
3505 /* If there's no standout mode, try to use underlining instead. */
3506 if (tty->TS_standout_mode == 0)
3508 tty->TS_standout_mode = tty->TS_enter_underline_mode;
3509 tty->TS_end_standout_mode = tty->TS_exit_underline_mode;
3512 /* If no `se' string, try using a `me' string instead.
3513 If that fails, we can't use standout mode at all. */
3514 if (tty->TS_end_standout_mode == 0)
3516 char *s = tgetstr ("me", address);
3517 if (s != 0)
3518 tty->TS_end_standout_mode = s;
3519 else
3520 tty->TS_standout_mode = 0;
3523 if (tty->TF_teleray)
3525 tty->Wcm->cm_tab = 0;
3526 /* We can't support standout mode, because it uses magic cookies. */
3527 tty->TS_standout_mode = 0;
3528 /* But that means we cannot rely on ^M to go to column zero! */
3529 CR (tty) = 0;
3530 /* LF can't be trusted either -- can alter hpos */
3531 /* if move at column 0 thru a line with TS_standout_mode */
3532 Down (tty) = 0;
3535 /* Special handling for certain terminal types known to need it */
3537 if (!strcmp (terminal_type, "supdup"))
3539 terminal->memory_below_frame = 1;
3540 tty->Wcm->cm_losewrap = 1;
3542 if (!strncmp (terminal_type, "c10", 3)
3543 || !strcmp (terminal_type, "perq"))
3545 /* Supply a makeshift :wi string.
3546 This string is not valid in general since it works only
3547 for windows starting at the upper left corner;
3548 but that is all Emacs uses.
3550 This string works only if the frame is using
3551 the top of the video memory, because addressing is memory-relative.
3552 So first check the :ti string to see if that is true.
3554 It would be simpler if the :wi string could go in the termcap
3555 entry, but it can't because it is not fully valid.
3556 If it were in the termcap entry, it would confuse other programs. */
3557 if (!tty->TS_set_window)
3559 p = tty->TS_termcap_modes;
3560 while (*p && strcmp (p, "\033v "))
3561 p++;
3562 if (*p)
3563 tty->TS_set_window = "\033v%C %C %C %C ";
3565 /* Termcap entry often fails to have :in: flag */
3566 terminal->must_write_spaces = 1;
3567 /* :ti string typically fails to have \E^G! in it */
3568 /* This limits scope of insert-char to one line. */
3569 strcpy (area, tty->TS_termcap_modes);
3570 strcat (area, "\033\007!");
3571 tty->TS_termcap_modes = area;
3572 area += strlen (area) + 1;
3573 p = AbsPosition (tty);
3574 /* Change all %+ parameters to %C, to handle
3575 values above 96 correctly for the C100. */
3576 while (*p)
3578 if (p[0] == '%' && p[1] == '+')
3579 p[1] = 'C';
3580 p++;
3584 tty->specified_window = FrameRows (tty);
3586 if (Wcm_init (tty) == -1) /* can't do cursor motion */
3588 maybe_fatal (must_succeed, terminal,
3589 "Terminal type \"%s\" is not powerful enough to run Emacs",
3590 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3591 It lacks the ability to position the cursor.\n\
3592 If that is not the actual type of terminal you have,\n\
3593 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3594 `setenv TERM ...') to specify the correct type. It may be necessary\n"
3595 # ifdef TERMINFO
3596 "to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3597 # else /* TERMCAP */
3598 "to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3599 # endif /* TERMINFO */
3600 terminal_type);
3603 if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
3604 maybe_fatal (must_succeed, terminal,
3605 "Could not determine the frame size",
3606 "Could not determine the frame size");
3608 tty->delete_in_insert_mode
3609 = tty->TS_delete_mode && tty->TS_insert_mode
3610 && !strcmp (tty->TS_delete_mode, tty->TS_insert_mode);
3612 tty->se_is_so = (tty->TS_standout_mode
3613 && tty->TS_end_standout_mode
3614 && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode));
3616 UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8;
3618 terminal->scroll_region_ok
3619 = (tty->Wcm->cm_abs
3620 && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
3622 terminal->line_ins_del_ok
3623 = (((tty->TS_ins_line || tty->TS_ins_multi_lines)
3624 && (tty->TS_del_line || tty->TS_del_multi_lines))
3625 || (terminal->scroll_region_ok
3626 && tty->TS_fwd_scroll && tty->TS_rev_scroll));
3628 terminal->char_ins_del_ok
3629 = ((tty->TS_ins_char || tty->TS_insert_mode
3630 || tty->TS_pad_inserted_char || tty->TS_ins_multi_chars)
3631 && (tty->TS_del_char || tty->TS_del_multi_chars));
3633 terminal->fast_clear_end_of_line = tty->TS_clr_line != 0;
3635 init_baud_rate (fileno (tty->input));
3637 #endif /* not DOS_NT */
3639 /* Init system terminal modes (RAW or CBREAK, etc.). */
3640 init_sys_modes (tty);
3642 return terminal;
3646 static void
3647 vfatal (const char *str, va_list ap)
3649 fprintf (stderr, "emacs: ");
3650 vfprintf (stderr, str, ap);
3651 if (!(strlen (str) > 0 && str[strlen (str) - 1] == '\n'))
3652 fprintf (stderr, "\n");
3653 va_end (ap);
3654 fflush (stderr);
3655 exit (1);
3659 /* Auxiliary error-handling function for init_tty.
3660 Delete TERMINAL, then call error or fatal with str1 or str2,
3661 respectively, according to MUST_SUCCEED. */
3663 static void
3664 maybe_fatal (int must_succeed, struct terminal *terminal,
3665 const char *str1, const char *str2, ...)
3667 va_list ap;
3668 va_start (ap, str2);
3669 if (terminal)
3670 delete_tty (terminal);
3672 if (must_succeed)
3673 vfatal (str2, ap);
3674 else
3675 verror (str1, ap);
3677 va_end (ap);
3678 abort ();
3681 void
3682 fatal (const char *str, ...)
3684 va_list ap;
3685 va_start (ap, str);
3686 vfatal (str, ap);
3687 va_end (ap);
3692 /* Delete the given tty terminal, closing all frames on it. */
3694 static void
3695 delete_tty (struct terminal *terminal)
3697 struct tty_display_info *tty;
3699 /* Protect against recursive calls. delete_frame in
3700 delete_terminal calls us back when it deletes our last frame. */
3701 if (!terminal->name)
3702 return;
3704 if (terminal->type != output_termcap)
3705 abort ();
3707 tty = terminal->display_info.tty;
3709 if (tty == tty_list)
3710 tty_list = tty->next;
3711 else
3713 struct tty_display_info *p;
3714 for (p = tty_list; p && p->next != tty; p = p->next)
3717 if (! p)
3718 /* This should not happen. */
3719 abort ();
3721 p->next = tty->next;
3722 tty->next = 0;
3725 /* reset_sys_modes needs a valid device, so this call needs to be
3726 before delete_terminal. */
3727 reset_sys_modes (tty);
3729 delete_terminal (terminal);
3731 xfree (tty->name);
3732 xfree (tty->type);
3734 if (tty->input)
3736 delete_keyboard_wait_descriptor (fileno (tty->input));
3737 if (tty->input != stdin)
3738 fclose (tty->input);
3740 if (tty->output && tty->output != stdout && tty->output != tty->input)
3741 fclose (tty->output);
3742 if (tty->termscript)
3743 fclose (tty->termscript);
3745 xfree (tty->old_tty);
3746 xfree (tty->Wcm);
3747 xfree (tty->termcap_strings_buffer);
3748 xfree (tty->termcap_term_buffer);
3750 memset (tty, 0, sizeof (struct tty_display_info));
3751 xfree (tty);
3756 /* Mark the pointers in the tty_display_info objects.
3757 Called by the Fgarbage_collector. */
3759 void
3760 mark_ttys (void)
3762 struct tty_display_info *tty;
3764 for (tty = tty_list; tty; tty = tty->next)
3765 mark_object (tty->top_frame);
3770 void
3771 syms_of_term (void)
3773 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
3774 doc: /* Non-nil means the system uses terminfo rather than termcap.
3775 This variable can be used by terminal emulator packages. */);
3776 #ifdef TERMINFO
3777 system_uses_terminfo = 1;
3778 #else
3779 system_uses_terminfo = 0;
3780 #endif
3782 DEFVAR_LISP ("suspend-tty-functions", &Vsuspend_tty_functions,
3783 doc: /* Functions to be run after suspending a tty.
3784 The functions are run with one argument, the terminal object to be suspended.
3785 See `suspend-tty'. */);
3786 Vsuspend_tty_functions = Qnil;
3789 DEFVAR_LISP ("resume-tty-functions", &Vresume_tty_functions,
3790 doc: /* Functions to be run after resuming a tty.
3791 The functions are run with one argument, the terminal object that was revived.
3792 See `resume-tty'. */);
3793 Vresume_tty_functions = Qnil;
3795 DEFVAR_BOOL ("visible-cursor", &visible_cursor,
3796 doc: /* Non-nil means to make the cursor very visible.
3797 This only has an effect when running in a text terminal.
3798 What means \"very visible\" is up to your terminal. It may make the cursor
3799 bigger, or it may make it blink, or it may do nothing at all. */);
3800 visible_cursor = 1;
3802 defsubr (&Stty_display_color_p);
3803 defsubr (&Stty_display_color_cells);
3804 defsubr (&Stty_no_underline);
3805 defsubr (&Stty_type);
3806 defsubr (&Scontrolling_tty_p);
3807 defsubr (&Ssuspend_tty);
3808 defsubr (&Sresume_tty);
3809 #ifdef HAVE_GPM
3810 defsubr (&Sgpm_mouse_start);
3811 defsubr (&Sgpm_mouse_stop);
3812 #endif /* HAVE_GPM */
3814 #ifndef DOS_NT
3815 default_orig_pair = NULL;
3816 default_set_foreground = NULL;
3817 default_set_background = NULL;
3818 #endif /* !DOS_NT */
3820 encode_terminal_src = NULL;
3821 encode_terminal_dst = NULL;