* src/term.c (init_tty) [HAVE_GPM]: Move mouse settings after set_tty_hooks.
[emacs.git] / src / term.c
blob8672a2417c81e12b2401ece2ef24d8388c2cd053
1 /* Terminal control module for terminals described by TERMCAP
2 Copyright (C) 1985-1987, 1993-1995, 1998, 2000-2011
3 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20 /* New redisplay, TTY faces by Gerd Moellmann <gerd@gnu.org>. */
22 #include <config.h>
23 #include <stdio.h>
24 #include <ctype.h>
25 #include <errno.h>
26 #include <sys/file.h>
27 #include <unistd.h>
28 #include <signal.h>
29 #include <setjmp.h>
31 #include "lisp.h"
32 #include "termchar.h"
33 #include "termopts.h"
34 #include "tparam.h"
35 #include "buffer.h"
36 #include "character.h"
37 #include "charset.h"
38 #include "coding.h"
39 #include "composite.h"
40 #include "keyboard.h"
41 #include "frame.h"
42 #include "disptab.h"
43 #include "termhooks.h"
44 #include "dispextern.h"
45 #include "window.h"
46 #include "keymap.h"
47 #include "blockinput.h"
48 #include "syssignal.h"
49 #include "systty.h"
50 #include "intervals.h"
51 #ifdef MSDOS
52 #include "msdos.h"
53 static int been_here = -1;
54 #endif
56 #include "cm.h"
57 #ifdef HAVE_X_WINDOWS
58 #include "xterm.h"
59 #endif
61 #ifndef O_RDWR
62 #define O_RDWR 2
63 #endif
65 #ifndef O_NOCTTY
66 #define O_NOCTTY 0
67 #endif
69 /* The name of the default console device. */
70 #ifdef WINDOWSNT
71 #define DEV_TTY "CONOUT$"
72 #else
73 #define DEV_TTY "/dev/tty"
74 #endif
76 static void tty_set_scroll_region (struct frame *f, int start, int stop);
77 static void turn_on_face (struct frame *, int face_id);
78 static void turn_off_face (struct frame *, int face_id);
79 static void tty_turn_off_highlight (struct tty_display_info *);
80 static void tty_show_cursor (struct tty_display_info *);
81 static void tty_hide_cursor (struct tty_display_info *);
82 static void tty_background_highlight (struct tty_display_info *tty);
83 static struct terminal *get_tty_terminal (Lisp_Object, int);
84 static void clear_tty_hooks (struct terminal *terminal);
85 static void set_tty_hooks (struct terminal *terminal);
86 static void dissociate_if_controlling_tty (int fd);
87 static void delete_tty (struct terminal *);
88 static void maybe_fatal (int must_succeed, struct terminal *terminal,
89 const char *str1, const char *str2, ...)
90 NO_RETURN ATTRIBUTE_FORMAT_PRINTF (3, 5) ATTRIBUTE_FORMAT_PRINTF (4, 5);
91 static void vfatal (const char *str, va_list ap)
92 NO_RETURN ATTRIBUTE_FORMAT_PRINTF (1, 0);
95 #define OUTPUT(tty, a) \
96 emacs_tputs ((tty), a, \
97 (int) (FRAME_LINES (XFRAME (selected_frame)) \
98 - curY (tty)), \
99 cmputc)
101 #define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
102 #define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
104 #define OUTPUT_IF(tty, a) \
105 do { \
106 if (a) \
107 OUTPUT (tty, a); \
108 } while (0)
110 #define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
112 /* Display space properties */
114 /* Chain of all tty device parameters. */
115 struct tty_display_info *tty_list;
117 /* Meaning of bits in no_color_video. Each bit set means that the
118 corresponding attribute cannot be combined with colors. */
120 enum no_color_bit
122 NC_STANDOUT = 1 << 0,
123 NC_UNDERLINE = 1 << 1,
124 NC_REVERSE = 1 << 2,
125 NC_BLINK = 1 << 3,
126 NC_DIM = 1 << 4,
127 NC_BOLD = 1 << 5,
128 NC_INVIS = 1 << 6,
129 NC_PROTECT = 1 << 7,
130 NC_ALT_CHARSET = 1 << 8
133 /* internal state */
135 /* The largest frame width in any call to calculate_costs. */
137 static int max_frame_cols;
139 /* Non-zero if we have dropped our controlling tty and therefore
140 should not open a frame on stdout. */
141 static int no_controlling_tty;
145 #ifdef HAVE_GPM
146 #include <sys/fcntl.h>
148 /* The device for which we have enabled gpm support (or NULL). */
149 struct tty_display_info *gpm_tty = NULL;
151 /* Last recorded mouse coordinates. */
152 static int last_mouse_x, last_mouse_y;
153 #endif /* HAVE_GPM */
155 /* Ring the bell on a tty. */
157 static void
158 tty_ring_bell (struct frame *f)
160 struct tty_display_info *tty = FRAME_TTY (f);
162 if (tty->output)
164 OUTPUT (tty, (tty->TS_visible_bell && visible_bell
165 ? tty->TS_visible_bell
166 : tty->TS_bell));
167 fflush (tty->output);
171 /* Set up termcap modes for Emacs. */
173 static void
174 tty_set_terminal_modes (struct terminal *terminal)
176 struct tty_display_info *tty = terminal->display_info.tty;
178 if (tty->output)
180 if (tty->TS_termcap_modes)
181 OUTPUT (tty, tty->TS_termcap_modes);
182 else
184 /* Output enough newlines to scroll all the old screen contents
185 off the screen, so it won't be overwritten and lost. */
186 int i;
187 current_tty = tty;
188 for (i = 0; i < FRAME_LINES (XFRAME (selected_frame)); i++)
189 cmputc ('\n');
192 OUTPUT_IF (tty, visible_cursor ? tty->TS_cursor_visible : tty->TS_cursor_normal);
193 OUTPUT_IF (tty, tty->TS_keypad_mode);
194 losecursor (tty);
195 fflush (tty->output);
199 /* Reset termcap modes before exiting Emacs. */
201 static void
202 tty_reset_terminal_modes (struct terminal *terminal)
204 struct tty_display_info *tty = terminal->display_info.tty;
206 if (tty->output)
208 tty_turn_off_highlight (tty);
209 tty_turn_off_insert (tty);
210 OUTPUT_IF (tty, tty->TS_end_keypad_mode);
211 OUTPUT_IF (tty, tty->TS_cursor_normal);
212 OUTPUT_IF (tty, tty->TS_end_termcap_modes);
213 OUTPUT_IF (tty, tty->TS_orig_pair);
214 /* Output raw CR so kernel can track the cursor hpos. */
215 current_tty = tty;
216 cmputc ('\r');
217 fflush (tty->output);
221 /* Flag the end of a display update on a termcap terminal. */
223 static void
224 tty_update_end (struct frame *f)
226 struct tty_display_info *tty = FRAME_TTY (f);
228 if (!XWINDOW (selected_window)->cursor_off_p)
229 tty_show_cursor (tty);
230 tty_turn_off_insert (tty);
231 tty_background_highlight (tty);
234 /* The implementation of set_terminal_window for termcap frames. */
236 static void
237 tty_set_terminal_window (struct frame *f, int size)
239 struct tty_display_info *tty = FRAME_TTY (f);
241 tty->specified_window = size ? size : FRAME_LINES (f);
242 if (FRAME_SCROLL_REGION_OK (f))
243 tty_set_scroll_region (f, 0, tty->specified_window);
246 static void
247 tty_set_scroll_region (struct frame *f, int start, int stop)
249 char *buf;
250 struct tty_display_info *tty = FRAME_TTY (f);
252 if (tty->TS_set_scroll_region)
253 buf = tparam (tty->TS_set_scroll_region, 0, 0, start, stop - 1, 0, 0);
254 else if (tty->TS_set_scroll_region_1)
255 buf = tparam (tty->TS_set_scroll_region_1, 0, 0,
256 FRAME_LINES (f), start,
257 FRAME_LINES (f) - stop,
258 FRAME_LINES (f));
259 else
260 buf = tparam (tty->TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (f));
262 OUTPUT (tty, buf);
263 xfree (buf);
264 losecursor (tty);
268 static void
269 tty_turn_on_insert (struct tty_display_info *tty)
271 if (!tty->insert_mode)
272 OUTPUT (tty, tty->TS_insert_mode);
273 tty->insert_mode = 1;
276 void
277 tty_turn_off_insert (struct tty_display_info *tty)
279 if (tty->insert_mode)
280 OUTPUT (tty, tty->TS_end_insert_mode);
281 tty->insert_mode = 0;
284 /* Handle highlighting. */
286 static void
287 tty_turn_off_highlight (struct tty_display_info *tty)
289 if (tty->standout_mode)
290 OUTPUT_IF (tty, tty->TS_end_standout_mode);
291 tty->standout_mode = 0;
294 static void
295 tty_turn_on_highlight (struct tty_display_info *tty)
297 if (!tty->standout_mode)
298 OUTPUT_IF (tty, tty->TS_standout_mode);
299 tty->standout_mode = 1;
302 static void
303 tty_toggle_highlight (struct tty_display_info *tty)
305 if (tty->standout_mode)
306 tty_turn_off_highlight (tty);
307 else
308 tty_turn_on_highlight (tty);
312 /* Make cursor invisible. */
314 static void
315 tty_hide_cursor (struct tty_display_info *tty)
317 if (tty->cursor_hidden == 0)
319 tty->cursor_hidden = 1;
320 OUTPUT_IF (tty, tty->TS_cursor_invisible);
325 /* Ensure that cursor is visible. */
327 static void
328 tty_show_cursor (struct tty_display_info *tty)
330 if (tty->cursor_hidden)
332 tty->cursor_hidden = 0;
333 OUTPUT_IF (tty, tty->TS_cursor_normal);
334 if (visible_cursor)
335 OUTPUT_IF (tty, tty->TS_cursor_visible);
340 /* Set standout mode to the state it should be in for
341 empty space inside windows. What this is,
342 depends on the user option inverse-video. */
344 static void
345 tty_background_highlight (struct tty_display_info *tty)
347 if (inverse_video)
348 tty_turn_on_highlight (tty);
349 else
350 tty_turn_off_highlight (tty);
353 /* Set standout mode to the mode specified for the text to be output. */
355 static void
356 tty_highlight_if_desired (struct tty_display_info *tty)
358 if (inverse_video)
359 tty_turn_on_highlight (tty);
360 else
361 tty_turn_off_highlight (tty);
365 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
366 frame-relative coordinates. */
368 static void
369 tty_cursor_to (struct frame *f, int vpos, int hpos)
371 struct tty_display_info *tty = FRAME_TTY (f);
373 /* Detect the case where we are called from reset_sys_modes
374 and the costs have never been calculated. Do nothing. */
375 if (! tty->costs_set)
376 return;
378 if (curY (tty) == vpos
379 && curX (tty) == hpos)
380 return;
381 if (!tty->TF_standout_motion)
382 tty_background_highlight (tty);
383 if (!tty->TF_insmode_motion)
384 tty_turn_off_insert (tty);
385 cmgoto (tty, vpos, hpos);
388 /* Similar but don't take any account of the wasted characters. */
390 static void
391 tty_raw_cursor_to (struct frame *f, int row, int col)
393 struct tty_display_info *tty = FRAME_TTY (f);
395 if (curY (tty) == row
396 && curX (tty) == col)
397 return;
398 if (!tty->TF_standout_motion)
399 tty_background_highlight (tty);
400 if (!tty->TF_insmode_motion)
401 tty_turn_off_insert (tty);
402 cmgoto (tty, row, col);
405 /* Erase operations */
407 /* Clear from cursor to end of frame on a termcap device. */
409 static void
410 tty_clear_to_end (struct frame *f)
412 register int i;
413 struct tty_display_info *tty = FRAME_TTY (f);
415 if (tty->TS_clr_to_bottom)
417 tty_background_highlight (tty);
418 OUTPUT (tty, tty->TS_clr_to_bottom);
420 else
422 for (i = curY (tty); i < FRAME_LINES (f); i++)
424 cursor_to (f, i, 0);
425 clear_end_of_line (f, FRAME_COLS (f));
430 /* Clear an entire termcap frame. */
432 static void
433 tty_clear_frame (struct frame *f)
435 struct tty_display_info *tty = FRAME_TTY (f);
437 if (tty->TS_clr_frame)
439 tty_background_highlight (tty);
440 OUTPUT (tty, tty->TS_clr_frame);
441 cmat (tty, 0, 0);
443 else
445 cursor_to (f, 0, 0);
446 clear_to_end (f);
450 /* An implementation of clear_end_of_line for termcap frames.
452 Note that the cursor may be moved, on terminals lacking a `ce' string. */
454 static void
455 tty_clear_end_of_line (struct frame *f, int first_unused_hpos)
457 register int i;
458 struct tty_display_info *tty = FRAME_TTY (f);
460 /* Detect the case where we are called from reset_sys_modes
461 and the costs have never been calculated. Do nothing. */
462 if (! tty->costs_set)
463 return;
465 if (curX (tty) >= first_unused_hpos)
466 return;
467 tty_background_highlight (tty);
468 if (tty->TS_clr_line)
470 OUTPUT1 (tty, tty->TS_clr_line);
472 else
473 { /* have to do it the hard way */
474 tty_turn_off_insert (tty);
476 /* Do not write in last row last col with Auto-wrap on. */
477 if (AutoWrap (tty)
478 && curY (tty) == FrameRows (tty) - 1
479 && first_unused_hpos == FrameCols (tty))
480 first_unused_hpos--;
482 for (i = curX (tty); i < first_unused_hpos; i++)
484 if (tty->termscript)
485 fputc (' ', tty->termscript);
486 fputc (' ', tty->output);
488 cmplus (tty, first_unused_hpos - curX (tty));
492 /* Buffers to store the source and result of code conversion for terminal. */
493 static unsigned char *encode_terminal_src;
494 static unsigned char *encode_terminal_dst;
495 /* Allocated sizes of the above buffers. */
496 static ptrdiff_t encode_terminal_src_size;
497 static ptrdiff_t encode_terminal_dst_size;
499 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes.
500 Set CODING->produced to the byte-length of the resulting byte
501 sequence, and return a pointer to that byte sequence. */
503 unsigned char *
504 encode_terminal_code (struct glyph *src, int src_len, struct coding_system *coding)
506 struct glyph *src_end = src + src_len;
507 unsigned char *buf;
508 ptrdiff_t nchars, nbytes, required;
509 ptrdiff_t tlen = GLYPH_TABLE_LENGTH;
510 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
511 Lisp_Object charset_list;
513 /* Allocate sufficient size of buffer to store all characters in
514 multibyte-form. But, it may be enlarged on demand if
515 Vglyph_table contains a string or a composite glyph is
516 encountered. */
517 if (min (PTRDIFF_MAX, SIZE_MAX) / MAX_MULTIBYTE_LENGTH < src_len)
518 memory_full (SIZE_MAX);
519 required = src_len;
520 required *= MAX_MULTIBYTE_LENGTH;
521 if (encode_terminal_src_size < required)
523 encode_terminal_src = xrealloc (encode_terminal_src, required);
524 encode_terminal_src_size = required;
527 charset_list = coding_charset_list (coding);
529 buf = encode_terminal_src;
530 nchars = 0;
531 while (src < src_end)
533 if (src->type == COMPOSITE_GLYPH)
535 struct composition *cmp IF_LINT (= NULL);
536 Lisp_Object gstring IF_LINT (= Qnil);
537 int i;
539 nbytes = buf - encode_terminal_src;
540 if (src->u.cmp.automatic)
542 gstring = composition_gstring_from_id (src->u.cmp.id);
543 required = src->slice.cmp.to - src->slice.cmp.from + 1;
545 else
547 cmp = composition_table[src->u.cmp.id];
548 required = cmp->glyph_len;
549 required *= MAX_MULTIBYTE_LENGTH;
552 if (encode_terminal_src_size - nbytes < required)
554 encode_terminal_src =
555 xpalloc (encode_terminal_src, &encode_terminal_src_size,
556 required - (encode_terminal_src_size - nbytes),
557 -1, 1);
558 buf = encode_terminal_src + nbytes;
561 if (src->u.cmp.automatic)
562 for (i = src->slice.cmp.from; i <= src->slice.cmp.to; i++)
564 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
565 int c = LGLYPH_CHAR (g);
567 if (! char_charset (c, charset_list, NULL))
568 c = '?';
569 buf += CHAR_STRING (c, buf);
570 nchars++;
572 else
573 for (i = 0; i < cmp->glyph_len; i++)
575 int c = COMPOSITION_GLYPH (cmp, i);
577 if (c == '\t')
578 continue;
579 if (char_charset (c, charset_list, NULL))
581 if (CHAR_WIDTH (c) == 0
582 && i > 0 && COMPOSITION_GLYPH (cmp, i - 1) == '\t')
583 /* Should be left-padded */
585 buf += CHAR_STRING (' ', buf);
586 nchars++;
589 else
590 c = '?';
591 buf += CHAR_STRING (c, buf);
592 nchars++;
595 /* We must skip glyphs to be padded for a wide character. */
596 else if (! CHAR_GLYPH_PADDING_P (*src))
598 GLYPH g;
599 int c IF_LINT (= 0);
600 Lisp_Object string;
602 string = Qnil;
603 SET_GLYPH_FROM_CHAR_GLYPH (g, src[0]);
605 if (GLYPH_INVALID_P (g) || GLYPH_SIMPLE_P (tbase, tlen, g))
607 /* This glyph doesn't have an entry in Vglyph_table. */
608 c = src->u.ch;
610 else
612 /* This glyph has an entry in Vglyph_table,
613 so process any alias before testing for simpleness. */
614 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
616 if (GLYPH_SIMPLE_P (tbase, tlen, g))
617 /* We set the multi-byte form of a character in G
618 (that should be an ASCII character) at WORKBUF. */
619 c = GLYPH_CHAR (g);
620 else
621 /* We have a string in Vglyph_table. */
622 string = tbase[GLYPH_CHAR (g)];
625 if (NILP (string))
627 nbytes = buf - encode_terminal_src;
628 if (encode_terminal_src_size - nbytes < MAX_MULTIBYTE_LENGTH)
630 encode_terminal_src =
631 xpalloc (encode_terminal_src, &encode_terminal_src_size,
632 MAX_MULTIBYTE_LENGTH, -1, 1);
633 buf = encode_terminal_src + nbytes;
635 if (CHAR_BYTE8_P (c)
636 || char_charset (c, charset_list, NULL))
638 /* Store the multibyte form of C at BUF. */
639 buf += CHAR_STRING (c, buf);
640 nchars++;
642 else
644 /* C is not encodable. */
645 *buf++ = '?';
646 nchars++;
647 while (src + 1 < src_end && CHAR_GLYPH_PADDING_P (src[1]))
649 *buf++ = '?';
650 nchars++;
651 src++;
655 else
657 if (! STRING_MULTIBYTE (string))
658 string = string_to_multibyte (string);
659 nbytes = buf - encode_terminal_src;
660 if (encode_terminal_src_size - nbytes < SBYTES (string))
662 encode_terminal_src =
663 xpalloc (encode_terminal_src, &encode_terminal_src_size,
664 (SBYTES (string)
665 - (encode_terminal_src_size - nbytes)),
666 -1, 1);
667 buf = encode_terminal_src + nbytes;
669 memcpy (buf, SDATA (string), SBYTES (string));
670 buf += SBYTES (string);
671 nchars += SCHARS (string);
674 src++;
677 if (nchars == 0)
679 coding->produced = 0;
680 return NULL;
683 nbytes = buf - encode_terminal_src;
684 coding->source = encode_terminal_src;
685 if (encode_terminal_dst_size == 0)
687 encode_terminal_dst = xrealloc (encode_terminal_dst,
688 encode_terminal_src_size);
689 encode_terminal_dst_size = encode_terminal_src_size;
691 coding->destination = encode_terminal_dst;
692 coding->dst_bytes = encode_terminal_dst_size;
693 encode_coding_object (coding, Qnil, 0, 0, nchars, nbytes, Qnil);
694 /* coding->destination may have been reallocated. */
695 encode_terminal_dst = coding->destination;
696 encode_terminal_dst_size = coding->dst_bytes;
698 return (encode_terminal_dst);
703 /* An implementation of write_glyphs for termcap frames. */
705 static void
706 tty_write_glyphs (struct frame *f, struct glyph *string, int len)
708 unsigned char *conversion_buffer;
709 struct coding_system *coding;
710 size_t n, stringlen;
712 struct tty_display_info *tty = FRAME_TTY (f);
714 tty_turn_off_insert (tty);
715 tty_hide_cursor (tty);
717 /* Don't dare write in last column of bottom line, if Auto-Wrap,
718 since that would scroll the whole frame on some terminals. */
720 if (AutoWrap (tty)
721 && curY (tty) + 1 == FRAME_LINES (f)
722 && (curX (tty) + len) == FRAME_COLS (f))
723 len --;
724 if (len <= 0)
725 return;
727 cmplus (tty, len);
729 /* If terminal_coding does any conversion, use it, otherwise use
730 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
731 because it always return 1 if the member src_multibyte is 1. */
732 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
733 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
734 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
735 the tail. */
736 coding->mode &= ~CODING_MODE_LAST_BLOCK;
738 for (stringlen = len; stringlen != 0; stringlen -= n)
740 /* Identify a run of glyphs with the same face. */
741 int face_id = string->face_id;
743 for (n = 1; n < stringlen; ++n)
744 if (string[n].face_id != face_id)
745 break;
747 /* Turn appearance modes of the face of the run on. */
748 tty_highlight_if_desired (tty);
749 turn_on_face (f, face_id);
751 if (n == stringlen)
752 /* This is the last run. */
753 coding->mode |= CODING_MODE_LAST_BLOCK;
754 conversion_buffer = encode_terminal_code (string, n, coding);
755 if (coding->produced > 0)
757 BLOCK_INPUT;
758 fwrite (conversion_buffer, 1, coding->produced, tty->output);
759 if (ferror (tty->output))
760 clearerr (tty->output);
761 if (tty->termscript)
762 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
763 UNBLOCK_INPUT;
765 string += n;
767 /* Turn appearance modes off. */
768 turn_off_face (f, face_id);
769 tty_turn_off_highlight (tty);
772 cmcheckmagic (tty);
775 #ifdef HAVE_GPM /* Only used by GPM code. */
777 static void
778 tty_write_glyphs_with_face (register struct frame *f, register struct glyph *string,
779 register int len, register int face_id)
781 unsigned char *conversion_buffer;
782 struct coding_system *coding;
784 struct tty_display_info *tty = FRAME_TTY (f);
786 tty_turn_off_insert (tty);
787 tty_hide_cursor (tty);
789 /* Don't dare write in last column of bottom line, if Auto-Wrap,
790 since that would scroll the whole frame on some terminals. */
792 if (AutoWrap (tty)
793 && curY (tty) + 1 == FRAME_LINES (f)
794 && (curX (tty) + len) == FRAME_COLS (f))
795 len --;
796 if (len <= 0)
797 return;
799 cmplus (tty, len);
801 /* If terminal_coding does any conversion, use it, otherwise use
802 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
803 because it always return 1 if the member src_multibyte is 1. */
804 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
805 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
806 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
807 the tail. */
808 coding->mode &= ~CODING_MODE_LAST_BLOCK;
810 /* Turn appearance modes of the face. */
811 tty_highlight_if_desired (tty);
812 turn_on_face (f, face_id);
814 coding->mode |= CODING_MODE_LAST_BLOCK;
815 conversion_buffer = encode_terminal_code (string, len, coding);
816 if (coding->produced > 0)
818 BLOCK_INPUT;
819 fwrite (conversion_buffer, 1, coding->produced, tty->output);
820 if (ferror (tty->output))
821 clearerr (tty->output);
822 if (tty->termscript)
823 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
824 UNBLOCK_INPUT;
827 /* Turn appearance modes off. */
828 turn_off_face (f, face_id);
829 tty_turn_off_highlight (tty);
831 cmcheckmagic (tty);
833 #endif
835 /* An implementation of insert_glyphs for termcap frames. */
837 static void
838 tty_insert_glyphs (struct frame *f, struct glyph *start, int len)
840 char *buf;
841 struct glyph *glyph = NULL;
842 unsigned char *conversion_buffer;
843 unsigned char space[1];
844 struct coding_system *coding;
846 struct tty_display_info *tty = FRAME_TTY (f);
848 if (tty->TS_ins_multi_chars)
850 buf = tparam (tty->TS_ins_multi_chars, 0, 0, len, 0, 0, 0);
851 OUTPUT1 (tty, buf);
852 xfree (buf);
853 if (start)
854 write_glyphs (f, start, len);
855 return;
858 tty_turn_on_insert (tty);
859 cmplus (tty, len);
861 if (! start)
862 space[0] = SPACEGLYPH;
864 /* If terminal_coding does any conversion, use it, otherwise use
865 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
866 because it always return 1 if the member src_multibyte is 1. */
867 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
868 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
869 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
870 the tail. */
871 coding->mode &= ~CODING_MODE_LAST_BLOCK;
873 while (len-- > 0)
875 OUTPUT1_IF (tty, tty->TS_ins_char);
876 if (!start)
878 conversion_buffer = space;
879 coding->produced = 1;
881 else
883 tty_highlight_if_desired (tty);
884 turn_on_face (f, start->face_id);
885 glyph = start;
886 ++start;
887 /* We must open sufficient space for a character which
888 occupies more than one column. */
889 while (len && CHAR_GLYPH_PADDING_P (*start))
891 OUTPUT1_IF (tty, tty->TS_ins_char);
892 start++, len--;
895 if (len <= 0)
896 /* This is the last glyph. */
897 coding->mode |= CODING_MODE_LAST_BLOCK;
899 conversion_buffer = encode_terminal_code (glyph, 1, coding);
902 if (coding->produced > 0)
904 BLOCK_INPUT;
905 fwrite (conversion_buffer, 1, coding->produced, tty->output);
906 if (ferror (tty->output))
907 clearerr (tty->output);
908 if (tty->termscript)
909 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
910 UNBLOCK_INPUT;
913 OUTPUT1_IF (tty, tty->TS_pad_inserted_char);
914 if (start)
916 turn_off_face (f, glyph->face_id);
917 tty_turn_off_highlight (tty);
921 cmcheckmagic (tty);
924 /* An implementation of delete_glyphs for termcap frames. */
926 static void
927 tty_delete_glyphs (struct frame *f, int n)
929 char *buf;
930 register int i;
932 struct tty_display_info *tty = FRAME_TTY (f);
934 if (tty->delete_in_insert_mode)
936 tty_turn_on_insert (tty);
938 else
940 tty_turn_off_insert (tty);
941 OUTPUT_IF (tty, tty->TS_delete_mode);
944 if (tty->TS_del_multi_chars)
946 buf = tparam (tty->TS_del_multi_chars, 0, 0, n, 0, 0, 0);
947 OUTPUT1 (tty, buf);
948 xfree (buf);
950 else
951 for (i = 0; i < n; i++)
952 OUTPUT1 (tty, tty->TS_del_char);
953 if (!tty->delete_in_insert_mode)
954 OUTPUT_IF (tty, tty->TS_end_delete_mode);
957 /* An implementation of ins_del_lines for termcap frames. */
959 static void
960 tty_ins_del_lines (struct frame *f, int vpos, int n)
962 struct tty_display_info *tty = FRAME_TTY (f);
963 const char *multi =
964 n > 0 ? tty->TS_ins_multi_lines : tty->TS_del_multi_lines;
965 const char *single = n > 0 ? tty->TS_ins_line : tty->TS_del_line;
966 const char *scroll = n > 0 ? tty->TS_rev_scroll : tty->TS_fwd_scroll;
968 register int i = n > 0 ? n : -n;
969 register char *buf;
971 /* If the lines below the insertion are being pushed
972 into the end of the window, this is the same as clearing;
973 and we know the lines are already clear, since the matching
974 deletion has already been done. So can ignore this. */
975 /* If the lines below the deletion are blank lines coming
976 out of the end of the window, don't bother,
977 as there will be a matching inslines later that will flush them. */
978 if (FRAME_SCROLL_REGION_OK (f)
979 && vpos + i >= tty->specified_window)
980 return;
981 if (!FRAME_MEMORY_BELOW_FRAME (f)
982 && vpos + i >= FRAME_LINES (f))
983 return;
985 if (multi)
987 raw_cursor_to (f, vpos, 0);
988 tty_background_highlight (tty);
989 buf = tparam (multi, 0, 0, i, 0, 0, 0);
990 OUTPUT (tty, buf);
991 xfree (buf);
993 else if (single)
995 raw_cursor_to (f, vpos, 0);
996 tty_background_highlight (tty);
997 while (--i >= 0)
998 OUTPUT (tty, single);
999 if (tty->TF_teleray)
1000 curX (tty) = 0;
1002 else
1004 tty_set_scroll_region (f, vpos, tty->specified_window);
1005 if (n < 0)
1006 raw_cursor_to (f, tty->specified_window - 1, 0);
1007 else
1008 raw_cursor_to (f, vpos, 0);
1009 tty_background_highlight (tty);
1010 while (--i >= 0)
1011 OUTPUTL (tty, scroll, tty->specified_window - vpos);
1012 tty_set_scroll_region (f, 0, tty->specified_window);
1015 if (!FRAME_SCROLL_REGION_OK (f)
1016 && FRAME_MEMORY_BELOW_FRAME (f)
1017 && n < 0)
1019 cursor_to (f, FRAME_LINES (f) + n, 0);
1020 clear_to_end (f);
1024 /* Compute cost of sending "str", in characters,
1025 not counting any line-dependent padding. */
1028 string_cost (const char *str)
1030 cost = 0;
1031 if (str)
1032 tputs (str, 0, evalcost);
1033 return cost;
1036 /* Compute cost of sending "str", in characters,
1037 counting any line-dependent padding at one line. */
1039 static int
1040 string_cost_one_line (const char *str)
1042 cost = 0;
1043 if (str)
1044 tputs (str, 1, evalcost);
1045 return cost;
1048 /* Compute per line amount of line-dependent padding,
1049 in tenths of characters. */
1052 per_line_cost (const char *str)
1054 cost = 0;
1055 if (str)
1056 tputs (str, 0, evalcost);
1057 cost = - cost;
1058 if (str)
1059 tputs (str, 10, evalcost);
1060 return cost;
1063 /* char_ins_del_cost[n] is cost of inserting N characters.
1064 char_ins_del_cost[-n] is cost of deleting N characters.
1065 The length of this vector is based on max_frame_cols. */
1067 int *char_ins_del_vector;
1069 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
1071 /* ARGSUSED */
1072 static void
1073 calculate_ins_del_char_costs (struct frame *f)
1075 struct tty_display_info *tty = FRAME_TTY (f);
1076 int ins_startup_cost, del_startup_cost;
1077 int ins_cost_per_char, del_cost_per_char;
1078 register int i;
1079 register int *p;
1081 if (tty->TS_ins_multi_chars)
1083 ins_cost_per_char = 0;
1084 ins_startup_cost = string_cost_one_line (tty->TS_ins_multi_chars);
1086 else if (tty->TS_ins_char || tty->TS_pad_inserted_char
1087 || (tty->TS_insert_mode && tty->TS_end_insert_mode))
1089 ins_startup_cost = (30 * (string_cost (tty->TS_insert_mode)
1090 + string_cost (tty->TS_end_insert_mode))) / 100;
1091 ins_cost_per_char = (string_cost_one_line (tty->TS_ins_char)
1092 + string_cost_one_line (tty->TS_pad_inserted_char));
1094 else
1096 ins_startup_cost = 9999;
1097 ins_cost_per_char = 0;
1100 if (tty->TS_del_multi_chars)
1102 del_cost_per_char = 0;
1103 del_startup_cost = string_cost_one_line (tty->TS_del_multi_chars);
1105 else if (tty->TS_del_char)
1107 del_startup_cost = (string_cost (tty->TS_delete_mode)
1108 + string_cost (tty->TS_end_delete_mode));
1109 if (tty->delete_in_insert_mode)
1110 del_startup_cost /= 2;
1111 del_cost_per_char = string_cost_one_line (tty->TS_del_char);
1113 else
1115 del_startup_cost = 9999;
1116 del_cost_per_char = 0;
1119 /* Delete costs are at negative offsets */
1120 p = &char_ins_del_cost (f)[0];
1121 for (i = FRAME_COLS (f); --i >= 0;)
1122 *--p = (del_startup_cost += del_cost_per_char);
1124 /* Doing nothing is free */
1125 p = &char_ins_del_cost (f)[0];
1126 *p++ = 0;
1128 /* Insert costs are at positive offsets */
1129 for (i = FRAME_COLS (f); --i >= 0;)
1130 *p++ = (ins_startup_cost += ins_cost_per_char);
1133 void
1134 calculate_costs (struct frame *frame)
1136 FRAME_COST_BAUD_RATE (frame) = baud_rate;
1138 if (FRAME_TERMCAP_P (frame))
1140 struct tty_display_info *tty = FRAME_TTY (frame);
1141 register const char *f = (tty->TS_set_scroll_region
1142 ? tty->TS_set_scroll_region
1143 : tty->TS_set_scroll_region_1);
1145 FRAME_SCROLL_REGION_COST (frame) = string_cost (f);
1147 tty->costs_set = 1;
1149 /* These variables are only used for terminal stuff. They are
1150 allocated once for the terminal frame of X-windows emacs, but not
1151 used afterwards.
1153 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1154 X turns off char_ins_del_ok. */
1156 max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
1157 if ((min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) - 1) / 2
1158 < max_frame_cols)
1159 memory_full (SIZE_MAX);
1161 char_ins_del_vector =
1162 xrealloc (char_ins_del_vector,
1163 (sizeof (int) + 2 * sizeof (int) * max_frame_cols));
1165 memset (char_ins_del_vector, 0,
1166 (sizeof (int) + 2 * sizeof (int) * max_frame_cols));
1169 if (f && (!tty->TS_ins_line && !tty->TS_del_line))
1170 do_line_insertion_deletion_costs (frame,
1171 tty->TS_rev_scroll, tty->TS_ins_multi_lines,
1172 tty->TS_fwd_scroll, tty->TS_del_multi_lines,
1173 f, f, 1);
1174 else
1175 do_line_insertion_deletion_costs (frame,
1176 tty->TS_ins_line, tty->TS_ins_multi_lines,
1177 tty->TS_del_line, tty->TS_del_multi_lines,
1178 0, 0, 1);
1180 calculate_ins_del_char_costs (frame);
1182 /* Don't use TS_repeat if its padding is worse than sending the chars */
1183 if (tty->TS_repeat && per_line_cost (tty->TS_repeat) * baud_rate < 9000)
1184 tty->RPov = string_cost (tty->TS_repeat);
1185 else
1186 tty->RPov = FRAME_COLS (frame) * 2;
1188 cmcostinit (FRAME_TTY (frame)); /* set up cursor motion costs */
1192 struct fkey_table {
1193 const char *cap, *name;
1196 /* Termcap capability names that correspond directly to X keysyms.
1197 Some of these (marked "terminfo") aren't supplied by old-style
1198 (Berkeley) termcap entries. They're listed in X keysym order;
1199 except we put the keypad keys first, so that if they clash with
1200 other keys (as on the IBM PC keyboard) they get overridden.
1203 static const struct fkey_table keys[] =
1205 {"kh", "home"}, /* termcap */
1206 {"kl", "left"}, /* termcap */
1207 {"ku", "up"}, /* termcap */
1208 {"kr", "right"}, /* termcap */
1209 {"kd", "down"}, /* termcap */
1210 {"%8", "prior"}, /* terminfo */
1211 {"%5", "next"}, /* terminfo */
1212 {"@7", "end"}, /* terminfo */
1213 {"@1", "begin"}, /* terminfo */
1214 {"*6", "select"}, /* terminfo */
1215 {"%9", "print"}, /* terminfo */
1216 {"@4", "execute"}, /* terminfo --- actually the `command' key */
1218 * "insert" --- see below
1220 {"&8", "undo"}, /* terminfo */
1221 {"%0", "redo"}, /* terminfo */
1222 {"%7", "menu"}, /* terminfo --- actually the `options' key */
1223 {"@0", "find"}, /* terminfo */
1224 {"@2", "cancel"}, /* terminfo */
1225 {"%1", "help"}, /* terminfo */
1227 * "break" goes here, but can't be reliably intercepted with termcap
1229 {"&4", "reset"}, /* terminfo --- actually `restart' */
1231 * "system" and "user" --- no termcaps
1233 {"kE", "clearline"}, /* terminfo */
1234 {"kA", "insertline"}, /* terminfo */
1235 {"kL", "deleteline"}, /* terminfo */
1236 {"kI", "insertchar"}, /* terminfo */
1237 {"kD", "deletechar"}, /* terminfo */
1238 {"kB", "backtab"}, /* terminfo */
1240 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1242 {"@8", "kp-enter"}, /* terminfo */
1244 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1245 * "kp-multiply", "kp-add", "kp-separator",
1246 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1247 * --- no termcaps for any of these.
1249 {"K4", "kp-1"}, /* terminfo */
1251 * "kp-2" --- no termcap
1253 {"K5", "kp-3"}, /* terminfo */
1255 * "kp-4" --- no termcap
1257 {"K2", "kp-5"}, /* terminfo */
1259 * "kp-6" --- no termcap
1261 {"K1", "kp-7"}, /* terminfo */
1263 * "kp-8" --- no termcap
1265 {"K3", "kp-9"}, /* terminfo */
1267 * "kp-equal" --- no termcap
1269 {"k1", "f1"},
1270 {"k2", "f2"},
1271 {"k3", "f3"},
1272 {"k4", "f4"},
1273 {"k5", "f5"},
1274 {"k6", "f6"},
1275 {"k7", "f7"},
1276 {"k8", "f8"},
1277 {"k9", "f9"},
1279 {"&0", "S-cancel"}, /*shifted cancel key*/
1280 {"&9", "S-begin"}, /*shifted begin key*/
1281 {"*0", "S-find"}, /*shifted find key*/
1282 {"*1", "S-execute"}, /*shifted execute? actually shifted command key*/
1283 {"*4", "S-delete"}, /*shifted delete-character key*/
1284 {"*7", "S-end"}, /*shifted end key*/
1285 {"*8", "S-clearline"}, /*shifted clear-to end-of-line key*/
1286 {"#1", "S-help"}, /*shifted help key*/
1287 {"#2", "S-home"}, /*shifted home key*/
1288 {"#3", "S-insert"}, /*shifted insert-character key*/
1289 {"#4", "S-left"}, /*shifted left-arrow key*/
1290 {"%d", "S-menu"}, /*shifted menu? actually shifted options key*/
1291 {"%c", "S-next"}, /*shifted next key*/
1292 {"%e", "S-prior"}, /*shifted previous key*/
1293 {"%f", "S-print"}, /*shifted print key*/
1294 {"%g", "S-redo"}, /*shifted redo key*/
1295 {"%i", "S-right"}, /*shifted right-arrow key*/
1296 {"!3", "S-undo"} /*shifted undo key*/
1299 #ifndef DOS_NT
1300 static char **term_get_fkeys_address;
1301 static KBOARD *term_get_fkeys_kboard;
1302 static Lisp_Object term_get_fkeys_1 (void);
1304 /* Find the escape codes sent by the function keys for Vinput_decode_map.
1305 This function scans the termcap function key sequence entries, and
1306 adds entries to Vinput_decode_map for each function key it finds. */
1308 static void
1309 term_get_fkeys (char **address, KBOARD *kboard)
1311 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1312 errors during the call. The only errors should be from Fdefine_key
1313 when given a key sequence containing an invalid prefix key. If the
1314 termcap defines function keys which use a prefix that is already bound
1315 to a command by the default bindings, we should silently ignore that
1316 function key specification, rather than giving the user an error and
1317 refusing to run at all on such a terminal. */
1319 term_get_fkeys_address = address;
1320 term_get_fkeys_kboard = kboard;
1321 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1324 static Lisp_Object
1325 term_get_fkeys_1 (void)
1327 int i;
1329 char **address = term_get_fkeys_address;
1330 KBOARD *kboard = term_get_fkeys_kboard;
1332 /* This can happen if CANNOT_DUMP or with strange options. */
1333 if (!KEYMAPP (KVAR (kboard, Vinput_decode_map)))
1334 KVAR (kboard, Vinput_decode_map) = Fmake_sparse_keymap (Qnil);
1336 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1338 char *sequence = tgetstr (keys[i].cap, address);
1339 if (sequence)
1340 Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (sequence),
1341 Fmake_vector (make_number (1),
1342 intern (keys[i].name)));
1345 /* The uses of the "k0" capability are inconsistent; sometimes it
1346 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1347 We will attempt to politely accommodate both systems by testing for
1348 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1351 const char *k_semi = tgetstr ("k;", address);
1352 const char *k0 = tgetstr ("k0", address);
1353 const char *k0_name = "f10";
1355 if (k_semi)
1357 if (k0)
1358 /* Define f0 first, so that f10 takes precedence in case the
1359 key sequences happens to be the same. */
1360 Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (k0),
1361 Fmake_vector (make_number (1), intern ("f0")));
1362 Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (k_semi),
1363 Fmake_vector (make_number (1), intern ("f10")));
1365 else if (k0)
1366 Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (k0),
1367 Fmake_vector (make_number (1), intern (k0_name)));
1370 /* Set up cookies for numbered function keys above f10. */
1372 char fcap[3], fkey[4];
1374 fcap[0] = 'F'; fcap[2] = '\0';
1375 for (i = 11; i < 64; i++)
1377 if (i <= 19)
1378 fcap[1] = '1' + i - 11;
1379 else if (i <= 45)
1380 fcap[1] = 'A' + i - 20;
1381 else
1382 fcap[1] = 'a' + i - 46;
1385 char *sequence = tgetstr (fcap, address);
1386 if (sequence)
1388 sprintf (fkey, "f%d", i);
1389 Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (sequence),
1390 Fmake_vector (make_number (1),
1391 intern (fkey)));
1398 * Various mappings to try and get a better fit.
1401 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1402 if (!tgetstr (cap1, address)) \
1404 char *sequence = tgetstr (cap2, address); \
1405 if (sequence) \
1406 Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (sequence), \
1407 Fmake_vector (make_number (1), \
1408 intern (sym))); \
1411 /* if there's no key_next keycap, map key_npage to `next' keysym */
1412 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1413 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1414 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1415 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1416 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1417 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1418 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1420 /* IBM has their own non-standard dialect of terminfo.
1421 If the standard name isn't found, try the IBM name. */
1422 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1423 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1424 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1425 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1426 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1427 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1428 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1429 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1430 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1431 #undef CONDITIONAL_REASSIGN
1434 return Qnil;
1436 #endif /* not DOS_NT */
1439 /***********************************************************************
1440 Character Display Information
1441 ***********************************************************************/
1442 static void append_glyph (struct it *);
1443 static void produce_stretch_glyph (struct it *);
1444 static void append_composite_glyph (struct it *);
1445 static void produce_composite_glyph (struct it *);
1446 static void append_glyphless_glyph (struct it *, int, const char *);
1447 static void produce_glyphless_glyph (struct it *, int, Lisp_Object);
1449 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1450 terminal frames if IT->glyph_row != NULL. IT->char_to_display is
1451 the character for which to produce glyphs; IT->face_id contains the
1452 character's face. Padding glyphs are appended if IT->c has a
1453 IT->pixel_width > 1. */
1455 static void
1456 append_glyph (struct it *it)
1458 struct glyph *glyph, *end;
1459 int i;
1461 xassert (it->glyph_row);
1462 glyph = (it->glyph_row->glyphs[it->area]
1463 + it->glyph_row->used[it->area]);
1464 end = it->glyph_row->glyphs[1 + it->area];
1466 /* If the glyph row is reversed, we need to prepend the glyph rather
1467 than append it. */
1468 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1470 struct glyph *g;
1471 int move_by = it->pixel_width;
1473 /* Make room for the new glyphs. */
1474 if (move_by > end - glyph) /* don't overstep end of this area */
1475 move_by = end - glyph;
1476 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1477 g[move_by] = *g;
1478 glyph = it->glyph_row->glyphs[it->area];
1479 end = glyph + move_by;
1482 /* BIDI Note: we put the glyphs of a "multi-pixel" character left to
1483 right, even in the REVERSED_P case, since (a) all of its u.ch are
1484 identical, and (b) the PADDING_P flag needs to be set for the
1485 leftmost one, because we write to the terminal left-to-right. */
1486 for (i = 0;
1487 i < it->pixel_width && glyph < end;
1488 ++i)
1490 glyph->type = CHAR_GLYPH;
1491 glyph->pixel_width = 1;
1492 glyph->u.ch = it->char_to_display;
1493 glyph->face_id = it->face_id;
1494 glyph->padding_p = i > 0;
1495 glyph->charpos = CHARPOS (it->position);
1496 glyph->object = it->object;
1497 if (it->bidi_p)
1499 glyph->resolved_level = it->bidi_it.resolved_level;
1500 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1501 abort ();
1502 glyph->bidi_type = it->bidi_it.type;
1504 else
1506 glyph->resolved_level = 0;
1507 glyph->bidi_type = UNKNOWN_BT;
1510 ++it->glyph_row->used[it->area];
1511 ++glyph;
1515 /* Produce glyphs for the display element described by IT. *IT
1516 specifies what we want to produce a glyph for (character, image, ...),
1517 and where in the glyph matrix we currently are (glyph row and hpos).
1518 produce_glyphs fills in output fields of *IT with information such as the
1519 pixel width and height of a character, and maybe output actual glyphs at
1520 the same time if IT->glyph_row is non-null. For an overview, see
1521 the explanation in dispextern.h, before the definition of the
1522 display_element_type enumeration.
1524 produce_glyphs also stores the result of glyph width, ascent
1525 etc. computations in *IT.
1527 IT->glyph_row may be null, in which case produce_glyphs does not
1528 actually fill in the glyphs. This is used in the move_* functions
1529 in xdisp.c for text width and height computations.
1531 Callers usually don't call produce_glyphs directly;
1532 instead they use the macro PRODUCE_GLYPHS. */
1534 void
1535 produce_glyphs (struct it *it)
1537 /* If a hook is installed, let it do the work. */
1539 /* Nothing but characters are supported on terminal frames. */
1540 xassert (it->what == IT_CHARACTER
1541 || it->what == IT_COMPOSITION
1542 || it->what == IT_STRETCH
1543 || it->what == IT_GLYPHLESS);
1545 if (it->what == IT_STRETCH)
1547 produce_stretch_glyph (it);
1548 goto done;
1551 if (it->what == IT_COMPOSITION)
1553 produce_composite_glyph (it);
1554 goto done;
1557 if (it->what == IT_GLYPHLESS)
1559 produce_glyphless_glyph (it, 0, Qnil);
1560 goto done;
1563 if (it->char_to_display >= 040 && it->char_to_display < 0177)
1565 it->pixel_width = it->nglyphs = 1;
1566 if (it->glyph_row)
1567 append_glyph (it);
1569 else if (it->char_to_display == '\n')
1570 it->pixel_width = it->nglyphs = 0;
1571 else if (it->char_to_display == '\t')
1573 int absolute_x = (it->current_x
1574 + it->continuation_lines_width);
1575 int next_tab_x
1576 = (((1 + absolute_x + it->tab_width - 1)
1577 / it->tab_width)
1578 * it->tab_width);
1579 int nspaces;
1581 /* If part of the TAB has been displayed on the previous line
1582 which is continued now, continuation_lines_width will have
1583 been incremented already by the part that fitted on the
1584 continued line. So, we will get the right number of spaces
1585 here. */
1586 nspaces = next_tab_x - absolute_x;
1588 if (it->glyph_row)
1590 int n = nspaces;
1592 it->char_to_display = ' ';
1593 it->pixel_width = it->len = 1;
1595 while (n--)
1596 append_glyph (it);
1599 it->pixel_width = nspaces;
1600 it->nglyphs = nspaces;
1602 else if (CHAR_BYTE8_P (it->char_to_display))
1604 /* Coming here means that we must send the raw 8-bit byte as is
1605 to the terminal. Although there's no way to know how many
1606 columns it occupies on a screen, it is a good assumption that
1607 a single byte code has 1-column width. */
1608 it->pixel_width = it->nglyphs = 1;
1609 if (it->glyph_row)
1610 append_glyph (it);
1612 else
1614 Lisp_Object charset_list = FRAME_TERMINAL (it->f)->charset_list;
1616 if (char_charset (it->char_to_display, charset_list, NULL))
1618 it->pixel_width = CHAR_WIDTH (it->char_to_display);
1619 it->nglyphs = it->pixel_width;
1620 if (it->glyph_row)
1621 append_glyph (it);
1623 else
1625 Lisp_Object acronym = lookup_glyphless_char_display (-1, it);
1627 xassert (it->what == IT_GLYPHLESS);
1628 produce_glyphless_glyph (it, 1, acronym);
1632 done:
1633 /* Advance current_x by the pixel width as a convenience for
1634 the caller. */
1635 if (it->area == TEXT_AREA)
1636 it->current_x += it->pixel_width;
1637 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1638 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
1642 /* Produce a stretch glyph for iterator IT. IT->object is the value
1643 of the glyph property displayed. The value must be a list
1644 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1645 being recognized:
1647 1. `:width WIDTH' specifies that the space should be WIDTH *
1648 canonical char width wide. WIDTH may be an integer or floating
1649 point number.
1651 2. `:align-to HPOS' specifies that the space should be wide enough
1652 to reach HPOS, a value in canonical character units. */
1654 static void
1655 produce_stretch_glyph (struct it *it)
1657 /* (space :width WIDTH ...) */
1658 Lisp_Object prop, plist;
1659 int width = 0, align_to = -1;
1660 int zero_width_ok_p = 0;
1661 double tem;
1663 /* List should start with `space'. */
1664 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1665 plist = XCDR (it->object);
1667 /* Compute the width of the stretch. */
1668 if ((prop = Fplist_get (plist, QCwidth), !NILP (prop))
1669 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, 0))
1671 /* Absolute width `:width WIDTH' specified and valid. */
1672 zero_width_ok_p = 1;
1673 width = (int)(tem + 0.5);
1675 else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
1676 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, &align_to))
1678 if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
1679 align_to = (align_to < 0
1681 : align_to - window_box_left_offset (it->w, TEXT_AREA));
1682 else if (align_to < 0)
1683 align_to = window_box_left_offset (it->w, TEXT_AREA);
1684 width = max (0, (int)(tem + 0.5) + align_to - it->current_x);
1685 zero_width_ok_p = 1;
1687 else
1688 /* Nothing specified -> width defaults to canonical char width. */
1689 width = FRAME_COLUMN_WIDTH (it->f);
1691 if (width <= 0 && (width < 0 || !zero_width_ok_p))
1692 width = 1;
1694 if (width > 0 && it->line_wrap != TRUNCATE
1695 && it->current_x + width > it->last_visible_x)
1696 width = it->last_visible_x - it->current_x - 1;
1698 if (width > 0 && it->glyph_row)
1700 Lisp_Object o_object = it->object;
1701 Lisp_Object object = it->stack[it->sp - 1].string;
1702 int n = width;
1704 if (!STRINGP (object))
1705 object = it->w->buffer;
1706 it->object = object;
1707 it->char_to_display = ' ';
1708 it->pixel_width = it->len = 1;
1709 while (n--)
1710 append_glyph (it);
1711 it->object = o_object;
1713 it->pixel_width = width;
1714 it->nglyphs = width;
1718 /* Append glyphs to IT's glyph_row for the composition IT->cmp_id.
1719 Called from produce_composite_glyph for terminal frames if
1720 IT->glyph_row != NULL. IT->face_id contains the character's
1721 face. */
1723 static void
1724 append_composite_glyph (struct it *it)
1726 struct glyph *glyph;
1728 xassert (it->glyph_row);
1729 glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
1730 if (glyph < it->glyph_row->glyphs[1 + it->area])
1732 /* If the glyph row is reversed, we need to prepend the glyph
1733 rather than append it. */
1734 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1736 struct glyph *g;
1738 /* Make room for the new glyph. */
1739 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1740 g[1] = *g;
1741 glyph = it->glyph_row->glyphs[it->area];
1743 glyph->type = COMPOSITE_GLYPH;
1744 glyph->pixel_width = it->pixel_width;
1745 glyph->u.cmp.id = it->cmp_it.id;
1746 if (it->cmp_it.ch < 0)
1748 glyph->u.cmp.automatic = 0;
1749 glyph->u.cmp.id = it->cmp_it.id;
1751 else
1753 glyph->u.cmp.automatic = 1;
1754 glyph->u.cmp.id = it->cmp_it.id;
1755 glyph->slice.cmp.from = it->cmp_it.from;
1756 glyph->slice.cmp.to = it->cmp_it.to - 1;
1759 glyph->face_id = it->face_id;
1760 glyph->padding_p = 0;
1761 glyph->charpos = CHARPOS (it->position);
1762 glyph->object = it->object;
1763 if (it->bidi_p)
1765 glyph->resolved_level = it->bidi_it.resolved_level;
1766 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1767 abort ();
1768 glyph->bidi_type = it->bidi_it.type;
1770 else
1772 glyph->resolved_level = 0;
1773 glyph->bidi_type = UNKNOWN_BT;
1776 ++it->glyph_row->used[it->area];
1777 ++glyph;
1782 /* Produce a composite glyph for iterator IT. IT->cmp_id is the ID of
1783 the composition. We simply produces components of the composition
1784 assuming that the terminal has a capability to layout/render it
1785 correctly. */
1787 static void
1788 produce_composite_glyph (struct it *it)
1790 if (it->cmp_it.ch < 0)
1792 struct composition *cmp = composition_table[it->cmp_it.id];
1794 it->pixel_width = cmp->width;
1796 else
1798 Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id);
1800 it->pixel_width = composition_gstring_width (gstring, it->cmp_it.from,
1801 it->cmp_it.to, NULL);
1803 it->nglyphs = 1;
1804 if (it->glyph_row)
1805 append_composite_glyph (it);
1809 /* Append a glyph for a glyphless character to IT->glyph_row. FACE_ID
1810 is a face ID to be used for the glyph. What is actually appended
1811 are glyphs of type CHAR_GLYPH whose characters are in STR (which
1812 comes from it->nglyphs bytes). */
1814 static void
1815 append_glyphless_glyph (struct it *it, int face_id, const char *str)
1817 struct glyph *glyph, *end;
1818 int i;
1820 xassert (it->glyph_row);
1821 glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
1822 end = it->glyph_row->glyphs[1 + it->area];
1824 /* If the glyph row is reversed, we need to prepend the glyph rather
1825 than append it. */
1826 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1828 struct glyph *g;
1829 int move_by = it->pixel_width;
1831 /* Make room for the new glyphs. */
1832 if (move_by > end - glyph) /* don't overstep end of this area */
1833 move_by = end - glyph;
1834 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1835 g[move_by] = *g;
1836 glyph = it->glyph_row->glyphs[it->area];
1837 end = glyph + move_by;
1840 if (glyph >= end)
1841 return;
1842 glyph->type = CHAR_GLYPH;
1843 glyph->pixel_width = 1;
1844 glyph->face_id = face_id;
1845 glyph->padding_p = 0;
1846 glyph->charpos = CHARPOS (it->position);
1847 glyph->object = it->object;
1848 if (it->bidi_p)
1850 glyph->resolved_level = it->bidi_it.resolved_level;
1851 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1852 abort ();
1853 glyph->bidi_type = it->bidi_it.type;
1855 else
1857 glyph->resolved_level = 0;
1858 glyph->bidi_type = UNKNOWN_BT;
1861 /* BIDI Note: we put the glyphs of characters left to right, even in
1862 the REVERSED_P case because we write to the terminal
1863 left-to-right. */
1864 for (i = 0; i < it->nglyphs && glyph < end; ++i)
1866 if (i > 0)
1867 glyph[0] = glyph[-1];
1868 glyph->u.ch = str[i];
1869 ++it->glyph_row->used[it->area];
1870 ++glyph;
1874 /* Produce glyphs for a glyphless character for iterator IT.
1875 IT->glyphless_method specifies which method to use for displaying
1876 the character. See the description of enum
1877 glyphless_display_method in dispextern.h for the details.
1879 FOR_NO_FONT is nonzero if and only if this is for a character that
1880 is not supproted by the coding system of the terminal. ACRONYM, if
1881 non-nil, is an acronym string for the character.
1883 The glyphs actually produced are of type CHAR_GLYPH. */
1885 static void
1886 produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym)
1888 int face_id;
1889 int len;
1890 char buf[9];
1891 char const *str = " ";
1893 /* Get a face ID for the glyph by utilizing a cache (the same way as
1894 done for `escape-glyph' in get_next_display_element). */
1895 if (it->f == last_glyphless_glyph_frame
1896 && it->face_id == last_glyphless_glyph_face_id)
1898 face_id = last_glyphless_glyph_merged_face_id;
1900 else
1902 /* Merge the `glyphless-char' face into the current face. */
1903 face_id = merge_faces (it->f, Qglyphless_char, 0, it->face_id);
1904 last_glyphless_glyph_frame = it->f;
1905 last_glyphless_glyph_face_id = it->face_id;
1906 last_glyphless_glyph_merged_face_id = face_id;
1909 if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE)
1911 /* As there's no way to produce a thin space, we produce a space
1912 of canonical width. */
1913 len = 1;
1915 else if (it->glyphless_method == GLYPHLESS_DISPLAY_EMPTY_BOX)
1917 len = CHAR_WIDTH (it->c);
1918 if (len == 0)
1919 len = 1;
1920 else if (len > 4)
1921 len = 4;
1922 sprintf (buf, "[%.*s]", len, str);
1923 len += 2;
1924 str = buf;
1926 else
1928 if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM)
1930 if (! STRINGP (acronym) && CHAR_TABLE_P (Vglyphless_char_display))
1931 acronym = CHAR_TABLE_REF (Vglyphless_char_display, it->c);
1932 if (CONSP (acronym))
1933 acronym = XCDR (acronym);
1934 buf[0] = '[';
1935 str = STRINGP (acronym) ? SSDATA (acronym) : "";
1936 for (len = 0; len < 6 && str[len] && ASCII_BYTE_P (str[len]); len++)
1937 buf[1 + len] = str[len];
1938 buf[1 + len] = ']';
1939 len += 2;
1941 else
1943 xassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEX_CODE);
1944 len = (it->c < 0x10000 ? sprintf (buf, "\\u%04X", it->c)
1945 : it->c <= MAX_UNICODE_CHAR ? sprintf (buf, "\\U%06X", it->c)
1946 : sprintf (buf, "\\x%06X", it->c));
1948 str = buf;
1951 it->pixel_width = len;
1952 it->nglyphs = len;
1953 if (it->glyph_row)
1954 append_glyphless_glyph (it, face_id, str);
1958 /* Get information about special display element WHAT in an
1959 environment described by IT. WHAT is one of IT_TRUNCATION or
1960 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1961 non-null glyph_row member. This function ensures that fields like
1962 face_id, c, len of IT are left untouched. */
1964 void
1965 produce_special_glyphs (struct it *it, enum display_element_type what)
1967 struct it temp_it;
1968 Lisp_Object gc;
1969 GLYPH glyph;
1971 temp_it = *it;
1972 temp_it.dp = NULL;
1973 temp_it.what = IT_CHARACTER;
1974 temp_it.len = 1;
1975 temp_it.object = make_number (0);
1976 memset (&temp_it.current, 0, sizeof temp_it.current);
1978 if (what == IT_CONTINUATION)
1980 /* Continuation glyph. For R2L lines, we mirror it by hand. */
1981 if (it->bidi_it.paragraph_dir == R2L)
1982 SET_GLYPH_FROM_CHAR (glyph, '/');
1983 else
1984 SET_GLYPH_FROM_CHAR (glyph, '\\');
1985 if (it->dp
1986 && (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc))
1987 && GLYPH_CODE_CHAR_VALID_P (gc))
1989 /* FIXME: Should we mirror GC for R2L lines? */
1990 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
1991 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
1994 else if (what == IT_TRUNCATION)
1996 /* Truncation glyph. */
1997 SET_GLYPH_FROM_CHAR (glyph, '$');
1998 if (it->dp
1999 && (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc))
2000 && GLYPH_CODE_CHAR_VALID_P (gc))
2002 /* FIXME: Should we mirror GC for R2L lines? */
2003 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
2004 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
2007 else
2008 abort ();
2010 temp_it.c = temp_it.char_to_display = GLYPH_CHAR (glyph);
2011 temp_it.face_id = GLYPH_FACE (glyph);
2012 temp_it.len = CHAR_BYTES (temp_it.c);
2014 produce_glyphs (&temp_it);
2015 it->pixel_width = temp_it.pixel_width;
2016 it->nglyphs = temp_it.pixel_width;
2021 /***********************************************************************
2022 Faces
2023 ***********************************************************************/
2025 /* Value is non-zero if attribute ATTR may be used. ATTR should be
2026 one of the enumerators from enum no_color_bit, or a bit set built
2027 from them. Some display attributes may not be used together with
2028 color; the termcap capability `NC' specifies which ones. */
2030 #define MAY_USE_WITH_COLORS_P(tty, ATTR) \
2031 (tty->TN_max_colors > 0 \
2032 ? (tty->TN_no_color_video & (ATTR)) == 0 \
2033 : 1)
2035 /* Turn appearances of face FACE_ID on tty frame F on.
2036 FACE_ID is a realized face ID number, in the face cache. */
2038 static void
2039 turn_on_face (struct frame *f, int face_id)
2041 struct face *face = FACE_FROM_ID (f, face_id);
2042 long fg = face->foreground;
2043 long bg = face->background;
2044 struct tty_display_info *tty = FRAME_TTY (f);
2046 /* Do this first because TS_end_standout_mode may be the same
2047 as TS_exit_attribute_mode, which turns all appearances off. */
2048 if (MAY_USE_WITH_COLORS_P (tty, NC_REVERSE))
2050 if (tty->TN_max_colors > 0)
2052 if (fg >= 0 && bg >= 0)
2054 /* If the terminal supports colors, we can set them
2055 below without using reverse video. The face's fg
2056 and bg colors are set as they should appear on
2057 the screen, i.e. they take the inverse-video'ness
2058 of the face already into account. */
2060 else if (inverse_video)
2062 if (fg == FACE_TTY_DEFAULT_FG_COLOR
2063 || bg == FACE_TTY_DEFAULT_BG_COLOR)
2064 tty_toggle_highlight (tty);
2066 else
2068 if (fg == FACE_TTY_DEFAULT_BG_COLOR
2069 || bg == FACE_TTY_DEFAULT_FG_COLOR)
2070 tty_toggle_highlight (tty);
2073 else
2075 /* If we can't display colors, use reverse video
2076 if the face specifies that. */
2077 if (inverse_video)
2079 if (fg == FACE_TTY_DEFAULT_FG_COLOR
2080 || bg == FACE_TTY_DEFAULT_BG_COLOR)
2081 tty_toggle_highlight (tty);
2083 else
2085 if (fg == FACE_TTY_DEFAULT_BG_COLOR
2086 || bg == FACE_TTY_DEFAULT_FG_COLOR)
2087 tty_toggle_highlight (tty);
2092 if (face->tty_bold_p && MAY_USE_WITH_COLORS_P (tty, NC_BOLD))
2093 OUTPUT1_IF (tty, tty->TS_enter_bold_mode);
2095 if (face->tty_dim_p && MAY_USE_WITH_COLORS_P (tty, NC_DIM))
2096 OUTPUT1_IF (tty, tty->TS_enter_dim_mode);
2098 /* Alternate charset and blinking not yet used. */
2099 if (face->tty_alt_charset_p
2100 && MAY_USE_WITH_COLORS_P (tty, NC_ALT_CHARSET))
2101 OUTPUT1_IF (tty, tty->TS_enter_alt_charset_mode);
2103 if (face->tty_blinking_p
2104 && MAY_USE_WITH_COLORS_P (tty, NC_BLINK))
2105 OUTPUT1_IF (tty, tty->TS_enter_blink_mode);
2107 if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (tty, NC_UNDERLINE))
2108 OUTPUT1_IF (tty, tty->TS_enter_underline_mode);
2110 if (tty->TN_max_colors > 0)
2112 const char *ts;
2113 char *p;
2115 ts = tty->standout_mode ? tty->TS_set_background : tty->TS_set_foreground;
2116 if (fg >= 0 && ts)
2118 p = tparam (ts, NULL, 0, (int) fg, 0, 0, 0);
2119 OUTPUT (tty, p);
2120 xfree (p);
2123 ts = tty->standout_mode ? tty->TS_set_foreground : tty->TS_set_background;
2124 if (bg >= 0 && ts)
2126 p = tparam (ts, NULL, 0, (int) bg, 0, 0, 0);
2127 OUTPUT (tty, p);
2128 xfree (p);
2134 /* Turn off appearances of face FACE_ID on tty frame F. */
2136 static void
2137 turn_off_face (struct frame *f, int face_id)
2139 struct face *face = FACE_FROM_ID (f, face_id);
2140 struct tty_display_info *tty = FRAME_TTY (f);
2142 xassert (face != NULL);
2144 if (tty->TS_exit_attribute_mode)
2146 /* Capability "me" will turn off appearance modes double-bright,
2147 half-bright, reverse-video, standout, underline. It may or
2148 may not turn off alt-char-mode. */
2149 if (face->tty_bold_p
2150 || face->tty_dim_p
2151 || face->tty_reverse_p
2152 || face->tty_alt_charset_p
2153 || face->tty_blinking_p
2154 || face->tty_underline_p)
2156 OUTPUT1_IF (tty, tty->TS_exit_attribute_mode);
2157 if (strcmp (tty->TS_exit_attribute_mode, tty->TS_end_standout_mode) == 0)
2158 tty->standout_mode = 0;
2161 if (face->tty_alt_charset_p)
2162 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
2164 else
2166 /* If we don't have "me" we can only have those appearances
2167 that have exit sequences defined. */
2168 if (face->tty_alt_charset_p)
2169 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
2171 if (face->tty_underline_p)
2172 OUTPUT_IF (tty, tty->TS_exit_underline_mode);
2175 /* Switch back to default colors. */
2176 if (tty->TN_max_colors > 0
2177 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
2178 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
2179 || (face->background != FACE_TTY_DEFAULT_COLOR
2180 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
2181 OUTPUT1_IF (tty, tty->TS_orig_pair);
2185 /* Return non-zero if the terminal on frame F supports all of the
2186 capabilities in CAPS simultaneously, with foreground and background
2187 colors FG and BG. */
2190 tty_capable_p (struct tty_display_info *tty, unsigned int caps,
2191 unsigned long fg, unsigned long bg)
2193 #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
2194 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
2195 return 0;
2197 TTY_CAPABLE_P_TRY (tty, TTY_CAP_INVERSE, tty->TS_standout_mode, NC_REVERSE);
2198 TTY_CAPABLE_P_TRY (tty, TTY_CAP_UNDERLINE, tty->TS_enter_underline_mode, NC_UNDERLINE);
2199 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BOLD, tty->TS_enter_bold_mode, NC_BOLD);
2200 TTY_CAPABLE_P_TRY (tty, TTY_CAP_DIM, tty->TS_enter_dim_mode, NC_DIM);
2201 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BLINK, tty->TS_enter_blink_mode, NC_BLINK);
2202 TTY_CAPABLE_P_TRY (tty, TTY_CAP_ALT_CHARSET, tty->TS_enter_alt_charset_mode, NC_ALT_CHARSET);
2204 /* We can do it! */
2205 return 1;
2208 /* Return non-zero if the terminal is capable to display colors. */
2210 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
2211 0, 1, 0,
2212 doc: /* Return non-nil if the tty device TERMINAL can display colors.
2214 TERMINAL can be a terminal object, a frame, or nil (meaning the
2215 selected frame's terminal). This function always returns nil if
2216 TERMINAL does not refer to a text-only terminal. */)
2217 (Lisp_Object terminal)
2219 struct terminal *t = get_tty_terminal (terminal, 0);
2220 if (!t)
2221 return Qnil;
2222 else
2223 return t->display_info.tty->TN_max_colors > 0 ? Qt : Qnil;
2226 /* Return the number of supported colors. */
2227 DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
2228 Stty_display_color_cells, 0, 1, 0,
2229 doc: /* Return the number of colors supported by the tty device TERMINAL.
2231 TERMINAL can be a terminal object, a frame, or nil (meaning the
2232 selected frame's terminal). This function always returns 0 if
2233 TERMINAL does not refer to a text-only terminal. */)
2234 (Lisp_Object terminal)
2236 struct terminal *t = get_tty_terminal (terminal, 0);
2237 if (!t)
2238 return make_number (0);
2239 else
2240 return make_number (t->display_info.tty->TN_max_colors);
2243 #ifndef DOS_NT
2245 /* Declare here rather than in the function, as in the rest of Emacs,
2246 to work around an HPUX compiler bug (?). See
2247 http://lists.gnu.org/archive/html/emacs-devel/2007-08/msg00410.html */
2248 static int default_max_colors;
2249 static int default_max_pairs;
2250 static int default_no_color_video;
2251 static char *default_orig_pair;
2252 static char *default_set_foreground;
2253 static char *default_set_background;
2255 /* Save or restore the default color-related capabilities of this
2256 terminal. */
2257 static void
2258 tty_default_color_capabilities (struct tty_display_info *tty, int save)
2261 if (save)
2263 xfree (default_orig_pair);
2264 default_orig_pair = tty->TS_orig_pair ? xstrdup (tty->TS_orig_pair) : NULL;
2266 xfree (default_set_foreground);
2267 default_set_foreground = tty->TS_set_foreground ? xstrdup (tty->TS_set_foreground)
2268 : NULL;
2270 xfree (default_set_background);
2271 default_set_background = tty->TS_set_background ? xstrdup (tty->TS_set_background)
2272 : NULL;
2274 default_max_colors = tty->TN_max_colors;
2275 default_max_pairs = tty->TN_max_pairs;
2276 default_no_color_video = tty->TN_no_color_video;
2278 else
2280 tty->TS_orig_pair = default_orig_pair;
2281 tty->TS_set_foreground = default_set_foreground;
2282 tty->TS_set_background = default_set_background;
2283 tty->TN_max_colors = default_max_colors;
2284 tty->TN_max_pairs = default_max_pairs;
2285 tty->TN_no_color_video = default_no_color_video;
2289 /* Setup one of the standard tty color schemes according to MODE.
2290 MODE's value is generally the number of colors which we want to
2291 support; zero means set up for the default capabilities, the ones
2292 we saw at init_tty time; -1 means turn off color support. */
2293 static void
2294 tty_setup_colors (struct tty_display_info *tty, int mode)
2296 /* Canonicalize all negative values of MODE. */
2297 if (mode < -1)
2298 mode = -1;
2300 switch (mode)
2302 case -1: /* no colors at all */
2303 tty->TN_max_colors = 0;
2304 tty->TN_max_pairs = 0;
2305 tty->TN_no_color_video = 0;
2306 tty->TS_set_foreground = tty->TS_set_background = tty->TS_orig_pair = NULL;
2307 break;
2308 case 0: /* default colors, if any */
2309 default:
2310 tty_default_color_capabilities (tty, 0);
2311 break;
2312 case 8: /* 8 standard ANSI colors */
2313 tty->TS_orig_pair = "\033[0m";
2314 #ifdef TERMINFO
2315 tty->TS_set_foreground = "\033[3%p1%dm";
2316 tty->TS_set_background = "\033[4%p1%dm";
2317 #else
2318 tty->TS_set_foreground = "\033[3%dm";
2319 tty->TS_set_background = "\033[4%dm";
2320 #endif
2321 tty->TN_max_colors = 8;
2322 tty->TN_max_pairs = 64;
2323 tty->TN_no_color_video = 0;
2324 break;
2328 void
2329 set_tty_color_mode (struct tty_display_info *tty, struct frame *f)
2331 Lisp_Object tem, val;
2332 Lisp_Object color_mode;
2333 int mode;
2334 Lisp_Object tty_color_mode_alist
2335 = Fintern_soft (build_string ("tty-color-mode-alist"), Qnil);
2337 tem = assq_no_quit (Qtty_color_mode, f->param_alist);
2338 val = CONSP (tem) ? XCDR (tem) : Qnil;
2340 if (INTEGERP (val))
2341 color_mode = val;
2342 else if (SYMBOLP (tty_color_mode_alist))
2344 tem = Fassq (val, Fsymbol_value (tty_color_mode_alist));
2345 color_mode = CONSP (tem) ? XCDR (tem) : Qnil;
2347 else
2348 color_mode = Qnil;
2350 mode = INTEGERP (color_mode) ? XINT (color_mode) : 0;
2352 if (mode != tty->previous_color_mode)
2354 Lisp_Object funsym = intern ("tty-set-up-initial-frame-faces");
2355 tty->previous_color_mode = mode;
2356 tty_setup_colors (tty , mode);
2357 /* This recomputes all the faces given the new color definitions. */
2358 safe_call (1, &funsym);
2362 #endif /* !DOS_NT */
2366 /* Return the tty display object specified by TERMINAL. */
2368 static struct terminal *
2369 get_tty_terminal (Lisp_Object terminal, int throw)
2371 struct terminal *t = get_terminal (terminal, throw);
2373 if (t && t->type != output_termcap && t->type != output_msdos_raw)
2375 if (throw)
2376 error ("Device %d is not a termcap terminal device", t->id);
2377 else
2378 return NULL;
2381 return t;
2384 /* Return an active termcap device that uses the tty device with the
2385 given name.
2387 This function ignores suspended devices.
2389 Returns NULL if the named terminal device is not opened. */
2391 struct terminal *
2392 get_named_tty (const char *name)
2394 struct terminal *t;
2396 if (!name)
2397 abort ();
2399 for (t = terminal_list; t; t = t->next_terminal)
2401 if ((t->type == output_termcap || t->type == output_msdos_raw)
2402 && !strcmp (t->display_info.tty->name, name)
2403 && TERMINAL_ACTIVE_P (t))
2404 return t;
2407 return 0;
2411 DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0,
2412 doc: /* Return the type of the tty device that TERMINAL uses.
2413 Returns nil if TERMINAL is not on a tty device.
2415 TERMINAL can be a terminal object, a frame, or nil (meaning the
2416 selected frame's terminal). */)
2417 (Lisp_Object terminal)
2419 struct terminal *t = get_terminal (terminal, 1);
2421 if (t->type != output_termcap && t->type != output_msdos_raw)
2422 return Qnil;
2424 if (t->display_info.tty->type)
2425 return build_string (t->display_info.tty->type);
2426 else
2427 return Qnil;
2430 DEFUN ("controlling-tty-p", Fcontrolling_tty_p, Scontrolling_tty_p, 0, 1, 0,
2431 doc: /* Return non-nil if TERMINAL is the controlling tty of the Emacs process.
2433 TERMINAL can be a terminal object, a frame, or nil (meaning the
2434 selected frame's terminal). This function always returns nil if
2435 TERMINAL is not on a tty device. */)
2436 (Lisp_Object terminal)
2438 struct terminal *t = get_terminal (terminal, 1);
2440 if ((t->type != output_termcap && t->type != output_msdos_raw)
2441 || strcmp (t->display_info.tty->name, DEV_TTY) != 0)
2442 return Qnil;
2443 else
2444 return Qt;
2447 DEFUN ("tty-no-underline", Ftty_no_underline, Stty_no_underline, 0, 1, 0,
2448 doc: /* Declare that the tty used by TERMINAL does not handle underlining.
2449 This is used to override the terminfo data, for certain terminals that
2450 do not really do underlining, but say that they do. This function has
2451 no effect if used on a non-tty terminal.
2453 TERMINAL can be a terminal object, a frame or nil (meaning the
2454 selected frame's terminal). This function always returns nil if
2455 TERMINAL does not refer to a text-only terminal. */)
2456 (Lisp_Object terminal)
2458 struct terminal *t = get_terminal (terminal, 1);
2460 if (t->type == output_termcap)
2461 t->display_info.tty->TS_enter_underline_mode = 0;
2462 return Qnil;
2467 DEFUN ("suspend-tty", Fsuspend_tty, Ssuspend_tty, 0, 1, 0,
2468 doc: /* Suspend the terminal device TTY.
2470 The device is restored to its default state, and Emacs ceases all
2471 access to the tty device. Frames that use the device are not deleted,
2472 but input is not read from them and if they change, their display is
2473 not updated.
2475 TTY may be a terminal object, a frame, or nil for the terminal device
2476 of the currently selected frame.
2478 This function runs `suspend-tty-functions' after suspending the
2479 device. The functions are run with one arg, the id of the suspended
2480 terminal device.
2482 `suspend-tty' does nothing if it is called on a device that is already
2483 suspended.
2485 A suspended tty may be resumed by calling `resume-tty' on it. */)
2486 (Lisp_Object tty)
2488 struct terminal *t = get_tty_terminal (tty, 1);
2489 FILE *f;
2491 if (!t)
2492 error ("Unknown tty device");
2494 f = t->display_info.tty->input;
2496 if (f)
2498 /* First run `suspend-tty-functions' and then clean up the tty
2499 state because `suspend-tty-functions' might need to change
2500 the tty state. */
2501 Lisp_Object args[2];
2502 args[0] = intern ("suspend-tty-functions");
2503 XSETTERMINAL (args[1], t);
2504 Frun_hook_with_args (2, args);
2506 reset_sys_modes (t->display_info.tty);
2507 delete_keyboard_wait_descriptor (fileno (f));
2509 #ifndef MSDOS
2510 fclose (f);
2511 if (f != t->display_info.tty->output)
2512 fclose (t->display_info.tty->output);
2513 #endif
2515 t->display_info.tty->input = 0;
2516 t->display_info.tty->output = 0;
2518 if (FRAMEP (t->display_info.tty->top_frame))
2519 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0);
2523 /* Clear display hooks to prevent further output. */
2524 clear_tty_hooks (t);
2526 return Qnil;
2529 DEFUN ("resume-tty", Fresume_tty, Sresume_tty, 0, 1, 0,
2530 doc: /* Resume the previously suspended terminal device TTY.
2531 The terminal is opened and reinitialized. Frames that are on the
2532 suspended terminal are revived.
2534 It is an error to resume a terminal while another terminal is active
2535 on the same device.
2537 This function runs `resume-tty-functions' after resuming the terminal.
2538 The functions are run with one arg, the id of the resumed terminal
2539 device.
2541 `resume-tty' does nothing if it is called on a device that is not
2542 suspended.
2544 TTY may be a terminal object, a frame, or nil (meaning the selected
2545 frame's terminal). */)
2546 (Lisp_Object tty)
2548 struct terminal *t = get_tty_terminal (tty, 1);
2549 int fd;
2551 if (!t)
2552 error ("Unknown tty device");
2554 if (!t->display_info.tty->input)
2556 if (get_named_tty (t->display_info.tty->name))
2557 error ("Cannot resume display while another display is active on the same device");
2559 #ifdef MSDOS
2560 t->display_info.tty->output = stdout;
2561 t->display_info.tty->input = stdin;
2562 #else /* !MSDOS */
2563 fd = emacs_open (t->display_info.tty->name, O_RDWR | O_NOCTTY, 0);
2565 if (fd == -1)
2566 error ("Can not reopen tty device %s: %s", t->display_info.tty->name, strerror (errno));
2568 if (strcmp (t->display_info.tty->name, DEV_TTY))
2569 dissociate_if_controlling_tty (fd);
2571 t->display_info.tty->output = fdopen (fd, "w+");
2572 t->display_info.tty->input = t->display_info.tty->output;
2573 #endif
2575 add_keyboard_wait_descriptor (fd);
2577 if (FRAMEP (t->display_info.tty->top_frame))
2579 struct frame *f = XFRAME (t->display_info.tty->top_frame);
2580 int width, height;
2581 int old_height = FRAME_COLS (f);
2582 int old_width = FRAME_LINES (f);
2584 /* Check if terminal/window size has changed while the frame
2585 was suspended. */
2586 get_tty_size (fileno (t->display_info.tty->input), &width, &height);
2587 if (width != old_width || height != old_height)
2588 change_frame_size (f, height, width, 0, 0, 0);
2589 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
2592 set_tty_hooks (t);
2593 init_sys_modes (t->display_info.tty);
2596 /* Run `resume-tty-functions'. */
2597 Lisp_Object args[2];
2598 args[0] = intern ("resume-tty-functions");
2599 XSETTERMINAL (args[1], t);
2600 Frun_hook_with_args (2, args);
2604 set_tty_hooks (t);
2606 return Qnil;
2610 /***********************************************************************
2611 Mouse
2612 ***********************************************************************/
2614 #ifdef HAVE_GPM
2616 #ifndef HAVE_WINDOW_SYSTEM
2617 void
2618 term_mouse_moveto (int x, int y)
2620 /* TODO: how to set mouse position?
2621 const char *name;
2622 int fd;
2623 name = (const char *) ttyname (0);
2624 fd = open (name, O_WRONLY);
2625 SOME_FUNCTION (x, y, fd);
2626 close (fd);
2627 last_mouse_x = x;
2628 last_mouse_y = y; */
2630 #endif /* HAVE_WINDOW_SYSTEM */
2632 /* Implementation of draw_row_with_mouse_face for TTY/GPM. */
2633 void
2634 tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *row,
2635 int start_hpos, int end_hpos,
2636 enum draw_glyphs_face draw)
2638 int nglyphs = end_hpos - start_hpos;
2639 struct frame *f = XFRAME (WINDOW_FRAME (w));
2640 struct tty_display_info *tty = FRAME_TTY (f);
2641 int face_id = tty->mouse_highlight.mouse_face_face_id;
2642 int save_x, save_y, pos_x, pos_y;
2644 if (end_hpos >= row->used[TEXT_AREA])
2645 nglyphs = row->used[TEXT_AREA] - start_hpos;
2647 pos_y = row->y + WINDOW_TOP_EDGE_Y (w);
2648 pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos + WINDOW_LEFT_EDGE_X (w);
2650 /* Save current cursor co-ordinates. */
2651 save_y = curY (tty);
2652 save_x = curX (tty);
2653 cursor_to (f, pos_y, pos_x);
2655 if (draw == DRAW_MOUSE_FACE)
2656 tty_write_glyphs_with_face (f, row->glyphs[TEXT_AREA] + start_hpos,
2657 nglyphs, face_id);
2658 else if (draw == DRAW_NORMAL_TEXT)
2659 write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
2661 cursor_to (f, save_y, save_x);
2664 static int
2665 term_mouse_movement (FRAME_PTR frame, Gpm_Event *event)
2667 /* Has the mouse moved off the glyph it was on at the last sighting? */
2668 if (event->x != last_mouse_x || event->y != last_mouse_y)
2670 frame->mouse_moved = 1;
2671 note_mouse_highlight (frame, event->x, event->y);
2672 /* Remember which glyph we're now on. */
2673 last_mouse_x = event->x;
2674 last_mouse_y = event->y;
2675 return 1;
2677 return 0;
2680 /* Return the current position of the mouse.
2682 Set *f to the frame the mouse is in, or zero if the mouse is in no
2683 Emacs frame. If it is set to zero, all the other arguments are
2684 garbage.
2686 Set *bar_window to Qnil, and *x and *y to the column and
2687 row of the character cell the mouse is over.
2689 Set *timeptr to the time the mouse was at the returned position.
2691 This clears mouse_moved until the next motion
2692 event arrives. */
2693 static void
2694 term_mouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
2695 enum scroll_bar_part *part, Lisp_Object *x,
2696 Lisp_Object *y, Time *timeptr)
2698 struct timeval now;
2699 Time sec, usec;
2701 *fp = SELECTED_FRAME ();
2702 (*fp)->mouse_moved = 0;
2704 *bar_window = Qnil;
2705 *part = 0;
2707 XSETINT (*x, last_mouse_x);
2708 XSETINT (*y, last_mouse_y);
2709 gettimeofday(&now, 0);
2710 sec = now.tv_sec;
2711 usec = now.tv_usec;
2712 *timeptr = (sec * 1000) + (usec / 1000);
2715 /* Prepare a mouse-event in *RESULT for placement in the input queue.
2717 If the event is a button press, then note that we have grabbed
2718 the mouse. */
2720 static Lisp_Object
2721 term_mouse_click (struct input_event *result, Gpm_Event *event,
2722 struct frame *f)
2724 struct timeval now;
2725 int i, j;
2727 result->kind = GPM_CLICK_EVENT;
2728 for (i = 0, j = GPM_B_LEFT; i < 3; i++, j >>= 1 )
2730 if (event->buttons & j) {
2731 result->code = i; /* button number */
2732 break;
2735 gettimeofday(&now, 0);
2736 result->timestamp = (now.tv_sec * 1000) + (now.tv_usec / 1000);
2738 if (event->type & GPM_UP)
2739 result->modifiers = up_modifier;
2740 else if (event->type & GPM_DOWN)
2741 result->modifiers = down_modifier;
2742 else
2743 result->modifiers = 0;
2745 if (event->type & GPM_SINGLE)
2746 result->modifiers |= click_modifier;
2748 if (event->type & GPM_DOUBLE)
2749 result->modifiers |= double_modifier;
2751 if (event->type & GPM_TRIPLE)
2752 result->modifiers |= triple_modifier;
2754 if (event->type & GPM_DRAG)
2755 result->modifiers |= drag_modifier;
2757 if (!(event->type & (GPM_MOVE | GPM_DRAG))) {
2759 /* 1 << KG_SHIFT */
2760 if (event->modifiers & (1 << 0))
2761 result->modifiers |= shift_modifier;
2763 /* 1 << KG_CTRL */
2764 if (event->modifiers & (1 << 2))
2765 result->modifiers |= ctrl_modifier;
2767 /* 1 << KG_ALT || KG_ALTGR */
2768 if (event->modifiers & (1 << 3)
2769 || event->modifiers & (1 << 1))
2770 result->modifiers |= meta_modifier;
2773 XSETINT (result->x, event->x);
2774 XSETINT (result->y, event->y);
2775 XSETFRAME (result->frame_or_window, f);
2776 result->arg = Qnil;
2777 return Qnil;
2781 handle_one_term_event (struct tty_display_info *tty, Gpm_Event *event, struct input_event* hold_quit)
2783 struct frame *f = XFRAME (tty->top_frame);
2784 struct input_event ie;
2785 int do_help = 0;
2786 int count = 0;
2788 EVENT_INIT (ie);
2789 ie.kind = NO_EVENT;
2790 ie.arg = Qnil;
2792 if (event->type & (GPM_MOVE | GPM_DRAG)) {
2793 previous_help_echo_string = help_echo_string;
2794 help_echo_string = Qnil;
2796 Gpm_DrawPointer (event->x, event->y, fileno (tty->output));
2798 if (!term_mouse_movement (f, event))
2799 help_echo_string = previous_help_echo_string;
2801 /* If the contents of the global variable help_echo_string
2802 has changed, generate a HELP_EVENT. */
2803 if (!NILP (help_echo_string)
2804 || !NILP (previous_help_echo_string))
2805 do_help = 1;
2807 goto done;
2809 else {
2810 f->mouse_moved = 0;
2811 term_mouse_click (&ie, event, f);
2814 done:
2815 if (ie.kind != NO_EVENT)
2817 kbd_buffer_store_event_hold (&ie, hold_quit);
2818 count++;
2821 if (do_help
2822 && !(hold_quit && hold_quit->kind != NO_EVENT))
2824 Lisp_Object frame;
2826 if (f)
2827 XSETFRAME (frame, f);
2828 else
2829 frame = Qnil;
2831 gen_help_event (help_echo_string, frame, help_echo_window,
2832 help_echo_object, help_echo_pos);
2833 count++;
2836 return count;
2839 DEFUN ("gpm-mouse-start", Fgpm_mouse_start, Sgpm_mouse_start,
2840 0, 0, 0,
2841 doc: /* Open a connection to Gpm.
2842 Gpm-mouse can only be activated for one tty at a time. */)
2843 (void)
2845 struct frame *f = SELECTED_FRAME ();
2846 struct tty_display_info *tty
2847 = ((f)->output_method == output_termcap
2848 ? (f)->terminal->display_info.tty : NULL);
2849 Gpm_Connect connection;
2851 if (!tty)
2852 error ("Gpm-mouse only works in the GNU/Linux console");
2853 if (gpm_tty == tty)
2854 return Qnil; /* Already activated, nothing to do. */
2855 if (gpm_tty)
2856 error ("Gpm-mouse can only be activated for one tty at a time");
2858 connection.eventMask = ~0;
2859 connection.defaultMask = ~GPM_HARD;
2860 connection.maxMod = ~0;
2861 connection.minMod = 0;
2862 gpm_zerobased = 1;
2864 if (Gpm_Open (&connection, 0) < 0)
2865 error ("Gpm-mouse failed to connect to the gpm daemon");
2866 else
2868 gpm_tty = tty;
2869 /* `init_sys_modes' arranges for mouse movements sent through gpm_fd
2870 to generate SIGIOs. Apparently we need to call reset_sys_modes
2871 before calling init_sys_modes. */
2872 reset_sys_modes (tty);
2873 init_sys_modes (tty);
2874 add_gpm_wait_descriptor (gpm_fd);
2875 return Qnil;
2879 void
2880 close_gpm (int fd)
2882 if (fd >= 0)
2883 delete_gpm_wait_descriptor (fd);
2884 while (Gpm_Close()); /* close all the stack */
2885 gpm_tty = NULL;
2888 DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop, Sgpm_mouse_stop,
2889 0, 0, 0,
2890 doc: /* Close a connection to Gpm. */)
2891 (void)
2893 struct frame *f = SELECTED_FRAME ();
2894 struct tty_display_info *tty
2895 = ((f)->output_method == output_termcap
2896 ? (f)->terminal->display_info.tty : NULL);
2898 if (!tty || gpm_tty != tty)
2899 return Qnil; /* Not activated on this terminal, nothing to do. */
2901 close_gpm (gpm_fd);
2902 return Qnil;
2904 #endif /* HAVE_GPM */
2907 #ifndef MSDOS
2908 /***********************************************************************
2909 Initialization
2910 ***********************************************************************/
2912 /* Initialize the tty-dependent part of frame F. The frame must
2913 already have its device initialized. */
2915 void
2916 create_tty_output (struct frame *f)
2918 struct tty_output *t;
2920 if (! FRAME_TERMCAP_P (f))
2921 abort ();
2923 t = xmalloc (sizeof (struct tty_output));
2924 memset (t, 0, sizeof (struct tty_output));
2926 t->display_info = FRAME_TERMINAL (f)->display_info.tty;
2928 f->output_data.tty = t;
2931 /* Delete frame F's face cache, and its tty-dependent part. */
2933 static void
2934 tty_free_frame_resources (struct frame *f)
2936 if (! FRAME_TERMCAP_P (f))
2937 abort ();
2939 if (FRAME_FACE_CACHE (f))
2940 free_frame_faces (f);
2942 xfree (f->output_data.tty);
2945 #else /* MSDOS */
2947 /* Delete frame F's face cache. */
2949 static void
2950 tty_free_frame_resources (struct frame *f)
2952 if (! FRAME_TERMCAP_P (f) && ! FRAME_MSDOS_P (f))
2953 abort ();
2955 if (FRAME_FACE_CACHE (f))
2956 free_frame_faces (f);
2958 #endif /* MSDOS */
2960 /* Reset the hooks in TERMINAL. */
2962 static void
2963 clear_tty_hooks (struct terminal *terminal)
2965 terminal->rif = 0;
2966 terminal->cursor_to_hook = 0;
2967 terminal->raw_cursor_to_hook = 0;
2968 terminal->clear_to_end_hook = 0;
2969 terminal->clear_frame_hook = 0;
2970 terminal->clear_end_of_line_hook = 0;
2971 terminal->ins_del_lines_hook = 0;
2972 terminal->insert_glyphs_hook = 0;
2973 terminal->write_glyphs_hook = 0;
2974 terminal->delete_glyphs_hook = 0;
2975 terminal->ring_bell_hook = 0;
2976 terminal->reset_terminal_modes_hook = 0;
2977 terminal->set_terminal_modes_hook = 0;
2978 terminal->update_begin_hook = 0;
2979 terminal->update_end_hook = 0;
2980 terminal->set_terminal_window_hook = 0;
2981 terminal->mouse_position_hook = 0;
2982 terminal->frame_rehighlight_hook = 0;
2983 terminal->frame_raise_lower_hook = 0;
2984 terminal->fullscreen_hook = 0;
2985 terminal->set_vertical_scroll_bar_hook = 0;
2986 terminal->condemn_scroll_bars_hook = 0;
2987 terminal->redeem_scroll_bar_hook = 0;
2988 terminal->judge_scroll_bars_hook = 0;
2989 terminal->read_socket_hook = 0;
2990 terminal->frame_up_to_date_hook = 0;
2992 /* Leave these two set, or suspended frames are not deleted
2993 correctly. */
2994 terminal->delete_frame_hook = &tty_free_frame_resources;
2995 terminal->delete_terminal_hook = &delete_tty;
2998 /* Initialize hooks in TERMINAL with the values needed for a tty. */
3000 static void
3001 set_tty_hooks (struct terminal *terminal)
3003 terminal->rif = 0; /* ttys don't support window-based redisplay. */
3005 terminal->cursor_to_hook = &tty_cursor_to;
3006 terminal->raw_cursor_to_hook = &tty_raw_cursor_to;
3008 terminal->clear_to_end_hook = &tty_clear_to_end;
3009 terminal->clear_frame_hook = &tty_clear_frame;
3010 terminal->clear_end_of_line_hook = &tty_clear_end_of_line;
3012 terminal->ins_del_lines_hook = &tty_ins_del_lines;
3014 terminal->insert_glyphs_hook = &tty_insert_glyphs;
3015 terminal->write_glyphs_hook = &tty_write_glyphs;
3016 terminal->delete_glyphs_hook = &tty_delete_glyphs;
3018 terminal->ring_bell_hook = &tty_ring_bell;
3020 terminal->reset_terminal_modes_hook = &tty_reset_terminal_modes;
3021 terminal->set_terminal_modes_hook = &tty_set_terminal_modes;
3022 terminal->update_begin_hook = 0; /* Not needed. */
3023 terminal->update_end_hook = &tty_update_end;
3024 terminal->set_terminal_window_hook = &tty_set_terminal_window;
3026 terminal->mouse_position_hook = 0; /* Not needed. */
3027 terminal->frame_rehighlight_hook = 0; /* Not needed. */
3028 terminal->frame_raise_lower_hook = 0; /* Not needed. */
3030 terminal->set_vertical_scroll_bar_hook = 0; /* Not needed. */
3031 terminal->condemn_scroll_bars_hook = 0; /* Not needed. */
3032 terminal->redeem_scroll_bar_hook = 0; /* Not needed. */
3033 terminal->judge_scroll_bars_hook = 0; /* Not needed. */
3035 terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */
3036 terminal->frame_up_to_date_hook = 0; /* Not needed. */
3038 terminal->delete_frame_hook = &tty_free_frame_resources;
3039 terminal->delete_terminal_hook = &delete_tty;
3042 /* Drop the controlling terminal if fd is the same device. */
3043 static void
3044 dissociate_if_controlling_tty (int fd)
3046 #ifndef DOS_NT
3047 int pgid = tcgetpgrp (fd); /* If tcgetpgrp succeeds, fd is the ctty. */
3048 if (pgid != -1)
3050 #if defined (USG5)
3051 setpgrp ();
3052 no_controlling_tty = 1;
3053 #elif defined (CYGWIN)
3054 setsid ();
3055 no_controlling_tty = 1;
3056 #else
3057 #ifdef TIOCNOTTY /* Try BSD ioctls. */
3058 sigblock (sigmask (SIGTTOU));
3059 fd = emacs_open (DEV_TTY, O_RDWR, 0);
3060 if (fd != -1 && ioctl (fd, TIOCNOTTY, 0) != -1)
3062 no_controlling_tty = 1;
3064 if (fd != -1)
3065 emacs_close (fd);
3066 sigunblock (sigmask (SIGTTOU));
3067 #else
3068 /* Unknown system. */
3069 croak ();
3070 #endif /* ! TIOCNOTTY */
3071 #endif /* ! USG */
3073 #endif /* !DOS_NT */
3076 /* Create a termcap display on the tty device with the given name and
3077 type.
3079 If NAME is NULL, then use the controlling tty, i.e., "/dev/tty".
3080 Otherwise NAME should be a path to the tty device file,
3081 e.g. "/dev/pts/7".
3083 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
3085 If MUST_SUCCEED is true, then all errors are fatal. */
3087 struct terminal *
3088 init_tty (const char *name, const char *terminal_type, int must_succeed)
3090 char *area = NULL;
3091 char **address = &area;
3092 int buffer_size = 4096;
3093 int status;
3094 struct tty_display_info *tty = NULL;
3095 struct terminal *terminal = NULL;
3096 int ctty = 0; /* 1 if asked to open controlling tty. */
3098 if (!terminal_type)
3099 maybe_fatal (must_succeed, 0,
3100 "Unknown terminal type",
3101 "Unknown terminal type");
3103 if (name == NULL)
3104 name = DEV_TTY;
3105 if (!strcmp (name, DEV_TTY))
3106 ctty = 1;
3108 /* If we already have a terminal on the given device, use that. If
3109 all such terminals are suspended, create a new one instead. */
3110 /* XXX Perhaps this should be made explicit by having init_tty
3111 always create a new terminal and separating terminal and frame
3112 creation on Lisp level. */
3113 terminal = get_named_tty (name);
3114 if (terminal)
3115 return terminal;
3117 terminal = create_terminal ();
3118 #ifdef MSDOS
3119 if (been_here > 0)
3120 maybe_fatal (0, 0, "Attempt to create another terminal %s", "",
3121 name, "");
3122 been_here = 1;
3123 tty = &the_only_display_info;
3124 #else
3125 tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info));
3126 #endif
3127 memset (tty, 0, sizeof (struct tty_display_info));
3128 tty->next = tty_list;
3129 tty_list = tty;
3131 terminal->type = output_termcap;
3132 terminal->display_info.tty = tty;
3133 tty->terminal = terminal;
3135 tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
3136 Wcm_clear (tty);
3138 encode_terminal_src_size = 0;
3139 encode_terminal_dst_size = 0;
3142 #ifndef DOS_NT
3143 set_tty_hooks (terminal);
3146 int fd;
3147 FILE *file;
3149 #ifdef O_IGNORE_CTTY
3150 if (!ctty)
3151 /* Open the terminal device. Don't recognize it as our
3152 controlling terminal, and don't make it the controlling tty
3153 if we don't have one at the moment. */
3154 fd = emacs_open (name, O_RDWR | O_IGNORE_CTTY | O_NOCTTY, 0);
3155 else
3156 #endif /* O_IGNORE_CTTY */
3157 /* Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
3158 defined on Hurd. On other systems, we need to explicitly
3159 dissociate ourselves from the controlling tty when we want to
3160 open a frame on the same terminal. */
3161 fd = emacs_open (name, O_RDWR | O_NOCTTY, 0);
3163 tty->name = xstrdup (name);
3164 terminal->name = xstrdup (name);
3166 if (fd < 0)
3167 maybe_fatal (must_succeed, terminal,
3168 "Could not open file: %s",
3169 "Could not open file: %s",
3170 name);
3171 if (!isatty (fd))
3173 close (fd);
3174 maybe_fatal (must_succeed, terminal,
3175 "Not a tty device: %s",
3176 "Not a tty device: %s",
3177 name);
3180 #ifndef O_IGNORE_CTTY
3181 if (!ctty)
3182 dissociate_if_controlling_tty (fd);
3183 #endif
3185 file = fdopen (fd, "w+");
3186 tty->input = file;
3187 tty->output = file;
3190 tty->type = xstrdup (terminal_type);
3192 add_keyboard_wait_descriptor (fileno (tty->input));
3194 Wcm_clear (tty);
3196 tty->termcap_term_buffer = (char *) xmalloc (buffer_size);
3198 /* On some systems, tgetent tries to access the controlling
3199 terminal. */
3200 sigblock (sigmask (SIGTTOU));
3201 status = tgetent (tty->termcap_term_buffer, terminal_type);
3202 sigunblock (sigmask (SIGTTOU));
3204 if (status < 0)
3206 #ifdef TERMINFO
3207 maybe_fatal (must_succeed, terminal,
3208 "Cannot open terminfo database file",
3209 "Cannot open terminfo database file");
3210 #else
3211 maybe_fatal (must_succeed, terminal,
3212 "Cannot open termcap database file",
3213 "Cannot open termcap database file");
3214 #endif
3216 if (status == 0)
3218 maybe_fatal (must_succeed, terminal,
3219 "Terminal type %s is not defined",
3220 "Terminal type %s is not defined.\n\
3221 If that is not the actual type of terminal you have,\n\
3222 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3223 `setenv TERM ...') to specify the correct type. It may be necessary\n"
3224 #ifdef TERMINFO
3225 "to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3226 #else
3227 "to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3228 #endif
3229 terminal_type);
3232 #ifndef TERMINFO
3233 if (strlen (tty->termcap_term_buffer) >= buffer_size)
3234 abort ();
3235 buffer_size = strlen (tty->termcap_term_buffer);
3236 #endif
3237 tty->termcap_strings_buffer = area = (char *) xmalloc (buffer_size);
3238 tty->TS_ins_line = tgetstr ("al", address);
3239 tty->TS_ins_multi_lines = tgetstr ("AL", address);
3240 tty->TS_bell = tgetstr ("bl", address);
3241 BackTab (tty) = tgetstr ("bt", address);
3242 tty->TS_clr_to_bottom = tgetstr ("cd", address);
3243 tty->TS_clr_line = tgetstr ("ce", address);
3244 tty->TS_clr_frame = tgetstr ("cl", address);
3245 ColPosition (tty) = NULL; /* tgetstr ("ch", address); */
3246 AbsPosition (tty) = tgetstr ("cm", address);
3247 CR (tty) = tgetstr ("cr", address);
3248 tty->TS_set_scroll_region = tgetstr ("cs", address);
3249 tty->TS_set_scroll_region_1 = tgetstr ("cS", address);
3250 RowPosition (tty) = tgetstr ("cv", address);
3251 tty->TS_del_char = tgetstr ("dc", address);
3252 tty->TS_del_multi_chars = tgetstr ("DC", address);
3253 tty->TS_del_line = tgetstr ("dl", address);
3254 tty->TS_del_multi_lines = tgetstr ("DL", address);
3255 tty->TS_delete_mode = tgetstr ("dm", address);
3256 tty->TS_end_delete_mode = tgetstr ("ed", address);
3257 tty->TS_end_insert_mode = tgetstr ("ei", address);
3258 Home (tty) = tgetstr ("ho", address);
3259 tty->TS_ins_char = tgetstr ("ic", address);
3260 tty->TS_ins_multi_chars = tgetstr ("IC", address);
3261 tty->TS_insert_mode = tgetstr ("im", address);
3262 tty->TS_pad_inserted_char = tgetstr ("ip", address);
3263 tty->TS_end_keypad_mode = tgetstr ("ke", address);
3264 tty->TS_keypad_mode = tgetstr ("ks", address);
3265 LastLine (tty) = tgetstr ("ll", address);
3266 Right (tty) = tgetstr ("nd", address);
3267 Down (tty) = tgetstr ("do", address);
3268 if (!Down (tty))
3269 Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do" */
3270 if (tgetflag ("bs"))
3271 Left (tty) = "\b"; /* can't possibly be longer! */
3272 else /* (Actually, "bs" is obsolete...) */
3273 Left (tty) = tgetstr ("le", address);
3274 if (!Left (tty))
3275 Left (tty) = tgetstr ("bc", address); /* Obsolete name for "le" */
3276 tty->TS_pad_char = tgetstr ("pc", address);
3277 tty->TS_repeat = tgetstr ("rp", address);
3278 tty->TS_end_standout_mode = tgetstr ("se", address);
3279 tty->TS_fwd_scroll = tgetstr ("sf", address);
3280 tty->TS_standout_mode = tgetstr ("so", address);
3281 tty->TS_rev_scroll = tgetstr ("sr", address);
3282 tty->Wcm->cm_tab = tgetstr ("ta", address);
3283 tty->TS_end_termcap_modes = tgetstr ("te", address);
3284 tty->TS_termcap_modes = tgetstr ("ti", address);
3285 Up (tty) = tgetstr ("up", address);
3286 tty->TS_visible_bell = tgetstr ("vb", address);
3287 tty->TS_cursor_normal = tgetstr ("ve", address);
3288 tty->TS_cursor_visible = tgetstr ("vs", address);
3289 tty->TS_cursor_invisible = tgetstr ("vi", address);
3290 tty->TS_set_window = tgetstr ("wi", address);
3292 tty->TS_enter_underline_mode = tgetstr ("us", address);
3293 tty->TS_exit_underline_mode = tgetstr ("ue", address);
3294 tty->TS_enter_bold_mode = tgetstr ("md", address);
3295 tty->TS_enter_dim_mode = tgetstr ("mh", address);
3296 tty->TS_enter_blink_mode = tgetstr ("mb", address);
3297 tty->TS_enter_reverse_mode = tgetstr ("mr", address);
3298 tty->TS_enter_alt_charset_mode = tgetstr ("as", address);
3299 tty->TS_exit_alt_charset_mode = tgetstr ("ae", address);
3300 tty->TS_exit_attribute_mode = tgetstr ("me", address);
3302 MultiUp (tty) = tgetstr ("UP", address);
3303 MultiDown (tty) = tgetstr ("DO", address);
3304 MultiLeft (tty) = tgetstr ("LE", address);
3305 MultiRight (tty) = tgetstr ("RI", address);
3307 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
3308 color because we can't switch back to the default foreground and
3309 background. */
3310 tty->TS_orig_pair = tgetstr ("op", address);
3311 if (tty->TS_orig_pair)
3313 tty->TS_set_foreground = tgetstr ("AF", address);
3314 tty->TS_set_background = tgetstr ("AB", address);
3315 if (!tty->TS_set_foreground)
3317 /* SVr4. */
3318 tty->TS_set_foreground = tgetstr ("Sf", address);
3319 tty->TS_set_background = tgetstr ("Sb", address);
3322 tty->TN_max_colors = tgetnum ("Co");
3323 tty->TN_max_pairs = tgetnum ("pa");
3325 tty->TN_no_color_video = tgetnum ("NC");
3326 if (tty->TN_no_color_video == -1)
3327 tty->TN_no_color_video = 0;
3330 tty_default_color_capabilities (tty, 1);
3332 MagicWrap (tty) = tgetflag ("xn");
3333 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
3334 the former flag imply the latter. */
3335 AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
3336 terminal->memory_below_frame = tgetflag ("db");
3337 tty->TF_hazeltine = tgetflag ("hz");
3338 terminal->must_write_spaces = tgetflag ("in");
3339 tty->meta_key = tgetflag ("km") || tgetflag ("MT");
3340 tty->TF_insmode_motion = tgetflag ("mi");
3341 tty->TF_standout_motion = tgetflag ("ms");
3342 tty->TF_underscore = tgetflag ("ul");
3343 tty->TF_teleray = tgetflag ("xt");
3345 #else /* DOS_NT */
3346 #ifdef WINDOWSNT
3348 struct frame *f = XFRAME (selected_frame);
3350 initialize_w32_display (terminal);
3352 FrameRows (tty) = FRAME_LINES (f);
3353 FrameCols (tty) = FRAME_COLS (f);
3354 tty->specified_window = FRAME_LINES (f);
3356 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
3357 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
3358 terminal->char_ins_del_ok = 1;
3359 baud_rate = 19200;
3361 #else /* MSDOS */
3363 int height, width;
3364 if (strcmp (terminal_type, "internal") == 0)
3365 terminal->type = output_msdos_raw;
3366 initialize_msdos_display (terminal);
3368 get_tty_size (fileno (tty->input), &width, &height);
3369 FrameCols (tty) = width;
3370 FrameRows (tty) = height;
3371 terminal->char_ins_del_ok = 0;
3372 init_baud_rate (fileno (tty->input));
3374 #endif /* MSDOS */
3375 tty->output = stdout;
3376 tty->input = stdin;
3377 /* The following two are inaccessible from w32console.c. */
3378 terminal->delete_frame_hook = &tty_free_frame_resources;
3379 terminal->delete_terminal_hook = &delete_tty;
3381 tty->name = xstrdup (name);
3382 terminal->name = xstrdup (name);
3383 tty->type = xstrdup (terminal_type);
3385 add_keyboard_wait_descriptor (0);
3387 tty->delete_in_insert_mode = 1;
3389 UseTabs (tty) = 0;
3390 terminal->scroll_region_ok = 0;
3392 /* Seems to insert lines when it's not supposed to, messing up the
3393 display. In doing a trace, it didn't seem to be called much, so I
3394 don't think we're losing anything by turning it off. */
3395 terminal->line_ins_del_ok = 0;
3397 tty->TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
3398 #endif /* DOS_NT */
3400 #ifdef HAVE_GPM
3401 terminal->mouse_position_hook = term_mouse_position;
3402 tty->mouse_highlight.mouse_face_window = Qnil;
3403 #endif
3405 terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
3406 init_kboard (terminal->kboard);
3407 KVAR (terminal->kboard, Vwindow_system) = Qnil;
3408 terminal->kboard->next_kboard = all_kboards;
3409 all_kboards = terminal->kboard;
3410 terminal->kboard->reference_count++;
3411 /* Don't let the initial kboard remain current longer than necessary.
3412 That would cause problems if a file loaded on startup tries to
3413 prompt in the mini-buffer. */
3414 if (current_kboard == initial_kboard)
3415 current_kboard = terminal->kboard;
3416 #ifndef DOS_NT
3417 term_get_fkeys (address, terminal->kboard);
3419 /* Get frame size from system, or else from termcap. */
3421 int height, width;
3422 get_tty_size (fileno (tty->input), &width, &height);
3423 FrameCols (tty) = width;
3424 FrameRows (tty) = height;
3427 if (FrameCols (tty) <= 0)
3428 FrameCols (tty) = tgetnum ("co");
3429 if (FrameRows (tty) <= 0)
3430 FrameRows (tty) = tgetnum ("li");
3432 if (FrameRows (tty) < 3 || FrameCols (tty) < 3)
3433 maybe_fatal (must_succeed, terminal,
3434 "Screen size %dx%d is too small",
3435 "Screen size %dx%d is too small",
3436 FrameCols (tty), FrameRows (tty));
3438 TabWidth (tty) = tgetnum ("tw");
3440 if (!tty->TS_bell)
3441 tty->TS_bell = "\07";
3443 if (!tty->TS_fwd_scroll)
3444 tty->TS_fwd_scroll = Down (tty);
3446 PC = tty->TS_pad_char ? *tty->TS_pad_char : 0;
3448 if (TabWidth (tty) < 0)
3449 TabWidth (tty) = 8;
3451 /* Turned off since /etc/termcap seems to have :ta= for most terminals
3452 and newer termcap doc does not seem to say there is a default.
3453 if (!tty->Wcm->cm_tab)
3454 tty->Wcm->cm_tab = "\t";
3457 /* We don't support standout modes that use `magic cookies', so
3458 turn off any that do. */
3459 if (tty->TS_standout_mode && tgetnum ("sg") >= 0)
3461 tty->TS_standout_mode = 0;
3462 tty->TS_end_standout_mode = 0;
3464 if (tty->TS_enter_underline_mode && tgetnum ("ug") >= 0)
3466 tty->TS_enter_underline_mode = 0;
3467 tty->TS_exit_underline_mode = 0;
3470 /* If there's no standout mode, try to use underlining instead. */
3471 if (tty->TS_standout_mode == 0)
3473 tty->TS_standout_mode = tty->TS_enter_underline_mode;
3474 tty->TS_end_standout_mode = tty->TS_exit_underline_mode;
3477 /* If no `se' string, try using a `me' string instead.
3478 If that fails, we can't use standout mode at all. */
3479 if (tty->TS_end_standout_mode == 0)
3481 char *s = tgetstr ("me", address);
3482 if (s != 0)
3483 tty->TS_end_standout_mode = s;
3484 else
3485 tty->TS_standout_mode = 0;
3488 if (tty->TF_teleray)
3490 tty->Wcm->cm_tab = 0;
3491 /* We can't support standout mode, because it uses magic cookies. */
3492 tty->TS_standout_mode = 0;
3493 /* But that means we cannot rely on ^M to go to column zero! */
3494 CR (tty) = 0;
3495 /* LF can't be trusted either -- can alter hpos */
3496 /* if move at column 0 thru a line with TS_standout_mode */
3497 Down (tty) = 0;
3500 tty->specified_window = FrameRows (tty);
3502 if (Wcm_init (tty) == -1) /* can't do cursor motion */
3504 maybe_fatal (must_succeed, terminal,
3505 "Terminal type \"%s\" is not powerful enough to run Emacs",
3506 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3507 It lacks the ability to position the cursor.\n\
3508 If that is not the actual type of terminal you have,\n\
3509 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3510 `setenv TERM ...') to specify the correct type. It may be necessary\n"
3511 # ifdef TERMINFO
3512 "to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3513 # else /* TERMCAP */
3514 "to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3515 # endif /* TERMINFO */
3516 terminal_type);
3519 if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
3520 maybe_fatal (must_succeed, terminal,
3521 "Could not determine the frame size",
3522 "Could not determine the frame size");
3524 tty->delete_in_insert_mode
3525 = tty->TS_delete_mode && tty->TS_insert_mode
3526 && !strcmp (tty->TS_delete_mode, tty->TS_insert_mode);
3528 tty->se_is_so = (tty->TS_standout_mode
3529 && tty->TS_end_standout_mode
3530 && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode));
3532 UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8;
3534 terminal->scroll_region_ok
3535 = (tty->Wcm->cm_abs
3536 && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
3538 terminal->line_ins_del_ok
3539 = (((tty->TS_ins_line || tty->TS_ins_multi_lines)
3540 && (tty->TS_del_line || tty->TS_del_multi_lines))
3541 || (terminal->scroll_region_ok
3542 && tty->TS_fwd_scroll && tty->TS_rev_scroll));
3544 terminal->char_ins_del_ok
3545 = ((tty->TS_ins_char || tty->TS_insert_mode
3546 || tty->TS_pad_inserted_char || tty->TS_ins_multi_chars)
3547 && (tty->TS_del_char || tty->TS_del_multi_chars));
3549 terminal->fast_clear_end_of_line = tty->TS_clr_line != 0;
3551 init_baud_rate (fileno (tty->input));
3553 #endif /* not DOS_NT */
3555 /* Init system terminal modes (RAW or CBREAK, etc.). */
3556 init_sys_modes (tty);
3558 return terminal;
3562 static void
3563 vfatal (const char *str, va_list ap)
3565 fprintf (stderr, "emacs: ");
3566 vfprintf (stderr, str, ap);
3567 if (!(strlen (str) > 0 && str[strlen (str) - 1] == '\n'))
3568 fprintf (stderr, "\n");
3569 fflush (stderr);
3570 exit (1);
3574 /* Auxiliary error-handling function for init_tty.
3575 Delete TERMINAL, then call error or fatal with str1 or str2,
3576 respectively, according to whether MUST_SUCCEED is zero or not. */
3578 static void
3579 maybe_fatal (int must_succeed, struct terminal *terminal,
3580 const char *str1, const char *str2, ...)
3582 va_list ap;
3583 va_start (ap, str2);
3584 if (terminal)
3585 delete_tty (terminal);
3587 if (must_succeed)
3588 vfatal (str2, ap);
3589 else
3590 verror (str1, ap);
3592 va_end (ap);
3593 abort ();
3596 void
3597 fatal (const char *str, ...)
3599 va_list ap;
3600 va_start (ap, str);
3601 vfatal (str, ap);
3602 va_end (ap);
3607 /* Delete the given tty terminal, closing all frames on it. */
3609 static void
3610 delete_tty (struct terminal *terminal)
3612 struct tty_display_info *tty;
3614 /* Protect against recursive calls. delete_frame in
3615 delete_terminal calls us back when it deletes our last frame. */
3616 if (!terminal->name)
3617 return;
3619 if (terminal->type != output_termcap)
3620 abort ();
3622 tty = terminal->display_info.tty;
3624 if (tty == tty_list)
3625 tty_list = tty->next;
3626 else
3628 struct tty_display_info *p;
3629 for (p = tty_list; p && p->next != tty; p = p->next)
3632 if (! p)
3633 /* This should not happen. */
3634 abort ();
3636 p->next = tty->next;
3637 tty->next = 0;
3640 /* reset_sys_modes needs a valid device, so this call needs to be
3641 before delete_terminal. */
3642 reset_sys_modes (tty);
3644 delete_terminal (terminal);
3646 xfree (tty->name);
3647 xfree (tty->type);
3649 if (tty->input)
3651 delete_keyboard_wait_descriptor (fileno (tty->input));
3652 if (tty->input != stdin)
3653 fclose (tty->input);
3655 if (tty->output && tty->output != stdout && tty->output != tty->input)
3656 fclose (tty->output);
3657 if (tty->termscript)
3658 fclose (tty->termscript);
3660 xfree (tty->old_tty);
3661 xfree (tty->Wcm);
3662 xfree (tty->termcap_strings_buffer);
3663 xfree (tty->termcap_term_buffer);
3665 memset (tty, 0, sizeof (struct tty_display_info));
3666 xfree (tty);
3671 /* Mark the pointers in the tty_display_info objects.
3672 Called by the Fgarbage_collector. */
3674 void
3675 mark_ttys (void)
3677 struct tty_display_info *tty;
3679 for (tty = tty_list; tty; tty = tty->next)
3680 mark_object (tty->top_frame);
3685 void
3686 syms_of_term (void)
3688 DEFVAR_BOOL ("system-uses-terminfo", system_uses_terminfo,
3689 doc: /* Non-nil means the system uses terminfo rather than termcap.
3690 This variable can be used by terminal emulator packages. */);
3691 #ifdef TERMINFO
3692 system_uses_terminfo = 1;
3693 #else
3694 system_uses_terminfo = 0;
3695 #endif
3697 DEFVAR_LISP ("suspend-tty-functions", Vsuspend_tty_functions,
3698 doc: /* Functions to be run after suspending a tty.
3699 The functions are run with one argument, the terminal object to be suspended.
3700 See `suspend-tty'. */);
3701 Vsuspend_tty_functions = Qnil;
3704 DEFVAR_LISP ("resume-tty-functions", Vresume_tty_functions,
3705 doc: /* Functions to be run after resuming a tty.
3706 The functions are run with one argument, the terminal object that was revived.
3707 See `resume-tty'. */);
3708 Vresume_tty_functions = Qnil;
3710 DEFVAR_BOOL ("visible-cursor", visible_cursor,
3711 doc: /* Non-nil means to make the cursor very visible.
3712 This only has an effect when running in a text terminal.
3713 What means \"very visible\" is up to your terminal. It may make the cursor
3714 bigger, or it may make it blink, or it may do nothing at all. */);
3715 visible_cursor = 1;
3717 defsubr (&Stty_display_color_p);
3718 defsubr (&Stty_display_color_cells);
3719 defsubr (&Stty_no_underline);
3720 defsubr (&Stty_type);
3721 defsubr (&Scontrolling_tty_p);
3722 defsubr (&Ssuspend_tty);
3723 defsubr (&Sresume_tty);
3724 #ifdef HAVE_GPM
3725 defsubr (&Sgpm_mouse_start);
3726 defsubr (&Sgpm_mouse_stop);
3727 #endif /* HAVE_GPM */
3729 #ifndef DOS_NT
3730 default_orig_pair = NULL;
3731 default_set_foreground = NULL;
3732 default_set_background = NULL;
3733 #endif /* !DOS_NT */
3735 encode_terminal_src = NULL;
3736 encode_terminal_dst = NULL;