* net/dbus.el (dbus-unregister-service): Complete doc. Fix
[emacs.git] / src / term.c
bloba684edc5a85d9cd8c89ec68e5fa1dccb040a4d89
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
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>
29 #ifdef HAVE_UNISTD_H
30 #include <unistd.h>
31 #endif
33 #include <signal.h>
34 #include <stdarg.h>
35 #include <setjmp.h>
37 #include "lisp.h"
38 #include "termchar.h"
39 #include "termopts.h"
40 #include "buffer.h"
41 #include "character.h"
42 #include "charset.h"
43 #include "coding.h"
44 #include "composite.h"
45 #include "keyboard.h"
46 #include "frame.h"
47 #include "disptab.h"
48 #include "termhooks.h"
49 #include "dispextern.h"
50 #include "window.h"
51 #include "keymap.h"
52 #include "blockinput.h"
53 #include "syssignal.h"
54 #include "systty.h"
55 #include "intervals.h"
56 #ifdef MSDOS
57 #include "msdos.h"
58 static int been_here = -1;
59 #endif
61 /* For now, don't try to include termcap.h. On some systems,
62 configure finds a non-standard termcap.h that the main build
63 won't find. */
64 extern void tputs (const char *, int, int (*)(int));
65 extern int tgetent (char *, const char *);
66 extern int tgetflag (char *id);
67 extern int tgetnum (char *id);
69 char *tparam (char *, char *, int, int, ...);
71 extern char *tgetstr (char *, char **);
73 #include "cm.h"
74 #ifdef HAVE_X_WINDOWS
75 #include "xterm.h"
76 #endif
78 #ifndef O_RDWR
79 #define O_RDWR 2
80 #endif
82 #ifndef O_NOCTTY
83 #define O_NOCTTY 0
84 #endif
86 /* The name of the default console device. */
87 #ifdef WINDOWSNT
88 #define DEV_TTY "CONOUT$"
89 #else
90 #define DEV_TTY "/dev/tty"
91 #endif
93 static void tty_set_scroll_region (struct frame *f, int start, int stop);
94 static void turn_on_face (struct frame *, int face_id);
95 static void turn_off_face (struct frame *, int face_id);
96 static void tty_show_cursor (struct tty_display_info *);
97 static void tty_hide_cursor (struct tty_display_info *);
98 static void tty_background_highlight (struct tty_display_info *tty);
99 static void clear_tty_hooks (struct terminal *terminal);
100 static void set_tty_hooks (struct terminal *terminal);
101 static void dissociate_if_controlling_tty (int fd);
102 static void delete_tty (struct terminal *);
103 static void maybe_fatal (int must_succeed, struct terminal *terminal,
104 const char *str1, const char *str2, ...) NO_RETURN;
105 static void vfatal (const char *str, va_list ap) NO_RETURN;
108 #define OUTPUT(tty, a) \
109 emacs_tputs ((tty), a, \
110 (int) (FRAME_LINES (XFRAME (selected_frame)) \
111 - curY (tty)), \
112 cmputc)
114 #define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
115 #define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
117 #define OUTPUT_IF(tty, a) \
118 do { \
119 if (a) \
120 emacs_tputs ((tty), a, \
121 (int) (FRAME_LINES (XFRAME (selected_frame)) \
122 - curY (tty) ), \
123 cmputc); \
124 } while (0)
126 #define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
128 /* If true, use "vs", otherwise use "ve" to make the cursor visible. */
130 static int visible_cursor;
132 /* Display space properties */
134 /* Functions to call after suspending a tty. */
135 Lisp_Object Vsuspend_tty_functions;
137 /* Functions to call after resuming a tty. */
138 Lisp_Object Vresume_tty_functions;
140 /* Chain of all tty device parameters. */
141 struct tty_display_info *tty_list;
143 /* Nonzero means no need to redraw the entire frame on resuming a
144 suspended Emacs. This is useful on terminals with multiple
145 pages, where one page is used for Emacs and another for all
146 else. */
147 int no_redraw_on_reenter;
149 /* Meaning of bits in no_color_video. Each bit set means that the
150 corresponding attribute cannot be combined with colors. */
152 enum no_color_bit
154 NC_STANDOUT = 1 << 0,
155 NC_UNDERLINE = 1 << 1,
156 NC_REVERSE = 1 << 2,
157 NC_BLINK = 1 << 3,
158 NC_DIM = 1 << 4,
159 NC_BOLD = 1 << 5,
160 NC_INVIS = 1 << 6,
161 NC_PROTECT = 1 << 7,
162 NC_ALT_CHARSET = 1 << 8
165 /* internal state */
167 /* The largest frame width in any call to calculate_costs. */
169 int max_frame_cols;
171 /* The largest frame height in any call to calculate_costs. */
173 int max_frame_lines;
175 /* Non-zero if we have dropped our controlling tty and therefore
176 should not open a frame on stdout. */
177 static int no_controlling_tty;
179 /* Provided for lisp packages. */
181 static int system_uses_terminfo;
185 #ifdef HAVE_GPM
186 #include <sys/fcntl.h>
188 /* The device for which we have enabled gpm support (or NULL). */
189 struct tty_display_info *gpm_tty = NULL;
191 /* Last recorded mouse coordinates. */
192 static int last_mouse_x, last_mouse_y;
193 #endif /* HAVE_GPM */
195 /* Ring the bell on a tty. */
197 static void
198 tty_ring_bell (struct frame *f)
200 struct tty_display_info *tty = FRAME_TTY (f);
202 if (tty->output)
204 OUTPUT (tty, (tty->TS_visible_bell && visible_bell
205 ? tty->TS_visible_bell
206 : tty->TS_bell));
207 fflush (tty->output);
211 /* Set up termcap modes for Emacs. */
213 void
214 tty_set_terminal_modes (struct terminal *terminal)
216 struct tty_display_info *tty = terminal->display_info.tty;
218 if (tty->output)
220 if (tty->TS_termcap_modes)
221 OUTPUT (tty, tty->TS_termcap_modes);
222 else
224 /* Output enough newlines to scroll all the old screen contents
225 off the screen, so it won't be overwritten and lost. */
226 int i;
227 current_tty = tty;
228 for (i = 0; i < FRAME_LINES (XFRAME (selected_frame)); i++)
229 cmputc ('\n');
232 OUTPUT_IF (tty, visible_cursor ? tty->TS_cursor_visible : tty->TS_cursor_normal);
233 OUTPUT_IF (tty, tty->TS_keypad_mode);
234 losecursor (tty);
235 fflush (tty->output);
239 /* Reset termcap modes before exiting Emacs. */
241 void
242 tty_reset_terminal_modes (struct terminal *terminal)
244 struct tty_display_info *tty = terminal->display_info.tty;
246 if (tty->output)
248 tty_turn_off_highlight (tty);
249 tty_turn_off_insert (tty);
250 OUTPUT_IF (tty, tty->TS_end_keypad_mode);
251 OUTPUT_IF (tty, tty->TS_cursor_normal);
252 OUTPUT_IF (tty, tty->TS_end_termcap_modes);
253 OUTPUT_IF (tty, tty->TS_orig_pair);
254 /* Output raw CR so kernel can track the cursor hpos. */
255 current_tty = tty;
256 cmputc ('\r');
257 fflush (tty->output);
261 /* Flag the end of a display update on a termcap terminal. */
263 static void
264 tty_update_end (struct frame *f)
266 struct tty_display_info *tty = FRAME_TTY (f);
268 if (!XWINDOW (selected_window)->cursor_off_p)
269 tty_show_cursor (tty);
270 tty_turn_off_insert (tty);
271 tty_background_highlight (tty);
274 /* The implementation of set_terminal_window for termcap frames. */
276 static void
277 tty_set_terminal_window (struct frame *f, int size)
279 struct tty_display_info *tty = FRAME_TTY (f);
281 tty->specified_window = size ? size : FRAME_LINES (f);
282 if (FRAME_SCROLL_REGION_OK (f))
283 tty_set_scroll_region (f, 0, tty->specified_window);
286 static void
287 tty_set_scroll_region (struct frame *f, int start, int stop)
289 char *buf;
290 struct tty_display_info *tty = FRAME_TTY (f);
292 if (tty->TS_set_scroll_region)
293 buf = tparam (tty->TS_set_scroll_region, 0, 0, start, stop - 1);
294 else if (tty->TS_set_scroll_region_1)
295 buf = tparam (tty->TS_set_scroll_region_1, 0, 0,
296 FRAME_LINES (f), start,
297 FRAME_LINES (f) - stop,
298 FRAME_LINES (f));
299 else
300 buf = tparam (tty->TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (f));
302 OUTPUT (tty, buf);
303 xfree (buf);
304 losecursor (tty);
308 static void
309 tty_turn_on_insert (struct tty_display_info *tty)
311 if (!tty->insert_mode)
312 OUTPUT (tty, tty->TS_insert_mode);
313 tty->insert_mode = 1;
316 void
317 tty_turn_off_insert (struct tty_display_info *tty)
319 if (tty->insert_mode)
320 OUTPUT (tty, tty->TS_end_insert_mode);
321 tty->insert_mode = 0;
324 /* Handle highlighting. */
326 void
327 tty_turn_off_highlight (struct tty_display_info *tty)
329 if (tty->standout_mode)
330 OUTPUT_IF (tty, tty->TS_end_standout_mode);
331 tty->standout_mode = 0;
334 static void
335 tty_turn_on_highlight (struct tty_display_info *tty)
337 if (!tty->standout_mode)
338 OUTPUT_IF (tty, tty->TS_standout_mode);
339 tty->standout_mode = 1;
342 static void
343 tty_toggle_highlight (struct tty_display_info *tty)
345 if (tty->standout_mode)
346 tty_turn_off_highlight (tty);
347 else
348 tty_turn_on_highlight (tty);
352 /* Make cursor invisible. */
354 static void
355 tty_hide_cursor (struct tty_display_info *tty)
357 if (tty->cursor_hidden == 0)
359 tty->cursor_hidden = 1;
360 OUTPUT_IF (tty, tty->TS_cursor_invisible);
365 /* Ensure that cursor is visible. */
367 static void
368 tty_show_cursor (struct tty_display_info *tty)
370 if (tty->cursor_hidden)
372 tty->cursor_hidden = 0;
373 OUTPUT_IF (tty, tty->TS_cursor_normal);
374 if (visible_cursor)
375 OUTPUT_IF (tty, tty->TS_cursor_visible);
380 /* Set standout mode to the state it should be in for
381 empty space inside windows. What this is,
382 depends on the user option inverse-video. */
384 static void
385 tty_background_highlight (struct tty_display_info *tty)
387 if (inverse_video)
388 tty_turn_on_highlight (tty);
389 else
390 tty_turn_off_highlight (tty);
393 /* Set standout mode to the mode specified for the text to be output. */
395 static void
396 tty_highlight_if_desired (struct tty_display_info *tty)
398 if (inverse_video)
399 tty_turn_on_highlight (tty);
400 else
401 tty_turn_off_highlight (tty);
405 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
406 frame-relative coordinates. */
408 static void
409 tty_cursor_to (struct frame *f, int vpos, int hpos)
411 struct tty_display_info *tty = FRAME_TTY (f);
413 /* Detect the case where we are called from reset_sys_modes
414 and the costs have never been calculated. Do nothing. */
415 if (! tty->costs_set)
416 return;
418 if (curY (tty) == vpos
419 && curX (tty) == hpos)
420 return;
421 if (!tty->TF_standout_motion)
422 tty_background_highlight (tty);
423 if (!tty->TF_insmode_motion)
424 tty_turn_off_insert (tty);
425 cmgoto (tty, vpos, hpos);
428 /* Similar but don't take any account of the wasted characters. */
430 static void
431 tty_raw_cursor_to (struct frame *f, int row, int col)
433 struct tty_display_info *tty = FRAME_TTY (f);
435 if (curY (tty) == row
436 && curX (tty) == col)
437 return;
438 if (!tty->TF_standout_motion)
439 tty_background_highlight (tty);
440 if (!tty->TF_insmode_motion)
441 tty_turn_off_insert (tty);
442 cmgoto (tty, row, col);
445 /* Erase operations */
447 /* Clear from cursor to end of frame on a termcap device. */
449 static void
450 tty_clear_to_end (struct frame *f)
452 register int i;
453 struct tty_display_info *tty = FRAME_TTY (f);
455 if (tty->TS_clr_to_bottom)
457 tty_background_highlight (tty);
458 OUTPUT (tty, tty->TS_clr_to_bottom);
460 else
462 for (i = curY (tty); i < FRAME_LINES (f); i++)
464 cursor_to (f, i, 0);
465 clear_end_of_line (f, FRAME_COLS (f));
470 /* Clear an entire termcap frame. */
472 static void
473 tty_clear_frame (struct frame *f)
475 struct tty_display_info *tty = FRAME_TTY (f);
477 if (tty->TS_clr_frame)
479 tty_background_highlight (tty);
480 OUTPUT (tty, tty->TS_clr_frame);
481 cmat (tty, 0, 0);
483 else
485 cursor_to (f, 0, 0);
486 clear_to_end (f);
490 /* An implementation of clear_end_of_line for termcap frames.
492 Note that the cursor may be moved, on terminals lacking a `ce' string. */
494 static void
495 tty_clear_end_of_line (struct frame *f, int first_unused_hpos)
497 register int i;
498 struct tty_display_info *tty = FRAME_TTY (f);
500 /* Detect the case where we are called from reset_sys_modes
501 and the costs have never been calculated. Do nothing. */
502 if (! tty->costs_set)
503 return;
505 if (curX (tty) >= first_unused_hpos)
506 return;
507 tty_background_highlight (tty);
508 if (tty->TS_clr_line)
510 OUTPUT1 (tty, tty->TS_clr_line);
512 else
513 { /* have to do it the hard way */
514 tty_turn_off_insert (tty);
516 /* Do not write in last row last col with Auto-wrap on. */
517 if (AutoWrap (tty)
518 && curY (tty) == FrameRows (tty) - 1
519 && first_unused_hpos == FrameCols (tty))
520 first_unused_hpos--;
522 for (i = curX (tty); i < first_unused_hpos; i++)
524 if (tty->termscript)
525 fputc (' ', tty->termscript);
526 fputc (' ', tty->output);
528 cmplus (tty, first_unused_hpos - curX (tty));
532 /* Buffers to store the source and result of code conversion for terminal. */
533 static unsigned char *encode_terminal_src;
534 static unsigned char *encode_terminal_dst;
535 /* Allocated sizes of the above buffers. */
536 static int encode_terminal_src_size;
537 static int encode_terminal_dst_size;
539 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes.
540 Set CODING->produced to the byte-length of the resulting byte
541 sequence, and return a pointer to that byte sequence. */
543 unsigned char *
544 encode_terminal_code (struct glyph *src, int src_len, struct coding_system *coding)
546 struct glyph *src_end = src + src_len;
547 unsigned char *buf;
548 int nchars, nbytes, required;
549 register int tlen = GLYPH_TABLE_LENGTH;
550 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
551 Lisp_Object charset_list;
553 /* Allocate sufficient size of buffer to store all characters in
554 multibyte-form. But, it may be enlarged on demand if
555 Vglyph_table contains a string or a composite glyph is
556 encountered. */
557 required = MAX_MULTIBYTE_LENGTH * src_len;
558 if (encode_terminal_src_size < required)
560 if (encode_terminal_src)
561 encode_terminal_src = xrealloc (encode_terminal_src, required);
562 else
563 encode_terminal_src = xmalloc (required);
564 encode_terminal_src_size = required;
567 charset_list = coding_charset_list (coding);
569 buf = encode_terminal_src;
570 nchars = 0;
571 while (src < src_end)
573 if (src->type == COMPOSITE_GLYPH)
575 struct composition *cmp;
576 Lisp_Object gstring;
577 int i;
579 nbytes = buf - encode_terminal_src;
580 if (src->u.cmp.automatic)
582 gstring = composition_gstring_from_id (src->u.cmp.id);
583 required = src->slice.cmp.to + 1 - src->slice.cmp.from;
585 else
587 cmp = composition_table[src->u.cmp.id];
588 required = MAX_MULTIBYTE_LENGTH * cmp->glyph_len;
591 if (encode_terminal_src_size < nbytes + required)
593 encode_terminal_src_size = nbytes + required;
594 encode_terminal_src = xrealloc (encode_terminal_src,
595 encode_terminal_src_size);
596 buf = encode_terminal_src + nbytes;
599 if (src->u.cmp.automatic)
600 for (i = src->slice.cmp.from; i <= src->slice.cmp.to; i++)
602 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
603 int c = LGLYPH_CHAR (g);
605 if (! char_charset (c, charset_list, NULL))
606 c = '?';
607 buf += CHAR_STRING (c, buf);
608 nchars++;
610 else
611 for (i = 0; i < cmp->glyph_len; i++)
613 int c = COMPOSITION_GLYPH (cmp, i);
615 if (c == '\t')
616 continue;
617 if (char_charset (c, charset_list, NULL))
619 if (CHAR_WIDTH (c) == 0
620 && i > 0 && COMPOSITION_GLYPH (cmp, i - 1) == '\t')
621 /* Should be left-padded */
623 buf += CHAR_STRING (' ', buf);
624 nchars++;
627 else
628 c = '?';
629 buf += CHAR_STRING (c, buf);
630 nchars++;
633 /* We must skip glyphs to be padded for a wide character. */
634 else if (! CHAR_GLYPH_PADDING_P (*src))
636 GLYPH g;
637 int c;
638 Lisp_Object string;
640 string = Qnil;
641 SET_GLYPH_FROM_CHAR_GLYPH (g, src[0]);
643 if (GLYPH_INVALID_P (g) || GLYPH_SIMPLE_P (tbase, tlen, g))
645 /* This glyph doesn't have an entry in Vglyph_table. */
646 c = src->u.ch;
648 else
650 /* This glyph has an entry in Vglyph_table,
651 so process any alias before testing for simpleness. */
652 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
654 if (GLYPH_SIMPLE_P (tbase, tlen, g))
655 /* We set the multi-byte form of a character in G
656 (that should be an ASCII character) at WORKBUF. */
657 c = GLYPH_CHAR (g);
658 else
659 /* We have a string in Vglyph_table. */
660 string = tbase[GLYPH_CHAR (g)];
663 if (NILP (string))
665 nbytes = buf - encode_terminal_src;
666 if (encode_terminal_src_size < nbytes + MAX_MULTIBYTE_LENGTH)
668 encode_terminal_src_size = nbytes + MAX_MULTIBYTE_LENGTH;
669 encode_terminal_src = xrealloc (encode_terminal_src,
670 encode_terminal_src_size);
671 buf = encode_terminal_src + nbytes;
673 if (CHAR_BYTE8_P (c)
674 || char_charset (c, charset_list, NULL))
676 /* Store the multibyte form of C at BUF. */
677 buf += CHAR_STRING (c, buf);
678 nchars++;
680 else
682 /* C is not encodable. */
683 *buf++ = '?';
684 nchars++;
685 while (src + 1 < src_end && CHAR_GLYPH_PADDING_P (src[1]))
687 *buf++ = '?';
688 nchars++;
689 src++;
693 else
695 unsigned char *p = SDATA (string);
697 if (! STRING_MULTIBYTE (string))
698 string = string_to_multibyte (string);
699 nbytes = buf - encode_terminal_src;
700 if (encode_terminal_src_size < nbytes + SBYTES (string))
702 encode_terminal_src_size = nbytes + SBYTES (string);
703 encode_terminal_src = xrealloc (encode_terminal_src,
704 encode_terminal_src_size);
705 buf = encode_terminal_src + nbytes;
707 memcpy (buf, SDATA (string), SBYTES (string));
708 buf += SBYTES (string);
709 nchars += SCHARS (string);
712 src++;
715 if (nchars == 0)
717 coding->produced = 0;
718 return NULL;
721 nbytes = buf - encode_terminal_src;
722 coding->source = encode_terminal_src;
723 if (encode_terminal_dst_size == 0)
725 encode_terminal_dst_size = encode_terminal_src_size;
726 if (encode_terminal_dst)
727 encode_terminal_dst = xrealloc (encode_terminal_dst,
728 encode_terminal_dst_size);
729 else
730 encode_terminal_dst = xmalloc (encode_terminal_dst_size);
732 coding->destination = encode_terminal_dst;
733 coding->dst_bytes = encode_terminal_dst_size;
734 encode_coding_object (coding, Qnil, 0, 0, nchars, nbytes, Qnil);
735 /* coding->destination may have been reallocated. */
736 encode_terminal_dst = coding->destination;
737 encode_terminal_dst_size = coding->dst_bytes;
739 return (encode_terminal_dst);
744 /* An implementation of write_glyphs for termcap frames. */
746 static void
747 tty_write_glyphs (struct frame *f, struct glyph *string, int len)
749 unsigned char *conversion_buffer;
750 struct coding_system *coding;
752 struct tty_display_info *tty = FRAME_TTY (f);
754 tty_turn_off_insert (tty);
755 tty_hide_cursor (tty);
757 /* Don't dare write in last column of bottom line, if Auto-Wrap,
758 since that would scroll the whole frame on some terminals. */
760 if (AutoWrap (tty)
761 && curY (tty) + 1 == FRAME_LINES (f)
762 && (curX (tty) + len) == FRAME_COLS (f))
763 len --;
764 if (len <= 0)
765 return;
767 cmplus (tty, len);
769 /* If terminal_coding does any conversion, use it, otherwise use
770 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
771 because it always return 1 if the member src_multibyte is 1. */
772 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
773 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
774 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
775 the tail. */
776 coding->mode &= ~CODING_MODE_LAST_BLOCK;
778 while (len > 0)
780 /* Identify a run of glyphs with the same face. */
781 int face_id = string->face_id;
782 int n;
784 for (n = 1; n < len; ++n)
785 if (string[n].face_id != face_id)
786 break;
788 /* Turn appearance modes of the face of the run on. */
789 tty_highlight_if_desired (tty);
790 turn_on_face (f, face_id);
792 if (n == len)
793 /* This is the last run. */
794 coding->mode |= CODING_MODE_LAST_BLOCK;
795 conversion_buffer = encode_terminal_code (string, n, coding);
796 if (coding->produced > 0)
798 BLOCK_INPUT;
799 fwrite (conversion_buffer, 1, coding->produced, tty->output);
800 if (ferror (tty->output))
801 clearerr (tty->output);
802 if (tty->termscript)
803 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
804 UNBLOCK_INPUT;
806 len -= n;
807 string += n;
809 /* Turn appearance modes off. */
810 turn_off_face (f, face_id);
811 tty_turn_off_highlight (tty);
814 cmcheckmagic (tty);
817 #ifdef HAVE_GPM /* Only used by GPM code. */
819 static void
820 tty_write_glyphs_with_face (register struct frame *f, register struct glyph *string,
821 register int len, register int face_id)
823 unsigned char *conversion_buffer;
824 struct coding_system *coding;
826 struct tty_display_info *tty = FRAME_TTY (f);
828 tty_turn_off_insert (tty);
829 tty_hide_cursor (tty);
831 /* Don't dare write in last column of bottom line, if Auto-Wrap,
832 since that would scroll the whole frame on some terminals. */
834 if (AutoWrap (tty)
835 && curY (tty) + 1 == FRAME_LINES (f)
836 && (curX (tty) + len) == FRAME_COLS (f))
837 len --;
838 if (len <= 0)
839 return;
841 cmplus (tty, len);
843 /* If terminal_coding does any conversion, use it, otherwise use
844 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
845 because it always return 1 if the member src_multibyte is 1. */
846 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
847 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
848 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
849 the tail. */
850 coding->mode &= ~CODING_MODE_LAST_BLOCK;
852 /* Turn appearance modes of the face. */
853 tty_highlight_if_desired (tty);
854 turn_on_face (f, face_id);
856 coding->mode |= CODING_MODE_LAST_BLOCK;
857 conversion_buffer = encode_terminal_code (string, len, coding);
858 if (coding->produced > 0)
860 BLOCK_INPUT;
861 fwrite (conversion_buffer, 1, coding->produced, tty->output);
862 if (ferror (tty->output))
863 clearerr (tty->output);
864 if (tty->termscript)
865 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
866 UNBLOCK_INPUT;
869 /* Turn appearance modes off. */
870 turn_off_face (f, face_id);
871 tty_turn_off_highlight (tty);
873 cmcheckmagic (tty);
875 #endif
877 /* An implementation of insert_glyphs for termcap frames. */
879 static void
880 tty_insert_glyphs (struct frame *f, struct glyph *start, int len)
882 char *buf;
883 struct glyph *glyph = NULL;
884 unsigned char *conversion_buffer;
885 unsigned char space[1];
886 struct coding_system *coding;
888 struct tty_display_info *tty = FRAME_TTY (f);
890 if (tty->TS_ins_multi_chars)
892 buf = tparam (tty->TS_ins_multi_chars, 0, 0, len);
893 OUTPUT1 (tty, buf);
894 xfree (buf);
895 if (start)
896 write_glyphs (f, start, len);
897 return;
900 tty_turn_on_insert (tty);
901 cmplus (tty, len);
903 if (! start)
904 space[0] = SPACEGLYPH;
906 /* If terminal_coding does any conversion, use it, otherwise use
907 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
908 because it always return 1 if the member src_multibyte is 1. */
909 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
910 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
911 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
912 the tail. */
913 coding->mode &= ~CODING_MODE_LAST_BLOCK;
915 while (len-- > 0)
917 OUTPUT1_IF (tty, tty->TS_ins_char);
918 if (!start)
920 conversion_buffer = space;
921 coding->produced = 1;
923 else
925 tty_highlight_if_desired (tty);
926 turn_on_face (f, start->face_id);
927 glyph = start;
928 ++start;
929 /* We must open sufficient space for a character which
930 occupies more than one column. */
931 while (len && CHAR_GLYPH_PADDING_P (*start))
933 OUTPUT1_IF (tty, tty->TS_ins_char);
934 start++, len--;
937 if (len <= 0)
938 /* This is the last glyph. */
939 coding->mode |= CODING_MODE_LAST_BLOCK;
941 conversion_buffer = encode_terminal_code (glyph, 1, coding);
944 if (coding->produced > 0)
946 BLOCK_INPUT;
947 fwrite (conversion_buffer, 1, coding->produced, tty->output);
948 if (ferror (tty->output))
949 clearerr (tty->output);
950 if (tty->termscript)
951 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
952 UNBLOCK_INPUT;
955 OUTPUT1_IF (tty, tty->TS_pad_inserted_char);
956 if (start)
958 turn_off_face (f, glyph->face_id);
959 tty_turn_off_highlight (tty);
963 cmcheckmagic (tty);
966 /* An implementation of delete_glyphs for termcap frames. */
968 static void
969 tty_delete_glyphs (struct frame *f, int n)
971 char *buf;
972 register int i;
974 struct tty_display_info *tty = FRAME_TTY (f);
976 if (tty->delete_in_insert_mode)
978 tty_turn_on_insert (tty);
980 else
982 tty_turn_off_insert (tty);
983 OUTPUT_IF (tty, tty->TS_delete_mode);
986 if (tty->TS_del_multi_chars)
988 buf = tparam (tty->TS_del_multi_chars, 0, 0, n);
989 OUTPUT1 (tty, buf);
990 xfree (buf);
992 else
993 for (i = 0; i < n; i++)
994 OUTPUT1 (tty, tty->TS_del_char);
995 if (!tty->delete_in_insert_mode)
996 OUTPUT_IF (tty, tty->TS_end_delete_mode);
999 /* An implementation of ins_del_lines for termcap frames. */
1001 static void
1002 tty_ins_del_lines (struct frame *f, int vpos, int n)
1004 struct tty_display_info *tty = FRAME_TTY (f);
1005 char *multi = n > 0 ? tty->TS_ins_multi_lines : tty->TS_del_multi_lines;
1006 char *single = n > 0 ? tty->TS_ins_line : tty->TS_del_line;
1007 char *scroll = n > 0 ? tty->TS_rev_scroll : tty->TS_fwd_scroll;
1009 register int i = n > 0 ? n : -n;
1010 register char *buf;
1012 /* If the lines below the insertion are being pushed
1013 into the end of the window, this is the same as clearing;
1014 and we know the lines are already clear, since the matching
1015 deletion has already been done. So can ignore this. */
1016 /* If the lines below the deletion are blank lines coming
1017 out of the end of the window, don't bother,
1018 as there will be a matching inslines later that will flush them. */
1019 if (FRAME_SCROLL_REGION_OK (f)
1020 && vpos + i >= tty->specified_window)
1021 return;
1022 if (!FRAME_MEMORY_BELOW_FRAME (f)
1023 && vpos + i >= FRAME_LINES (f))
1024 return;
1026 if (multi)
1028 raw_cursor_to (f, vpos, 0);
1029 tty_background_highlight (tty);
1030 buf = tparam (multi, 0, 0, i);
1031 OUTPUT (tty, buf);
1032 xfree (buf);
1034 else if (single)
1036 raw_cursor_to (f, vpos, 0);
1037 tty_background_highlight (tty);
1038 while (--i >= 0)
1039 OUTPUT (tty, single);
1040 if (tty->TF_teleray)
1041 curX (tty) = 0;
1043 else
1045 tty_set_scroll_region (f, vpos, tty->specified_window);
1046 if (n < 0)
1047 raw_cursor_to (f, tty->specified_window - 1, 0);
1048 else
1049 raw_cursor_to (f, vpos, 0);
1050 tty_background_highlight (tty);
1051 while (--i >= 0)
1052 OUTPUTL (tty, scroll, tty->specified_window - vpos);
1053 tty_set_scroll_region (f, 0, tty->specified_window);
1056 if (!FRAME_SCROLL_REGION_OK (f)
1057 && FRAME_MEMORY_BELOW_FRAME (f)
1058 && n < 0)
1060 cursor_to (f, FRAME_LINES (f) + n, 0);
1061 clear_to_end (f);
1065 /* Compute cost of sending "str", in characters,
1066 not counting any line-dependent padding. */
1069 string_cost (const char *str)
1071 cost = 0;
1072 if (str)
1073 tputs (str, 0, evalcost);
1074 return cost;
1077 /* Compute cost of sending "str", in characters,
1078 counting any line-dependent padding at one line. */
1080 static int
1081 string_cost_one_line (const char *str)
1083 cost = 0;
1084 if (str)
1085 tputs (str, 1, evalcost);
1086 return cost;
1089 /* Compute per line amount of line-dependent padding,
1090 in tenths of characters. */
1093 per_line_cost (const char *str)
1095 cost = 0;
1096 if (str)
1097 tputs (str, 0, evalcost);
1098 cost = - cost;
1099 if (str)
1100 tputs (str, 10, evalcost);
1101 return cost;
1104 /* char_ins_del_cost[n] is cost of inserting N characters.
1105 char_ins_del_cost[-n] is cost of deleting N characters.
1106 The length of this vector is based on max_frame_cols. */
1108 int *char_ins_del_vector;
1110 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
1112 /* ARGSUSED */
1113 static void
1114 calculate_ins_del_char_costs (struct frame *f)
1116 struct tty_display_info *tty = FRAME_TTY (f);
1117 int ins_startup_cost, del_startup_cost;
1118 int ins_cost_per_char, del_cost_per_char;
1119 register int i;
1120 register int *p;
1122 if (tty->TS_ins_multi_chars)
1124 ins_cost_per_char = 0;
1125 ins_startup_cost = string_cost_one_line (tty->TS_ins_multi_chars);
1127 else if (tty->TS_ins_char || tty->TS_pad_inserted_char
1128 || (tty->TS_insert_mode && tty->TS_end_insert_mode))
1130 ins_startup_cost = (30 * (string_cost (tty->TS_insert_mode)
1131 + string_cost (tty->TS_end_insert_mode))) / 100;
1132 ins_cost_per_char = (string_cost_one_line (tty->TS_ins_char)
1133 + string_cost_one_line (tty->TS_pad_inserted_char));
1135 else
1137 ins_startup_cost = 9999;
1138 ins_cost_per_char = 0;
1141 if (tty->TS_del_multi_chars)
1143 del_cost_per_char = 0;
1144 del_startup_cost = string_cost_one_line (tty->TS_del_multi_chars);
1146 else if (tty->TS_del_char)
1148 del_startup_cost = (string_cost (tty->TS_delete_mode)
1149 + string_cost (tty->TS_end_delete_mode));
1150 if (tty->delete_in_insert_mode)
1151 del_startup_cost /= 2;
1152 del_cost_per_char = string_cost_one_line (tty->TS_del_char);
1154 else
1156 del_startup_cost = 9999;
1157 del_cost_per_char = 0;
1160 /* Delete costs are at negative offsets */
1161 p = &char_ins_del_cost (f)[0];
1162 for (i = FRAME_COLS (f); --i >= 0;)
1163 *--p = (del_startup_cost += del_cost_per_char);
1165 /* Doing nothing is free */
1166 p = &char_ins_del_cost (f)[0];
1167 *p++ = 0;
1169 /* Insert costs are at positive offsets */
1170 for (i = FRAME_COLS (f); --i >= 0;)
1171 *p++ = (ins_startup_cost += ins_cost_per_char);
1174 void
1175 calculate_costs (struct frame *frame)
1177 FRAME_COST_BAUD_RATE (frame) = baud_rate;
1179 if (FRAME_TERMCAP_P (frame))
1181 struct tty_display_info *tty = FRAME_TTY (frame);
1182 register char *f = (tty->TS_set_scroll_region
1183 ? tty->TS_set_scroll_region
1184 : tty->TS_set_scroll_region_1);
1186 FRAME_SCROLL_REGION_COST (frame) = string_cost (f);
1188 tty->costs_set = 1;
1190 /* These variables are only used for terminal stuff. They are
1191 allocated once for the terminal frame of X-windows emacs, but not
1192 used afterwards.
1194 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1195 X turns off char_ins_del_ok. */
1197 max_frame_lines = max (max_frame_lines, FRAME_LINES (frame));
1198 max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
1200 if (char_ins_del_vector != 0)
1201 char_ins_del_vector
1202 = (int *) xrealloc (char_ins_del_vector,
1203 (sizeof (int)
1204 + 2 * max_frame_cols * sizeof (int)));
1205 else
1206 char_ins_del_vector
1207 = (int *) xmalloc (sizeof (int)
1208 + 2 * max_frame_cols * sizeof (int));
1210 memset (char_ins_del_vector, 0,
1211 (sizeof (int) + 2 * max_frame_cols * sizeof (int)));
1214 if (f && (!tty->TS_ins_line && !tty->TS_del_line))
1215 do_line_insertion_deletion_costs (frame,
1216 tty->TS_rev_scroll, tty->TS_ins_multi_lines,
1217 tty->TS_fwd_scroll, tty->TS_del_multi_lines,
1218 f, f, 1);
1219 else
1220 do_line_insertion_deletion_costs (frame,
1221 tty->TS_ins_line, tty->TS_ins_multi_lines,
1222 tty->TS_del_line, tty->TS_del_multi_lines,
1223 0, 0, 1);
1225 calculate_ins_del_char_costs (frame);
1227 /* Don't use TS_repeat if its padding is worse than sending the chars */
1228 if (tty->TS_repeat && per_line_cost (tty->TS_repeat) * baud_rate < 9000)
1229 tty->RPov = string_cost (tty->TS_repeat);
1230 else
1231 tty->RPov = FRAME_COLS (frame) * 2;
1233 cmcostinit (FRAME_TTY (frame)); /* set up cursor motion costs */
1237 struct fkey_table {
1238 char *cap, *name;
1241 /* Termcap capability names that correspond directly to X keysyms.
1242 Some of these (marked "terminfo") aren't supplied by old-style
1243 (Berkeley) termcap entries. They're listed in X keysym order;
1244 except we put the keypad keys first, so that if they clash with
1245 other keys (as on the IBM PC keyboard) they get overridden.
1248 static const struct fkey_table keys[] =
1250 {"kh", "home"}, /* termcap */
1251 {"kl", "left"}, /* termcap */
1252 {"ku", "up"}, /* termcap */
1253 {"kr", "right"}, /* termcap */
1254 {"kd", "down"}, /* termcap */
1255 {"%8", "prior"}, /* terminfo */
1256 {"%5", "next"}, /* terminfo */
1257 {"@7", "end"}, /* terminfo */
1258 {"@1", "begin"}, /* terminfo */
1259 {"*6", "select"}, /* terminfo */
1260 {"%9", "print"}, /* terminfo */
1261 {"@4", "execute"}, /* terminfo --- actually the `command' key */
1263 * "insert" --- see below
1265 {"&8", "undo"}, /* terminfo */
1266 {"%0", "redo"}, /* terminfo */
1267 {"%7", "menu"}, /* terminfo --- actually the `options' key */
1268 {"@0", "find"}, /* terminfo */
1269 {"@2", "cancel"}, /* terminfo */
1270 {"%1", "help"}, /* terminfo */
1272 * "break" goes here, but can't be reliably intercepted with termcap
1274 {"&4", "reset"}, /* terminfo --- actually `restart' */
1276 * "system" and "user" --- no termcaps
1278 {"kE", "clearline"}, /* terminfo */
1279 {"kA", "insertline"}, /* terminfo */
1280 {"kL", "deleteline"}, /* terminfo */
1281 {"kI", "insertchar"}, /* terminfo */
1282 {"kD", "deletechar"}, /* terminfo */
1283 {"kB", "backtab"}, /* terminfo */
1285 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1287 {"@8", "kp-enter"}, /* terminfo */
1289 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1290 * "kp-multiply", "kp-add", "kp-separator",
1291 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1292 * --- no termcaps for any of these.
1294 {"K4", "kp-1"}, /* terminfo */
1296 * "kp-2" --- no termcap
1298 {"K5", "kp-3"}, /* terminfo */
1300 * "kp-4" --- no termcap
1302 {"K2", "kp-5"}, /* terminfo */
1304 * "kp-6" --- no termcap
1306 {"K1", "kp-7"}, /* terminfo */
1308 * "kp-8" --- no termcap
1310 {"K3", "kp-9"}, /* terminfo */
1312 * "kp-equal" --- no termcap
1314 {"k1", "f1"},
1315 {"k2", "f2"},
1316 {"k3", "f3"},
1317 {"k4", "f4"},
1318 {"k5", "f5"},
1319 {"k6", "f6"},
1320 {"k7", "f7"},
1321 {"k8", "f8"},
1322 {"k9", "f9"},
1324 {"&0", "S-cancel"}, /*shifted cancel key*/
1325 {"&9", "S-begin"}, /*shifted begin key*/
1326 {"*0", "S-find"}, /*shifted find key*/
1327 {"*1", "S-execute"}, /*shifted execute? actually shifted command key*/
1328 {"*4", "S-delete"}, /*shifted delete-character key*/
1329 {"*7", "S-end"}, /*shifted end key*/
1330 {"*8", "S-clearline"}, /*shifted clear-to end-of-line key*/
1331 {"#1", "S-help"}, /*shifted help key*/
1332 {"#2", "S-home"}, /*shifted home key*/
1333 {"#3", "S-insert"}, /*shifted insert-character key*/
1334 {"#4", "S-left"}, /*shifted left-arrow key*/
1335 {"%d", "S-menu"}, /*shifted menu? actually shifted options key*/
1336 {"%c", "S-next"}, /*shifted next key*/
1337 {"%e", "S-prior"}, /*shifted previous key*/
1338 {"%f", "S-print"}, /*shifted print key*/
1339 {"%g", "S-redo"}, /*shifted redo key*/
1340 {"%i", "S-right"}, /*shifted right-arrow key*/
1341 {"!3", "S-undo"} /*shifted undo key*/
1344 #ifndef DOS_NT
1345 static char **term_get_fkeys_address;
1346 static KBOARD *term_get_fkeys_kboard;
1347 static Lisp_Object term_get_fkeys_1 (void);
1349 /* Find the escape codes sent by the function keys for Vinput_decode_map.
1350 This function scans the termcap function key sequence entries, and
1351 adds entries to Vinput_decode_map for each function key it finds. */
1353 static void
1354 term_get_fkeys (char **address, KBOARD *kboard)
1356 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1357 errors during the call. The only errors should be from Fdefine_key
1358 when given a key sequence containing an invalid prefix key. If the
1359 termcap defines function keys which use a prefix that is already bound
1360 to a command by the default bindings, we should silently ignore that
1361 function key specification, rather than giving the user an error and
1362 refusing to run at all on such a terminal. */
1364 term_get_fkeys_address = address;
1365 term_get_fkeys_kboard = kboard;
1366 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1369 static Lisp_Object
1370 term_get_fkeys_1 (void)
1372 int i;
1374 char **address = term_get_fkeys_address;
1375 KBOARD *kboard = term_get_fkeys_kboard;
1377 /* This can happen if CANNOT_DUMP or with strange options. */
1378 if (!KEYMAPP (kboard->Vinput_decode_map))
1379 kboard->Vinput_decode_map = Fmake_sparse_keymap (Qnil);
1381 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1383 char *sequence = tgetstr (keys[i].cap, address);
1384 if (sequence)
1385 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence),
1386 Fmake_vector (make_number (1),
1387 intern (keys[i].name)));
1390 /* The uses of the "k0" capability are inconsistent; sometimes it
1391 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1392 We will attempt to politely accommodate both systems by testing for
1393 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1396 char *k_semi = tgetstr ("k;", address);
1397 char *k0 = tgetstr ("k0", address);
1398 char *k0_name = "f10";
1400 if (k_semi)
1402 if (k0)
1403 /* Define f0 first, so that f10 takes precedence in case the
1404 key sequences happens to be the same. */
1405 Fdefine_key (kboard->Vinput_decode_map, build_string (k0),
1406 Fmake_vector (make_number (1), intern ("f0")));
1407 Fdefine_key (kboard->Vinput_decode_map, build_string (k_semi),
1408 Fmake_vector (make_number (1), intern ("f10")));
1410 else if (k0)
1411 Fdefine_key (kboard->Vinput_decode_map, build_string (k0),
1412 Fmake_vector (make_number (1), intern (k0_name)));
1415 /* Set up cookies for numbered function keys above f10. */
1417 char fcap[3], fkey[4];
1419 fcap[0] = 'F'; fcap[2] = '\0';
1420 for (i = 11; i < 64; i++)
1422 if (i <= 19)
1423 fcap[1] = '1' + i - 11;
1424 else if (i <= 45)
1425 fcap[1] = 'A' + i - 20;
1426 else
1427 fcap[1] = 'a' + i - 46;
1430 char *sequence = tgetstr (fcap, address);
1431 if (sequence)
1433 sprintf (fkey, "f%d", i);
1434 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence),
1435 Fmake_vector (make_number (1),
1436 intern (fkey)));
1443 * Various mappings to try and get a better fit.
1446 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1447 if (!tgetstr (cap1, address)) \
1449 char *sequence = tgetstr (cap2, address); \
1450 if (sequence) \
1451 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence), \
1452 Fmake_vector (make_number (1), \
1453 intern (sym))); \
1456 /* if there's no key_next keycap, map key_npage to `next' keysym */
1457 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1458 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1459 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1460 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1461 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1462 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1463 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1465 /* IBM has their own non-standard dialect of terminfo.
1466 If the standard name isn't found, try the IBM name. */
1467 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1468 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1469 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1470 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1471 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1472 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1473 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1474 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1475 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1476 #undef CONDITIONAL_REASSIGN
1479 return Qnil;
1481 #endif /* not DOS_NT */
1484 /***********************************************************************
1485 Character Display Information
1486 ***********************************************************************/
1487 static void append_glyph (struct it *);
1488 static void produce_stretch_glyph (struct it *);
1489 static void append_composite_glyph (struct it *);
1490 static void produce_composite_glyph (struct it *);
1491 static void append_glyphless_glyph (struct it *, int, char *);
1492 static void produce_glyphless_glyph (struct it *, int, Lisp_Object);
1494 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1495 terminal frames if IT->glyph_row != NULL. IT->char_to_display is
1496 the character for which to produce glyphs; IT->face_id contains the
1497 character's face. Padding glyphs are appended if IT->c has a
1498 IT->pixel_width > 1. */
1500 static void
1501 append_glyph (struct it *it)
1503 struct glyph *glyph, *end;
1504 int i;
1506 xassert (it->glyph_row);
1507 glyph = (it->glyph_row->glyphs[it->area]
1508 + it->glyph_row->used[it->area]);
1509 end = it->glyph_row->glyphs[1 + it->area];
1511 /* If the glyph row is reversed, we need to prepend the glyph rather
1512 than append it. */
1513 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1515 struct glyph *g;
1516 int move_by = it->pixel_width;
1518 /* Make room for the new glyphs. */
1519 if (move_by > end - glyph) /* don't overstep end of this area */
1520 move_by = end - glyph;
1521 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1522 g[move_by] = *g;
1523 glyph = it->glyph_row->glyphs[it->area];
1524 end = glyph + move_by;
1527 /* BIDI Note: we put the glyphs of a "multi-pixel" character left to
1528 right, even in the REVERSED_P case, since (a) all of its u.ch are
1529 identical, and (b) the PADDING_P flag needs to be set for the
1530 leftmost one, because we write to the terminal left-to-right. */
1531 for (i = 0;
1532 i < it->pixel_width && glyph < end;
1533 ++i)
1535 glyph->type = CHAR_GLYPH;
1536 glyph->pixel_width = 1;
1537 glyph->u.ch = it->char_to_display;
1538 glyph->face_id = it->face_id;
1539 glyph->padding_p = i > 0;
1540 glyph->charpos = CHARPOS (it->position);
1541 glyph->object = it->object;
1542 if (it->bidi_p)
1544 glyph->resolved_level = it->bidi_it.resolved_level;
1545 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1546 abort ();
1547 glyph->bidi_type = it->bidi_it.type;
1549 else
1551 glyph->resolved_level = 0;
1552 glyph->bidi_type = UNKNOWN_BT;
1555 ++it->glyph_row->used[it->area];
1556 ++glyph;
1560 /* Produce glyphs for the display element described by IT. *IT
1561 specifies what we want to produce a glyph for (character, image, ...),
1562 and where in the glyph matrix we currently are (glyph row and hpos).
1563 produce_glyphs fills in output fields of *IT with information such as the
1564 pixel width and height of a character, and maybe output actual glyphs at
1565 the same time if IT->glyph_row is non-null. For an overview, see
1566 the explanation in dispextern.h, before the definition of the
1567 display_element_type enumeration.
1569 produce_glyphs also stores the result of glyph width, ascent
1570 etc. computations in *IT.
1572 IT->glyph_row may be null, in which case produce_glyphs does not
1573 actually fill in the glyphs. This is used in the move_* functions
1574 in xdisp.c for text width and height computations.
1576 Callers usually don't call produce_glyphs directly;
1577 instead they use the macro PRODUCE_GLYPHS. */
1579 void
1580 produce_glyphs (struct it *it)
1582 /* If a hook is installed, let it do the work. */
1584 /* Nothing but characters are supported on terminal frames. */
1585 xassert (it->what == IT_CHARACTER
1586 || it->what == IT_COMPOSITION
1587 || it->what == IT_STRETCH);
1589 if (it->what == IT_STRETCH)
1591 produce_stretch_glyph (it);
1592 goto done;
1595 if (it->what == IT_COMPOSITION)
1597 produce_composite_glyph (it);
1598 goto done;
1601 if (it->what == IT_GLYPHLESS)
1603 produce_glyphless_glyph (it, 0, Qnil);
1604 goto done;
1607 if (it->char_to_display >= 040 && it->char_to_display < 0177)
1609 it->pixel_width = it->nglyphs = 1;
1610 if (it->glyph_row)
1611 append_glyph (it);
1613 else if (it->char_to_display == '\n')
1614 it->pixel_width = it->nglyphs = 0;
1615 else if (it->char_to_display == '\t')
1617 int absolute_x = (it->current_x
1618 + it->continuation_lines_width);
1619 int next_tab_x
1620 = (((1 + absolute_x + it->tab_width - 1)
1621 / it->tab_width)
1622 * it->tab_width);
1623 int nspaces;
1625 /* If part of the TAB has been displayed on the previous line
1626 which is continued now, continuation_lines_width will have
1627 been incremented already by the part that fitted on the
1628 continued line. So, we will get the right number of spaces
1629 here. */
1630 nspaces = next_tab_x - absolute_x;
1632 if (it->glyph_row)
1634 int n = nspaces;
1636 it->char_to_display = ' ';
1637 it->pixel_width = it->len = 1;
1639 while (n--)
1640 append_glyph (it);
1643 it->pixel_width = nspaces;
1644 it->nglyphs = nspaces;
1646 else if (CHAR_BYTE8_P (it->char_to_display))
1648 /* Coming here means that we must send the raw 8-bit byte as is
1649 to the terminal. Although there's no way to know how many
1650 columns it occupies on a screen, it is a good assumption that
1651 a single byte code has 1-column width. */
1652 it->pixel_width = it->nglyphs = 1;
1653 if (it->glyph_row)
1654 append_glyph (it);
1656 else
1658 Lisp_Object charset_list = FRAME_TERMINAL (it->f)->charset_list;
1660 if (char_charset (it->char_to_display, charset_list, NULL))
1662 it->pixel_width = CHAR_WIDTH (it->char_to_display);
1663 it->nglyphs = it->pixel_width;
1664 if (it->glyph_row)
1665 append_glyph (it);
1667 else
1669 Lisp_Object acronym = lookup_glyphless_char_display (-1, it);
1671 xassert (it->what == IT_GLYPHLESS);
1672 produce_glyphless_glyph (it, 1, acronym);
1676 done:
1677 /* Advance current_x by the pixel width as a convenience for
1678 the caller. */
1679 if (it->area == TEXT_AREA)
1680 it->current_x += it->pixel_width;
1681 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1682 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
1686 /* Produce a stretch glyph for iterator IT. IT->object is the value
1687 of the glyph property displayed. The value must be a list
1688 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1689 being recognized:
1691 1. `:width WIDTH' specifies that the space should be WIDTH *
1692 canonical char width wide. WIDTH may be an integer or floating
1693 point number.
1695 2. `:align-to HPOS' specifies that the space should be wide enough
1696 to reach HPOS, a value in canonical character units. */
1698 static void
1699 produce_stretch_glyph (struct it *it)
1701 /* (space :width WIDTH ...) */
1702 Lisp_Object prop, plist;
1703 int width = 0, align_to = -1;
1704 int zero_width_ok_p = 0;
1705 double tem;
1707 /* List should start with `space'. */
1708 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1709 plist = XCDR (it->object);
1711 /* Compute the width of the stretch. */
1712 if ((prop = Fplist_get (plist, QCwidth), !NILP (prop))
1713 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, 0))
1715 /* Absolute width `:width WIDTH' specified and valid. */
1716 zero_width_ok_p = 1;
1717 width = (int)(tem + 0.5);
1719 else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
1720 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, &align_to))
1722 if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
1723 align_to = (align_to < 0
1725 : align_to - window_box_left_offset (it->w, TEXT_AREA));
1726 else if (align_to < 0)
1727 align_to = window_box_left_offset (it->w, TEXT_AREA);
1728 width = max (0, (int)(tem + 0.5) + align_to - it->current_x);
1729 zero_width_ok_p = 1;
1731 else
1732 /* Nothing specified -> width defaults to canonical char width. */
1733 width = FRAME_COLUMN_WIDTH (it->f);
1735 if (width <= 0 && (width < 0 || !zero_width_ok_p))
1736 width = 1;
1738 if (width > 0 && it->line_wrap != TRUNCATE
1739 && it->current_x + width > it->last_visible_x)
1740 width = it->last_visible_x - it->current_x - 1;
1742 if (width > 0 && it->glyph_row)
1744 Lisp_Object o_object = it->object;
1745 Lisp_Object object = it->stack[it->sp - 1].string;
1746 int n = width;
1748 if (!STRINGP (object))
1749 object = it->w->buffer;
1750 it->object = object;
1751 it->char_to_display = ' ';
1752 it->pixel_width = it->len = 1;
1753 while (n--)
1754 append_glyph (it);
1755 it->object = o_object;
1757 it->pixel_width = width;
1758 it->nglyphs = width;
1762 /* Append glyphs to IT's glyph_row for the composition IT->cmp_id.
1763 Called from produce_composite_glyph for terminal frames if
1764 IT->glyph_row != NULL. IT->face_id contains the character's
1765 face. */
1767 static void
1768 append_composite_glyph (struct it *it)
1770 struct glyph *glyph;
1772 xassert (it->glyph_row);
1773 glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
1774 if (glyph < it->glyph_row->glyphs[1 + it->area])
1776 /* If the glyph row is reversed, we need to prepend the glyph
1777 rather than append it. */
1778 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1780 struct glyph *g;
1782 /* Make room for the new glyph. */
1783 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1784 g[1] = *g;
1785 glyph = it->glyph_row->glyphs[it->area];
1787 glyph->type = COMPOSITE_GLYPH;
1788 glyph->pixel_width = it->pixel_width;
1789 glyph->u.cmp.id = it->cmp_it.id;
1790 if (it->cmp_it.ch < 0)
1792 glyph->u.cmp.automatic = 0;
1793 glyph->u.cmp.id = it->cmp_it.id;
1795 else
1797 glyph->u.cmp.automatic = 1;
1798 glyph->u.cmp.id = it->cmp_it.id;
1799 glyph->slice.cmp.from = it->cmp_it.from;
1800 glyph->slice.cmp.to = it->cmp_it.to - 1;
1803 glyph->face_id = it->face_id;
1804 glyph->padding_p = 0;
1805 glyph->charpos = CHARPOS (it->position);
1806 glyph->object = it->object;
1807 if (it->bidi_p)
1809 glyph->resolved_level = it->bidi_it.resolved_level;
1810 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1811 abort ();
1812 glyph->bidi_type = it->bidi_it.type;
1814 else
1816 glyph->resolved_level = 0;
1817 glyph->bidi_type = UNKNOWN_BT;
1820 ++it->glyph_row->used[it->area];
1821 ++glyph;
1826 /* Produce a composite glyph for iterator IT. IT->cmp_id is the ID of
1827 the composition. We simply produces components of the composition
1828 assuming that the terminal has a capability to layout/render it
1829 correctly. */
1831 static void
1832 produce_composite_glyph (struct it *it)
1834 if (it->cmp_it.ch < 0)
1836 struct composition *cmp = composition_table[it->cmp_it.id];
1838 it->pixel_width = cmp->width;
1840 else
1842 Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id);
1844 it->pixel_width = composition_gstring_width (gstring, it->cmp_it.from,
1845 it->cmp_it.to, NULL);
1847 it->nglyphs = 1;
1848 if (it->glyph_row)
1849 append_composite_glyph (it);
1853 /* Append a glyph for a glyphless character to IT->glyph_row. FACE_ID
1854 is a face ID to be used for the glyph. What is actually appended
1855 are glyphs of type CHAR_GLYPH whose characters are in STR (which
1856 comes from it->nglyphs bytes). */
1858 static void
1859 append_glyphless_glyph (struct it *it, int face_id, char *str)
1861 struct glyph *glyph, *end;
1862 int i;
1864 xassert (it->glyph_row);
1865 glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
1866 end = it->glyph_row->glyphs[1 + it->area];
1868 /* If the glyph row is reversed, we need to prepend the glyph rather
1869 than append it. */
1870 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1872 struct glyph *g;
1873 int move_by = it->pixel_width;
1875 /* Make room for the new glyphs. */
1876 if (move_by > end - glyph) /* don't overstep end of this area */
1877 move_by = end - glyph;
1878 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1879 g[move_by] = *g;
1880 glyph = it->glyph_row->glyphs[it->area];
1881 end = glyph + move_by;
1884 if (glyph >= end)
1885 return;
1886 glyph->type = CHAR_GLYPH;
1887 glyph->pixel_width = 1;
1888 glyph->face_id = face_id;
1889 glyph->padding_p = 0;
1890 glyph->charpos = CHARPOS (it->position);
1891 glyph->object = it->object;
1892 if (it->bidi_p)
1894 glyph->resolved_level = it->bidi_it.resolved_level;
1895 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1896 abort ();
1897 glyph->bidi_type = it->bidi_it.type;
1899 else
1901 glyph->resolved_level = 0;
1902 glyph->bidi_type = UNKNOWN_BT;
1905 /* BIDI Note: we put the glyphs of characters left to right, even in
1906 the REVERSED_P case because we write to the terminal
1907 left-to-right. */
1908 for (i = 0; i < it->nglyphs && glyph < end; ++i)
1910 if (i > 0)
1911 glyph[0] = glyph[-1];
1912 glyph->u.ch = str[i];
1913 ++it->glyph_row->used[it->area];
1914 ++glyph;
1918 /* Produce glyphs for a glyphless character for iterator IT.
1919 IT->glyphless_method specifies which method to use for displaying
1920 the character. See the description of enum
1921 glyphless_display_method in dispextern.h for the details.
1923 FOR_NO_FONT is nonzero if and only if this is for a character that
1924 is not supproted by the coding system of the terminal. ACRONYM, if
1925 non-nil, is an acronym string for the character.
1927 The glyphs actually produced are of type CHAR_GLYPH. */
1929 static void
1930 produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym)
1932 int face_id;
1933 int len;
1934 char buf[9], *str = " ";
1936 /* Get a face ID for the glyph by utilizing a cache (the same way as
1937 done for `escape-glyph' in get_next_display_element). */
1938 if (it->f == last_glyphless_glyph_frame
1939 && it->face_id == last_glyphless_glyph_face_id)
1941 face_id = last_glyphless_glyph_merged_face_id;
1943 else
1945 /* Merge the `glyphless-char' face into the current face. */
1946 face_id = merge_faces (it->f, Qglyphless_char, 0, it->face_id);
1947 last_glyphless_glyph_frame = it->f;
1948 last_glyphless_glyph_face_id = it->face_id;
1949 last_glyphless_glyph_merged_face_id = face_id;
1952 if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE)
1954 /* As there's no way to produce a thin space, we produce a space
1955 of canonical width. */
1956 len = 1;
1958 else if (it->glyphless_method == GLYPHLESS_DISPLAY_EMPTY_BOX)
1960 len = CHAR_WIDTH (it->c);
1961 if (len == 0)
1962 len = 1;
1963 else if (len > 4)
1964 len = 4;
1965 sprintf (buf, "[%.*s]", len, str);
1966 len += 2;
1967 str = buf;
1969 else
1971 if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM)
1973 if (! STRINGP (acronym) && CHAR_TABLE_P (Vglyphless_char_display))
1974 acronym = CHAR_TABLE_REF (Vglyphless_char_display, it->c);
1975 buf[0] = '[';
1976 str = STRINGP (acronym) ? (char *) SDATA (acronym) : "";
1977 for (len = 0; len < 6 && str[len] && ASCII_BYTE_P (str[len]); len++)
1978 buf[1 + len] = str[len];
1979 buf[1 + len] = ']';
1980 len += 2;
1982 else
1984 xassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEX_CODE);
1985 len = (it->c < 0x10000 ? sprintf (buf, "\\u%04X", it->c)
1986 : it->c <= MAX_UNICODE_CHAR ? sprintf (buf, "\\U%06X", it->c)
1987 : sprintf (buf, "\\x%06X", it->c));
1989 str = buf;
1992 it->pixel_width = len;
1993 it->nglyphs = len;
1994 if (len > 0 && it->glyph_row)
1995 append_glyphless_glyph (it, face_id, str);
1999 /* Get information about special display element WHAT in an
2000 environment described by IT. WHAT is one of IT_TRUNCATION or
2001 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
2002 non-null glyph_row member. This function ensures that fields like
2003 face_id, c, len of IT are left untouched. */
2005 void
2006 produce_special_glyphs (struct it *it, enum display_element_type what)
2008 struct it temp_it;
2009 Lisp_Object gc;
2010 GLYPH glyph;
2012 temp_it = *it;
2013 temp_it.dp = NULL;
2014 temp_it.what = IT_CHARACTER;
2015 temp_it.len = 1;
2016 temp_it.object = make_number (0);
2017 memset (&temp_it.current, 0, sizeof temp_it.current);
2019 if (what == IT_CONTINUATION)
2021 /* Continuation glyph. For R2L lines, we mirror it by hand. */
2022 if (it->bidi_it.paragraph_dir == R2L)
2023 SET_GLYPH_FROM_CHAR (glyph, '/');
2024 else
2025 SET_GLYPH_FROM_CHAR (glyph, '\\');
2026 if (it->dp
2027 && (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc))
2028 && GLYPH_CODE_CHAR_VALID_P (gc))
2030 /* FIXME: Should we mirror GC for R2L lines? */
2031 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
2032 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
2035 else if (what == IT_TRUNCATION)
2037 /* Truncation glyph. */
2038 SET_GLYPH_FROM_CHAR (glyph, '$');
2039 if (it->dp
2040 && (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc))
2041 && GLYPH_CODE_CHAR_VALID_P (gc))
2043 /* FIXME: Should we mirror GC for R2L lines? */
2044 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
2045 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
2048 else
2049 abort ();
2051 temp_it.c = temp_it.char_to_display = GLYPH_CHAR (glyph);
2052 temp_it.face_id = GLYPH_FACE (glyph);
2053 temp_it.len = CHAR_BYTES (temp_it.c);
2055 produce_glyphs (&temp_it);
2056 it->pixel_width = temp_it.pixel_width;
2057 it->nglyphs = temp_it.pixel_width;
2062 /***********************************************************************
2063 Faces
2064 ***********************************************************************/
2066 /* Value is non-zero if attribute ATTR may be used. ATTR should be
2067 one of the enumerators from enum no_color_bit, or a bit set built
2068 from them. Some display attributes may not be used together with
2069 color; the termcap capability `NC' specifies which ones. */
2071 #define MAY_USE_WITH_COLORS_P(tty, ATTR) \
2072 (tty->TN_max_colors > 0 \
2073 ? (tty->TN_no_color_video & (ATTR)) == 0 \
2074 : 1)
2076 /* Turn appearances of face FACE_ID on tty frame F on.
2077 FACE_ID is a realized face ID number, in the face cache. */
2079 static void
2080 turn_on_face (struct frame *f, int face_id)
2082 struct face *face = FACE_FROM_ID (f, face_id);
2083 long fg = face->foreground;
2084 long bg = face->background;
2085 struct tty_display_info *tty = FRAME_TTY (f);
2087 /* Do this first because TS_end_standout_mode may be the same
2088 as TS_exit_attribute_mode, which turns all appearances off. */
2089 if (MAY_USE_WITH_COLORS_P (tty, NC_REVERSE))
2091 if (tty->TN_max_colors > 0)
2093 if (fg >= 0 && bg >= 0)
2095 /* If the terminal supports colors, we can set them
2096 below without using reverse video. The face's fg
2097 and bg colors are set as they should appear on
2098 the screen, i.e. they take the inverse-video'ness
2099 of the face already into account. */
2101 else if (inverse_video)
2103 if (fg == FACE_TTY_DEFAULT_FG_COLOR
2104 || bg == FACE_TTY_DEFAULT_BG_COLOR)
2105 tty_toggle_highlight (tty);
2107 else
2109 if (fg == FACE_TTY_DEFAULT_BG_COLOR
2110 || bg == FACE_TTY_DEFAULT_FG_COLOR)
2111 tty_toggle_highlight (tty);
2114 else
2116 /* If we can't display colors, use reverse video
2117 if the face specifies that. */
2118 if (inverse_video)
2120 if (fg == FACE_TTY_DEFAULT_FG_COLOR
2121 || bg == FACE_TTY_DEFAULT_BG_COLOR)
2122 tty_toggle_highlight (tty);
2124 else
2126 if (fg == FACE_TTY_DEFAULT_BG_COLOR
2127 || bg == FACE_TTY_DEFAULT_FG_COLOR)
2128 tty_toggle_highlight (tty);
2133 if (face->tty_bold_p && MAY_USE_WITH_COLORS_P (tty, NC_BOLD))
2134 OUTPUT1_IF (tty, tty->TS_enter_bold_mode);
2136 if (face->tty_dim_p && MAY_USE_WITH_COLORS_P (tty, NC_DIM))
2137 OUTPUT1_IF (tty, tty->TS_enter_dim_mode);
2139 /* Alternate charset and blinking not yet used. */
2140 if (face->tty_alt_charset_p
2141 && MAY_USE_WITH_COLORS_P (tty, NC_ALT_CHARSET))
2142 OUTPUT1_IF (tty, tty->TS_enter_alt_charset_mode);
2144 if (face->tty_blinking_p
2145 && MAY_USE_WITH_COLORS_P (tty, NC_BLINK))
2146 OUTPUT1_IF (tty, tty->TS_enter_blink_mode);
2148 if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (tty, NC_UNDERLINE))
2149 OUTPUT1_IF (tty, tty->TS_enter_underline_mode);
2151 if (tty->TN_max_colors > 0)
2153 char *ts, *p;
2155 ts = tty->standout_mode ? tty->TS_set_background : tty->TS_set_foreground;
2156 if (fg >= 0 && ts)
2158 p = tparam (ts, NULL, 0, (int) fg);
2159 OUTPUT (tty, p);
2160 xfree (p);
2163 ts = tty->standout_mode ? tty->TS_set_foreground : tty->TS_set_background;
2164 if (bg >= 0 && ts)
2166 p = tparam (ts, NULL, 0, (int) bg);
2167 OUTPUT (tty, p);
2168 xfree (p);
2174 /* Turn off appearances of face FACE_ID on tty frame F. */
2176 static void
2177 turn_off_face (struct frame *f, int face_id)
2179 struct face *face = FACE_FROM_ID (f, face_id);
2180 struct tty_display_info *tty = FRAME_TTY (f);
2182 xassert (face != NULL);
2184 if (tty->TS_exit_attribute_mode)
2186 /* Capability "me" will turn off appearance modes double-bright,
2187 half-bright, reverse-video, standout, underline. It may or
2188 may not turn off alt-char-mode. */
2189 if (face->tty_bold_p
2190 || face->tty_dim_p
2191 || face->tty_reverse_p
2192 || face->tty_alt_charset_p
2193 || face->tty_blinking_p
2194 || face->tty_underline_p)
2196 OUTPUT1_IF (tty, tty->TS_exit_attribute_mode);
2197 if (strcmp (tty->TS_exit_attribute_mode, tty->TS_end_standout_mode) == 0)
2198 tty->standout_mode = 0;
2201 if (face->tty_alt_charset_p)
2202 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
2204 else
2206 /* If we don't have "me" we can only have those appearances
2207 that have exit sequences defined. */
2208 if (face->tty_alt_charset_p)
2209 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
2211 if (face->tty_underline_p)
2212 OUTPUT_IF (tty, tty->TS_exit_underline_mode);
2215 /* Switch back to default colors. */
2216 if (tty->TN_max_colors > 0
2217 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
2218 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
2219 || (face->background != FACE_TTY_DEFAULT_COLOR
2220 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
2221 OUTPUT1_IF (tty, tty->TS_orig_pair);
2225 /* Return non-zero if the terminal on frame F supports all of the
2226 capabilities in CAPS simultaneously, with foreground and background
2227 colors FG and BG. */
2230 tty_capable_p (struct tty_display_info *tty, unsigned int caps,
2231 unsigned long fg, unsigned long bg)
2233 #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
2234 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
2235 return 0;
2237 TTY_CAPABLE_P_TRY (tty, TTY_CAP_INVERSE, tty->TS_standout_mode, NC_REVERSE);
2238 TTY_CAPABLE_P_TRY (tty, TTY_CAP_UNDERLINE, tty->TS_enter_underline_mode, NC_UNDERLINE);
2239 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BOLD, tty->TS_enter_bold_mode, NC_BOLD);
2240 TTY_CAPABLE_P_TRY (tty, TTY_CAP_DIM, tty->TS_enter_dim_mode, NC_DIM);
2241 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BLINK, tty->TS_enter_blink_mode, NC_BLINK);
2242 TTY_CAPABLE_P_TRY (tty, TTY_CAP_ALT_CHARSET, tty->TS_enter_alt_charset_mode, NC_ALT_CHARSET);
2244 /* We can do it! */
2245 return 1;
2248 /* Return non-zero if the terminal is capable to display colors. */
2250 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
2251 0, 1, 0,
2252 doc: /* Return non-nil if the tty device TERMINAL can display colors.
2254 TERMINAL can be a terminal object, a frame, or nil (meaning the
2255 selected frame's terminal). This function always returns nil if
2256 TERMINAL does not refer to a text-only terminal. */)
2257 (Lisp_Object terminal)
2259 struct terminal *t = get_tty_terminal (terminal, 0);
2260 if (!t)
2261 return Qnil;
2262 else
2263 return t->display_info.tty->TN_max_colors > 0 ? Qt : Qnil;
2266 /* Return the number of supported colors. */
2267 DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
2268 Stty_display_color_cells, 0, 1, 0,
2269 doc: /* Return the number of colors supported by the tty device TERMINAL.
2271 TERMINAL can be a terminal object, a frame, or nil (meaning the
2272 selected frame's terminal). This function always returns 0 if
2273 TERMINAL does not refer to a text-only terminal. */)
2274 (Lisp_Object terminal)
2276 struct terminal *t = get_tty_terminal (terminal, 0);
2277 if (!t)
2278 return make_number (0);
2279 else
2280 return make_number (t->display_info.tty->TN_max_colors);
2283 #ifndef DOS_NT
2285 /* Declare here rather than in the function, as in the rest of Emacs,
2286 to work around an HPUX compiler bug (?). See
2287 http://lists.gnu.org/archive/html/emacs-devel/2007-08/msg00410.html */
2288 static int default_max_colors;
2289 static int default_max_pairs;
2290 static int default_no_color_video;
2291 static char *default_orig_pair;
2292 static char *default_set_foreground;
2293 static char *default_set_background;
2295 /* Save or restore the default color-related capabilities of this
2296 terminal. */
2297 static void
2298 tty_default_color_capabilities (struct tty_display_info *tty, int save)
2301 if (save)
2303 xfree (default_orig_pair);
2304 default_orig_pair = tty->TS_orig_pair ? xstrdup (tty->TS_orig_pair) : NULL;
2306 xfree (default_set_foreground);
2307 default_set_foreground = tty->TS_set_foreground ? xstrdup (tty->TS_set_foreground)
2308 : NULL;
2310 xfree (default_set_background);
2311 default_set_background = tty->TS_set_background ? xstrdup (tty->TS_set_background)
2312 : NULL;
2314 default_max_colors = tty->TN_max_colors;
2315 default_max_pairs = tty->TN_max_pairs;
2316 default_no_color_video = tty->TN_no_color_video;
2318 else
2320 tty->TS_orig_pair = default_orig_pair;
2321 tty->TS_set_foreground = default_set_foreground;
2322 tty->TS_set_background = default_set_background;
2323 tty->TN_max_colors = default_max_colors;
2324 tty->TN_max_pairs = default_max_pairs;
2325 tty->TN_no_color_video = default_no_color_video;
2329 /* Setup one of the standard tty color schemes according to MODE.
2330 MODE's value is generally the number of colors which we want to
2331 support; zero means set up for the default capabilities, the ones
2332 we saw at init_tty time; -1 means turn off color support. */
2333 static void
2334 tty_setup_colors (struct tty_display_info *tty, int mode)
2336 /* Canonicalize all negative values of MODE. */
2337 if (mode < -1)
2338 mode = -1;
2340 switch (mode)
2342 case -1: /* no colors at all */
2343 tty->TN_max_colors = 0;
2344 tty->TN_max_pairs = 0;
2345 tty->TN_no_color_video = 0;
2346 tty->TS_set_foreground = tty->TS_set_background = tty->TS_orig_pair = NULL;
2347 break;
2348 case 0: /* default colors, if any */
2349 default:
2350 tty_default_color_capabilities (tty, 0);
2351 break;
2352 case 8: /* 8 standard ANSI colors */
2353 tty->TS_orig_pair = "\033[0m";
2354 #ifdef TERMINFO
2355 tty->TS_set_foreground = "\033[3%p1%dm";
2356 tty->TS_set_background = "\033[4%p1%dm";
2357 #else
2358 tty->TS_set_foreground = "\033[3%dm";
2359 tty->TS_set_background = "\033[4%dm";
2360 #endif
2361 tty->TN_max_colors = 8;
2362 tty->TN_max_pairs = 64;
2363 tty->TN_no_color_video = 0;
2364 break;
2368 void
2369 set_tty_color_mode (struct tty_display_info *tty, struct frame *f)
2371 Lisp_Object tem, val;
2372 Lisp_Object color_mode;
2373 int mode;
2374 Lisp_Object tty_color_mode_alist
2375 = Fintern_soft (build_string ("tty-color-mode-alist"), Qnil);
2377 tem = assq_no_quit (Qtty_color_mode, f->param_alist);
2378 val = CONSP (tem) ? XCDR (tem) : Qnil;
2380 if (INTEGERP (val))
2381 color_mode = val;
2382 else if (SYMBOLP (tty_color_mode_alist))
2384 tem = Fassq (val, Fsymbol_value (tty_color_mode_alist));
2385 color_mode = CONSP (tem) ? XCDR (tem) : Qnil;
2387 else
2388 color_mode = Qnil;
2390 mode = INTEGERP (color_mode) ? XINT (color_mode) : 0;
2392 if (mode != tty->previous_color_mode)
2394 Lisp_Object funsym = intern ("tty-set-up-initial-frame-faces");
2395 tty->previous_color_mode = mode;
2396 tty_setup_colors (tty , mode);
2397 /* This recomputes all the faces given the new color definitions. */
2398 safe_call (1, &funsym);
2402 #endif /* !DOS_NT */
2406 /* Return the tty display object specified by TERMINAL. */
2408 struct terminal *
2409 get_tty_terminal (Lisp_Object terminal, int throw)
2411 struct terminal *t = get_terminal (terminal, throw);
2413 if (t && t->type != output_termcap && t->type != output_msdos_raw)
2415 if (throw)
2416 error ("Device %d is not a termcap terminal device", t->id);
2417 else
2418 return NULL;
2421 return t;
2424 /* Return an active termcap device that uses the tty device with the
2425 given name.
2427 This function ignores suspended devices.
2429 Returns NULL if the named terminal device is not opened. */
2431 struct terminal *
2432 get_named_tty (const char *name)
2434 struct terminal *t;
2436 if (!name)
2437 abort ();
2439 for (t = terminal_list; t; t = t->next_terminal)
2441 if ((t->type == output_termcap || t->type == output_msdos_raw)
2442 && !strcmp (t->display_info.tty->name, name)
2443 && TERMINAL_ACTIVE_P (t))
2444 return t;
2447 return 0;
2451 DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0,
2452 doc: /* Return the type of the tty device that TERMINAL uses.
2453 Returns nil if TERMINAL is not on a tty device.
2455 TERMINAL can be a terminal object, a frame, or nil (meaning the
2456 selected frame's terminal). */)
2457 (Lisp_Object terminal)
2459 struct terminal *t = get_terminal (terminal, 1);
2461 if (t->type != output_termcap && t->type != output_msdos_raw)
2462 return Qnil;
2464 if (t->display_info.tty->type)
2465 return build_string (t->display_info.tty->type);
2466 else
2467 return Qnil;
2470 DEFUN ("controlling-tty-p", Fcontrolling_tty_p, Scontrolling_tty_p, 0, 1, 0,
2471 doc: /* Return non-nil if TERMINAL is the controlling tty of the Emacs process.
2473 TERMINAL can be a terminal object, a frame, or nil (meaning the
2474 selected frame's terminal). This function always returns nil if
2475 TERMINAL is not on a tty device. */)
2476 (Lisp_Object terminal)
2478 struct terminal *t = get_terminal (terminal, 1);
2480 if ((t->type != output_termcap && t->type != output_msdos_raw)
2481 || strcmp (t->display_info.tty->name, DEV_TTY) != 0)
2482 return Qnil;
2483 else
2484 return Qt;
2487 DEFUN ("tty-no-underline", Ftty_no_underline, Stty_no_underline, 0, 1, 0,
2488 doc: /* Declare that the tty used by TERMINAL does not handle underlining.
2489 This is used to override the terminfo data, for certain terminals that
2490 do not really do underlining, but say that they do. This function has
2491 no effect if used on a non-tty terminal.
2493 TERMINAL can be a terminal object, a frame or nil (meaning the
2494 selected frame's terminal). This function always returns nil if
2495 TERMINAL does not refer to a text-only terminal. */)
2496 (Lisp_Object terminal)
2498 struct terminal *t = get_terminal (terminal, 1);
2500 if (t->type == output_termcap)
2501 t->display_info.tty->TS_enter_underline_mode = 0;
2502 return Qnil;
2507 DEFUN ("suspend-tty", Fsuspend_tty, Ssuspend_tty, 0, 1, 0,
2508 doc: /* Suspend the terminal device TTY.
2510 The device is restored to its default state, and Emacs ceases all
2511 access to the tty device. Frames that use the device are not deleted,
2512 but input is not read from them and if they change, their display is
2513 not updated.
2515 TTY may be a terminal object, a frame, or nil for the terminal device
2516 of the currently selected frame.
2518 This function runs `suspend-tty-functions' after suspending the
2519 device. The functions are run with one arg, the id of the suspended
2520 terminal device.
2522 `suspend-tty' does nothing if it is called on a device that is already
2523 suspended.
2525 A suspended tty may be resumed by calling `resume-tty' on it. */)
2526 (Lisp_Object tty)
2528 struct terminal *t = get_tty_terminal (tty, 1);
2529 FILE *f;
2531 if (!t)
2532 error ("Unknown tty device");
2534 f = t->display_info.tty->input;
2536 if (f)
2538 /* First run `suspend-tty-functions' and then clean up the tty
2539 state because `suspend-tty-functions' might need to change
2540 the tty state. */
2541 if (!NILP (Vrun_hooks))
2543 Lisp_Object args[2];
2544 args[0] = intern ("suspend-tty-functions");
2545 XSETTERMINAL (args[1], t);
2546 Frun_hook_with_args (2, args);
2549 reset_sys_modes (t->display_info.tty);
2550 delete_keyboard_wait_descriptor (fileno (f));
2552 #ifndef MSDOS
2553 fclose (f);
2554 if (f != t->display_info.tty->output)
2555 fclose (t->display_info.tty->output);
2556 #endif
2558 t->display_info.tty->input = 0;
2559 t->display_info.tty->output = 0;
2561 if (FRAMEP (t->display_info.tty->top_frame))
2562 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0);
2566 /* Clear display hooks to prevent further output. */
2567 clear_tty_hooks (t);
2569 return Qnil;
2572 DEFUN ("resume-tty", Fresume_tty, Sresume_tty, 0, 1, 0,
2573 doc: /* Resume the previously suspended terminal device TTY.
2574 The terminal is opened and reinitialized. Frames that are on the
2575 suspended terminal are revived.
2577 It is an error to resume a terminal while another terminal is active
2578 on the same device.
2580 This function runs `resume-tty-functions' after resuming the terminal.
2581 The functions are run with one arg, the id of the resumed terminal
2582 device.
2584 `resume-tty' does nothing if it is called on a device that is not
2585 suspended.
2587 TTY may be a terminal object, a frame, or nil (meaning the selected
2588 frame's terminal). */)
2589 (Lisp_Object tty)
2591 struct terminal *t = get_tty_terminal (tty, 1);
2592 int fd;
2594 if (!t)
2595 error ("Unknown tty device");
2597 if (!t->display_info.tty->input)
2599 if (get_named_tty (t->display_info.tty->name))
2600 error ("Cannot resume display while another display is active on the same device");
2602 #ifdef MSDOS
2603 t->display_info.tty->output = stdout;
2604 t->display_info.tty->input = stdin;
2605 #else /* !MSDOS */
2606 fd = emacs_open (t->display_info.tty->name, O_RDWR | O_NOCTTY, 0);
2608 if (fd == -1)
2609 error ("Can not reopen tty device %s: %s", t->display_info.tty->name, strerror (errno));
2611 if (strcmp (t->display_info.tty->name, DEV_TTY))
2612 dissociate_if_controlling_tty (fd);
2614 t->display_info.tty->output = fdopen (fd, "w+");
2615 t->display_info.tty->input = t->display_info.tty->output;
2616 #endif
2618 add_keyboard_wait_descriptor (fd);
2620 if (FRAMEP (t->display_info.tty->top_frame))
2622 struct frame *f = XFRAME (t->display_info.tty->top_frame);
2623 int width, height;
2624 int old_height = FRAME_COLS (f);
2625 int old_width = FRAME_LINES (f);
2627 /* Check if terminal/window size has changed while the frame
2628 was suspended. */
2629 get_tty_size (fileno (t->display_info.tty->input), &width, &height);
2630 if (width != old_width || height != old_height)
2631 change_frame_size (f, height, width, 0, 0, 0);
2632 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
2635 init_sys_modes (t->display_info.tty);
2637 /* Run `resume-tty-functions'. */
2638 if (!NILP (Vrun_hooks))
2640 Lisp_Object args[2];
2641 args[0] = intern ("resume-tty-functions");
2642 XSETTERMINAL (args[1], t);
2643 Frun_hook_with_args (2, args);
2647 set_tty_hooks (t);
2649 return Qnil;
2653 /***********************************************************************
2654 Mouse
2655 ***********************************************************************/
2657 #ifdef HAVE_GPM
2658 void
2659 term_mouse_moveto (int x, int y)
2661 /* TODO: how to set mouse position?
2662 const char *name;
2663 int fd;
2664 name = (const char *) ttyname (0);
2665 fd = open (name, O_WRONLY);
2666 SOME_FUNCTION (x, y, fd);
2667 close (fd);
2668 last_mouse_x = x;
2669 last_mouse_y = y; */
2672 /* Implementation of draw_row_with_mouse_face for TTY/GPM. */
2673 void
2674 tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *row,
2675 int start_hpos, int end_hpos,
2676 enum draw_glyphs_face draw)
2678 int nglyphs = end_hpos - start_hpos;
2679 struct frame *f = XFRAME (WINDOW_FRAME (w));
2680 struct tty_display_info *tty = FRAME_TTY (f);
2681 int face_id = tty->mouse_highlight.mouse_face_face_id;
2682 int save_x, save_y, pos_x, pos_y;
2684 if (end_hpos >= row->used[TEXT_AREA])
2685 nglyphs = row->used[TEXT_AREA] - start_hpos;
2687 pos_y = row->y + WINDOW_TOP_EDGE_Y (w);
2688 pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos + WINDOW_LEFT_EDGE_X (w);
2690 /* Save current cursor co-ordinates. */
2691 save_y = curY (tty);
2692 save_x = curX (tty);
2693 cursor_to (f, pos_y, pos_x);
2695 if (draw == DRAW_MOUSE_FACE)
2696 tty_write_glyphs_with_face (f, row->glyphs[TEXT_AREA] + start_hpos,
2697 nglyphs, face_id);
2698 else if (draw == DRAW_NORMAL_TEXT)
2699 write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
2701 cursor_to (f, save_y, save_x);
2704 static int
2705 term_mouse_movement (FRAME_PTR frame, Gpm_Event *event)
2707 /* Has the mouse moved off the glyph it was on at the last sighting? */
2708 if (event->x != last_mouse_x || event->y != last_mouse_y)
2710 frame->mouse_moved = 1;
2711 note_mouse_highlight (frame, event->x, event->y);
2712 /* Remember which glyph we're now on. */
2713 last_mouse_x = event->x;
2714 last_mouse_y = event->y;
2715 return 1;
2717 return 0;
2720 /* Return the current position of the mouse.
2722 Set *f to the frame the mouse is in, or zero if the mouse is in no
2723 Emacs frame. If it is set to zero, all the other arguments are
2724 garbage.
2726 Set *bar_window to Qnil, and *x and *y to the column and
2727 row of the character cell the mouse is over.
2729 Set *time to the time the mouse was at the returned position.
2731 This clears mouse_moved until the next motion
2732 event arrives. */
2733 static void
2734 term_mouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
2735 enum scroll_bar_part *part, Lisp_Object *x,
2736 Lisp_Object *y, unsigned long *time)
2738 struct timeval now;
2740 *fp = SELECTED_FRAME ();
2741 (*fp)->mouse_moved = 0;
2743 *bar_window = Qnil;
2744 *part = 0;
2746 XSETINT (*x, last_mouse_x);
2747 XSETINT (*y, last_mouse_y);
2748 gettimeofday(&now, 0);
2749 *time = (now.tv_sec * 1000) + (now.tv_usec / 1000);
2752 /* Prepare a mouse-event in *RESULT for placement in the input queue.
2754 If the event is a button press, then note that we have grabbed
2755 the mouse. */
2757 static Lisp_Object
2758 term_mouse_click (struct input_event *result, Gpm_Event *event,
2759 struct frame *f)
2761 struct timeval now;
2762 int i, j;
2764 result->kind = GPM_CLICK_EVENT;
2765 for (i = 0, j = GPM_B_LEFT; i < 3; i++, j >>= 1 )
2767 if (event->buttons & j) {
2768 result->code = i; /* button number */
2769 break;
2772 gettimeofday(&now, 0);
2773 result->timestamp = (now.tv_sec * 1000) + (now.tv_usec / 1000);
2775 if (event->type & GPM_UP)
2776 result->modifiers = up_modifier;
2777 else if (event->type & GPM_DOWN)
2778 result->modifiers = down_modifier;
2779 else
2780 result->modifiers = 0;
2782 if (event->type & GPM_SINGLE)
2783 result->modifiers |= click_modifier;
2785 if (event->type & GPM_DOUBLE)
2786 result->modifiers |= double_modifier;
2788 if (event->type & GPM_TRIPLE)
2789 result->modifiers |= triple_modifier;
2791 if (event->type & GPM_DRAG)
2792 result->modifiers |= drag_modifier;
2794 if (!(event->type & (GPM_MOVE | GPM_DRAG))) {
2796 /* 1 << KG_SHIFT */
2797 if (event->modifiers & (1 << 0))
2798 result->modifiers |= shift_modifier;
2800 /* 1 << KG_CTRL */
2801 if (event->modifiers & (1 << 2))
2802 result->modifiers |= ctrl_modifier;
2804 /* 1 << KG_ALT || KG_ALTGR */
2805 if (event->modifiers & (1 << 3)
2806 || event->modifiers & (1 << 1))
2807 result->modifiers |= meta_modifier;
2810 XSETINT (result->x, event->x);
2811 XSETINT (result->y, event->y);
2812 XSETFRAME (result->frame_or_window, f);
2813 result->arg = Qnil;
2814 return Qnil;
2818 handle_one_term_event (struct tty_display_info *tty, Gpm_Event *event, struct input_event* hold_quit)
2820 struct frame *f = XFRAME (tty->top_frame);
2821 struct input_event ie;
2822 int do_help = 0;
2823 int count = 0;
2825 EVENT_INIT (ie);
2826 ie.kind = NO_EVENT;
2827 ie.arg = Qnil;
2829 if (event->type & (GPM_MOVE | GPM_DRAG)) {
2830 previous_help_echo_string = help_echo_string;
2831 help_echo_string = Qnil;
2833 Gpm_DrawPointer (event->x, event->y, fileno (tty->output));
2835 if (!term_mouse_movement (f, event))
2836 help_echo_string = previous_help_echo_string;
2838 /* If the contents of the global variable help_echo_string
2839 has changed, generate a HELP_EVENT. */
2840 if (!NILP (help_echo_string)
2841 || !NILP (previous_help_echo_string))
2842 do_help = 1;
2844 goto done;
2846 else {
2847 f->mouse_moved = 0;
2848 term_mouse_click (&ie, event, f);
2851 done:
2852 if (ie.kind != NO_EVENT)
2854 kbd_buffer_store_event_hold (&ie, hold_quit);
2855 count++;
2858 if (do_help
2859 && !(hold_quit && hold_quit->kind != NO_EVENT))
2861 Lisp_Object frame;
2863 if (f)
2864 XSETFRAME (frame, f);
2865 else
2866 frame = Qnil;
2868 gen_help_event (help_echo_string, frame, help_echo_window,
2869 help_echo_object, help_echo_pos);
2870 count++;
2873 return count;
2876 DEFUN ("gpm-mouse-start", Fgpm_mouse_start, Sgpm_mouse_start,
2877 0, 0, 0,
2878 doc: /* Open a connection to Gpm.
2879 Gpm-mouse can only be activated for one tty at a time. */)
2880 (void)
2882 struct frame *f = SELECTED_FRAME ();
2883 struct tty_display_info *tty
2884 = ((f)->output_method == output_termcap
2885 ? (f)->terminal->display_info.tty : NULL);
2886 Gpm_Connect connection;
2888 if (!tty)
2889 error ("Gpm-mouse only works in the GNU/Linux console");
2890 if (gpm_tty == tty)
2891 return Qnil; /* Already activated, nothing to do. */
2892 if (gpm_tty)
2893 error ("Gpm-mouse can only be activated for one tty at a time");
2895 connection.eventMask = ~0;
2896 connection.defaultMask = ~GPM_HARD;
2897 connection.maxMod = ~0;
2898 connection.minMod = 0;
2899 gpm_zerobased = 1;
2901 if (Gpm_Open (&connection, 0) < 0)
2902 error ("Gpm-mouse failed to connect to the gpm daemon");
2903 else
2905 gpm_tty = tty;
2906 /* `init_sys_modes' arranges for mouse movements sent through gpm_fd
2907 to generate SIGIOs. Apparently we need to call reset_sys_modes
2908 before calling init_sys_modes. */
2909 reset_sys_modes (tty);
2910 init_sys_modes (tty);
2911 add_gpm_wait_descriptor (gpm_fd);
2912 return Qnil;
2916 void
2917 close_gpm (int fd)
2919 if (fd >= 0)
2920 delete_gpm_wait_descriptor (fd);
2921 while (Gpm_Close()); /* close all the stack */
2922 gpm_tty = NULL;
2925 DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop, Sgpm_mouse_stop,
2926 0, 0, 0,
2927 doc: /* Close a connection to Gpm. */)
2928 (void)
2930 struct frame *f = SELECTED_FRAME ();
2931 struct tty_display_info *tty
2932 = ((f)->output_method == output_termcap
2933 ? (f)->terminal->display_info.tty : NULL);
2935 if (!tty || gpm_tty != tty)
2936 return Qnil; /* Not activated on this terminal, nothing to do. */
2938 close_gpm (gpm_fd);
2939 return Qnil;
2941 #endif /* HAVE_GPM */
2944 #ifndef MSDOS
2945 /***********************************************************************
2946 Initialization
2947 ***********************************************************************/
2949 /* Initialize the tty-dependent part of frame F. The frame must
2950 already have its device initialized. */
2952 void
2953 create_tty_output (struct frame *f)
2955 struct tty_output *t;
2957 if (! FRAME_TERMCAP_P (f))
2958 abort ();
2960 t = xmalloc (sizeof (struct tty_output));
2961 memset (t, 0, sizeof (struct tty_output));
2963 t->display_info = FRAME_TERMINAL (f)->display_info.tty;
2965 f->output_data.tty = t;
2968 /* Delete frame F's face cache, and its tty-dependent part. */
2970 static void
2971 tty_free_frame_resources (struct frame *f)
2973 if (! FRAME_TERMCAP_P (f))
2974 abort ();
2976 if (FRAME_FACE_CACHE (f))
2977 free_frame_faces (f);
2979 xfree (f->output_data.tty);
2982 #else /* MSDOS */
2984 /* Delete frame F's face cache. */
2986 static void
2987 tty_free_frame_resources (struct frame *f)
2989 if (! FRAME_TERMCAP_P (f) && ! FRAME_MSDOS_P (f))
2990 abort ();
2992 if (FRAME_FACE_CACHE (f))
2993 free_frame_faces (f);
2995 #endif /* MSDOS */
2997 /* Reset the hooks in TERMINAL. */
2999 static void
3000 clear_tty_hooks (struct terminal *terminal)
3002 terminal->rif = 0;
3003 terminal->cursor_to_hook = 0;
3004 terminal->raw_cursor_to_hook = 0;
3005 terminal->clear_to_end_hook = 0;
3006 terminal->clear_frame_hook = 0;
3007 terminal->clear_end_of_line_hook = 0;
3008 terminal->ins_del_lines_hook = 0;
3009 terminal->insert_glyphs_hook = 0;
3010 terminal->write_glyphs_hook = 0;
3011 terminal->delete_glyphs_hook = 0;
3012 terminal->ring_bell_hook = 0;
3013 terminal->reset_terminal_modes_hook = 0;
3014 terminal->set_terminal_modes_hook = 0;
3015 terminal->update_begin_hook = 0;
3016 terminal->update_end_hook = 0;
3017 terminal->set_terminal_window_hook = 0;
3018 terminal->mouse_position_hook = 0;
3019 terminal->frame_rehighlight_hook = 0;
3020 terminal->frame_raise_lower_hook = 0;
3021 terminal->fullscreen_hook = 0;
3022 terminal->set_vertical_scroll_bar_hook = 0;
3023 terminal->condemn_scroll_bars_hook = 0;
3024 terminal->redeem_scroll_bar_hook = 0;
3025 terminal->judge_scroll_bars_hook = 0;
3026 terminal->read_socket_hook = 0;
3027 terminal->frame_up_to_date_hook = 0;
3029 /* Leave these two set, or suspended frames are not deleted
3030 correctly. */
3031 terminal->delete_frame_hook = &tty_free_frame_resources;
3032 terminal->delete_terminal_hook = &delete_tty;
3035 /* Initialize hooks in TERMINAL with the values needed for a tty. */
3037 static void
3038 set_tty_hooks (struct terminal *terminal)
3040 terminal->rif = 0; /* ttys don't support window-based redisplay. */
3042 terminal->cursor_to_hook = &tty_cursor_to;
3043 terminal->raw_cursor_to_hook = &tty_raw_cursor_to;
3045 terminal->clear_to_end_hook = &tty_clear_to_end;
3046 terminal->clear_frame_hook = &tty_clear_frame;
3047 terminal->clear_end_of_line_hook = &tty_clear_end_of_line;
3049 terminal->ins_del_lines_hook = &tty_ins_del_lines;
3051 terminal->insert_glyphs_hook = &tty_insert_glyphs;
3052 terminal->write_glyphs_hook = &tty_write_glyphs;
3053 terminal->delete_glyphs_hook = &tty_delete_glyphs;
3055 terminal->ring_bell_hook = &tty_ring_bell;
3057 terminal->reset_terminal_modes_hook = &tty_reset_terminal_modes;
3058 terminal->set_terminal_modes_hook = &tty_set_terminal_modes;
3059 terminal->update_begin_hook = 0; /* Not needed. */
3060 terminal->update_end_hook = &tty_update_end;
3061 terminal->set_terminal_window_hook = &tty_set_terminal_window;
3063 terminal->mouse_position_hook = 0; /* Not needed. */
3064 terminal->frame_rehighlight_hook = 0; /* Not needed. */
3065 terminal->frame_raise_lower_hook = 0; /* Not needed. */
3067 terminal->set_vertical_scroll_bar_hook = 0; /* Not needed. */
3068 terminal->condemn_scroll_bars_hook = 0; /* Not needed. */
3069 terminal->redeem_scroll_bar_hook = 0; /* Not needed. */
3070 terminal->judge_scroll_bars_hook = 0; /* Not needed. */
3072 terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */
3073 terminal->frame_up_to_date_hook = 0; /* Not needed. */
3075 terminal->delete_frame_hook = &tty_free_frame_resources;
3076 terminal->delete_terminal_hook = &delete_tty;
3079 /* Drop the controlling terminal if fd is the same device. */
3080 static void
3081 dissociate_if_controlling_tty (int fd)
3083 #ifndef DOS_NT
3084 int pgid = tcgetpgrp (fd); /* If tcgetpgrp succeeds, fd is the ctty. */
3085 if (pgid != -1)
3087 #if defined (USG5)
3088 setpgrp ();
3089 no_controlling_tty = 1;
3090 #elif defined (CYGWIN)
3091 setsid ();
3092 no_controlling_tty = 1;
3093 #else
3094 #ifdef TIOCNOTTY /* Try BSD ioctls. */
3095 sigblock (sigmask (SIGTTOU));
3096 fd = emacs_open (DEV_TTY, O_RDWR, 0);
3097 if (fd != -1 && ioctl (fd, TIOCNOTTY, 0) != -1)
3099 no_controlling_tty = 1;
3101 if (fd != -1)
3102 emacs_close (fd);
3103 sigunblock (sigmask (SIGTTOU));
3104 #else
3105 /* Unknown system. */
3106 croak ();
3107 #endif /* ! TIOCNOTTY */
3108 #endif /* ! USG */
3110 #endif /* !DOS_NT */
3113 /* Create a termcap display on the tty device with the given name and
3114 type.
3116 If NAME is NULL, then use the controlling tty, i.e., "/dev/tty".
3117 Otherwise NAME should be a path to the tty device file,
3118 e.g. "/dev/pts/7".
3120 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
3122 If MUST_SUCCEED is true, then all errors are fatal. */
3124 struct terminal *
3125 init_tty (const char *name, const char *terminal_type, int must_succeed)
3127 char *area = NULL;
3128 char **address = &area;
3129 int buffer_size = 4096;
3130 register char *p = NULL;
3131 int status;
3132 struct tty_display_info *tty = NULL;
3133 struct terminal *terminal = NULL;
3134 int ctty = 0; /* 1 if asked to open controlling tty. */
3136 if (!terminal_type)
3137 maybe_fatal (must_succeed, 0,
3138 "Unknown terminal type",
3139 "Unknown terminal type");
3141 if (name == NULL)
3142 name = DEV_TTY;
3143 if (!strcmp (name, DEV_TTY))
3144 ctty = 1;
3146 /* If we already have a terminal on the given device, use that. If
3147 all such terminals are suspended, create a new one instead. */
3148 /* XXX Perhaps this should be made explicit by having init_tty
3149 always create a new terminal and separating terminal and frame
3150 creation on Lisp level. */
3151 terminal = get_named_tty (name);
3152 if (terminal)
3153 return terminal;
3155 terminal = create_terminal ();
3156 #ifdef MSDOS
3157 if (been_here > 0)
3158 maybe_fatal (1, 0, "Attempt to create another terminal %s", "",
3159 name, "");
3160 been_here = 1;
3161 tty = &the_only_display_info;
3162 #else
3163 tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info));
3164 #endif
3165 memset (tty, 0, sizeof (struct tty_display_info));
3166 tty->next = tty_list;
3167 tty_list = tty;
3169 terminal->type = output_termcap;
3170 terminal->display_info.tty = tty;
3171 tty->terminal = terminal;
3173 tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
3174 Wcm_clear (tty);
3176 encode_terminal_src_size = 0;
3177 encode_terminal_dst_size = 0;
3179 #ifdef HAVE_GPM
3180 terminal->mouse_position_hook = term_mouse_position;
3181 tty->mouse_highlight.mouse_face_window = Qnil;
3182 #endif
3185 #ifndef DOS_NT
3186 set_tty_hooks (terminal);
3189 int fd;
3190 FILE *file;
3192 #ifdef O_IGNORE_CTTY
3193 if (!ctty)
3194 /* Open the terminal device. Don't recognize it as our
3195 controlling terminal, and don't make it the controlling tty
3196 if we don't have one at the moment. */
3197 fd = emacs_open (name, O_RDWR | O_IGNORE_CTTY | O_NOCTTY, 0);
3198 else
3199 #else
3200 /* Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
3201 defined on Hurd. On other systems, we need to explicitly
3202 dissociate ourselves from the controlling tty when we want to
3203 open a frame on the same terminal. */
3204 fd = emacs_open (name, O_RDWR | O_NOCTTY, 0);
3205 #endif /* O_IGNORE_CTTY */
3207 tty->name = xstrdup (name);
3208 terminal->name = xstrdup (name);
3210 if (fd < 0)
3211 maybe_fatal (must_succeed, terminal,
3212 "Could not open file: %s",
3213 "Could not open file: %s",
3214 name);
3215 if (!isatty (fd))
3217 close (fd);
3218 maybe_fatal (must_succeed, terminal,
3219 "Not a tty device: %s",
3220 "Not a tty device: %s",
3221 name);
3224 #ifndef O_IGNORE_CTTY
3225 if (!ctty)
3226 dissociate_if_controlling_tty (fd);
3227 #endif
3229 file = fdopen (fd, "w+");
3230 tty->input = file;
3231 tty->output = file;
3234 tty->type = xstrdup (terminal_type);
3236 add_keyboard_wait_descriptor (fileno (tty->input));
3238 Wcm_clear (tty);
3240 tty->termcap_term_buffer = (char *) xmalloc (buffer_size);
3242 /* On some systems, tgetent tries to access the controlling
3243 terminal. */
3244 sigblock (sigmask (SIGTTOU));
3245 status = tgetent (tty->termcap_term_buffer, terminal_type);
3246 sigunblock (sigmask (SIGTTOU));
3248 if (status < 0)
3250 #ifdef TERMINFO
3251 maybe_fatal (must_succeed, terminal,
3252 "Cannot open terminfo database file",
3253 "Cannot open terminfo database file");
3254 #else
3255 maybe_fatal (must_succeed, terminal,
3256 "Cannot open termcap database file",
3257 "Cannot open termcap database file");
3258 #endif
3260 if (status == 0)
3262 maybe_fatal (must_succeed, terminal,
3263 "Terminal type %s is not defined",
3264 "Terminal type %s is not defined.\n\
3265 If that is not the actual type of terminal you have,\n\
3266 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3267 `setenv TERM ...') to specify the correct type. It may be necessary\n"
3268 #ifdef TERMINFO
3269 "to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3270 #else
3271 "to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3272 #endif
3273 terminal_type);
3276 #ifndef TERMINFO
3277 if (strlen (tty->termcap_term_buffer) >= buffer_size)
3278 abort ();
3279 buffer_size = strlen (tty->termcap_term_buffer);
3280 #endif
3281 tty->termcap_strings_buffer = area = (char *) xmalloc (buffer_size);
3282 tty->TS_ins_line = tgetstr ("al", address);
3283 tty->TS_ins_multi_lines = tgetstr ("AL", address);
3284 tty->TS_bell = tgetstr ("bl", address);
3285 BackTab (tty) = tgetstr ("bt", address);
3286 tty->TS_clr_to_bottom = tgetstr ("cd", address);
3287 tty->TS_clr_line = tgetstr ("ce", address);
3288 tty->TS_clr_frame = tgetstr ("cl", address);
3289 ColPosition (tty) = NULL; /* tgetstr ("ch", address); */
3290 AbsPosition (tty) = tgetstr ("cm", address);
3291 CR (tty) = tgetstr ("cr", address);
3292 tty->TS_set_scroll_region = tgetstr ("cs", address);
3293 tty->TS_set_scroll_region_1 = tgetstr ("cS", address);
3294 RowPosition (tty) = tgetstr ("cv", address);
3295 tty->TS_del_char = tgetstr ("dc", address);
3296 tty->TS_del_multi_chars = tgetstr ("DC", address);
3297 tty->TS_del_line = tgetstr ("dl", address);
3298 tty->TS_del_multi_lines = tgetstr ("DL", address);
3299 tty->TS_delete_mode = tgetstr ("dm", address);
3300 tty->TS_end_delete_mode = tgetstr ("ed", address);
3301 tty->TS_end_insert_mode = tgetstr ("ei", address);
3302 Home (tty) = tgetstr ("ho", address);
3303 tty->TS_ins_char = tgetstr ("ic", address);
3304 tty->TS_ins_multi_chars = tgetstr ("IC", address);
3305 tty->TS_insert_mode = tgetstr ("im", address);
3306 tty->TS_pad_inserted_char = tgetstr ("ip", address);
3307 tty->TS_end_keypad_mode = tgetstr ("ke", address);
3308 tty->TS_keypad_mode = tgetstr ("ks", address);
3309 LastLine (tty) = tgetstr ("ll", address);
3310 Right (tty) = tgetstr ("nd", address);
3311 Down (tty) = tgetstr ("do", address);
3312 if (!Down (tty))
3313 Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do" */
3314 if (tgetflag ("bs"))
3315 Left (tty) = "\b"; /* can't possibly be longer! */
3316 else /* (Actually, "bs" is obsolete...) */
3317 Left (tty) = tgetstr ("le", address);
3318 if (!Left (tty))
3319 Left (tty) = tgetstr ("bc", address); /* Obsolete name for "le" */
3320 tty->TS_pad_char = tgetstr ("pc", address);
3321 tty->TS_repeat = tgetstr ("rp", address);
3322 tty->TS_end_standout_mode = tgetstr ("se", address);
3323 tty->TS_fwd_scroll = tgetstr ("sf", address);
3324 tty->TS_standout_mode = tgetstr ("so", address);
3325 tty->TS_rev_scroll = tgetstr ("sr", address);
3326 tty->Wcm->cm_tab = tgetstr ("ta", address);
3327 tty->TS_end_termcap_modes = tgetstr ("te", address);
3328 tty->TS_termcap_modes = tgetstr ("ti", address);
3329 Up (tty) = tgetstr ("up", address);
3330 tty->TS_visible_bell = tgetstr ("vb", address);
3331 tty->TS_cursor_normal = tgetstr ("ve", address);
3332 tty->TS_cursor_visible = tgetstr ("vs", address);
3333 tty->TS_cursor_invisible = tgetstr ("vi", address);
3334 tty->TS_set_window = tgetstr ("wi", address);
3336 tty->TS_enter_underline_mode = tgetstr ("us", address);
3337 tty->TS_exit_underline_mode = tgetstr ("ue", address);
3338 tty->TS_enter_bold_mode = tgetstr ("md", address);
3339 tty->TS_enter_dim_mode = tgetstr ("mh", address);
3340 tty->TS_enter_blink_mode = tgetstr ("mb", address);
3341 tty->TS_enter_reverse_mode = tgetstr ("mr", address);
3342 tty->TS_enter_alt_charset_mode = tgetstr ("as", address);
3343 tty->TS_exit_alt_charset_mode = tgetstr ("ae", address);
3344 tty->TS_exit_attribute_mode = tgetstr ("me", address);
3346 MultiUp (tty) = tgetstr ("UP", address);
3347 MultiDown (tty) = tgetstr ("DO", address);
3348 MultiLeft (tty) = tgetstr ("LE", address);
3349 MultiRight (tty) = tgetstr ("RI", address);
3351 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
3352 color because we can't switch back to the default foreground and
3353 background. */
3354 tty->TS_orig_pair = tgetstr ("op", address);
3355 if (tty->TS_orig_pair)
3357 tty->TS_set_foreground = tgetstr ("AF", address);
3358 tty->TS_set_background = tgetstr ("AB", address);
3359 if (!tty->TS_set_foreground)
3361 /* SVr4. */
3362 tty->TS_set_foreground = tgetstr ("Sf", address);
3363 tty->TS_set_background = tgetstr ("Sb", address);
3366 tty->TN_max_colors = tgetnum ("Co");
3367 tty->TN_max_pairs = tgetnum ("pa");
3369 tty->TN_no_color_video = tgetnum ("NC");
3370 if (tty->TN_no_color_video == -1)
3371 tty->TN_no_color_video = 0;
3374 tty_default_color_capabilities (tty, 1);
3376 MagicWrap (tty) = tgetflag ("xn");
3377 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
3378 the former flag imply the latter. */
3379 AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
3380 terminal->memory_below_frame = tgetflag ("db");
3381 tty->TF_hazeltine = tgetflag ("hz");
3382 terminal->must_write_spaces = tgetflag ("in");
3383 tty->meta_key = tgetflag ("km") || tgetflag ("MT");
3384 tty->TF_insmode_motion = tgetflag ("mi");
3385 tty->TF_standout_motion = tgetflag ("ms");
3386 tty->TF_underscore = tgetflag ("ul");
3387 tty->TF_teleray = tgetflag ("xt");
3389 #else /* DOS_NT */
3390 #ifdef WINDOWSNT
3392 struct frame *f = XFRAME (selected_frame);
3394 initialize_w32_display (terminal);
3396 FrameRows (tty) = FRAME_LINES (f);
3397 FrameCols (tty) = FRAME_COLS (f);
3398 tty->specified_window = FRAME_LINES (f);
3400 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
3401 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
3402 terminal->char_ins_del_ok = 1;
3403 baud_rate = 19200;
3405 #else /* MSDOS */
3407 int height, width;
3408 if (strcmp (terminal_type, "internal") == 0)
3409 terminal->type = output_msdos_raw;
3410 initialize_msdos_display (terminal);
3412 get_tty_size (fileno (tty->input), &width, &height);
3413 FrameCols (tty) = width;
3414 FrameRows (tty) = height;
3415 terminal->char_ins_del_ok = 0;
3416 init_baud_rate (fileno (tty->input));
3418 #endif /* MSDOS */
3419 tty->output = stdout;
3420 tty->input = stdin;
3421 /* The following two are inaccessible from w32console.c. */
3422 terminal->delete_frame_hook = &tty_free_frame_resources;
3423 terminal->delete_terminal_hook = &delete_tty;
3425 tty->name = xstrdup (name);
3426 terminal->name = xstrdup (name);
3427 tty->type = xstrdup (terminal_type);
3429 add_keyboard_wait_descriptor (0);
3431 tty->delete_in_insert_mode = 1;
3433 UseTabs (tty) = 0;
3434 terminal->scroll_region_ok = 0;
3436 /* Seems to insert lines when it's not supposed to, messing up the
3437 display. In doing a trace, it didn't seem to be called much, so I
3438 don't think we're losing anything by turning it off. */
3439 terminal->line_ins_del_ok = 0;
3441 tty->TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
3442 #endif /* DOS_NT */
3444 terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
3445 init_kboard (terminal->kboard);
3446 terminal->kboard->Vwindow_system = Qnil;
3447 terminal->kboard->next_kboard = all_kboards;
3448 all_kboards = terminal->kboard;
3449 terminal->kboard->reference_count++;
3450 /* Don't let the initial kboard remain current longer than necessary.
3451 That would cause problems if a file loaded on startup tries to
3452 prompt in the mini-buffer. */
3453 if (current_kboard == initial_kboard)
3454 current_kboard = terminal->kboard;
3455 #ifndef DOS_NT
3456 term_get_fkeys (address, terminal->kboard);
3458 /* Get frame size from system, or else from termcap. */
3460 int height, width;
3461 get_tty_size (fileno (tty->input), &width, &height);
3462 FrameCols (tty) = width;
3463 FrameRows (tty) = height;
3466 if (FrameCols (tty) <= 0)
3467 FrameCols (tty) = tgetnum ("co");
3468 if (FrameRows (tty) <= 0)
3469 FrameRows (tty) = tgetnum ("li");
3471 if (FrameRows (tty) < 3 || FrameCols (tty) < 3)
3472 maybe_fatal (must_succeed, terminal,
3473 "Screen size %dx%d is too small",
3474 "Screen size %dx%d is too small",
3475 FrameCols (tty), FrameRows (tty));
3477 TabWidth (tty) = tgetnum ("tw");
3479 if (!tty->TS_bell)
3480 tty->TS_bell = "\07";
3482 if (!tty->TS_fwd_scroll)
3483 tty->TS_fwd_scroll = Down (tty);
3485 PC = tty->TS_pad_char ? *tty->TS_pad_char : 0;
3487 if (TabWidth (tty) < 0)
3488 TabWidth (tty) = 8;
3490 /* Turned off since /etc/termcap seems to have :ta= for most terminals
3491 and newer termcap doc does not seem to say there is a default.
3492 if (!tty->Wcm->cm_tab)
3493 tty->Wcm->cm_tab = "\t";
3496 /* We don't support standout modes that use `magic cookies', so
3497 turn off any that do. */
3498 if (tty->TS_standout_mode && tgetnum ("sg") >= 0)
3500 tty->TS_standout_mode = 0;
3501 tty->TS_end_standout_mode = 0;
3503 if (tty->TS_enter_underline_mode && tgetnum ("ug") >= 0)
3505 tty->TS_enter_underline_mode = 0;
3506 tty->TS_exit_underline_mode = 0;
3509 /* If there's no standout mode, try to use underlining instead. */
3510 if (tty->TS_standout_mode == 0)
3512 tty->TS_standout_mode = tty->TS_enter_underline_mode;
3513 tty->TS_end_standout_mode = tty->TS_exit_underline_mode;
3516 /* If no `se' string, try using a `me' string instead.
3517 If that fails, we can't use standout mode at all. */
3518 if (tty->TS_end_standout_mode == 0)
3520 char *s = tgetstr ("me", address);
3521 if (s != 0)
3522 tty->TS_end_standout_mode = s;
3523 else
3524 tty->TS_standout_mode = 0;
3527 if (tty->TF_teleray)
3529 tty->Wcm->cm_tab = 0;
3530 /* We can't support standout mode, because it uses magic cookies. */
3531 tty->TS_standout_mode = 0;
3532 /* But that means we cannot rely on ^M to go to column zero! */
3533 CR (tty) = 0;
3534 /* LF can't be trusted either -- can alter hpos */
3535 /* if move at column 0 thru a line with TS_standout_mode */
3536 Down (tty) = 0;
3539 /* Special handling for certain terminal types known to need it */
3541 if (!strcmp (terminal_type, "supdup"))
3543 terminal->memory_below_frame = 1;
3544 tty->Wcm->cm_losewrap = 1;
3546 if (!strncmp (terminal_type, "c10", 3)
3547 || !strcmp (terminal_type, "perq"))
3549 /* Supply a makeshift :wi string.
3550 This string is not valid in general since it works only
3551 for windows starting at the upper left corner;
3552 but that is all Emacs uses.
3554 This string works only if the frame is using
3555 the top of the video memory, because addressing is memory-relative.
3556 So first check the :ti string to see if that is true.
3558 It would be simpler if the :wi string could go in the termcap
3559 entry, but it can't because it is not fully valid.
3560 If it were in the termcap entry, it would confuse other programs. */
3561 if (!tty->TS_set_window)
3563 p = tty->TS_termcap_modes;
3564 while (*p && strcmp (p, "\033v "))
3565 p++;
3566 if (*p)
3567 tty->TS_set_window = "\033v%C %C %C %C ";
3569 /* Termcap entry often fails to have :in: flag */
3570 terminal->must_write_spaces = 1;
3571 /* :ti string typically fails to have \E^G! in it */
3572 /* This limits scope of insert-char to one line. */
3573 strcpy (area, tty->TS_termcap_modes);
3574 strcat (area, "\033\007!");
3575 tty->TS_termcap_modes = area;
3576 area += strlen (area) + 1;
3577 p = AbsPosition (tty);
3578 /* Change all %+ parameters to %C, to handle
3579 values above 96 correctly for the C100. */
3580 while (*p)
3582 if (p[0] == '%' && p[1] == '+')
3583 p[1] = 'C';
3584 p++;
3588 tty->specified_window = FrameRows (tty);
3590 if (Wcm_init (tty) == -1) /* can't do cursor motion */
3592 maybe_fatal (must_succeed, terminal,
3593 "Terminal type \"%s\" is not powerful enough to run Emacs",
3594 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3595 It lacks the ability to position the cursor.\n\
3596 If that is not the actual type of terminal you have,\n\
3597 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3598 `setenv TERM ...') to specify the correct type. It may be necessary\n"
3599 # ifdef TERMINFO
3600 "to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3601 # else /* TERMCAP */
3602 "to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3603 # endif /* TERMINFO */
3604 terminal_type);
3607 if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
3608 maybe_fatal (must_succeed, terminal,
3609 "Could not determine the frame size",
3610 "Could not determine the frame size");
3612 tty->delete_in_insert_mode
3613 = tty->TS_delete_mode && tty->TS_insert_mode
3614 && !strcmp (tty->TS_delete_mode, tty->TS_insert_mode);
3616 tty->se_is_so = (tty->TS_standout_mode
3617 && tty->TS_end_standout_mode
3618 && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode));
3620 UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8;
3622 terminal->scroll_region_ok
3623 = (tty->Wcm->cm_abs
3624 && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
3626 terminal->line_ins_del_ok
3627 = (((tty->TS_ins_line || tty->TS_ins_multi_lines)
3628 && (tty->TS_del_line || tty->TS_del_multi_lines))
3629 || (terminal->scroll_region_ok
3630 && tty->TS_fwd_scroll && tty->TS_rev_scroll));
3632 terminal->char_ins_del_ok
3633 = ((tty->TS_ins_char || tty->TS_insert_mode
3634 || tty->TS_pad_inserted_char || tty->TS_ins_multi_chars)
3635 && (tty->TS_del_char || tty->TS_del_multi_chars));
3637 terminal->fast_clear_end_of_line = tty->TS_clr_line != 0;
3639 init_baud_rate (fileno (tty->input));
3641 #endif /* not DOS_NT */
3643 /* Init system terminal modes (RAW or CBREAK, etc.). */
3644 init_sys_modes (tty);
3646 return terminal;
3650 static void
3651 vfatal (const char *str, va_list ap)
3653 fprintf (stderr, "emacs: ");
3654 vfprintf (stderr, str, ap);
3655 if (!(strlen (str) > 0 && str[strlen (str) - 1] == '\n'))
3656 fprintf (stderr, "\n");
3657 va_end (ap);
3658 fflush (stderr);
3659 exit (1);
3663 /* Auxiliary error-handling function for init_tty.
3664 Delete TERMINAL, then call error or fatal with str1 or str2,
3665 respectively, according to MUST_SUCCEED. */
3667 static void
3668 maybe_fatal (int must_succeed, struct terminal *terminal,
3669 const char *str1, const char *str2, ...)
3671 va_list ap;
3672 va_start (ap, str2);
3673 if (terminal)
3674 delete_tty (terminal);
3676 if (must_succeed)
3677 vfatal (str2, ap);
3678 else
3679 verror (str1, ap);
3681 va_end (ap);
3682 abort ();
3685 void
3686 fatal (const char *str, ...)
3688 va_list ap;
3689 va_start (ap, str);
3690 vfatal (str, ap);
3691 va_end (ap);
3696 /* Delete the given tty terminal, closing all frames on it. */
3698 static void
3699 delete_tty (struct terminal *terminal)
3701 struct tty_display_info *tty;
3703 /* Protect against recursive calls. delete_frame in
3704 delete_terminal calls us back when it deletes our last frame. */
3705 if (!terminal->name)
3706 return;
3708 if (terminal->type != output_termcap)
3709 abort ();
3711 tty = terminal->display_info.tty;
3713 if (tty == tty_list)
3714 tty_list = tty->next;
3715 else
3717 struct tty_display_info *p;
3718 for (p = tty_list; p && p->next != tty; p = p->next)
3721 if (! p)
3722 /* This should not happen. */
3723 abort ();
3725 p->next = tty->next;
3726 tty->next = 0;
3729 /* reset_sys_modes needs a valid device, so this call needs to be
3730 before delete_terminal. */
3731 reset_sys_modes (tty);
3733 delete_terminal (terminal);
3735 xfree (tty->name);
3736 xfree (tty->type);
3738 if (tty->input)
3740 delete_keyboard_wait_descriptor (fileno (tty->input));
3741 if (tty->input != stdin)
3742 fclose (tty->input);
3744 if (tty->output && tty->output != stdout && tty->output != tty->input)
3745 fclose (tty->output);
3746 if (tty->termscript)
3747 fclose (tty->termscript);
3749 xfree (tty->old_tty);
3750 xfree (tty->Wcm);
3751 xfree (tty->termcap_strings_buffer);
3752 xfree (tty->termcap_term_buffer);
3754 memset (tty, 0, sizeof (struct tty_display_info));
3755 xfree (tty);
3760 /* Mark the pointers in the tty_display_info objects.
3761 Called by the Fgarbage_collector. */
3763 void
3764 mark_ttys (void)
3766 struct tty_display_info *tty;
3768 for (tty = tty_list; tty; tty = tty->next)
3769 mark_object (tty->top_frame);
3774 void
3775 syms_of_term (void)
3777 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
3778 doc: /* Non-nil means the system uses terminfo rather than termcap.
3779 This variable can be used by terminal emulator packages. */);
3780 #ifdef TERMINFO
3781 system_uses_terminfo = 1;
3782 #else
3783 system_uses_terminfo = 0;
3784 #endif
3786 DEFVAR_LISP ("suspend-tty-functions", &Vsuspend_tty_functions,
3787 doc: /* Functions to be run after suspending a tty.
3788 The functions are run with one argument, the terminal object to be suspended.
3789 See `suspend-tty'. */);
3790 Vsuspend_tty_functions = Qnil;
3793 DEFVAR_LISP ("resume-tty-functions", &Vresume_tty_functions,
3794 doc: /* Functions to be run after resuming a tty.
3795 The functions are run with one argument, the terminal object that was revived.
3796 See `resume-tty'. */);
3797 Vresume_tty_functions = Qnil;
3799 DEFVAR_BOOL ("visible-cursor", &visible_cursor,
3800 doc: /* Non-nil means to make the cursor very visible.
3801 This only has an effect when running in a text terminal.
3802 What means \"very visible\" is up to your terminal. It may make the cursor
3803 bigger, or it may make it blink, or it may do nothing at all. */);
3804 visible_cursor = 1;
3806 defsubr (&Stty_display_color_p);
3807 defsubr (&Stty_display_color_cells);
3808 defsubr (&Stty_no_underline);
3809 defsubr (&Stty_type);
3810 defsubr (&Scontrolling_tty_p);
3811 defsubr (&Ssuspend_tty);
3812 defsubr (&Sresume_tty);
3813 #ifdef HAVE_GPM
3814 defsubr (&Sgpm_mouse_start);
3815 defsubr (&Sgpm_mouse_stop);
3816 #endif /* HAVE_GPM */
3818 #ifndef DOS_NT
3819 default_orig_pair = NULL;
3820 default_set_foreground = NULL;
3821 default_set_background = NULL;
3822 #endif /* !DOS_NT */
3824 encode_terminal_src = NULL;
3825 encode_terminal_dst = NULL;