gamegrid-add-score-with-update-game-score fix
[emacs.git] / src / term.c
bloba31fd51084e40af2fff6d27f71cad6b40d9a17ec
1 /* Terminal control module for terminals described by TERMCAP
2 Copyright (C) 1985-1987, 1993-1995, 1998, 2000-2013 Free Software
3 Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20 /* New redisplay, TTY faces by Gerd Moellmann <gerd@gnu.org>. */
22 #include <config.h>
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <stdio.h>
26 #include <sys/file.h>
27 #include <sys/time.h>
28 #include <unistd.h>
30 #include "lisp.h"
31 #include "termchar.h"
32 #include "tparam.h"
33 #include "character.h"
34 #include "buffer.h"
35 #include "charset.h"
36 #include "coding.h"
37 #include "composite.h"
38 #include "keyboard.h"
39 #include "frame.h"
40 #include "disptab.h"
41 #include "termhooks.h"
42 #include "dispextern.h"
43 #include "window.h"
44 #include "keymap.h"
45 #include "blockinput.h"
46 #include "syssignal.h"
47 #include "systty.h"
48 #include "intervals.h"
49 #ifdef MSDOS
50 #include "msdos.h"
51 static int been_here = -1;
52 #endif
54 #include "cm.h"
55 #ifdef HAVE_X_WINDOWS
56 #include "xterm.h"
57 #endif
59 /* The name of the default console device. */
60 #ifdef WINDOWSNT
61 #define DEV_TTY "CONOUT$"
62 #include "w32term.h"
63 #else
64 #define DEV_TTY "/dev/tty"
65 #endif
67 static void tty_set_scroll_region (struct frame *f, int start, int stop);
68 static void turn_on_face (struct frame *, int face_id);
69 static void turn_off_face (struct frame *, int face_id);
70 static void tty_turn_off_highlight (struct tty_display_info *);
71 static void tty_show_cursor (struct tty_display_info *);
72 static void tty_hide_cursor (struct tty_display_info *);
73 static void tty_background_highlight (struct tty_display_info *tty);
74 static struct terminal *get_tty_terminal (Lisp_Object, int);
75 static void clear_tty_hooks (struct terminal *terminal);
76 static void set_tty_hooks (struct terminal *terminal);
77 static void dissociate_if_controlling_tty (int fd);
78 static void delete_tty (struct terminal *);
79 static _Noreturn void maybe_fatal (int must_succeed, struct terminal *terminal,
80 const char *str1, const char *str2, ...)
81 ATTRIBUTE_FORMAT_PRINTF (3, 5) ATTRIBUTE_FORMAT_PRINTF (4, 5);
82 static _Noreturn void vfatal (const char *str, va_list ap)
83 ATTRIBUTE_FORMAT_PRINTF (1, 0);
86 #define OUTPUT(tty, a) \
87 emacs_tputs ((tty), a, \
88 (int) (FRAME_LINES (XFRAME (selected_frame)) \
89 - curY (tty)), \
90 cmputc)
92 #define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
93 #define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
95 #define OUTPUT_IF(tty, a) \
96 do { \
97 if (a) \
98 OUTPUT (tty, a); \
99 } while (0)
101 #define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
103 /* Display space properties */
105 /* Chain of all tty device parameters. */
106 struct tty_display_info *tty_list;
108 /* Meaning of bits in no_color_video. Each bit set means that the
109 corresponding attribute cannot be combined with colors. */
111 enum no_color_bit
113 NC_STANDOUT = 1 << 0,
114 NC_UNDERLINE = 1 << 1,
115 NC_REVERSE = 1 << 2,
116 NC_ITALIC = 1 << 3,
117 NC_DIM = 1 << 4,
118 NC_BOLD = 1 << 5,
119 NC_INVIS = 1 << 6,
120 NC_PROTECT = 1 << 7
123 /* internal state */
125 /* The largest frame width in any call to calculate_costs. */
127 static int max_frame_cols;
131 #ifdef HAVE_GPM
132 #include <sys/fcntl.h>
134 /* The device for which we have enabled gpm support (or NULL). */
135 struct tty_display_info *gpm_tty = NULL;
137 /* Last recorded mouse coordinates. */
138 static int last_mouse_x, last_mouse_y;
139 #endif /* HAVE_GPM */
141 /* Ring the bell on a tty. */
143 static void
144 tty_ring_bell (struct frame *f)
146 struct tty_display_info *tty = FRAME_TTY (f);
148 if (tty->output)
150 OUTPUT (tty, (tty->TS_visible_bell && visible_bell
151 ? tty->TS_visible_bell
152 : tty->TS_bell));
153 fflush (tty->output);
157 /* Set up termcap modes for Emacs. */
159 static void
160 tty_set_terminal_modes (struct terminal *terminal)
162 struct tty_display_info *tty = terminal->display_info.tty;
164 if (tty->output)
166 if (tty->TS_termcap_modes)
167 OUTPUT (tty, tty->TS_termcap_modes);
168 else
170 /* Output enough newlines to scroll all the old screen contents
171 off the screen, so it won't be overwritten and lost. */
172 int i;
173 current_tty = tty;
174 for (i = 0; i < FRAME_LINES (XFRAME (selected_frame)); i++)
175 cmputc ('\n');
178 OUTPUT_IF (tty, visible_cursor ? tty->TS_cursor_visible : tty->TS_cursor_normal);
179 OUTPUT_IF (tty, tty->TS_keypad_mode);
180 losecursor (tty);
181 fflush (tty->output);
185 /* Reset termcap modes before exiting Emacs. */
187 static void
188 tty_reset_terminal_modes (struct terminal *terminal)
190 struct tty_display_info *tty = terminal->display_info.tty;
192 if (tty->output)
194 tty_turn_off_highlight (tty);
195 tty_turn_off_insert (tty);
196 OUTPUT_IF (tty, tty->TS_end_keypad_mode);
197 OUTPUT_IF (tty, tty->TS_cursor_normal);
198 OUTPUT_IF (tty, tty->TS_end_termcap_modes);
199 OUTPUT_IF (tty, tty->TS_orig_pair);
200 /* Output raw CR so kernel can track the cursor hpos. */
201 current_tty = tty;
202 cmputc ('\r');
203 fflush (tty->output);
207 /* Flag the end of a display update on a termcap terminal. */
209 static void
210 tty_update_end (struct frame *f)
212 struct tty_display_info *tty = FRAME_TTY (f);
214 if (!XWINDOW (selected_window)->cursor_off_p)
215 tty_show_cursor (tty);
216 tty_turn_off_insert (tty);
217 tty_background_highlight (tty);
220 /* The implementation of set_terminal_window for termcap frames. */
222 static void
223 tty_set_terminal_window (struct frame *f, int size)
225 struct tty_display_info *tty = FRAME_TTY (f);
227 tty->specified_window = size ? size : FRAME_LINES (f);
228 if (FRAME_SCROLL_REGION_OK (f))
229 tty_set_scroll_region (f, 0, tty->specified_window);
232 static void
233 tty_set_scroll_region (struct frame *f, int start, int stop)
235 char *buf;
236 struct tty_display_info *tty = FRAME_TTY (f);
238 if (tty->TS_set_scroll_region)
239 buf = tparam (tty->TS_set_scroll_region, 0, 0, start, stop - 1, 0, 0);
240 else if (tty->TS_set_scroll_region_1)
241 buf = tparam (tty->TS_set_scroll_region_1, 0, 0,
242 FRAME_LINES (f), start,
243 FRAME_LINES (f) - stop,
244 FRAME_LINES (f));
245 else
246 buf = tparam (tty->TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (f));
248 OUTPUT (tty, buf);
249 xfree (buf);
250 losecursor (tty);
254 static void
255 tty_turn_on_insert (struct tty_display_info *tty)
257 if (!tty->insert_mode)
258 OUTPUT (tty, tty->TS_insert_mode);
259 tty->insert_mode = 1;
262 void
263 tty_turn_off_insert (struct tty_display_info *tty)
265 if (tty->insert_mode)
266 OUTPUT (tty, tty->TS_end_insert_mode);
267 tty->insert_mode = 0;
270 /* Handle highlighting. */
272 static void
273 tty_turn_off_highlight (struct tty_display_info *tty)
275 if (tty->standout_mode)
276 OUTPUT_IF (tty, tty->TS_end_standout_mode);
277 tty->standout_mode = 0;
280 static void
281 tty_turn_on_highlight (struct tty_display_info *tty)
283 if (!tty->standout_mode)
284 OUTPUT_IF (tty, tty->TS_standout_mode);
285 tty->standout_mode = 1;
288 static void
289 tty_toggle_highlight (struct tty_display_info *tty)
291 if (tty->standout_mode)
292 tty_turn_off_highlight (tty);
293 else
294 tty_turn_on_highlight (tty);
298 /* Make cursor invisible. */
300 static void
301 tty_hide_cursor (struct tty_display_info *tty)
303 if (tty->cursor_hidden == 0)
305 tty->cursor_hidden = 1;
306 OUTPUT_IF (tty, tty->TS_cursor_invisible);
311 /* Ensure that cursor is visible. */
313 static void
314 tty_show_cursor (struct tty_display_info *tty)
316 if (tty->cursor_hidden)
318 tty->cursor_hidden = 0;
319 OUTPUT_IF (tty, tty->TS_cursor_normal);
320 if (visible_cursor)
321 OUTPUT_IF (tty, tty->TS_cursor_visible);
326 /* Set standout mode to the state it should be in for
327 empty space inside windows. What this is,
328 depends on the user option inverse-video. */
330 static void
331 tty_background_highlight (struct tty_display_info *tty)
333 if (inverse_video)
334 tty_turn_on_highlight (tty);
335 else
336 tty_turn_off_highlight (tty);
339 /* Set standout mode to the mode specified for the text to be output. */
341 static void
342 tty_highlight_if_desired (struct tty_display_info *tty)
344 if (inverse_video)
345 tty_turn_on_highlight (tty);
346 else
347 tty_turn_off_highlight (tty);
351 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
352 frame-relative coordinates. */
354 static void
355 tty_cursor_to (struct frame *f, int vpos, int hpos)
357 struct tty_display_info *tty = FRAME_TTY (f);
359 /* Detect the case where we are called from reset_sys_modes
360 and the costs have never been calculated. Do nothing. */
361 if (! tty->costs_set)
362 return;
364 if (curY (tty) == vpos
365 && curX (tty) == hpos)
366 return;
367 if (!tty->TF_standout_motion)
368 tty_background_highlight (tty);
369 if (!tty->TF_insmode_motion)
370 tty_turn_off_insert (tty);
371 cmgoto (tty, vpos, hpos);
374 /* Similar but don't take any account of the wasted characters. */
376 static void
377 tty_raw_cursor_to (struct frame *f, int row, int col)
379 struct tty_display_info *tty = FRAME_TTY (f);
381 if (curY (tty) == row
382 && curX (tty) == col)
383 return;
384 if (!tty->TF_standout_motion)
385 tty_background_highlight (tty);
386 if (!tty->TF_insmode_motion)
387 tty_turn_off_insert (tty);
388 cmgoto (tty, row, col);
391 /* Erase operations */
393 /* Clear from cursor to end of frame on a termcap device. */
395 static void
396 tty_clear_to_end (struct frame *f)
398 register int i;
399 struct tty_display_info *tty = FRAME_TTY (f);
401 if (tty->TS_clr_to_bottom)
403 tty_background_highlight (tty);
404 OUTPUT (tty, tty->TS_clr_to_bottom);
406 else
408 for (i = curY (tty); i < FRAME_LINES (f); i++)
410 cursor_to (f, i, 0);
411 clear_end_of_line (f, FRAME_COLS (f));
416 /* Clear an entire termcap frame. */
418 static void
419 tty_clear_frame (struct frame *f)
421 struct tty_display_info *tty = FRAME_TTY (f);
423 if (tty->TS_clr_frame)
425 tty_background_highlight (tty);
426 OUTPUT (tty, tty->TS_clr_frame);
427 cmat (tty, 0, 0);
429 else
431 cursor_to (f, 0, 0);
432 clear_to_end (f);
436 /* An implementation of clear_end_of_line for termcap frames.
438 Note that the cursor may be moved, on terminals lacking a `ce' string. */
440 static void
441 tty_clear_end_of_line (struct frame *f, int first_unused_hpos)
443 register int i;
444 struct tty_display_info *tty = FRAME_TTY (f);
446 /* Detect the case where we are called from reset_sys_modes
447 and the costs have never been calculated. Do nothing. */
448 if (! tty->costs_set)
449 return;
451 if (curX (tty) >= first_unused_hpos)
452 return;
453 tty_background_highlight (tty);
454 if (tty->TS_clr_line)
456 OUTPUT1 (tty, tty->TS_clr_line);
458 else
459 { /* have to do it the hard way */
460 tty_turn_off_insert (tty);
462 /* Do not write in last row last col with Auto-wrap on. */
463 if (AutoWrap (tty)
464 && curY (tty) == FrameRows (tty) - 1
465 && first_unused_hpos == FrameCols (tty))
466 first_unused_hpos--;
468 for (i = curX (tty); i < first_unused_hpos; i++)
470 if (tty->termscript)
471 fputc (' ', tty->termscript);
472 fputc (' ', tty->output);
474 cmplus (tty, first_unused_hpos - curX (tty));
478 /* Buffers to store the source and result of code conversion for terminal. */
479 static unsigned char *encode_terminal_src;
480 static unsigned char *encode_terminal_dst;
481 /* Allocated sizes of the above buffers. */
482 static ptrdiff_t encode_terminal_src_size;
483 static ptrdiff_t encode_terminal_dst_size;
485 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes.
486 Set CODING->produced to the byte-length of the resulting byte
487 sequence, and return a pointer to that byte sequence. */
489 unsigned char *
490 encode_terminal_code (struct glyph *src, int src_len, struct coding_system *coding)
492 struct glyph *src_end = src + src_len;
493 unsigned char *buf;
494 ptrdiff_t nchars, nbytes, required;
495 ptrdiff_t tlen = GLYPH_TABLE_LENGTH;
496 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
497 Lisp_Object charset_list;
499 /* Allocate sufficient size of buffer to store all characters in
500 multibyte-form. But, it may be enlarged on demand if
501 Vglyph_table contains a string or a composite glyph is
502 encountered. */
503 if (min (PTRDIFF_MAX, SIZE_MAX) / MAX_MULTIBYTE_LENGTH < src_len)
504 memory_full (SIZE_MAX);
505 required = src_len;
506 required *= MAX_MULTIBYTE_LENGTH;
507 if (encode_terminal_src_size < required)
509 encode_terminal_src = xrealloc (encode_terminal_src, required);
510 encode_terminal_src_size = required;
513 charset_list = coding_charset_list (coding);
515 buf = encode_terminal_src;
516 nchars = 0;
517 while (src < src_end)
519 if (src->type == COMPOSITE_GLYPH)
521 struct composition *cmp IF_LINT (= NULL);
522 Lisp_Object gstring IF_LINT (= Qnil);
523 int i;
525 nbytes = buf - encode_terminal_src;
526 if (src->u.cmp.automatic)
528 gstring = composition_gstring_from_id (src->u.cmp.id);
529 required = src->slice.cmp.to - src->slice.cmp.from + 1;
531 else
533 cmp = composition_table[src->u.cmp.id];
534 required = cmp->glyph_len;
535 required *= MAX_MULTIBYTE_LENGTH;
538 if (encode_terminal_src_size - nbytes < required)
540 encode_terminal_src =
541 xpalloc (encode_terminal_src, &encode_terminal_src_size,
542 required - (encode_terminal_src_size - nbytes),
543 -1, 1);
544 buf = encode_terminal_src + nbytes;
547 if (src->u.cmp.automatic)
548 for (i = src->slice.cmp.from; i <= src->slice.cmp.to; i++)
550 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
551 int c = LGLYPH_CHAR (g);
553 if (! char_charset (c, charset_list, NULL))
554 c = '?';
555 buf += CHAR_STRING (c, buf);
556 nchars++;
558 else
559 for (i = 0; i < cmp->glyph_len; i++)
561 int c = COMPOSITION_GLYPH (cmp, i);
563 /* TAB in a composition means display glyphs with
564 padding space on the left or right. */
565 if (c == '\t')
566 continue;
567 if (char_charset (c, charset_list, NULL))
569 if (CHAR_WIDTH (c) == 0
570 && i > 0 && COMPOSITION_GLYPH (cmp, i - 1) == '\t')
571 /* Should be left-padded */
573 buf += CHAR_STRING (' ', buf);
574 nchars++;
577 else
578 c = '?';
579 buf += CHAR_STRING (c, buf);
580 nchars++;
583 /* We must skip glyphs to be padded for a wide character. */
584 else if (! CHAR_GLYPH_PADDING_P (*src))
586 GLYPH g;
587 int c IF_LINT (= 0);
588 Lisp_Object string;
590 string = Qnil;
591 SET_GLYPH_FROM_CHAR_GLYPH (g, src[0]);
593 if (GLYPH_INVALID_P (g) || GLYPH_SIMPLE_P (tbase, tlen, g))
595 /* This glyph doesn't have an entry in Vglyph_table. */
596 c = src->u.ch;
598 else
600 /* This glyph has an entry in Vglyph_table,
601 so process any alias before testing for simpleness. */
602 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
604 if (GLYPH_SIMPLE_P (tbase, tlen, g))
605 /* We set the multi-byte form of a character in G
606 (that should be an ASCII character) at WORKBUF. */
607 c = GLYPH_CHAR (g);
608 else
609 /* We have a string in Vglyph_table. */
610 string = tbase[GLYPH_CHAR (g)];
613 if (NILP (string))
615 nbytes = buf - encode_terminal_src;
616 if (encode_terminal_src_size - nbytes < MAX_MULTIBYTE_LENGTH)
618 encode_terminal_src =
619 xpalloc (encode_terminal_src, &encode_terminal_src_size,
620 MAX_MULTIBYTE_LENGTH, -1, 1);
621 buf = encode_terminal_src + nbytes;
623 if (CHAR_BYTE8_P (c)
624 || char_charset (c, charset_list, NULL))
626 /* Store the multibyte form of C at BUF. */
627 buf += CHAR_STRING (c, buf);
628 nchars++;
630 else
632 /* C is not encodable. */
633 *buf++ = '?';
634 nchars++;
635 while (src + 1 < src_end && CHAR_GLYPH_PADDING_P (src[1]))
637 *buf++ = '?';
638 nchars++;
639 src++;
643 else
645 if (! STRING_MULTIBYTE (string))
646 string = string_to_multibyte (string);
647 nbytes = buf - encode_terminal_src;
648 if (encode_terminal_src_size - nbytes < SBYTES (string))
650 encode_terminal_src =
651 xpalloc (encode_terminal_src, &encode_terminal_src_size,
652 (SBYTES (string)
653 - (encode_terminal_src_size - nbytes)),
654 -1, 1);
655 buf = encode_terminal_src + nbytes;
657 memcpy (buf, SDATA (string), SBYTES (string));
658 buf += SBYTES (string);
659 nchars += SCHARS (string);
662 src++;
665 if (nchars == 0)
667 coding->produced = 0;
668 return NULL;
671 nbytes = buf - encode_terminal_src;
672 coding->source = encode_terminal_src;
673 if (encode_terminal_dst_size == 0)
675 encode_terminal_dst = xrealloc (encode_terminal_dst,
676 encode_terminal_src_size);
677 encode_terminal_dst_size = encode_terminal_src_size;
679 coding->destination = encode_terminal_dst;
680 coding->dst_bytes = encode_terminal_dst_size;
681 encode_coding_object (coding, Qnil, 0, 0, nchars, nbytes, Qnil);
682 /* coding->destination may have been reallocated. */
683 encode_terminal_dst = coding->destination;
684 encode_terminal_dst_size = coding->dst_bytes;
686 return (encode_terminal_dst);
691 /* An implementation of write_glyphs for termcap frames. */
693 static void
694 tty_write_glyphs (struct frame *f, struct glyph *string, int len)
696 unsigned char *conversion_buffer;
697 struct coding_system *coding;
698 size_t n, stringlen;
700 struct tty_display_info *tty = FRAME_TTY (f);
702 tty_turn_off_insert (tty);
703 tty_hide_cursor (tty);
705 /* Don't dare write in last column of bottom line, if Auto-Wrap,
706 since that would scroll the whole frame on some terminals. */
708 if (AutoWrap (tty)
709 && curY (tty) + 1 == FRAME_LINES (f)
710 && (curX (tty) + len) == FRAME_COLS (f))
711 len --;
712 if (len <= 0)
713 return;
715 cmplus (tty, len);
717 /* If terminal_coding does any conversion, use it, otherwise use
718 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
719 because it always return 1 if the member src_multibyte is 1. */
720 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
721 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
722 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
723 the tail. */
724 coding->mode &= ~CODING_MODE_LAST_BLOCK;
726 for (stringlen = len; stringlen != 0; stringlen -= n)
728 /* Identify a run of glyphs with the same face. */
729 int face_id = string->face_id;
731 for (n = 1; n < stringlen; ++n)
732 if (string[n].face_id != face_id)
733 break;
735 /* Turn appearance modes of the face of the run on. */
736 tty_highlight_if_desired (tty);
737 turn_on_face (f, face_id);
739 if (n == stringlen)
740 /* This is the last run. */
741 coding->mode |= CODING_MODE_LAST_BLOCK;
742 conversion_buffer = encode_terminal_code (string, n, coding);
743 if (coding->produced > 0)
745 block_input ();
746 fwrite (conversion_buffer, 1, coding->produced, tty->output);
747 if (ferror (tty->output))
748 clearerr (tty->output);
749 if (tty->termscript)
750 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
751 unblock_input ();
753 string += n;
755 /* Turn appearance modes off. */
756 turn_off_face (f, face_id);
757 tty_turn_off_highlight (tty);
760 cmcheckmagic (tty);
763 #ifdef HAVE_GPM /* Only used by GPM code. */
765 static void
766 tty_write_glyphs_with_face (register struct frame *f, register struct glyph *string,
767 register int len, register int face_id)
769 unsigned char *conversion_buffer;
770 struct coding_system *coding;
772 struct tty_display_info *tty = FRAME_TTY (f);
774 tty_turn_off_insert (tty);
775 tty_hide_cursor (tty);
777 /* Don't dare write in last column of bottom line, if Auto-Wrap,
778 since that would scroll the whole frame on some terminals. */
780 if (AutoWrap (tty)
781 && curY (tty) + 1 == FRAME_LINES (f)
782 && (curX (tty) + len) == FRAME_COLS (f))
783 len --;
784 if (len <= 0)
785 return;
787 cmplus (tty, len);
789 /* If terminal_coding does any conversion, use it, otherwise use
790 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
791 because it always return 1 if the member src_multibyte is 1. */
792 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
793 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
794 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
795 the tail. */
796 coding->mode &= ~CODING_MODE_LAST_BLOCK;
798 /* Turn appearance modes of the face. */
799 tty_highlight_if_desired (tty);
800 turn_on_face (f, face_id);
802 coding->mode |= CODING_MODE_LAST_BLOCK;
803 conversion_buffer = encode_terminal_code (string, len, coding);
804 if (coding->produced > 0)
806 block_input ();
807 fwrite (conversion_buffer, 1, coding->produced, tty->output);
808 if (ferror (tty->output))
809 clearerr (tty->output);
810 if (tty->termscript)
811 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
812 unblock_input ();
815 /* Turn appearance modes off. */
816 turn_off_face (f, face_id);
817 tty_turn_off_highlight (tty);
819 cmcheckmagic (tty);
821 #endif
823 /* An implementation of insert_glyphs for termcap frames. */
825 static void
826 tty_insert_glyphs (struct frame *f, struct glyph *start, int len)
828 char *buf;
829 struct glyph *glyph = NULL;
830 unsigned char *conversion_buffer;
831 unsigned char space[1];
832 struct coding_system *coding;
834 struct tty_display_info *tty = FRAME_TTY (f);
836 if (tty->TS_ins_multi_chars)
838 buf = tparam (tty->TS_ins_multi_chars, 0, 0, len, 0, 0, 0);
839 OUTPUT1 (tty, buf);
840 xfree (buf);
841 if (start)
842 write_glyphs (f, start, len);
843 return;
846 tty_turn_on_insert (tty);
847 cmplus (tty, len);
849 if (! start)
850 space[0] = SPACEGLYPH;
852 /* If terminal_coding does any conversion, use it, otherwise use
853 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
854 because it always return 1 if the member src_multibyte is 1. */
855 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
856 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
857 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
858 the tail. */
859 coding->mode &= ~CODING_MODE_LAST_BLOCK;
861 while (len-- > 0)
863 OUTPUT1_IF (tty, tty->TS_ins_char);
864 if (!start)
866 conversion_buffer = space;
867 coding->produced = 1;
869 else
871 tty_highlight_if_desired (tty);
872 turn_on_face (f, start->face_id);
873 glyph = start;
874 ++start;
875 /* We must open sufficient space for a character which
876 occupies more than one column. */
877 while (len && CHAR_GLYPH_PADDING_P (*start))
879 OUTPUT1_IF (tty, tty->TS_ins_char);
880 start++, len--;
883 if (len <= 0)
884 /* This is the last glyph. */
885 coding->mode |= CODING_MODE_LAST_BLOCK;
887 conversion_buffer = encode_terminal_code (glyph, 1, coding);
890 if (coding->produced > 0)
892 block_input ();
893 fwrite (conversion_buffer, 1, coding->produced, tty->output);
894 if (ferror (tty->output))
895 clearerr (tty->output);
896 if (tty->termscript)
897 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
898 unblock_input ();
901 OUTPUT1_IF (tty, tty->TS_pad_inserted_char);
902 if (start)
904 turn_off_face (f, glyph->face_id);
905 tty_turn_off_highlight (tty);
909 cmcheckmagic (tty);
912 /* An implementation of delete_glyphs for termcap frames. */
914 static void
915 tty_delete_glyphs (struct frame *f, int n)
917 char *buf;
918 register int i;
920 struct tty_display_info *tty = FRAME_TTY (f);
922 if (tty->delete_in_insert_mode)
924 tty_turn_on_insert (tty);
926 else
928 tty_turn_off_insert (tty);
929 OUTPUT_IF (tty, tty->TS_delete_mode);
932 if (tty->TS_del_multi_chars)
934 buf = tparam (tty->TS_del_multi_chars, 0, 0, n, 0, 0, 0);
935 OUTPUT1 (tty, buf);
936 xfree (buf);
938 else
939 for (i = 0; i < n; i++)
940 OUTPUT1 (tty, tty->TS_del_char);
941 if (!tty->delete_in_insert_mode)
942 OUTPUT_IF (tty, tty->TS_end_delete_mode);
945 /* An implementation of ins_del_lines for termcap frames. */
947 static void
948 tty_ins_del_lines (struct frame *f, int vpos, int n)
950 struct tty_display_info *tty = FRAME_TTY (f);
951 const char *multi =
952 n > 0 ? tty->TS_ins_multi_lines : tty->TS_del_multi_lines;
953 const char *single = n > 0 ? tty->TS_ins_line : tty->TS_del_line;
954 const char *scroll = n > 0 ? tty->TS_rev_scroll : tty->TS_fwd_scroll;
956 int i = eabs (n);
957 char *buf;
959 /* If the lines below the insertion are being pushed
960 into the end of the window, this is the same as clearing;
961 and we know the lines are already clear, since the matching
962 deletion has already been done. So can ignore this. */
963 /* If the lines below the deletion are blank lines coming
964 out of the end of the window, don't bother,
965 as there will be a matching inslines later that will flush them. */
966 if (FRAME_SCROLL_REGION_OK (f)
967 && vpos + i >= tty->specified_window)
968 return;
969 if (!FRAME_MEMORY_BELOW_FRAME (f)
970 && vpos + i >= FRAME_LINES (f))
971 return;
973 if (multi)
975 raw_cursor_to (f, vpos, 0);
976 tty_background_highlight (tty);
977 buf = tparam (multi, 0, 0, i, 0, 0, 0);
978 OUTPUT (tty, buf);
979 xfree (buf);
981 else if (single)
983 raw_cursor_to (f, vpos, 0);
984 tty_background_highlight (tty);
985 while (--i >= 0)
986 OUTPUT (tty, single);
987 if (tty->TF_teleray)
988 curX (tty) = 0;
990 else
992 tty_set_scroll_region (f, vpos, tty->specified_window);
993 if (n < 0)
994 raw_cursor_to (f, tty->specified_window - 1, 0);
995 else
996 raw_cursor_to (f, vpos, 0);
997 tty_background_highlight (tty);
998 while (--i >= 0)
999 OUTPUTL (tty, scroll, tty->specified_window - vpos);
1000 tty_set_scroll_region (f, 0, tty->specified_window);
1003 if (!FRAME_SCROLL_REGION_OK (f)
1004 && FRAME_MEMORY_BELOW_FRAME (f)
1005 && n < 0)
1007 cursor_to (f, FRAME_LINES (f) + n, 0);
1008 clear_to_end (f);
1012 /* Compute cost of sending "str", in characters,
1013 not counting any line-dependent padding. */
1016 string_cost (const char *str)
1018 cost = 0;
1019 if (str)
1020 tputs (str, 0, evalcost);
1021 return cost;
1024 /* Compute cost of sending "str", in characters,
1025 counting any line-dependent padding at one line. */
1027 static int
1028 string_cost_one_line (const char *str)
1030 cost = 0;
1031 if (str)
1032 tputs (str, 1, evalcost);
1033 return cost;
1036 /* Compute per line amount of line-dependent padding,
1037 in tenths of characters. */
1040 per_line_cost (const char *str)
1042 cost = 0;
1043 if (str)
1044 tputs (str, 0, evalcost);
1045 cost = - cost;
1046 if (str)
1047 tputs (str, 10, evalcost);
1048 return cost;
1051 /* char_ins_del_cost[n] is cost of inserting N characters.
1052 char_ins_del_cost[-n] is cost of deleting N characters.
1053 The length of this vector is based on max_frame_cols. */
1055 int *char_ins_del_vector;
1057 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
1059 /* ARGSUSED */
1060 static void
1061 calculate_ins_del_char_costs (struct frame *f)
1063 struct tty_display_info *tty = FRAME_TTY (f);
1064 int ins_startup_cost, del_startup_cost;
1065 int ins_cost_per_char, del_cost_per_char;
1066 register int i;
1067 register int *p;
1069 if (tty->TS_ins_multi_chars)
1071 ins_cost_per_char = 0;
1072 ins_startup_cost = string_cost_one_line (tty->TS_ins_multi_chars);
1074 else if (tty->TS_ins_char || tty->TS_pad_inserted_char
1075 || (tty->TS_insert_mode && tty->TS_end_insert_mode))
1077 ins_startup_cost = (30 * (string_cost (tty->TS_insert_mode)
1078 + string_cost (tty->TS_end_insert_mode))) / 100;
1079 ins_cost_per_char = (string_cost_one_line (tty->TS_ins_char)
1080 + string_cost_one_line (tty->TS_pad_inserted_char));
1082 else
1084 ins_startup_cost = 9999;
1085 ins_cost_per_char = 0;
1088 if (tty->TS_del_multi_chars)
1090 del_cost_per_char = 0;
1091 del_startup_cost = string_cost_one_line (tty->TS_del_multi_chars);
1093 else if (tty->TS_del_char)
1095 del_startup_cost = (string_cost (tty->TS_delete_mode)
1096 + string_cost (tty->TS_end_delete_mode));
1097 if (tty->delete_in_insert_mode)
1098 del_startup_cost /= 2;
1099 del_cost_per_char = string_cost_one_line (tty->TS_del_char);
1101 else
1103 del_startup_cost = 9999;
1104 del_cost_per_char = 0;
1107 /* Delete costs are at negative offsets */
1108 p = &char_ins_del_cost (f)[0];
1109 for (i = FRAME_COLS (f); --i >= 0;)
1110 *--p = (del_startup_cost += del_cost_per_char);
1112 /* Doing nothing is free */
1113 p = &char_ins_del_cost (f)[0];
1114 *p++ = 0;
1116 /* Insert costs are at positive offsets */
1117 for (i = FRAME_COLS (f); --i >= 0;)
1118 *p++ = (ins_startup_cost += ins_cost_per_char);
1121 void
1122 calculate_costs (struct frame *frame)
1124 FRAME_COST_BAUD_RATE (frame) = baud_rate;
1126 if (FRAME_TERMCAP_P (frame))
1128 struct tty_display_info *tty = FRAME_TTY (frame);
1129 register const char *f = (tty->TS_set_scroll_region
1130 ? tty->TS_set_scroll_region
1131 : tty->TS_set_scroll_region_1);
1133 FRAME_SCROLL_REGION_COST (frame) = string_cost (f);
1135 tty->costs_set = 1;
1137 /* These variables are only used for terminal stuff. They are
1138 allocated once for the terminal frame of X-windows emacs, but not
1139 used afterwards.
1141 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1142 X turns off char_ins_del_ok. */
1144 max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
1145 if ((min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) - 1) / 2
1146 < max_frame_cols)
1147 memory_full (SIZE_MAX);
1149 char_ins_del_vector =
1150 xrealloc (char_ins_del_vector,
1151 (sizeof (int) + 2 * sizeof (int) * max_frame_cols));
1153 memset (char_ins_del_vector, 0,
1154 (sizeof (int) + 2 * sizeof (int) * max_frame_cols));
1157 if (f && (!tty->TS_ins_line && !tty->TS_del_line))
1158 do_line_insertion_deletion_costs (frame,
1159 tty->TS_rev_scroll, tty->TS_ins_multi_lines,
1160 tty->TS_fwd_scroll, tty->TS_del_multi_lines,
1161 f, f, 1);
1162 else
1163 do_line_insertion_deletion_costs (frame,
1164 tty->TS_ins_line, tty->TS_ins_multi_lines,
1165 tty->TS_del_line, tty->TS_del_multi_lines,
1166 0, 0, 1);
1168 calculate_ins_del_char_costs (frame);
1170 /* Don't use TS_repeat if its padding is worse than sending the chars */
1171 if (tty->TS_repeat && per_line_cost (tty->TS_repeat) * baud_rate < 9000)
1172 tty->RPov = string_cost (tty->TS_repeat);
1173 else
1174 tty->RPov = FRAME_COLS (frame) * 2;
1176 cmcostinit (FRAME_TTY (frame)); /* set up cursor motion costs */
1180 struct fkey_table {
1181 const char *cap, *name;
1184 /* Termcap capability names that correspond directly to X keysyms.
1185 Some of these (marked "terminfo") aren't supplied by old-style
1186 (Berkeley) termcap entries. They're listed in X keysym order;
1187 except we put the keypad keys first, so that if they clash with
1188 other keys (as on the IBM PC keyboard) they get overridden.
1191 static const struct fkey_table keys[] =
1193 {"kh", "home"}, /* termcap */
1194 {"kl", "left"}, /* termcap */
1195 {"ku", "up"}, /* termcap */
1196 {"kr", "right"}, /* termcap */
1197 {"kd", "down"}, /* termcap */
1198 {"%8", "prior"}, /* terminfo */
1199 {"%5", "next"}, /* terminfo */
1200 {"@7", "end"}, /* terminfo */
1201 {"@1", "begin"}, /* terminfo */
1202 {"*6", "select"}, /* terminfo */
1203 {"%9", "print"}, /* terminfo */
1204 {"@4", "execute"}, /* terminfo --- actually the `command' key */
1206 * "insert" --- see below
1208 {"&8", "undo"}, /* terminfo */
1209 {"%0", "redo"}, /* terminfo */
1210 {"%7", "menu"}, /* terminfo --- actually the `options' key */
1211 {"@0", "find"}, /* terminfo */
1212 {"@2", "cancel"}, /* terminfo */
1213 {"%1", "help"}, /* terminfo */
1215 * "break" goes here, but can't be reliably intercepted with termcap
1217 {"&4", "reset"}, /* terminfo --- actually `restart' */
1219 * "system" and "user" --- no termcaps
1221 {"kE", "clearline"}, /* terminfo */
1222 {"kA", "insertline"}, /* terminfo */
1223 {"kL", "deleteline"}, /* terminfo */
1224 {"kI", "insertchar"}, /* terminfo */
1225 {"kD", "deletechar"}, /* terminfo */
1226 {"kB", "backtab"}, /* terminfo */
1228 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1230 {"@8", "kp-enter"}, /* terminfo */
1232 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1233 * "kp-multiply", "kp-add", "kp-separator",
1234 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1235 * --- no termcaps for any of these.
1237 {"K4", "kp-1"}, /* terminfo */
1239 * "kp-2" --- no termcap
1241 {"K5", "kp-3"}, /* terminfo */
1243 * "kp-4" --- no termcap
1245 {"K2", "kp-5"}, /* terminfo */
1247 * "kp-6" --- no termcap
1249 {"K1", "kp-7"}, /* terminfo */
1251 * "kp-8" --- no termcap
1253 {"K3", "kp-9"}, /* terminfo */
1255 * "kp-equal" --- no termcap
1257 {"k1", "f1"},
1258 {"k2", "f2"},
1259 {"k3", "f3"},
1260 {"k4", "f4"},
1261 {"k5", "f5"},
1262 {"k6", "f6"},
1263 {"k7", "f7"},
1264 {"k8", "f8"},
1265 {"k9", "f9"},
1267 {"&0", "S-cancel"}, /*shifted cancel key*/
1268 {"&9", "S-begin"}, /*shifted begin key*/
1269 {"*0", "S-find"}, /*shifted find key*/
1270 {"*1", "S-execute"}, /*shifted execute? actually shifted command key*/
1271 {"*4", "S-delete"}, /*shifted delete-character key*/
1272 {"*7", "S-end"}, /*shifted end key*/
1273 {"*8", "S-clearline"}, /*shifted clear-to end-of-line key*/
1274 {"#1", "S-help"}, /*shifted help key*/
1275 {"#2", "S-home"}, /*shifted home key*/
1276 {"#3", "S-insert"}, /*shifted insert-character key*/
1277 {"#4", "S-left"}, /*shifted left-arrow key*/
1278 {"%d", "S-menu"}, /*shifted menu? actually shifted options key*/
1279 {"%c", "S-next"}, /*shifted next key*/
1280 {"%e", "S-prior"}, /*shifted previous key*/
1281 {"%f", "S-print"}, /*shifted print key*/
1282 {"%g", "S-redo"}, /*shifted redo key*/
1283 {"%i", "S-right"}, /*shifted right-arrow key*/
1284 {"!3", "S-undo"} /*shifted undo key*/
1287 #ifndef DOS_NT
1288 static char **term_get_fkeys_address;
1289 static KBOARD *term_get_fkeys_kboard;
1290 static Lisp_Object term_get_fkeys_1 (void);
1292 /* Find the escape codes sent by the function keys for Vinput_decode_map.
1293 This function scans the termcap function key sequence entries, and
1294 adds entries to Vinput_decode_map for each function key it finds. */
1296 static void
1297 term_get_fkeys (char **address, KBOARD *kboard)
1299 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1300 errors during the call. The only errors should be from Fdefine_key
1301 when given a key sequence containing an invalid prefix key. If the
1302 termcap defines function keys which use a prefix that is already bound
1303 to a command by the default bindings, we should silently ignore that
1304 function key specification, rather than giving the user an error and
1305 refusing to run at all on such a terminal. */
1307 term_get_fkeys_address = address;
1308 term_get_fkeys_kboard = kboard;
1309 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1312 static Lisp_Object
1313 term_get_fkeys_1 (void)
1315 int i;
1317 char **address = term_get_fkeys_address;
1318 KBOARD *kboard = term_get_fkeys_kboard;
1320 /* This can happen if CANNOT_DUMP or with strange options. */
1321 if (!KEYMAPP (KVAR (kboard, Vinput_decode_map)))
1322 kset_input_decode_map (kboard, Fmake_sparse_keymap (Qnil));
1324 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1326 char *sequence = tgetstr (keys[i].cap, address);
1327 if (sequence)
1328 Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (sequence),
1329 Fmake_vector (make_number (1),
1330 intern (keys[i].name)));
1333 /* The uses of the "k0" capability are inconsistent; sometimes it
1334 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1335 We will attempt to politely accommodate both systems by testing for
1336 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1339 const char *k_semi = tgetstr ("k;", address);
1340 const char *k0 = tgetstr ("k0", address);
1341 const char *k0_name = "f10";
1343 if (k_semi)
1345 if (k0)
1346 /* Define f0 first, so that f10 takes precedence in case the
1347 key sequences happens to be the same. */
1348 Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (k0),
1349 Fmake_vector (make_number (1), intern ("f0")));
1350 Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (k_semi),
1351 Fmake_vector (make_number (1), intern ("f10")));
1353 else if (k0)
1354 Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (k0),
1355 Fmake_vector (make_number (1), intern (k0_name)));
1358 /* Set up cookies for numbered function keys above f10. */
1360 char fcap[3], fkey[4];
1362 fcap[0] = 'F'; fcap[2] = '\0';
1363 for (i = 11; i < 64; i++)
1365 if (i <= 19)
1366 fcap[1] = '1' + i - 11;
1367 else if (i <= 45)
1368 fcap[1] = 'A' + i - 20;
1369 else
1370 fcap[1] = 'a' + i - 46;
1373 char *sequence = tgetstr (fcap, address);
1374 if (sequence)
1376 sprintf (fkey, "f%d", i);
1377 Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (sequence),
1378 Fmake_vector (make_number (1),
1379 intern (fkey)));
1386 * Various mappings to try and get a better fit.
1389 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1390 if (!tgetstr (cap1, address)) \
1392 char *sequence = tgetstr (cap2, address); \
1393 if (sequence) \
1394 Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (sequence), \
1395 Fmake_vector (make_number (1), \
1396 intern (sym))); \
1399 /* if there's no key_next keycap, map key_npage to `next' keysym */
1400 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1401 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1402 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1403 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1404 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1405 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1406 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1408 /* IBM has their own non-standard dialect of terminfo.
1409 If the standard name isn't found, try the IBM name. */
1410 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1411 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1412 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1413 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1414 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1415 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1416 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1417 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1418 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1419 #undef CONDITIONAL_REASSIGN
1422 return Qnil;
1424 #endif /* not DOS_NT */
1427 /***********************************************************************
1428 Character Display Information
1429 ***********************************************************************/
1430 static void append_glyph (struct it *);
1431 static void append_composite_glyph (struct it *);
1432 static void produce_composite_glyph (struct it *);
1433 static void append_glyphless_glyph (struct it *, int, const char *);
1434 static void produce_glyphless_glyph (struct it *, int, Lisp_Object);
1436 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1437 terminal frames if IT->glyph_row != NULL. IT->char_to_display is
1438 the character for which to produce glyphs; IT->face_id contains the
1439 character's face. Padding glyphs are appended if IT->c has a
1440 IT->pixel_width > 1. */
1442 static void
1443 append_glyph (struct it *it)
1445 struct glyph *glyph, *end;
1446 int i;
1448 eassert (it->glyph_row);
1449 glyph = (it->glyph_row->glyphs[it->area]
1450 + it->glyph_row->used[it->area]);
1451 end = it->glyph_row->glyphs[1 + it->area];
1453 /* If the glyph row is reversed, we need to prepend the glyph rather
1454 than append it. */
1455 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1457 struct glyph *g;
1458 int move_by = it->pixel_width;
1460 /* Make room for the new glyphs. */
1461 if (move_by > end - glyph) /* don't overstep end of this area */
1462 move_by = end - glyph;
1463 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1464 g[move_by] = *g;
1465 glyph = it->glyph_row->glyphs[it->area];
1466 end = glyph + move_by;
1469 /* BIDI Note: we put the glyphs of a "multi-pixel" character left to
1470 right, even in the REVERSED_P case, since (a) all of its u.ch are
1471 identical, and (b) the PADDING_P flag needs to be set for the
1472 leftmost one, because we write to the terminal left-to-right. */
1473 for (i = 0;
1474 i < it->pixel_width && glyph < end;
1475 ++i)
1477 glyph->type = CHAR_GLYPH;
1478 glyph->pixel_width = 1;
1479 glyph->u.ch = it->char_to_display;
1480 glyph->face_id = it->face_id;
1481 glyph->padding_p = i > 0;
1482 glyph->charpos = CHARPOS (it->position);
1483 glyph->object = it->object;
1484 if (it->bidi_p)
1486 glyph->resolved_level = it->bidi_it.resolved_level;
1487 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1488 emacs_abort ();
1489 glyph->bidi_type = it->bidi_it.type;
1491 else
1493 glyph->resolved_level = 0;
1494 glyph->bidi_type = UNKNOWN_BT;
1497 ++it->glyph_row->used[it->area];
1498 ++glyph;
1502 /* For external use. */
1503 void
1504 tty_append_glyph (struct it *it)
1506 append_glyph (it);
1510 /* Produce glyphs for the display element described by IT. *IT
1511 specifies what we want to produce a glyph for (character, image, ...),
1512 and where in the glyph matrix we currently are (glyph row and hpos).
1513 produce_glyphs fills in output fields of *IT with information such as the
1514 pixel width and height of a character, and maybe output actual glyphs at
1515 the same time if IT->glyph_row is non-null. For an overview, see
1516 the explanation in dispextern.h, before the definition of the
1517 display_element_type enumeration.
1519 produce_glyphs also stores the result of glyph width, ascent
1520 etc. computations in *IT.
1522 IT->glyph_row may be null, in which case produce_glyphs does not
1523 actually fill in the glyphs. This is used in the move_* functions
1524 in xdisp.c for text width and height computations.
1526 Callers usually don't call produce_glyphs directly;
1527 instead they use the macro PRODUCE_GLYPHS. */
1529 void
1530 produce_glyphs (struct it *it)
1532 /* If a hook is installed, let it do the work. */
1534 /* Nothing but characters are supported on terminal frames. */
1535 eassert (it->what == IT_CHARACTER
1536 || it->what == IT_COMPOSITION
1537 || it->what == IT_STRETCH
1538 || it->what == IT_GLYPHLESS);
1540 if (it->what == IT_STRETCH)
1542 produce_stretch_glyph (it);
1543 goto done;
1546 if (it->what == IT_COMPOSITION)
1548 produce_composite_glyph (it);
1549 goto done;
1552 if (it->what == IT_GLYPHLESS)
1554 produce_glyphless_glyph (it, 0, Qnil);
1555 goto done;
1558 if (it->char_to_display >= 040 && it->char_to_display < 0177)
1560 it->pixel_width = it->nglyphs = 1;
1561 if (it->glyph_row)
1562 append_glyph (it);
1564 else if (it->char_to_display == '\n')
1565 it->pixel_width = it->nglyphs = 0;
1566 else if (it->char_to_display == '\t')
1568 int absolute_x = (it->current_x
1569 + it->continuation_lines_width);
1570 int next_tab_x
1571 = (((1 + absolute_x + it->tab_width - 1)
1572 / it->tab_width)
1573 * it->tab_width);
1574 int nspaces;
1576 /* If part of the TAB has been displayed on the previous line
1577 which is continued now, continuation_lines_width will have
1578 been incremented already by the part that fitted on the
1579 continued line. So, we will get the right number of spaces
1580 here. */
1581 nspaces = next_tab_x - absolute_x;
1583 if (it->glyph_row)
1585 int n = nspaces;
1587 it->char_to_display = ' ';
1588 it->pixel_width = it->len = 1;
1590 while (n--)
1591 append_glyph (it);
1594 it->pixel_width = nspaces;
1595 it->nglyphs = nspaces;
1597 else if (CHAR_BYTE8_P (it->char_to_display))
1599 /* Coming here means that we must send the raw 8-bit byte as is
1600 to the terminal. Although there's no way to know how many
1601 columns it occupies on a screen, it is a good assumption that
1602 a single byte code has 1-column width. */
1603 it->pixel_width = it->nglyphs = 1;
1604 if (it->glyph_row)
1605 append_glyph (it);
1607 else
1609 Lisp_Object charset_list = FRAME_TERMINAL (it->f)->charset_list;
1611 if (char_charset (it->char_to_display, charset_list, NULL))
1613 it->pixel_width = CHAR_WIDTH (it->char_to_display);
1614 it->nglyphs = it->pixel_width;
1615 if (it->glyph_row)
1616 append_glyph (it);
1618 else
1620 Lisp_Object acronym = lookup_glyphless_char_display (-1, it);
1622 eassert (it->what == IT_GLYPHLESS);
1623 produce_glyphless_glyph (it, 1, acronym);
1627 done:
1628 /* Advance current_x by the pixel width as a convenience for
1629 the caller. */
1630 if (it->area == TEXT_AREA)
1631 it->current_x += it->pixel_width;
1632 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1633 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
1636 /* Append glyphs to IT's glyph_row for the composition IT->cmp_id.
1637 Called from produce_composite_glyph for terminal frames if
1638 IT->glyph_row != NULL. IT->face_id contains the character's
1639 face. */
1641 static void
1642 append_composite_glyph (struct it *it)
1644 struct glyph *glyph;
1646 eassert (it->glyph_row);
1647 glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
1648 if (glyph < it->glyph_row->glyphs[1 + it->area])
1650 /* If the glyph row is reversed, we need to prepend the glyph
1651 rather than append it. */
1652 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1654 struct glyph *g;
1656 /* Make room for the new glyph. */
1657 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1658 g[1] = *g;
1659 glyph = it->glyph_row->glyphs[it->area];
1661 glyph->type = COMPOSITE_GLYPH;
1662 glyph->pixel_width = it->pixel_width;
1663 glyph->u.cmp.id = it->cmp_it.id;
1664 if (it->cmp_it.ch < 0)
1666 glyph->u.cmp.automatic = 0;
1667 glyph->u.cmp.id = it->cmp_it.id;
1669 else
1671 glyph->u.cmp.automatic = 1;
1672 glyph->u.cmp.id = it->cmp_it.id;
1673 glyph->slice.cmp.from = it->cmp_it.from;
1674 glyph->slice.cmp.to = it->cmp_it.to - 1;
1677 glyph->face_id = it->face_id;
1678 glyph->padding_p = 0;
1679 glyph->charpos = CHARPOS (it->position);
1680 glyph->object = it->object;
1681 if (it->bidi_p)
1683 glyph->resolved_level = it->bidi_it.resolved_level;
1684 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1685 emacs_abort ();
1686 glyph->bidi_type = it->bidi_it.type;
1688 else
1690 glyph->resolved_level = 0;
1691 glyph->bidi_type = UNKNOWN_BT;
1694 ++it->glyph_row->used[it->area];
1695 ++glyph;
1700 /* Produce a composite glyph for iterator IT. IT->cmp_id is the ID of
1701 the composition. We simply produces components of the composition
1702 assuming that the terminal has a capability to layout/render it
1703 correctly. */
1705 static void
1706 produce_composite_glyph (struct it *it)
1708 if (it->cmp_it.ch < 0)
1710 struct composition *cmp = composition_table[it->cmp_it.id];
1712 it->pixel_width = cmp->width;
1714 else
1716 Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id);
1718 it->pixel_width = composition_gstring_width (gstring, it->cmp_it.from,
1719 it->cmp_it.to, NULL);
1721 it->nglyphs = 1;
1722 if (it->glyph_row)
1723 append_composite_glyph (it);
1727 /* Append a glyph for a glyphless character to IT->glyph_row. FACE_ID
1728 is a face ID to be used for the glyph. What is actually appended
1729 are glyphs of type CHAR_GLYPH whose characters are in STR (which
1730 comes from it->nglyphs bytes). */
1732 static void
1733 append_glyphless_glyph (struct it *it, int face_id, const char *str)
1735 struct glyph *glyph, *end;
1736 int i;
1738 eassert (it->glyph_row);
1739 glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
1740 end = it->glyph_row->glyphs[1 + it->area];
1742 /* If the glyph row is reversed, we need to prepend the glyph rather
1743 than append it. */
1744 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1746 struct glyph *g;
1747 int move_by = it->pixel_width;
1749 /* Make room for the new glyphs. */
1750 if (move_by > end - glyph) /* don't overstep end of this area */
1751 move_by = end - glyph;
1752 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1753 g[move_by] = *g;
1754 glyph = it->glyph_row->glyphs[it->area];
1755 end = glyph + move_by;
1758 if (glyph >= end)
1759 return;
1760 glyph->type = CHAR_GLYPH;
1761 glyph->pixel_width = 1;
1762 glyph->face_id = face_id;
1763 glyph->padding_p = 0;
1764 glyph->charpos = CHARPOS (it->position);
1765 glyph->object = it->object;
1766 if (it->bidi_p)
1768 glyph->resolved_level = it->bidi_it.resolved_level;
1769 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1770 emacs_abort ();
1771 glyph->bidi_type = it->bidi_it.type;
1773 else
1775 glyph->resolved_level = 0;
1776 glyph->bidi_type = UNKNOWN_BT;
1779 /* BIDI Note: we put the glyphs of characters left to right, even in
1780 the REVERSED_P case because we write to the terminal
1781 left-to-right. */
1782 for (i = 0; i < it->nglyphs && glyph < end; ++i)
1784 if (i > 0)
1785 glyph[0] = glyph[-1];
1786 glyph->u.ch = str[i];
1787 ++it->glyph_row->used[it->area];
1788 ++glyph;
1792 /* Produce glyphs for a glyphless character for iterator IT.
1793 IT->glyphless_method specifies which method to use for displaying
1794 the character. See the description of enum
1795 glyphless_display_method in dispextern.h for the details.
1797 FOR_NO_FONT is nonzero if and only if this is for a character that
1798 is not supported by the coding system of the terminal. ACRONYM, if
1799 non-nil, is an acronym string for the character.
1801 The glyphs actually produced are of type CHAR_GLYPH. */
1803 static void
1804 produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym)
1806 int face_id;
1807 int len;
1808 char buf[sizeof "\\x" + max (6, (sizeof it->c * CHAR_BIT + 3) / 4)];
1809 char const *str = " ";
1811 /* Get a face ID for the glyph by utilizing a cache (the same way as
1812 done for `escape-glyph' in get_next_display_element). */
1813 if (it->f == last_glyphless_glyph_frame
1814 && it->face_id == last_glyphless_glyph_face_id)
1816 face_id = last_glyphless_glyph_merged_face_id;
1818 else
1820 /* Merge the `glyphless-char' face into the current face. */
1821 face_id = merge_faces (it->f, Qglyphless_char, 0, it->face_id);
1822 last_glyphless_glyph_frame = it->f;
1823 last_glyphless_glyph_face_id = it->face_id;
1824 last_glyphless_glyph_merged_face_id = face_id;
1827 if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE)
1829 /* As there's no way to produce a thin space, we produce a space
1830 of canonical width. */
1831 len = 1;
1833 else if (it->glyphless_method == GLYPHLESS_DISPLAY_EMPTY_BOX)
1835 len = CHAR_WIDTH (it->c);
1836 if (len == 0)
1837 len = 1;
1838 else if (len > 4)
1839 len = 4;
1840 len = sprintf (buf, "[%.*s]", len, str);
1841 str = buf;
1843 else
1845 if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM)
1847 if (! STRINGP (acronym) && CHAR_TABLE_P (Vglyphless_char_display))
1848 acronym = CHAR_TABLE_REF (Vglyphless_char_display, it->c);
1849 if (CONSP (acronym))
1850 acronym = XCDR (acronym);
1851 buf[0] = '[';
1852 str = STRINGP (acronym) ? SSDATA (acronym) : "";
1853 for (len = 0; len < 6 && str[len] && ASCII_BYTE_P (str[len]); len++)
1854 buf[1 + len] = str[len];
1855 buf[1 + len] = ']';
1856 len += 2;
1858 else
1860 eassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEX_CODE);
1861 len = (it->c < 0x10000 ? sprintf (buf, "\\u%04X", it->c)
1862 : it->c <= MAX_UNICODE_CHAR ? sprintf (buf, "\\U%06X", it->c)
1863 : sprintf (buf, "\\x%06X", it->c));
1865 str = buf;
1868 it->pixel_width = len;
1869 it->nglyphs = len;
1870 if (it->glyph_row)
1871 append_glyphless_glyph (it, face_id, str);
1875 /***********************************************************************
1876 Faces
1877 ***********************************************************************/
1879 /* Value is non-zero if attribute ATTR may be used. ATTR should be
1880 one of the enumerators from enum no_color_bit, or a bit set built
1881 from them. Some display attributes may not be used together with
1882 color; the termcap capability `NC' specifies which ones. */
1884 #define MAY_USE_WITH_COLORS_P(tty, ATTR) \
1885 (tty->TN_max_colors > 0 \
1886 ? (tty->TN_no_color_video & (ATTR)) == 0 \
1887 : 1)
1889 /* Turn appearances of face FACE_ID on tty frame F on.
1890 FACE_ID is a realized face ID number, in the face cache. */
1892 static void
1893 turn_on_face (struct frame *f, int face_id)
1895 struct face *face = FACE_FROM_ID (f, face_id);
1896 long fg = face->foreground;
1897 long bg = face->background;
1898 struct tty_display_info *tty = FRAME_TTY (f);
1900 /* Do this first because TS_end_standout_mode may be the same
1901 as TS_exit_attribute_mode, which turns all appearances off. */
1902 if (MAY_USE_WITH_COLORS_P (tty, NC_REVERSE))
1904 if (tty->TN_max_colors > 0)
1906 if (fg >= 0 && bg >= 0)
1908 /* If the terminal supports colors, we can set them
1909 below without using reverse video. The face's fg
1910 and bg colors are set as they should appear on
1911 the screen, i.e. they take the inverse-video'ness
1912 of the face already into account. */
1914 else if (inverse_video)
1916 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1917 || bg == FACE_TTY_DEFAULT_BG_COLOR)
1918 tty_toggle_highlight (tty);
1920 else
1922 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1923 || bg == FACE_TTY_DEFAULT_FG_COLOR)
1924 tty_toggle_highlight (tty);
1927 else
1929 /* If we can't display colors, use reverse video
1930 if the face specifies that. */
1931 if (inverse_video)
1933 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1934 || bg == FACE_TTY_DEFAULT_BG_COLOR)
1935 tty_toggle_highlight (tty);
1937 else
1939 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1940 || bg == FACE_TTY_DEFAULT_FG_COLOR)
1941 tty_toggle_highlight (tty);
1946 if (face->tty_bold_p && MAY_USE_WITH_COLORS_P (tty, NC_BOLD))
1947 OUTPUT1_IF (tty, tty->TS_enter_bold_mode);
1949 if (face->tty_italic_p && MAY_USE_WITH_COLORS_P (tty, NC_ITALIC))
1951 if (tty->TS_enter_italic_mode)
1952 OUTPUT1 (tty, tty->TS_enter_italic_mode);
1953 else
1954 /* Italics mode is unavailable on many terminals. In that
1955 case, map slant to dimmed text; we want italic text to
1956 appear different and dimming is not otherwise used. */
1957 OUTPUT1 (tty, tty->TS_enter_dim_mode);
1960 if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (tty, NC_UNDERLINE))
1961 OUTPUT1_IF (tty, tty->TS_enter_underline_mode);
1963 if (tty->TN_max_colors > 0)
1965 const char *ts;
1966 char *p;
1968 ts = tty->standout_mode ? tty->TS_set_background : tty->TS_set_foreground;
1969 if (fg >= 0 && ts)
1971 p = tparam (ts, NULL, 0, (int) fg, 0, 0, 0);
1972 OUTPUT (tty, p);
1973 xfree (p);
1976 ts = tty->standout_mode ? tty->TS_set_foreground : tty->TS_set_background;
1977 if (bg >= 0 && ts)
1979 p = tparam (ts, NULL, 0, (int) bg, 0, 0, 0);
1980 OUTPUT (tty, p);
1981 xfree (p);
1987 /* Turn off appearances of face FACE_ID on tty frame F. */
1989 static void
1990 turn_off_face (struct frame *f, int face_id)
1992 struct face *face = FACE_FROM_ID (f, face_id);
1993 struct tty_display_info *tty = FRAME_TTY (f);
1995 eassert (face != NULL);
1997 if (tty->TS_exit_attribute_mode)
1999 /* Capability "me" will turn off appearance modes double-bright,
2000 half-bright, reverse-video, standout, underline. It may or
2001 may not turn off alt-char-mode. */
2002 if (face->tty_bold_p
2003 || face->tty_italic_p
2004 || face->tty_reverse_p
2005 || face->tty_underline_p)
2007 OUTPUT1_IF (tty, tty->TS_exit_attribute_mode);
2008 if (strcmp (tty->TS_exit_attribute_mode, tty->TS_end_standout_mode) == 0)
2009 tty->standout_mode = 0;
2012 else
2014 /* If we don't have "me" we can only have those appearances
2015 that have exit sequences defined. */
2016 if (face->tty_underline_p)
2017 OUTPUT_IF (tty, tty->TS_exit_underline_mode);
2020 /* Switch back to default colors. */
2021 if (tty->TN_max_colors > 0
2022 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
2023 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
2024 || (face->background != FACE_TTY_DEFAULT_COLOR
2025 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
2026 OUTPUT1_IF (tty, tty->TS_orig_pair);
2030 /* Return non-zero if the terminal on frame F supports all of the
2031 capabilities in CAPS simultaneously, with foreground and background
2032 colors FG and BG. */
2035 tty_capable_p (struct tty_display_info *tty, unsigned int caps,
2036 unsigned long fg, unsigned long bg)
2038 #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
2039 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
2040 return 0;
2042 TTY_CAPABLE_P_TRY (tty, TTY_CAP_INVERSE, tty->TS_standout_mode, NC_REVERSE);
2043 TTY_CAPABLE_P_TRY (tty, TTY_CAP_UNDERLINE, tty->TS_enter_underline_mode, NC_UNDERLINE);
2044 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BOLD, tty->TS_enter_bold_mode, NC_BOLD);
2045 TTY_CAPABLE_P_TRY (tty, TTY_CAP_DIM, tty->TS_enter_dim_mode, NC_DIM);
2046 TTY_CAPABLE_P_TRY (tty, TTY_CAP_ITALIC, tty->TS_enter_italic_mode, NC_ITALIC);
2048 /* We can do it! */
2049 return 1;
2052 /* Return non-zero if the terminal is capable to display colors. */
2054 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
2055 0, 1, 0,
2056 doc: /* Return non-nil if the tty device TERMINAL can display colors.
2058 TERMINAL can be a terminal object, a frame, or nil (meaning the
2059 selected frame's terminal). This function always returns nil if
2060 TERMINAL does not refer to a text terminal. */)
2061 (Lisp_Object terminal)
2063 struct terminal *t = get_tty_terminal (terminal, 0);
2064 if (!t)
2065 return Qnil;
2066 else
2067 return t->display_info.tty->TN_max_colors > 0 ? Qt : Qnil;
2070 /* Return the number of supported colors. */
2071 DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
2072 Stty_display_color_cells, 0, 1, 0,
2073 doc: /* Return the number of colors supported by the tty device TERMINAL.
2075 TERMINAL can be a terminal object, a frame, or nil (meaning the
2076 selected frame's terminal). This function always returns 0 if
2077 TERMINAL does not refer to a text terminal. */)
2078 (Lisp_Object terminal)
2080 struct terminal *t = get_tty_terminal (terminal, 0);
2081 if (!t)
2082 return make_number (0);
2083 else
2084 return make_number (t->display_info.tty->TN_max_colors);
2087 #ifndef DOS_NT
2089 /* Declare here rather than in the function, as in the rest of Emacs,
2090 to work around an HPUX compiler bug (?). See
2091 http://lists.gnu.org/archive/html/emacs-devel/2007-08/msg00410.html */
2092 static int default_max_colors;
2093 static int default_max_pairs;
2094 static int default_no_color_video;
2095 static char *default_orig_pair;
2096 static char *default_set_foreground;
2097 static char *default_set_background;
2099 /* Save or restore the default color-related capabilities of this
2100 terminal. */
2101 static void
2102 tty_default_color_capabilities (struct tty_display_info *tty, int save)
2105 if (save)
2107 xfree (default_orig_pair);
2108 default_orig_pair = tty->TS_orig_pair ? xstrdup (tty->TS_orig_pair) : NULL;
2110 xfree (default_set_foreground);
2111 default_set_foreground = tty->TS_set_foreground ? xstrdup (tty->TS_set_foreground)
2112 : NULL;
2114 xfree (default_set_background);
2115 default_set_background = tty->TS_set_background ? xstrdup (tty->TS_set_background)
2116 : NULL;
2118 default_max_colors = tty->TN_max_colors;
2119 default_max_pairs = tty->TN_max_pairs;
2120 default_no_color_video = tty->TN_no_color_video;
2122 else
2124 tty->TS_orig_pair = default_orig_pair;
2125 tty->TS_set_foreground = default_set_foreground;
2126 tty->TS_set_background = default_set_background;
2127 tty->TN_max_colors = default_max_colors;
2128 tty->TN_max_pairs = default_max_pairs;
2129 tty->TN_no_color_video = default_no_color_video;
2133 /* Setup one of the standard tty color schemes according to MODE.
2134 MODE's value is generally the number of colors which we want to
2135 support; zero means set up for the default capabilities, the ones
2136 we saw at init_tty time; -1 means turn off color support. */
2137 static void
2138 tty_setup_colors (struct tty_display_info *tty, int mode)
2140 /* Canonicalize all negative values of MODE. */
2141 if (mode < -1)
2142 mode = -1;
2144 switch (mode)
2146 case -1: /* no colors at all */
2147 tty->TN_max_colors = 0;
2148 tty->TN_max_pairs = 0;
2149 tty->TN_no_color_video = 0;
2150 tty->TS_set_foreground = tty->TS_set_background = tty->TS_orig_pair = NULL;
2151 break;
2152 case 0: /* default colors, if any */
2153 default:
2154 tty_default_color_capabilities (tty, 0);
2155 break;
2156 case 8: /* 8 standard ANSI colors */
2157 tty->TS_orig_pair = "\033[0m";
2158 #ifdef TERMINFO
2159 tty->TS_set_foreground = "\033[3%p1%dm";
2160 tty->TS_set_background = "\033[4%p1%dm";
2161 #else
2162 tty->TS_set_foreground = "\033[3%dm";
2163 tty->TS_set_background = "\033[4%dm";
2164 #endif
2165 tty->TN_max_colors = 8;
2166 tty->TN_max_pairs = 64;
2167 tty->TN_no_color_video = 0;
2168 break;
2172 void
2173 set_tty_color_mode (struct tty_display_info *tty, struct frame *f)
2175 Lisp_Object tem, val;
2176 Lisp_Object color_mode;
2177 int mode;
2178 Lisp_Object tty_color_mode_alist
2179 = Fintern_soft (build_string ("tty-color-mode-alist"), Qnil);
2181 tem = assq_no_quit (Qtty_color_mode, f->param_alist);
2182 val = CONSP (tem) ? XCDR (tem) : Qnil;
2184 if (INTEGERP (val))
2185 color_mode = val;
2186 else if (SYMBOLP (tty_color_mode_alist))
2188 tem = Fassq (val, Fsymbol_value (tty_color_mode_alist));
2189 color_mode = CONSP (tem) ? XCDR (tem) : Qnil;
2191 else
2192 color_mode = Qnil;
2194 mode = TYPE_RANGED_INTEGERP (int, color_mode) ? XINT (color_mode) : 0;
2196 if (mode != tty->previous_color_mode)
2198 tty->previous_color_mode = mode;
2199 tty_setup_colors (tty , mode);
2200 /* This recomputes all the faces given the new color definitions. */
2201 safe_call (1, intern ("tty-set-up-initial-frame-faces"));
2205 #endif /* !DOS_NT */
2209 /* Return the tty display object specified by TERMINAL. */
2211 static struct terminal *
2212 get_tty_terminal (Lisp_Object terminal, int throw)
2214 struct terminal *t = get_terminal (terminal, throw);
2216 if (t && t->type != output_termcap && t->type != output_msdos_raw)
2218 if (throw)
2219 error ("Device %d is not a termcap terminal device", t->id);
2220 else
2221 return NULL;
2224 return t;
2227 /* Return an active termcap device that uses the tty device with the
2228 given name.
2230 This function ignores suspended devices.
2232 Returns NULL if the named terminal device is not opened. */
2234 struct terminal *
2235 get_named_tty (const char *name)
2237 struct terminal *t;
2239 if (!name)
2240 emacs_abort ();
2242 for (t = terminal_list; t; t = t->next_terminal)
2244 if ((t->type == output_termcap || t->type == output_msdos_raw)
2245 && !strcmp (t->display_info.tty->name, name)
2246 && TERMINAL_ACTIVE_P (t))
2247 return t;
2250 return 0;
2254 DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0,
2255 doc: /* Return the type of the tty device that TERMINAL uses.
2256 Returns nil if TERMINAL is not on a tty device.
2258 TERMINAL can be a terminal object, a frame, or nil (meaning the
2259 selected frame's terminal). */)
2260 (Lisp_Object terminal)
2262 struct terminal *t = get_terminal (terminal, 1);
2264 if (t->type != output_termcap && t->type != output_msdos_raw)
2265 return Qnil;
2267 if (t->display_info.tty->type)
2268 return build_string (t->display_info.tty->type);
2269 else
2270 return Qnil;
2273 DEFUN ("controlling-tty-p", Fcontrolling_tty_p, Scontrolling_tty_p, 0, 1, 0,
2274 doc: /* Return non-nil if TERMINAL is the controlling tty of the Emacs process.
2276 TERMINAL can be a terminal object, a frame, or nil (meaning the
2277 selected frame's terminal). This function always returns nil if
2278 TERMINAL is not on a tty device. */)
2279 (Lisp_Object terminal)
2281 struct terminal *t = get_terminal (terminal, 1);
2283 if ((t->type != output_termcap && t->type != output_msdos_raw)
2284 || strcmp (t->display_info.tty->name, DEV_TTY) != 0)
2285 return Qnil;
2286 else
2287 return Qt;
2290 DEFUN ("tty-no-underline", Ftty_no_underline, Stty_no_underline, 0, 1, 0,
2291 doc: /* Declare that the tty used by TERMINAL does not handle underlining.
2292 This is used to override the terminfo data, for certain terminals that
2293 do not really do underlining, but say that they do. This function has
2294 no effect if used on a non-tty terminal.
2296 TERMINAL can be a terminal object, a frame or nil (meaning the
2297 selected frame's terminal). This function always returns nil if
2298 TERMINAL does not refer to a text terminal. */)
2299 (Lisp_Object terminal)
2301 struct terminal *t = get_terminal (terminal, 1);
2303 if (t->type == output_termcap)
2304 t->display_info.tty->TS_enter_underline_mode = 0;
2305 return Qnil;
2308 DEFUN ("tty-top-frame", Ftty_top_frame, Stty_top_frame, 0, 1, 0,
2309 doc: /* Return the topmost terminal frame on TERMINAL.
2310 TERMINAL can be a terminal object, a frame or nil (meaning the
2311 selected frame's terminal). This function returns nil if TERMINAL
2312 does not refer to a text terminal. Otherwise, it returns the
2313 top-most frame on the text terminal. */)
2314 (Lisp_Object terminal)
2316 struct terminal *t = get_terminal (terminal, 1);
2318 if (t->type == output_termcap)
2319 return t->display_info.tty->top_frame;
2320 return Qnil;
2325 DEFUN ("suspend-tty", Fsuspend_tty, Ssuspend_tty, 0, 1, 0,
2326 doc: /* Suspend the terminal device TTY.
2328 The device is restored to its default state, and Emacs ceases all
2329 access to the tty device. Frames that use the device are not deleted,
2330 but input is not read from them and if they change, their display is
2331 not updated.
2333 TTY may be a terminal object, a frame, or nil for the terminal device
2334 of the currently selected frame.
2336 This function runs `suspend-tty-functions' after suspending the
2337 device. The functions are run with one arg, the id of the suspended
2338 terminal device.
2340 `suspend-tty' does nothing if it is called on a device that is already
2341 suspended.
2343 A suspended tty may be resumed by calling `resume-tty' on it. */)
2344 (Lisp_Object tty)
2346 struct terminal *t = get_tty_terminal (tty, 1);
2347 FILE *f;
2349 if (!t)
2350 error ("Unknown tty device");
2352 f = t->display_info.tty->input;
2354 if (f)
2356 /* First run `suspend-tty-functions' and then clean up the tty
2357 state because `suspend-tty-functions' might need to change
2358 the tty state. */
2359 Lisp_Object args[2];
2360 args[0] = intern ("suspend-tty-functions");
2361 XSETTERMINAL (args[1], t);
2362 Frun_hook_with_args (2, args);
2364 reset_sys_modes (t->display_info.tty);
2365 delete_keyboard_wait_descriptor (fileno (f));
2367 #ifndef MSDOS
2368 fclose (f);
2369 if (f != t->display_info.tty->output)
2370 fclose (t->display_info.tty->output);
2371 #endif
2373 t->display_info.tty->input = 0;
2374 t->display_info.tty->output = 0;
2376 if (FRAMEP (t->display_info.tty->top_frame))
2377 SET_FRAME_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0);
2381 /* Clear display hooks to prevent further output. */
2382 clear_tty_hooks (t);
2384 return Qnil;
2387 DEFUN ("resume-tty", Fresume_tty, Sresume_tty, 0, 1, 0,
2388 doc: /* Resume the previously suspended terminal device TTY.
2389 The terminal is opened and reinitialized. Frames that are on the
2390 suspended terminal are revived.
2392 It is an error to resume a terminal while another terminal is active
2393 on the same device.
2395 This function runs `resume-tty-functions' after resuming the terminal.
2396 The functions are run with one arg, the id of the resumed terminal
2397 device.
2399 `resume-tty' does nothing if it is called on a device that is not
2400 suspended.
2402 TTY may be a terminal object, a frame, or nil (meaning the selected
2403 frame's terminal). */)
2404 (Lisp_Object tty)
2406 struct terminal *t = get_tty_terminal (tty, 1);
2407 int fd;
2409 if (!t)
2410 error ("Unknown tty device");
2412 if (!t->display_info.tty->input)
2414 if (get_named_tty (t->display_info.tty->name))
2415 error ("Cannot resume display while another display is active on the same device");
2417 #ifdef MSDOS
2418 t->display_info.tty->output = stdout;
2419 t->display_info.tty->input = stdin;
2420 #else /* !MSDOS */
2421 fd = emacs_open (t->display_info.tty->name, O_RDWR | O_NOCTTY, 0);
2423 if (fd == -1)
2424 error ("Can not reopen tty device %s: %s", t->display_info.tty->name, strerror (errno));
2426 if (!O_IGNORE_CTTY && strcmp (t->display_info.tty->name, DEV_TTY) != 0)
2427 dissociate_if_controlling_tty (fd);
2429 t->display_info.tty->output = fdopen (fd, "w+");
2430 t->display_info.tty->input = t->display_info.tty->output;
2431 #endif
2433 add_keyboard_wait_descriptor (fd);
2435 if (FRAMEP (t->display_info.tty->top_frame))
2437 struct frame *f = XFRAME (t->display_info.tty->top_frame);
2438 int width, height;
2439 int old_height = FRAME_COLS (f);
2440 int old_width = FRAME_LINES (f);
2442 /* Check if terminal/window size has changed while the frame
2443 was suspended. */
2444 get_tty_size (fileno (t->display_info.tty->input), &width, &height);
2445 if (width != old_width || height != old_height)
2446 change_frame_size (f, height, width, 0, 0, 0);
2447 SET_FRAME_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
2450 set_tty_hooks (t);
2451 init_sys_modes (t->display_info.tty);
2454 /* Run `resume-tty-functions'. */
2455 Lisp_Object args[2];
2456 args[0] = intern ("resume-tty-functions");
2457 XSETTERMINAL (args[1], t);
2458 Frun_hook_with_args (2, args);
2462 set_tty_hooks (t);
2464 return Qnil;
2468 /***********************************************************************
2469 Mouse
2470 ***********************************************************************/
2472 #ifdef HAVE_GPM
2474 #ifndef HAVE_WINDOW_SYSTEM
2475 void
2476 term_mouse_moveto (int x, int y)
2478 /* TODO: how to set mouse position?
2479 const char *name;
2480 int fd;
2481 name = (const char *) ttyname (0);
2482 fd = open (name, O_WRONLY);
2483 SOME_FUNCTION (x, y, fd);
2484 close (fd);
2485 last_mouse_x = x;
2486 last_mouse_y = y; */
2488 #endif /* HAVE_WINDOW_SYSTEM */
2490 /* Implementation of draw_row_with_mouse_face for TTY/GPM. */
2491 void
2492 tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *row,
2493 int start_hpos, int end_hpos,
2494 enum draw_glyphs_face draw)
2496 int nglyphs = end_hpos - start_hpos;
2497 struct frame *f = XFRAME (WINDOW_FRAME (w));
2498 struct tty_display_info *tty = FRAME_TTY (f);
2499 int face_id = tty->mouse_highlight.mouse_face_face_id;
2500 int save_x, save_y, pos_x, pos_y;
2502 if (end_hpos >= row->used[TEXT_AREA])
2503 nglyphs = row->used[TEXT_AREA] - start_hpos;
2505 pos_y = row->y + WINDOW_TOP_EDGE_Y (w);
2506 pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos + WINDOW_LEFT_EDGE_X (w);
2508 /* Save current cursor co-ordinates. */
2509 save_y = curY (tty);
2510 save_x = curX (tty);
2511 cursor_to (f, pos_y, pos_x);
2513 if (draw == DRAW_MOUSE_FACE)
2514 tty_write_glyphs_with_face (f, row->glyphs[TEXT_AREA] + start_hpos,
2515 nglyphs, face_id);
2516 else if (draw == DRAW_NORMAL_TEXT)
2517 write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
2519 cursor_to (f, save_y, save_x);
2522 static int
2523 term_mouse_movement (FRAME_PTR frame, Gpm_Event *event)
2525 /* Has the mouse moved off the glyph it was on at the last sighting? */
2526 if (event->x != last_mouse_x || event->y != last_mouse_y)
2528 frame->mouse_moved = 1;
2529 note_mouse_highlight (frame, event->x, event->y);
2530 /* Remember which glyph we're now on. */
2531 last_mouse_x = event->x;
2532 last_mouse_y = event->y;
2533 return 1;
2535 return 0;
2538 /* Return the Time that corresponds to T. Wrap around on overflow. */
2539 static Time
2540 timeval_to_Time (struct timeval const *t)
2542 Time s_1000, ms;
2544 s_1000 = t->tv_sec;
2545 s_1000 *= 1000;
2546 ms = t->tv_usec / 1000;
2547 return s_1000 + ms;
2550 /* Return the current position of the mouse.
2552 Set *f to the frame the mouse is in, or zero if the mouse is in no
2553 Emacs frame. If it is set to zero, all the other arguments are
2554 garbage.
2556 Set *bar_window to Qnil, and *x and *y to the column and
2557 row of the character cell the mouse is over.
2559 Set *timeptr to the time the mouse was at the returned position.
2561 This clears mouse_moved until the next motion
2562 event arrives. */
2563 static void
2564 term_mouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
2565 enum scroll_bar_part *part, Lisp_Object *x,
2566 Lisp_Object *y, Time *timeptr)
2568 struct timeval now;
2570 *fp = SELECTED_FRAME ();
2571 (*fp)->mouse_moved = 0;
2573 *bar_window = Qnil;
2574 *part = 0;
2576 XSETINT (*x, last_mouse_x);
2577 XSETINT (*y, last_mouse_y);
2578 gettimeofday(&now, 0);
2579 *timeptr = timeval_to_Time (&now);
2582 /* Prepare a mouse-event in *RESULT for placement in the input queue.
2584 If the event is a button press, then note that we have grabbed
2585 the mouse. */
2587 static Lisp_Object
2588 term_mouse_click (struct input_event *result, Gpm_Event *event,
2589 struct frame *f)
2591 struct timeval now;
2592 int i, j;
2594 result->kind = GPM_CLICK_EVENT;
2595 for (i = 0, j = GPM_B_LEFT; i < 3; i++, j >>= 1 )
2597 if (event->buttons & j) {
2598 result->code = i; /* button number */
2599 break;
2602 gettimeofday(&now, 0);
2603 result->timestamp = timeval_to_Time (&now);
2605 if (event->type & GPM_UP)
2606 result->modifiers = up_modifier;
2607 else if (event->type & GPM_DOWN)
2608 result->modifiers = down_modifier;
2609 else
2610 result->modifiers = 0;
2612 if (event->type & GPM_SINGLE)
2613 result->modifiers |= click_modifier;
2615 if (event->type & GPM_DOUBLE)
2616 result->modifiers |= double_modifier;
2618 if (event->type & GPM_TRIPLE)
2619 result->modifiers |= triple_modifier;
2621 if (event->type & GPM_DRAG)
2622 result->modifiers |= drag_modifier;
2624 if (!(event->type & (GPM_MOVE | GPM_DRAG))) {
2626 /* 1 << KG_SHIFT */
2627 if (event->modifiers & (1 << 0))
2628 result->modifiers |= shift_modifier;
2630 /* 1 << KG_CTRL */
2631 if (event->modifiers & (1 << 2))
2632 result->modifiers |= ctrl_modifier;
2634 /* 1 << KG_ALT || KG_ALTGR */
2635 if (event->modifiers & (1 << 3)
2636 || event->modifiers & (1 << 1))
2637 result->modifiers |= meta_modifier;
2640 XSETINT (result->x, event->x);
2641 XSETINT (result->y, event->y);
2642 XSETFRAME (result->frame_or_window, f);
2643 result->arg = Qnil;
2644 return Qnil;
2648 handle_one_term_event (struct tty_display_info *tty, Gpm_Event *event, struct input_event* hold_quit)
2650 struct frame *f = XFRAME (tty->top_frame);
2651 struct input_event ie;
2652 int do_help = 0;
2653 int count = 0;
2655 EVENT_INIT (ie);
2656 ie.kind = NO_EVENT;
2657 ie.arg = Qnil;
2659 if (event->type & (GPM_MOVE | GPM_DRAG)) {
2660 previous_help_echo_string = help_echo_string;
2661 help_echo_string = Qnil;
2663 Gpm_DrawPointer (event->x, event->y, fileno (tty->output));
2665 if (!term_mouse_movement (f, event))
2666 help_echo_string = previous_help_echo_string;
2668 /* If the contents of the global variable help_echo_string
2669 has changed, generate a HELP_EVENT. */
2670 if (!NILP (help_echo_string)
2671 || !NILP (previous_help_echo_string))
2672 do_help = 1;
2674 goto done;
2676 else {
2677 f->mouse_moved = 0;
2678 term_mouse_click (&ie, event, f);
2681 done:
2682 if (ie.kind != NO_EVENT)
2684 kbd_buffer_store_event_hold (&ie, hold_quit);
2685 count++;
2688 if (do_help
2689 && !(hold_quit && hold_quit->kind != NO_EVENT))
2691 Lisp_Object frame;
2693 if (f)
2694 XSETFRAME (frame, f);
2695 else
2696 frame = Qnil;
2698 gen_help_event (help_echo_string, frame, help_echo_window,
2699 help_echo_object, help_echo_pos);
2700 count++;
2703 return count;
2706 DEFUN ("gpm-mouse-start", Fgpm_mouse_start, Sgpm_mouse_start,
2707 0, 0, 0,
2708 doc: /* Open a connection to Gpm.
2709 Gpm-mouse can only be activated for one tty at a time. */)
2710 (void)
2712 struct frame *f = SELECTED_FRAME ();
2713 struct tty_display_info *tty
2714 = ((f)->output_method == output_termcap
2715 ? (f)->terminal->display_info.tty : NULL);
2716 Gpm_Connect connection;
2718 if (!tty)
2719 error ("Gpm-mouse only works in the GNU/Linux console");
2720 if (gpm_tty == tty)
2721 return Qnil; /* Already activated, nothing to do. */
2722 if (gpm_tty)
2723 error ("Gpm-mouse can only be activated for one tty at a time");
2725 connection.eventMask = ~0;
2726 connection.defaultMask = ~GPM_HARD;
2727 connection.maxMod = ~0;
2728 connection.minMod = 0;
2729 gpm_zerobased = 1;
2731 if (Gpm_Open (&connection, 0) < 0)
2732 error ("Gpm-mouse failed to connect to the gpm daemon");
2733 else
2735 gpm_tty = tty;
2736 /* `init_sys_modes' arranges for mouse movements sent through gpm_fd
2737 to generate SIGIOs. Apparently we need to call reset_sys_modes
2738 before calling init_sys_modes. */
2739 reset_sys_modes (tty);
2740 init_sys_modes (tty);
2741 add_gpm_wait_descriptor (gpm_fd);
2742 return Qnil;
2746 void
2747 close_gpm (int fd)
2749 if (fd >= 0)
2750 delete_gpm_wait_descriptor (fd);
2751 while (Gpm_Close()); /* close all the stack */
2752 gpm_tty = NULL;
2755 DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop, Sgpm_mouse_stop,
2756 0, 0, 0,
2757 doc: /* Close a connection to Gpm. */)
2758 (void)
2760 struct frame *f = SELECTED_FRAME ();
2761 struct tty_display_info *tty
2762 = ((f)->output_method == output_termcap
2763 ? (f)->terminal->display_info.tty : NULL);
2765 if (!tty || gpm_tty != tty)
2766 return Qnil; /* Not activated on this terminal, nothing to do. */
2768 close_gpm (gpm_fd);
2769 return Qnil;
2771 #endif /* HAVE_GPM */
2774 #ifndef MSDOS
2775 /***********************************************************************
2776 Initialization
2777 ***********************************************************************/
2779 /* Initialize the tty-dependent part of frame F. The frame must
2780 already have its device initialized. */
2782 void
2783 create_tty_output (struct frame *f)
2785 struct tty_output *t = xzalloc (sizeof *t);
2787 if (! FRAME_TERMCAP_P (f))
2788 emacs_abort ();
2790 t->display_info = FRAME_TERMINAL (f)->display_info.tty;
2792 f->output_data.tty = t;
2795 /* Delete frame F's face cache, and its tty-dependent part. */
2797 static void
2798 tty_free_frame_resources (struct frame *f)
2800 if (! FRAME_TERMCAP_P (f))
2801 emacs_abort ();
2803 if (FRAME_FACE_CACHE (f))
2804 free_frame_faces (f);
2806 xfree (f->output_data.tty);
2809 #else /* MSDOS */
2811 /* Delete frame F's face cache. */
2813 static void
2814 tty_free_frame_resources (struct frame *f)
2816 if (! FRAME_TERMCAP_P (f) && ! FRAME_MSDOS_P (f))
2817 emacs_abort ();
2819 if (FRAME_FACE_CACHE (f))
2820 free_frame_faces (f);
2822 #endif /* MSDOS */
2824 /* Reset the hooks in TERMINAL. */
2826 static void
2827 clear_tty_hooks (struct terminal *terminal)
2829 terminal->rif = 0;
2830 terminal->cursor_to_hook = 0;
2831 terminal->raw_cursor_to_hook = 0;
2832 terminal->clear_to_end_hook = 0;
2833 terminal->clear_frame_hook = 0;
2834 terminal->clear_end_of_line_hook = 0;
2835 terminal->ins_del_lines_hook = 0;
2836 terminal->insert_glyphs_hook = 0;
2837 terminal->write_glyphs_hook = 0;
2838 terminal->delete_glyphs_hook = 0;
2839 terminal->ring_bell_hook = 0;
2840 terminal->reset_terminal_modes_hook = 0;
2841 terminal->set_terminal_modes_hook = 0;
2842 terminal->update_begin_hook = 0;
2843 terminal->update_end_hook = 0;
2844 terminal->set_terminal_window_hook = 0;
2845 terminal->mouse_position_hook = 0;
2846 terminal->frame_rehighlight_hook = 0;
2847 terminal->frame_raise_lower_hook = 0;
2848 terminal->fullscreen_hook = 0;
2849 terminal->set_vertical_scroll_bar_hook = 0;
2850 terminal->condemn_scroll_bars_hook = 0;
2851 terminal->redeem_scroll_bar_hook = 0;
2852 terminal->judge_scroll_bars_hook = 0;
2853 terminal->read_socket_hook = 0;
2854 terminal->frame_up_to_date_hook = 0;
2856 /* Leave these two set, or suspended frames are not deleted
2857 correctly. */
2858 terminal->delete_frame_hook = &tty_free_frame_resources;
2859 terminal->delete_terminal_hook = &delete_tty;
2862 /* Initialize hooks in TERMINAL with the values needed for a tty. */
2864 static void
2865 set_tty_hooks (struct terminal *terminal)
2867 terminal->rif = 0; /* ttys don't support window-based redisplay. */
2869 terminal->cursor_to_hook = &tty_cursor_to;
2870 terminal->raw_cursor_to_hook = &tty_raw_cursor_to;
2872 terminal->clear_to_end_hook = &tty_clear_to_end;
2873 terminal->clear_frame_hook = &tty_clear_frame;
2874 terminal->clear_end_of_line_hook = &tty_clear_end_of_line;
2876 terminal->ins_del_lines_hook = &tty_ins_del_lines;
2878 terminal->insert_glyphs_hook = &tty_insert_glyphs;
2879 terminal->write_glyphs_hook = &tty_write_glyphs;
2880 terminal->delete_glyphs_hook = &tty_delete_glyphs;
2882 terminal->ring_bell_hook = &tty_ring_bell;
2884 terminal->reset_terminal_modes_hook = &tty_reset_terminal_modes;
2885 terminal->set_terminal_modes_hook = &tty_set_terminal_modes;
2886 terminal->update_begin_hook = 0; /* Not needed. */
2887 terminal->update_end_hook = &tty_update_end;
2888 terminal->set_terminal_window_hook = &tty_set_terminal_window;
2890 terminal->mouse_position_hook = 0; /* Not needed. */
2891 terminal->frame_rehighlight_hook = 0; /* Not needed. */
2892 terminal->frame_raise_lower_hook = 0; /* Not needed. */
2894 terminal->set_vertical_scroll_bar_hook = 0; /* Not needed. */
2895 terminal->condemn_scroll_bars_hook = 0; /* Not needed. */
2896 terminal->redeem_scroll_bar_hook = 0; /* Not needed. */
2897 terminal->judge_scroll_bars_hook = 0; /* Not needed. */
2899 terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */
2900 terminal->frame_up_to_date_hook = 0; /* Not needed. */
2902 terminal->delete_frame_hook = &tty_free_frame_resources;
2903 terminal->delete_terminal_hook = &delete_tty;
2906 /* If FD is the controlling terminal, drop it. */
2907 static void
2908 dissociate_if_controlling_tty (int fd)
2910 /* If tcgetpgrp succeeds, fd is the controlling terminal,
2911 so dissociate it by invoking setsid. */
2912 if (0 <= tcgetpgrp (fd) && setsid () < 0)
2914 #ifdef TIOCNOTTY
2915 /* setsid failed, presumably because Emacs is already a process
2916 group leader. Fall back on the obsolescent way to dissociate
2917 a controlling tty. */
2918 block_tty_out_signal ();
2919 ioctl (fd, TIOCNOTTY, 0);
2920 unblock_tty_out_signal ();
2921 #endif
2925 /* Create a termcap display on the tty device with the given name and
2926 type.
2928 If NAME is NULL, then use the controlling tty, i.e., "/dev/tty".
2929 Otherwise NAME should be a path to the tty device file,
2930 e.g. "/dev/pts/7".
2932 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
2934 If MUST_SUCCEED is true, then all errors are fatal. */
2936 struct terminal *
2937 init_tty (const char *name, const char *terminal_type, int must_succeed)
2939 char *area = NULL;
2940 char **address = &area;
2941 int buffer_size = 4096;
2942 int status;
2943 struct tty_display_info *tty = NULL;
2944 struct terminal *terminal = NULL;
2945 int ctty = 0; /* 1 if asked to open controlling tty. */
2947 if (!terminal_type)
2948 maybe_fatal (must_succeed, 0,
2949 "Unknown terminal type",
2950 "Unknown terminal type");
2952 if (name == NULL)
2953 name = DEV_TTY;
2954 if (!strcmp (name, DEV_TTY))
2955 ctty = 1;
2957 /* If we already have a terminal on the given device, use that. If
2958 all such terminals are suspended, create a new one instead. */
2959 /* XXX Perhaps this should be made explicit by having init_tty
2960 always create a new terminal and separating terminal and frame
2961 creation on Lisp level. */
2962 terminal = get_named_tty (name);
2963 if (terminal)
2964 return terminal;
2966 terminal = create_terminal ();
2967 #ifdef MSDOS
2968 if (been_here > 0)
2969 maybe_fatal (0, 0, "Attempt to create another terminal %s", "",
2970 name, "");
2971 been_here = 1;
2972 tty = &the_only_display_info;
2973 #else
2974 tty = xzalloc (sizeof *tty);
2975 #endif
2976 tty->top_frame = Qnil;
2977 tty->next = tty_list;
2978 tty_list = tty;
2980 terminal->type = output_termcap;
2981 terminal->display_info.tty = tty;
2982 tty->terminal = terminal;
2984 tty->Wcm = xmalloc (sizeof *tty->Wcm);
2985 Wcm_clear (tty);
2987 encode_terminal_src_size = 0;
2988 encode_terminal_dst_size = 0;
2991 #ifndef DOS_NT
2992 set_tty_hooks (terminal);
2995 /* Open the terminal device. */
2996 FILE *file;
2998 /* If !ctty, don't recognize it as our controlling terminal, and
2999 don't make it the controlling tty if we don't have one now.
3001 Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
3002 defined on Hurd. On other systems, we need to explicitly
3003 dissociate ourselves from the controlling tty when we want to
3004 open a frame on the same terminal. */
3005 int flags = O_RDWR | O_NOCTTY | (ctty ? 0 : O_IGNORE_CTTY);
3006 int fd = emacs_open (name, flags, 0);
3008 tty->name = xstrdup (name);
3009 terminal->name = xstrdup (name);
3011 if (fd < 0)
3012 maybe_fatal (must_succeed, terminal,
3013 "Could not open file: %s",
3014 "Could not open file: %s",
3015 name);
3016 if (!isatty (fd))
3018 close (fd);
3019 maybe_fatal (must_succeed, terminal,
3020 "Not a tty device: %s",
3021 "Not a tty device: %s",
3022 name);
3025 if (!O_IGNORE_CTTY && !ctty)
3026 dissociate_if_controlling_tty (fd);
3028 file = fdopen (fd, "w+");
3029 tty->input = file;
3030 tty->output = file;
3033 tty->type = xstrdup (terminal_type);
3035 add_keyboard_wait_descriptor (fileno (tty->input));
3037 Wcm_clear (tty);
3039 tty->termcap_term_buffer = xmalloc (buffer_size);
3041 /* On some systems, tgetent tries to access the controlling
3042 terminal. */
3043 block_tty_out_signal ();
3044 status = tgetent (tty->termcap_term_buffer, terminal_type);
3045 unblock_tty_out_signal ();
3047 if (status < 0)
3049 #ifdef TERMINFO
3050 maybe_fatal (must_succeed, terminal,
3051 "Cannot open terminfo database file",
3052 "Cannot open terminfo database file");
3053 #else
3054 maybe_fatal (must_succeed, terminal,
3055 "Cannot open termcap database file",
3056 "Cannot open termcap database file");
3057 #endif
3059 if (status == 0)
3061 maybe_fatal (must_succeed, terminal,
3062 "Terminal type %s is not defined",
3063 "Terminal type %s is not defined.\n\
3064 If that is not the actual type of terminal you have,\n\
3065 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3066 `setenv TERM ...') to specify the correct type. It may be necessary\n"
3067 #ifdef TERMINFO
3068 "to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3069 #else
3070 "to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3071 #endif
3072 terminal_type);
3075 #ifndef TERMINFO
3076 if (strlen (tty->termcap_term_buffer) >= buffer_size)
3077 emacs_abort ();
3078 buffer_size = strlen (tty->termcap_term_buffer);
3079 #endif
3080 tty->termcap_strings_buffer = area = xmalloc (buffer_size);
3081 tty->TS_ins_line = tgetstr ("al", address);
3082 tty->TS_ins_multi_lines = tgetstr ("AL", address);
3083 tty->TS_bell = tgetstr ("bl", address);
3084 BackTab (tty) = tgetstr ("bt", address);
3085 tty->TS_clr_to_bottom = tgetstr ("cd", address);
3086 tty->TS_clr_line = tgetstr ("ce", address);
3087 tty->TS_clr_frame = tgetstr ("cl", address);
3088 ColPosition (tty) = NULL; /* tgetstr ("ch", address); */
3089 AbsPosition (tty) = tgetstr ("cm", address);
3090 CR (tty) = tgetstr ("cr", address);
3091 tty->TS_set_scroll_region = tgetstr ("cs", address);
3092 tty->TS_set_scroll_region_1 = tgetstr ("cS", address);
3093 RowPosition (tty) = tgetstr ("cv", address);
3094 tty->TS_del_char = tgetstr ("dc", address);
3095 tty->TS_del_multi_chars = tgetstr ("DC", address);
3096 tty->TS_del_line = tgetstr ("dl", address);
3097 tty->TS_del_multi_lines = tgetstr ("DL", address);
3098 tty->TS_delete_mode = tgetstr ("dm", address);
3099 tty->TS_end_delete_mode = tgetstr ("ed", address);
3100 tty->TS_end_insert_mode = tgetstr ("ei", address);
3101 Home (tty) = tgetstr ("ho", address);
3102 tty->TS_ins_char = tgetstr ("ic", address);
3103 tty->TS_ins_multi_chars = tgetstr ("IC", address);
3104 tty->TS_insert_mode = tgetstr ("im", address);
3105 tty->TS_pad_inserted_char = tgetstr ("ip", address);
3106 tty->TS_end_keypad_mode = tgetstr ("ke", address);
3107 tty->TS_keypad_mode = tgetstr ("ks", address);
3108 LastLine (tty) = tgetstr ("ll", address);
3109 Right (tty) = tgetstr ("nd", address);
3110 Down (tty) = tgetstr ("do", address);
3111 if (!Down (tty))
3112 Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do" */
3113 if (tgetflag ("bs"))
3114 Left (tty) = "\b"; /* can't possibly be longer! */
3115 else /* (Actually, "bs" is obsolete...) */
3116 Left (tty) = tgetstr ("le", address);
3117 if (!Left (tty))
3118 Left (tty) = tgetstr ("bc", address); /* Obsolete name for "le" */
3119 tty->TS_pad_char = tgetstr ("pc", address);
3120 tty->TS_repeat = tgetstr ("rp", address);
3121 tty->TS_end_standout_mode = tgetstr ("se", address);
3122 tty->TS_fwd_scroll = tgetstr ("sf", address);
3123 tty->TS_standout_mode = tgetstr ("so", address);
3124 tty->TS_rev_scroll = tgetstr ("sr", address);
3125 tty->Wcm->cm_tab = tgetstr ("ta", address);
3126 tty->TS_end_termcap_modes = tgetstr ("te", address);
3127 tty->TS_termcap_modes = tgetstr ("ti", address);
3128 Up (tty) = tgetstr ("up", address);
3129 tty->TS_visible_bell = tgetstr ("vb", address);
3130 tty->TS_cursor_normal = tgetstr ("ve", address);
3131 tty->TS_cursor_visible = tgetstr ("vs", address);
3132 tty->TS_cursor_invisible = tgetstr ("vi", address);
3133 tty->TS_set_window = tgetstr ("wi", address);
3135 tty->TS_enter_underline_mode = tgetstr ("us", address);
3136 tty->TS_exit_underline_mode = tgetstr ("ue", address);
3137 tty->TS_enter_bold_mode = tgetstr ("md", address);
3138 tty->TS_enter_italic_mode = tgetstr ("ZH", address);
3139 tty->TS_enter_dim_mode = tgetstr ("mh", address);
3140 tty->TS_enter_reverse_mode = tgetstr ("mr", address);
3141 tty->TS_enter_alt_charset_mode = tgetstr ("as", address);
3142 tty->TS_exit_alt_charset_mode = tgetstr ("ae", address);
3143 tty->TS_exit_attribute_mode = tgetstr ("me", address);
3145 MultiUp (tty) = tgetstr ("UP", address);
3146 MultiDown (tty) = tgetstr ("DO", address);
3147 MultiLeft (tty) = tgetstr ("LE", address);
3148 MultiRight (tty) = tgetstr ("RI", address);
3150 /* SVr4/ANSI color support. If "op" isn't available, don't support
3151 color because we can't switch back to the default foreground and
3152 background. */
3153 tty->TS_orig_pair = tgetstr ("op", address);
3154 if (tty->TS_orig_pair)
3156 tty->TS_set_foreground = tgetstr ("AF", address);
3157 tty->TS_set_background = tgetstr ("AB", address);
3158 if (!tty->TS_set_foreground)
3160 /* SVr4. */
3161 tty->TS_set_foreground = tgetstr ("Sf", address);
3162 tty->TS_set_background = tgetstr ("Sb", address);
3165 tty->TN_max_colors = tgetnum ("Co");
3166 tty->TN_max_pairs = tgetnum ("pa");
3168 tty->TN_no_color_video = tgetnum ("NC");
3169 if (tty->TN_no_color_video == -1)
3170 tty->TN_no_color_video = 0;
3173 tty_default_color_capabilities (tty, 1);
3175 MagicWrap (tty) = tgetflag ("xn");
3176 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
3177 the former flag imply the latter. */
3178 AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
3179 terminal->memory_below_frame = tgetflag ("db");
3180 tty->TF_hazeltine = tgetflag ("hz");
3181 terminal->must_write_spaces = tgetflag ("in");
3182 tty->meta_key = tgetflag ("km") || tgetflag ("MT");
3183 tty->TF_insmode_motion = tgetflag ("mi");
3184 tty->TF_standout_motion = tgetflag ("ms");
3185 tty->TF_underscore = tgetflag ("ul");
3186 tty->TF_teleray = tgetflag ("xt");
3188 #else /* DOS_NT */
3189 #ifdef WINDOWSNT
3191 struct frame *f = XFRAME (selected_frame);
3193 initialize_w32_display (terminal);
3195 FrameRows (tty) = FRAME_LINES (f);
3196 FrameCols (tty) = FRAME_COLS (f);
3197 tty->specified_window = FRAME_LINES (f);
3199 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
3200 terminal->char_ins_del_ok = 1;
3201 baud_rate = 19200;
3203 #else /* MSDOS */
3205 int height, width;
3206 if (strcmp (terminal_type, "internal") == 0)
3207 terminal->type = output_msdos_raw;
3208 initialize_msdos_display (terminal);
3210 get_tty_size (fileno (tty->input), &width, &height);
3211 FrameCols (tty) = width;
3212 FrameRows (tty) = height;
3213 terminal->char_ins_del_ok = 0;
3214 init_baud_rate (fileno (tty->input));
3216 #endif /* MSDOS */
3217 tty->output = stdout;
3218 tty->input = stdin;
3219 /* The following two are inaccessible from w32console.c. */
3220 terminal->delete_frame_hook = &tty_free_frame_resources;
3221 terminal->delete_terminal_hook = &delete_tty;
3223 tty->name = xstrdup (name);
3224 terminal->name = xstrdup (name);
3225 tty->type = xstrdup (terminal_type);
3227 add_keyboard_wait_descriptor (0);
3229 tty->delete_in_insert_mode = 1;
3231 UseTabs (tty) = 0;
3232 terminal->scroll_region_ok = 0;
3234 /* Seems to insert lines when it's not supposed to, messing up the
3235 display. In doing a trace, it didn't seem to be called much, so I
3236 don't think we're losing anything by turning it off. */
3237 terminal->line_ins_del_ok = 0;
3239 tty->TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
3240 #endif /* DOS_NT */
3242 #ifdef HAVE_GPM
3243 terminal->mouse_position_hook = term_mouse_position;
3244 tty->mouse_highlight.mouse_face_window = Qnil;
3245 #endif
3247 terminal->kboard = xmalloc (sizeof *terminal->kboard);
3248 init_kboard (terminal->kboard);
3249 kset_window_system (terminal->kboard, Qnil);
3250 terminal->kboard->next_kboard = all_kboards;
3251 all_kboards = terminal->kboard;
3252 terminal->kboard->reference_count++;
3253 /* Don't let the initial kboard remain current longer than necessary.
3254 That would cause problems if a file loaded on startup tries to
3255 prompt in the mini-buffer. */
3256 if (current_kboard == initial_kboard)
3257 current_kboard = terminal->kboard;
3258 #ifndef DOS_NT
3259 term_get_fkeys (address, terminal->kboard);
3261 /* Get frame size from system, or else from termcap. */
3263 int height, width;
3264 get_tty_size (fileno (tty->input), &width, &height);
3265 FrameCols (tty) = width;
3266 FrameRows (tty) = height;
3269 if (FrameCols (tty) <= 0)
3270 FrameCols (tty) = tgetnum ("co");
3271 if (FrameRows (tty) <= 0)
3272 FrameRows (tty) = tgetnum ("li");
3274 if (FrameRows (tty) < 3 || FrameCols (tty) < 3)
3275 maybe_fatal (must_succeed, terminal,
3276 "Screen size %dx%d is too small",
3277 "Screen size %dx%d is too small",
3278 FrameCols (tty), FrameRows (tty));
3280 TabWidth (tty) = tgetnum ("tw");
3282 if (!tty->TS_bell)
3283 tty->TS_bell = "\07";
3285 if (!tty->TS_fwd_scroll)
3286 tty->TS_fwd_scroll = Down (tty);
3288 PC = tty->TS_pad_char ? *tty->TS_pad_char : 0;
3290 if (TabWidth (tty) < 0)
3291 TabWidth (tty) = 8;
3293 /* Turned off since /etc/termcap seems to have :ta= for most terminals
3294 and newer termcap doc does not seem to say there is a default.
3295 if (!tty->Wcm->cm_tab)
3296 tty->Wcm->cm_tab = "\t";
3299 /* We don't support standout modes that use `magic cookies', so
3300 turn off any that do. */
3301 if (tty->TS_standout_mode && tgetnum ("sg") >= 0)
3303 tty->TS_standout_mode = 0;
3304 tty->TS_end_standout_mode = 0;
3306 if (tty->TS_enter_underline_mode && tgetnum ("ug") >= 0)
3308 tty->TS_enter_underline_mode = 0;
3309 tty->TS_exit_underline_mode = 0;
3312 /* If there's no standout mode, try to use underlining instead. */
3313 if (tty->TS_standout_mode == 0)
3315 tty->TS_standout_mode = tty->TS_enter_underline_mode;
3316 tty->TS_end_standout_mode = tty->TS_exit_underline_mode;
3319 /* If no `se' string, try using a `me' string instead.
3320 If that fails, we can't use standout mode at all. */
3321 if (tty->TS_end_standout_mode == 0)
3323 char *s = tgetstr ("me", address);
3324 if (s != 0)
3325 tty->TS_end_standout_mode = s;
3326 else
3327 tty->TS_standout_mode = 0;
3330 if (tty->TF_teleray)
3332 tty->Wcm->cm_tab = 0;
3333 /* We can't support standout mode, because it uses magic cookies. */
3334 tty->TS_standout_mode = 0;
3335 /* But that means we cannot rely on ^M to go to column zero! */
3336 CR (tty) = 0;
3337 /* LF can't be trusted either -- can alter hpos */
3338 /* if move at column 0 thru a line with TS_standout_mode */
3339 Down (tty) = 0;
3342 tty->specified_window = FrameRows (tty);
3344 if (Wcm_init (tty) == -1) /* can't do cursor motion */
3346 maybe_fatal (must_succeed, terminal,
3347 "Terminal type \"%s\" is not powerful enough to run Emacs",
3348 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3349 It lacks the ability to position the cursor.\n\
3350 If that is not the actual type of terminal you have,\n\
3351 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3352 `setenv TERM ...') to specify the correct type. It may be necessary\n"
3353 # ifdef TERMINFO
3354 "to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3355 # else /* TERMCAP */
3356 "to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3357 # endif /* TERMINFO */
3358 terminal_type);
3361 if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
3362 maybe_fatal (must_succeed, terminal,
3363 "Could not determine the frame size",
3364 "Could not determine the frame size");
3366 tty->delete_in_insert_mode
3367 = tty->TS_delete_mode && tty->TS_insert_mode
3368 && !strcmp (tty->TS_delete_mode, tty->TS_insert_mode);
3370 UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8;
3372 terminal->scroll_region_ok
3373 = (tty->Wcm->cm_abs
3374 && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
3376 terminal->line_ins_del_ok
3377 = (((tty->TS_ins_line || tty->TS_ins_multi_lines)
3378 && (tty->TS_del_line || tty->TS_del_multi_lines))
3379 || (terminal->scroll_region_ok
3380 && tty->TS_fwd_scroll && tty->TS_rev_scroll));
3382 terminal->char_ins_del_ok
3383 = ((tty->TS_ins_char || tty->TS_insert_mode
3384 || tty->TS_pad_inserted_char || tty->TS_ins_multi_chars)
3385 && (tty->TS_del_char || tty->TS_del_multi_chars));
3387 terminal->fast_clear_end_of_line = tty->TS_clr_line != 0;
3389 init_baud_rate (fileno (tty->input));
3391 #endif /* not DOS_NT */
3393 /* Init system terminal modes (RAW or CBREAK, etc.). */
3394 init_sys_modes (tty);
3396 return terminal;
3400 static void
3401 vfatal (const char *str, va_list ap)
3403 fprintf (stderr, "emacs: ");
3404 vfprintf (stderr, str, ap);
3405 if (!(strlen (str) > 0 && str[strlen (str) - 1] == '\n'))
3406 fprintf (stderr, "\n");
3407 fflush (stderr);
3408 exit (1);
3412 /* Auxiliary error-handling function for init_tty.
3413 Delete TERMINAL, then call error or fatal with str1 or str2,
3414 respectively, according to whether MUST_SUCCEED is zero or not. */
3416 static void
3417 maybe_fatal (int must_succeed, struct terminal *terminal,
3418 const char *str1, const char *str2, ...)
3420 va_list ap;
3421 va_start (ap, str2);
3422 if (terminal)
3423 delete_tty (terminal);
3425 if (must_succeed)
3426 vfatal (str2, ap);
3427 else
3428 verror (str1, ap);
3430 va_end (ap);
3431 emacs_abort ();
3434 void
3435 fatal (const char *str, ...)
3437 va_list ap;
3438 va_start (ap, str);
3439 vfatal (str, ap);
3440 va_end (ap);
3445 /* Delete the given tty terminal, closing all frames on it. */
3447 static void
3448 delete_tty (struct terminal *terminal)
3450 struct tty_display_info *tty;
3452 /* Protect against recursive calls. delete_frame in
3453 delete_terminal calls us back when it deletes our last frame. */
3454 if (!terminal->name)
3455 return;
3457 if (terminal->type != output_termcap)
3458 emacs_abort ();
3460 tty = terminal->display_info.tty;
3462 if (tty == tty_list)
3463 tty_list = tty->next;
3464 else
3466 struct tty_display_info *p;
3467 for (p = tty_list; p && p->next != tty; p = p->next)
3470 if (! p)
3471 /* This should not happen. */
3472 emacs_abort ();
3474 p->next = tty->next;
3475 tty->next = 0;
3478 /* reset_sys_modes needs a valid device, so this call needs to be
3479 before delete_terminal. */
3480 reset_sys_modes (tty);
3482 delete_terminal (terminal);
3484 xfree (tty->name);
3485 xfree (tty->type);
3487 if (tty->input)
3489 delete_keyboard_wait_descriptor (fileno (tty->input));
3490 if (tty->input != stdin)
3491 fclose (tty->input);
3493 if (tty->output && tty->output != stdout && tty->output != tty->input)
3494 fclose (tty->output);
3495 if (tty->termscript)
3496 fclose (tty->termscript);
3498 xfree (tty->old_tty);
3499 xfree (tty->Wcm);
3500 xfree (tty->termcap_strings_buffer);
3501 xfree (tty->termcap_term_buffer);
3503 xfree (tty);
3506 void
3507 syms_of_term (void)
3509 DEFVAR_BOOL ("system-uses-terminfo", system_uses_terminfo,
3510 doc: /* Non-nil means the system uses terminfo rather than termcap.
3511 This variable can be used by terminal emulator packages. */);
3512 #ifdef TERMINFO
3513 system_uses_terminfo = 1;
3514 #else
3515 system_uses_terminfo = 0;
3516 #endif
3518 DEFVAR_LISP ("suspend-tty-functions", Vsuspend_tty_functions,
3519 doc: /* Functions run after suspending a tty.
3520 The functions are run with one argument, the terminal object to be suspended.
3521 See `suspend-tty'. */);
3522 Vsuspend_tty_functions = Qnil;
3525 DEFVAR_LISP ("resume-tty-functions", Vresume_tty_functions,
3526 doc: /* Functions run after resuming a tty.
3527 The functions are run with one argument, the terminal object that was revived.
3528 See `resume-tty'. */);
3529 Vresume_tty_functions = Qnil;
3531 DEFVAR_BOOL ("visible-cursor", visible_cursor,
3532 doc: /* Non-nil means to make the cursor very visible.
3533 This only has an effect when running in a text terminal.
3534 What means \"very visible\" is up to your terminal. It may make the cursor
3535 bigger, or it may make it blink, or it may do nothing at all. */);
3536 visible_cursor = 1;
3538 defsubr (&Stty_display_color_p);
3539 defsubr (&Stty_display_color_cells);
3540 defsubr (&Stty_no_underline);
3541 defsubr (&Stty_type);
3542 defsubr (&Scontrolling_tty_p);
3543 defsubr (&Stty_top_frame);
3544 defsubr (&Ssuspend_tty);
3545 defsubr (&Sresume_tty);
3546 #ifdef HAVE_GPM
3547 defsubr (&Sgpm_mouse_start);
3548 defsubr (&Sgpm_mouse_stop);
3549 #endif /* HAVE_GPM */
3551 #ifndef DOS_NT
3552 default_orig_pair = NULL;
3553 default_set_foreground = NULL;
3554 default_set_background = NULL;
3555 #endif /* !DOS_NT */
3557 encode_terminal_src = NULL;
3558 encode_terminal_dst = NULL;