* lisp/textmodes/rst.el: Minor cleanup to improve style.
[emacs.git] / src / term.c
blob4d452ed3e0050afe24cc5f28c3c7d0769c55323a
1 /* Terminal control module for terminals described by TERMCAP
2 Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1998, 2000, 2001,
3 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
4 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
21 /* New redisplay, TTY faces by Gerd Moellmann <gerd@gnu.org>. */
23 #include <config.h>
24 #include <stdio.h>
25 #include <ctype.h>
26 #include <errno.h>
27 #include <sys/file.h>
29 #ifdef HAVE_UNISTD_H
30 #include <unistd.h>
31 #endif
33 #include <signal.h>
34 #include <stdarg.h>
35 #include <setjmp.h>
37 #include "lisp.h"
38 #include "termchar.h"
39 #include "termopts.h"
40 #include "buffer.h"
41 #include "character.h"
42 #include "charset.h"
43 #include "coding.h"
44 #include "composite.h"
45 #include "keyboard.h"
46 #include "frame.h"
47 #include "disptab.h"
48 #include "termhooks.h"
49 #include "dispextern.h"
50 #include "window.h"
51 #include "keymap.h"
52 #include "blockinput.h"
53 #include "syssignal.h"
54 #include "systty.h"
55 #include "intervals.h"
56 #ifdef MSDOS
57 #include "msdos.h"
58 static int been_here = -1;
59 #endif
61 /* For now, don't try to include termcap.h. On some systems,
62 configure finds a non-standard termcap.h that the main build
63 won't find. */
64 extern void tputs (const char *, int, int (*)(int));
65 extern int tgetent (char *, const char *);
66 extern int tgetflag (char *id);
67 extern int tgetnum (char *id);
69 #include "cm.h"
70 #ifdef HAVE_X_WINDOWS
71 #include "xterm.h"
72 #endif
74 #ifndef O_RDWR
75 #define O_RDWR 2
76 #endif
78 #ifndef O_NOCTTY
79 #define O_NOCTTY 0
80 #endif
82 /* The name of the default console device. */
83 #ifdef WINDOWSNT
84 #define DEV_TTY "CONOUT$"
85 #else
86 #define DEV_TTY "/dev/tty"
87 #endif
89 static void tty_set_scroll_region (struct frame *f, int start, int stop);
90 static void turn_on_face (struct frame *, int face_id);
91 static void turn_off_face (struct frame *, int face_id);
92 static void tty_show_cursor (struct tty_display_info *);
93 static void tty_hide_cursor (struct tty_display_info *);
94 static void tty_background_highlight (struct tty_display_info *tty);
95 static void clear_tty_hooks (struct terminal *terminal);
96 static void set_tty_hooks (struct terminal *terminal);
97 static void dissociate_if_controlling_tty (int fd);
98 static void delete_tty (struct terminal *);
99 static void maybe_fatal (int must_succeed, struct terminal *terminal,
100 const char *str1, const char *str2, ...) NO_RETURN;
101 static void vfatal (const char *str, va_list ap) NO_RETURN;
104 #define OUTPUT(tty, a) \
105 emacs_tputs ((tty), a, \
106 (int) (FRAME_LINES (XFRAME (selected_frame)) \
107 - curY (tty)), \
108 cmputc)
110 #define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
111 #define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
113 #define OUTPUT_IF(tty, a) \
114 do { \
115 if (a) \
116 emacs_tputs ((tty), a, \
117 (int) (FRAME_LINES (XFRAME (selected_frame)) \
118 - curY (tty) ), \
119 cmputc); \
120 } while (0)
122 #define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
124 /* If true, use "vs", otherwise use "ve" to make the cursor visible. */
126 static int visible_cursor;
128 /* Display space properties */
130 /* Functions to call after suspending a tty. */
131 Lisp_Object Vsuspend_tty_functions;
133 /* Functions to call after resuming a tty. */
134 Lisp_Object Vresume_tty_functions;
136 /* Chain of all tty device parameters. */
137 struct tty_display_info *tty_list;
139 /* Nonzero means no need to redraw the entire frame on resuming a
140 suspended Emacs. This is useful on terminals with multiple
141 pages, where one page is used for Emacs and another for all
142 else. */
143 int no_redraw_on_reenter;
145 /* Meaning of bits in no_color_video. Each bit set means that the
146 corresponding attribute cannot be combined with colors. */
148 enum no_color_bit
150 NC_STANDOUT = 1 << 0,
151 NC_UNDERLINE = 1 << 1,
152 NC_REVERSE = 1 << 2,
153 NC_BLINK = 1 << 3,
154 NC_DIM = 1 << 4,
155 NC_BOLD = 1 << 5,
156 NC_INVIS = 1 << 6,
157 NC_PROTECT = 1 << 7,
158 NC_ALT_CHARSET = 1 << 8
161 /* internal state */
163 /* The largest frame width in any call to calculate_costs. */
165 int max_frame_cols;
167 /* The largest frame height in any call to calculate_costs. */
169 int max_frame_lines;
171 /* Non-zero if we have dropped our controlling tty and therefore
172 should not open a frame on stdout. */
173 static int no_controlling_tty;
175 /* Provided for lisp packages. */
177 static int system_uses_terminfo;
179 char *tparam (char *, char *, int, int, ...);
181 extern char *tgetstr (char *, char **);
184 #ifdef HAVE_GPM
185 #include <sys/fcntl.h>
187 /* The device for which we have enabled gpm support (or NULL). */
188 struct tty_display_info *gpm_tty = NULL;
190 /* Last recorded mouse coordinates. */
191 static int last_mouse_x, last_mouse_y;
192 #endif /* HAVE_GPM */
194 /* Ring the bell on a tty. */
196 static void
197 tty_ring_bell (struct frame *f)
199 struct tty_display_info *tty = FRAME_TTY (f);
201 if (tty->output)
203 OUTPUT (tty, (tty->TS_visible_bell && visible_bell
204 ? tty->TS_visible_bell
205 : tty->TS_bell));
206 fflush (tty->output);
210 /* Set up termcap modes for Emacs. */
212 void
213 tty_set_terminal_modes (struct terminal *terminal)
215 struct tty_display_info *tty = terminal->display_info.tty;
217 if (tty->output)
219 if (tty->TS_termcap_modes)
220 OUTPUT (tty, tty->TS_termcap_modes);
221 else
223 /* Output enough newlines to scroll all the old screen contents
224 off the screen, so it won't be overwritten and lost. */
225 int i;
226 current_tty = tty;
227 for (i = 0; i < FRAME_LINES (XFRAME (selected_frame)); i++)
228 cmputc ('\n');
231 OUTPUT_IF (tty, visible_cursor ? tty->TS_cursor_visible : tty->TS_cursor_normal);
232 OUTPUT_IF (tty, tty->TS_keypad_mode);
233 losecursor (tty);
234 fflush (tty->output);
238 /* Reset termcap modes before exiting Emacs. */
240 void
241 tty_reset_terminal_modes (struct terminal *terminal)
243 struct tty_display_info *tty = terminal->display_info.tty;
245 if (tty->output)
247 tty_turn_off_highlight (tty);
248 tty_turn_off_insert (tty);
249 OUTPUT_IF (tty, tty->TS_end_keypad_mode);
250 OUTPUT_IF (tty, tty->TS_cursor_normal);
251 OUTPUT_IF (tty, tty->TS_end_termcap_modes);
252 OUTPUT_IF (tty, tty->TS_orig_pair);
253 /* Output raw CR so kernel can track the cursor hpos. */
254 current_tty = tty;
255 cmputc ('\r');
256 fflush (tty->output);
260 /* Flag the end of a display update on a termcap terminal. */
262 static void
263 tty_update_end (struct frame *f)
265 struct tty_display_info *tty = FRAME_TTY (f);
267 if (!XWINDOW (selected_window)->cursor_off_p)
268 tty_show_cursor (tty);
269 tty_turn_off_insert (tty);
270 tty_background_highlight (tty);
273 /* The implementation of set_terminal_window for termcap frames. */
275 static void
276 tty_set_terminal_window (struct frame *f, int size)
278 struct tty_display_info *tty = FRAME_TTY (f);
280 tty->specified_window = size ? size : FRAME_LINES (f);
281 if (FRAME_SCROLL_REGION_OK (f))
282 tty_set_scroll_region (f, 0, tty->specified_window);
285 static void
286 tty_set_scroll_region (struct frame *f, int start, int stop)
288 char *buf;
289 struct tty_display_info *tty = FRAME_TTY (f);
291 if (tty->TS_set_scroll_region)
292 buf = tparam (tty->TS_set_scroll_region, 0, 0, start, stop - 1);
293 else if (tty->TS_set_scroll_region_1)
294 buf = tparam (tty->TS_set_scroll_region_1, 0, 0,
295 FRAME_LINES (f), start,
296 FRAME_LINES (f) - stop,
297 FRAME_LINES (f));
298 else
299 buf = tparam (tty->TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (f));
301 OUTPUT (tty, buf);
302 xfree (buf);
303 losecursor (tty);
307 static void
308 tty_turn_on_insert (struct tty_display_info *tty)
310 if (!tty->insert_mode)
311 OUTPUT (tty, tty->TS_insert_mode);
312 tty->insert_mode = 1;
315 void
316 tty_turn_off_insert (struct tty_display_info *tty)
318 if (tty->insert_mode)
319 OUTPUT (tty, tty->TS_end_insert_mode);
320 tty->insert_mode = 0;
323 /* Handle highlighting. */
325 void
326 tty_turn_off_highlight (struct tty_display_info *tty)
328 if (tty->standout_mode)
329 OUTPUT_IF (tty, tty->TS_end_standout_mode);
330 tty->standout_mode = 0;
333 static void
334 tty_turn_on_highlight (struct tty_display_info *tty)
336 if (!tty->standout_mode)
337 OUTPUT_IF (tty, tty->TS_standout_mode);
338 tty->standout_mode = 1;
341 static void
342 tty_toggle_highlight (struct tty_display_info *tty)
344 if (tty->standout_mode)
345 tty_turn_off_highlight (tty);
346 else
347 tty_turn_on_highlight (tty);
351 /* Make cursor invisible. */
353 static void
354 tty_hide_cursor (struct tty_display_info *tty)
356 if (tty->cursor_hidden == 0)
358 tty->cursor_hidden = 1;
359 OUTPUT_IF (tty, tty->TS_cursor_invisible);
364 /* Ensure that cursor is visible. */
366 static void
367 tty_show_cursor (struct tty_display_info *tty)
369 if (tty->cursor_hidden)
371 tty->cursor_hidden = 0;
372 OUTPUT_IF (tty, tty->TS_cursor_normal);
373 if (visible_cursor)
374 OUTPUT_IF (tty, tty->TS_cursor_visible);
379 /* Set standout mode to the state it should be in for
380 empty space inside windows. What this is,
381 depends on the user option inverse-video. */
383 static void
384 tty_background_highlight (struct tty_display_info *tty)
386 if (inverse_video)
387 tty_turn_on_highlight (tty);
388 else
389 tty_turn_off_highlight (tty);
392 /* Set standout mode to the mode specified for the text to be output. */
394 static void
395 tty_highlight_if_desired (struct tty_display_info *tty)
397 if (inverse_video)
398 tty_turn_on_highlight (tty);
399 else
400 tty_turn_off_highlight (tty);
404 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
405 frame-relative coordinates. */
407 static void
408 tty_cursor_to (struct frame *f, int vpos, int hpos)
410 struct tty_display_info *tty = FRAME_TTY (f);
412 /* Detect the case where we are called from reset_sys_modes
413 and the costs have never been calculated. Do nothing. */
414 if (! tty->costs_set)
415 return;
417 if (curY (tty) == vpos
418 && curX (tty) == hpos)
419 return;
420 if (!tty->TF_standout_motion)
421 tty_background_highlight (tty);
422 if (!tty->TF_insmode_motion)
423 tty_turn_off_insert (tty);
424 cmgoto (tty, vpos, hpos);
427 /* Similar but don't take any account of the wasted characters. */
429 static void
430 tty_raw_cursor_to (struct frame *f, int row, int col)
432 struct tty_display_info *tty = FRAME_TTY (f);
434 if (curY (tty) == row
435 && curX (tty) == col)
436 return;
437 if (!tty->TF_standout_motion)
438 tty_background_highlight (tty);
439 if (!tty->TF_insmode_motion)
440 tty_turn_off_insert (tty);
441 cmgoto (tty, row, col);
444 /* Erase operations */
446 /* Clear from cursor to end of frame on a termcap device. */
448 static void
449 tty_clear_to_end (struct frame *f)
451 register int i;
452 struct tty_display_info *tty = FRAME_TTY (f);
454 if (tty->TS_clr_to_bottom)
456 tty_background_highlight (tty);
457 OUTPUT (tty, tty->TS_clr_to_bottom);
459 else
461 for (i = curY (tty); i < FRAME_LINES (f); i++)
463 cursor_to (f, i, 0);
464 clear_end_of_line (f, FRAME_COLS (f));
469 /* Clear an entire termcap frame. */
471 static void
472 tty_clear_frame (struct frame *f)
474 struct tty_display_info *tty = FRAME_TTY (f);
476 if (tty->TS_clr_frame)
478 tty_background_highlight (tty);
479 OUTPUT (tty, tty->TS_clr_frame);
480 cmat (tty, 0, 0);
482 else
484 cursor_to (f, 0, 0);
485 clear_to_end (f);
489 /* An implementation of clear_end_of_line for termcap frames.
491 Note that the cursor may be moved, on terminals lacking a `ce' string. */
493 static void
494 tty_clear_end_of_line (struct frame *f, int first_unused_hpos)
496 register int i;
497 struct tty_display_info *tty = FRAME_TTY (f);
499 /* Detect the case where we are called from reset_sys_modes
500 and the costs have never been calculated. Do nothing. */
501 if (! tty->costs_set)
502 return;
504 if (curX (tty) >= first_unused_hpos)
505 return;
506 tty_background_highlight (tty);
507 if (tty->TS_clr_line)
509 OUTPUT1 (tty, tty->TS_clr_line);
511 else
512 { /* have to do it the hard way */
513 tty_turn_off_insert (tty);
515 /* Do not write in last row last col with Auto-wrap on. */
516 if (AutoWrap (tty)
517 && curY (tty) == FrameRows (tty) - 1
518 && first_unused_hpos == FrameCols (tty))
519 first_unused_hpos--;
521 for (i = curX (tty); i < first_unused_hpos; i++)
523 if (tty->termscript)
524 fputc (' ', tty->termscript);
525 fputc (' ', tty->output);
527 cmplus (tty, first_unused_hpos - curX (tty));
531 /* Buffers to store the source and result of code conversion for terminal. */
532 static unsigned char *encode_terminal_src;
533 static unsigned char *encode_terminal_dst;
534 /* Allocated sizes of the above buffers. */
535 static int encode_terminal_src_size;
536 static int encode_terminal_dst_size;
538 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes.
539 Set CODING->produced to the byte-length of the resulting byte
540 sequence, and return a pointer to that byte sequence. */
542 unsigned char *
543 encode_terminal_code (struct glyph *src, int src_len, struct coding_system *coding)
545 struct glyph *src_end = src + src_len;
546 unsigned char *buf;
547 int nchars, nbytes, required;
548 register int tlen = GLYPH_TABLE_LENGTH;
549 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
550 Lisp_Object charset_list;
552 /* Allocate sufficient size of buffer to store all characters in
553 multibyte-form. But, it may be enlarged on demand if
554 Vglyph_table contains a string or a composite glyph is
555 encountered. */
556 required = MAX_MULTIBYTE_LENGTH * src_len;
557 if (encode_terminal_src_size < required)
559 if (encode_terminal_src)
560 encode_terminal_src = xrealloc (encode_terminal_src, required);
561 else
562 encode_terminal_src = xmalloc (required);
563 encode_terminal_src_size = required;
566 charset_list = coding_charset_list (coding);
568 buf = encode_terminal_src;
569 nchars = 0;
570 while (src < src_end)
572 if (src->type == COMPOSITE_GLYPH)
574 struct composition *cmp;
575 Lisp_Object gstring;
576 int i;
578 nbytes = buf - encode_terminal_src;
579 if (src->u.cmp.automatic)
581 gstring = composition_gstring_from_id (src->u.cmp.id);
582 required = src->slice.cmp.to + 1 - src->slice.cmp.from;
584 else
586 cmp = composition_table[src->u.cmp.id];
587 required = MAX_MULTIBYTE_LENGTH * cmp->glyph_len;
590 if (encode_terminal_src_size < nbytes + required)
592 encode_terminal_src_size = nbytes + required;
593 encode_terminal_src = xrealloc (encode_terminal_src,
594 encode_terminal_src_size);
595 buf = encode_terminal_src + nbytes;
598 if (src->u.cmp.automatic)
599 for (i = src->slice.cmp.from; i <= src->slice.cmp.to; i++)
601 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
602 int c = LGLYPH_CHAR (g);
604 if (! char_charset (c, charset_list, NULL))
605 c = '?';
606 buf += CHAR_STRING (c, buf);
607 nchars++;
609 else
610 for (i = 0; i < cmp->glyph_len; i++)
612 int c = COMPOSITION_GLYPH (cmp, i);
614 if (c == '\t')
615 continue;
616 if (char_charset (c, charset_list, NULL))
618 if (CHAR_WIDTH (c) == 0
619 && i > 0 && COMPOSITION_GLYPH (cmp, i - 1) == '\t')
620 /* Should be left-padded */
622 buf += CHAR_STRING (' ', buf);
623 nchars++;
626 else
627 c = '?';
628 buf += CHAR_STRING (c, buf);
629 nchars++;
632 /* We must skip glyphs to be padded for a wide character. */
633 else if (! CHAR_GLYPH_PADDING_P (*src))
635 GLYPH g;
636 int c;
637 Lisp_Object string;
639 string = Qnil;
640 SET_GLYPH_FROM_CHAR_GLYPH (g, src[0]);
642 if (GLYPH_INVALID_P (g) || GLYPH_SIMPLE_P (tbase, tlen, g))
644 /* This glyph doesn't have an entry in Vglyph_table. */
645 c = src->u.ch;
647 else
649 /* This glyph has an entry in Vglyph_table,
650 so process any alias before testing for simpleness. */
651 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
653 if (GLYPH_SIMPLE_P (tbase, tlen, g))
654 /* We set the multi-byte form of a character in G
655 (that should be an ASCII character) at WORKBUF. */
656 c = GLYPH_CHAR (g);
657 else
658 /* We have a string in Vglyph_table. */
659 string = tbase[GLYPH_CHAR (g)];
662 if (NILP (string))
664 nbytes = buf - encode_terminal_src;
665 if (encode_terminal_src_size < nbytes + MAX_MULTIBYTE_LENGTH)
667 encode_terminal_src_size = nbytes + MAX_MULTIBYTE_LENGTH;
668 encode_terminal_src = xrealloc (encode_terminal_src,
669 encode_terminal_src_size);
670 buf = encode_terminal_src + nbytes;
672 if (CHAR_BYTE8_P (c)
673 || char_charset (c, charset_list, NULL))
675 /* Store the multibyte form of C at BUF. */
676 buf += CHAR_STRING (c, buf);
677 nchars++;
679 else
681 /* C is not encodable. */
682 *buf++ = '?';
683 nchars++;
684 while (src + 1 < src_end && CHAR_GLYPH_PADDING_P (src[1]))
686 *buf++ = '?';
687 nchars++;
688 src++;
692 else
694 unsigned char *p = SDATA (string);
696 if (! STRING_MULTIBYTE (string))
697 string = string_to_multibyte (string);
698 nbytes = buf - encode_terminal_src;
699 if (encode_terminal_src_size < nbytes + SBYTES (string))
701 encode_terminal_src_size = nbytes + SBYTES (string);
702 encode_terminal_src = xrealloc (encode_terminal_src,
703 encode_terminal_src_size);
704 buf = encode_terminal_src + nbytes;
706 memcpy (buf, SDATA (string), SBYTES (string));
707 buf += SBYTES (string);
708 nchars += SCHARS (string);
711 src++;
714 if (nchars == 0)
716 coding->produced = 0;
717 return NULL;
720 nbytes = buf - encode_terminal_src;
721 coding->source = encode_terminal_src;
722 if (encode_terminal_dst_size == 0)
724 encode_terminal_dst_size = encode_terminal_src_size;
725 if (encode_terminal_dst)
726 encode_terminal_dst = xrealloc (encode_terminal_dst,
727 encode_terminal_dst_size);
728 else
729 encode_terminal_dst = xmalloc (encode_terminal_dst_size);
731 coding->destination = encode_terminal_dst;
732 coding->dst_bytes = encode_terminal_dst_size;
733 encode_coding_object (coding, Qnil, 0, 0, nchars, nbytes, Qnil);
734 /* coding->destination may have been reallocated. */
735 encode_terminal_dst = coding->destination;
736 encode_terminal_dst_size = coding->dst_bytes;
738 return (encode_terminal_dst);
743 /* An implementation of write_glyphs for termcap frames. */
745 static void
746 tty_write_glyphs (struct frame *f, struct glyph *string, int len)
748 unsigned char *conversion_buffer;
749 struct coding_system *coding;
751 struct tty_display_info *tty = FRAME_TTY (f);
753 tty_turn_off_insert (tty);
754 tty_hide_cursor (tty);
756 /* Don't dare write in last column of bottom line, if Auto-Wrap,
757 since that would scroll the whole frame on some terminals. */
759 if (AutoWrap (tty)
760 && curY (tty) + 1 == FRAME_LINES (f)
761 && (curX (tty) + len) == FRAME_COLS (f))
762 len --;
763 if (len <= 0)
764 return;
766 cmplus (tty, len);
768 /* If terminal_coding does any conversion, use it, otherwise use
769 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
770 because it always return 1 if the member src_multibyte is 1. */
771 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
772 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
773 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
774 the tail. */
775 coding->mode &= ~CODING_MODE_LAST_BLOCK;
777 while (len > 0)
779 /* Identify a run of glyphs with the same face. */
780 int face_id = string->face_id;
781 int n;
783 for (n = 1; n < len; ++n)
784 if (string[n].face_id != face_id)
785 break;
787 /* Turn appearance modes of the face of the run on. */
788 tty_highlight_if_desired (tty);
789 turn_on_face (f, face_id);
791 if (n == len)
792 /* This is the last run. */
793 coding->mode |= CODING_MODE_LAST_BLOCK;
794 conversion_buffer = encode_terminal_code (string, n, coding);
795 if (coding->produced > 0)
797 BLOCK_INPUT;
798 fwrite (conversion_buffer, 1, coding->produced, tty->output);
799 if (ferror (tty->output))
800 clearerr (tty->output);
801 if (tty->termscript)
802 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
803 UNBLOCK_INPUT;
805 len -= n;
806 string += n;
808 /* Turn appearance modes off. */
809 turn_off_face (f, face_id);
810 tty_turn_off_highlight (tty);
813 cmcheckmagic (tty);
816 #ifdef HAVE_GPM /* Only used by GPM code. */
818 static void
819 tty_write_glyphs_with_face (register struct frame *f, register struct glyph *string,
820 register int len, register int face_id)
822 unsigned char *conversion_buffer;
823 struct coding_system *coding;
825 struct tty_display_info *tty = FRAME_TTY (f);
827 tty_turn_off_insert (tty);
828 tty_hide_cursor (tty);
830 /* Don't dare write in last column of bottom line, if Auto-Wrap,
831 since that would scroll the whole frame on some terminals. */
833 if (AutoWrap (tty)
834 && curY (tty) + 1 == FRAME_LINES (f)
835 && (curX (tty) + len) == FRAME_COLS (f))
836 len --;
837 if (len <= 0)
838 return;
840 cmplus (tty, len);
842 /* If terminal_coding does any conversion, use it, otherwise use
843 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
844 because it always return 1 if the member src_multibyte is 1. */
845 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
846 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
847 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
848 the tail. */
849 coding->mode &= ~CODING_MODE_LAST_BLOCK;
851 /* Turn appearance modes of the face. */
852 tty_highlight_if_desired (tty);
853 turn_on_face (f, face_id);
855 coding->mode |= CODING_MODE_LAST_BLOCK;
856 conversion_buffer = encode_terminal_code (string, len, coding);
857 if (coding->produced > 0)
859 BLOCK_INPUT;
860 fwrite (conversion_buffer, 1, coding->produced, tty->output);
861 if (ferror (tty->output))
862 clearerr (tty->output);
863 if (tty->termscript)
864 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
865 UNBLOCK_INPUT;
868 /* Turn appearance modes off. */
869 turn_off_face (f, face_id);
870 tty_turn_off_highlight (tty);
872 cmcheckmagic (tty);
874 #endif
876 /* An implementation of insert_glyphs for termcap frames. */
878 static void
879 tty_insert_glyphs (struct frame *f, struct glyph *start, int len)
881 char *buf;
882 struct glyph *glyph = NULL;
883 unsigned char *conversion_buffer;
884 unsigned char space[1];
885 struct coding_system *coding;
887 struct tty_display_info *tty = FRAME_TTY (f);
889 if (tty->TS_ins_multi_chars)
891 buf = tparam (tty->TS_ins_multi_chars, 0, 0, len);
892 OUTPUT1 (tty, buf);
893 xfree (buf);
894 if (start)
895 write_glyphs (f, start, len);
896 return;
899 tty_turn_on_insert (tty);
900 cmplus (tty, len);
902 if (! start)
903 space[0] = SPACEGLYPH;
905 /* If terminal_coding does any conversion, use it, otherwise use
906 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
907 because it always return 1 if the member src_multibyte is 1. */
908 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
909 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
910 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
911 the tail. */
912 coding->mode &= ~CODING_MODE_LAST_BLOCK;
914 while (len-- > 0)
916 OUTPUT1_IF (tty, tty->TS_ins_char);
917 if (!start)
919 conversion_buffer = space;
920 coding->produced = 1;
922 else
924 tty_highlight_if_desired (tty);
925 turn_on_face (f, start->face_id);
926 glyph = start;
927 ++start;
928 /* We must open sufficient space for a character which
929 occupies more than one column. */
930 while (len && CHAR_GLYPH_PADDING_P (*start))
932 OUTPUT1_IF (tty, tty->TS_ins_char);
933 start++, len--;
936 if (len <= 0)
937 /* This is the last glyph. */
938 coding->mode |= CODING_MODE_LAST_BLOCK;
940 conversion_buffer = encode_terminal_code (glyph, 1, coding);
943 if (coding->produced > 0)
945 BLOCK_INPUT;
946 fwrite (conversion_buffer, 1, coding->produced, tty->output);
947 if (ferror (tty->output))
948 clearerr (tty->output);
949 if (tty->termscript)
950 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
951 UNBLOCK_INPUT;
954 OUTPUT1_IF (tty, tty->TS_pad_inserted_char);
955 if (start)
957 turn_off_face (f, glyph->face_id);
958 tty_turn_off_highlight (tty);
962 cmcheckmagic (tty);
965 /* An implementation of delete_glyphs for termcap frames. */
967 static void
968 tty_delete_glyphs (struct frame *f, int n)
970 char *buf;
971 register int i;
973 struct tty_display_info *tty = FRAME_TTY (f);
975 if (tty->delete_in_insert_mode)
977 tty_turn_on_insert (tty);
979 else
981 tty_turn_off_insert (tty);
982 OUTPUT_IF (tty, tty->TS_delete_mode);
985 if (tty->TS_del_multi_chars)
987 buf = tparam (tty->TS_del_multi_chars, 0, 0, n);
988 OUTPUT1 (tty, buf);
989 xfree (buf);
991 else
992 for (i = 0; i < n; i++)
993 OUTPUT1 (tty, tty->TS_del_char);
994 if (!tty->delete_in_insert_mode)
995 OUTPUT_IF (tty, tty->TS_end_delete_mode);
998 /* An implementation of ins_del_lines for termcap frames. */
1000 static void
1001 tty_ins_del_lines (struct frame *f, int vpos, int n)
1003 struct tty_display_info *tty = FRAME_TTY (f);
1004 char *multi = n > 0 ? tty->TS_ins_multi_lines : tty->TS_del_multi_lines;
1005 char *single = n > 0 ? tty->TS_ins_line : tty->TS_del_line;
1006 char *scroll = n > 0 ? tty->TS_rev_scroll : tty->TS_fwd_scroll;
1008 register int i = n > 0 ? n : -n;
1009 register char *buf;
1011 /* If the lines below the insertion are being pushed
1012 into the end of the window, this is the same as clearing;
1013 and we know the lines are already clear, since the matching
1014 deletion has already been done. So can ignore this. */
1015 /* If the lines below the deletion are blank lines coming
1016 out of the end of the window, don't bother,
1017 as there will be a matching inslines later that will flush them. */
1018 if (FRAME_SCROLL_REGION_OK (f)
1019 && vpos + i >= tty->specified_window)
1020 return;
1021 if (!FRAME_MEMORY_BELOW_FRAME (f)
1022 && vpos + i >= FRAME_LINES (f))
1023 return;
1025 if (multi)
1027 raw_cursor_to (f, vpos, 0);
1028 tty_background_highlight (tty);
1029 buf = tparam (multi, 0, 0, i);
1030 OUTPUT (tty, buf);
1031 xfree (buf);
1033 else if (single)
1035 raw_cursor_to (f, vpos, 0);
1036 tty_background_highlight (tty);
1037 while (--i >= 0)
1038 OUTPUT (tty, single);
1039 if (tty->TF_teleray)
1040 curX (tty) = 0;
1042 else
1044 tty_set_scroll_region (f, vpos, tty->specified_window);
1045 if (n < 0)
1046 raw_cursor_to (f, tty->specified_window - 1, 0);
1047 else
1048 raw_cursor_to (f, vpos, 0);
1049 tty_background_highlight (tty);
1050 while (--i >= 0)
1051 OUTPUTL (tty, scroll, tty->specified_window - vpos);
1052 tty_set_scroll_region (f, 0, tty->specified_window);
1055 if (!FRAME_SCROLL_REGION_OK (f)
1056 && FRAME_MEMORY_BELOW_FRAME (f)
1057 && n < 0)
1059 cursor_to (f, FRAME_LINES (f) + n, 0);
1060 clear_to_end (f);
1064 /* Compute cost of sending "str", in characters,
1065 not counting any line-dependent padding. */
1068 string_cost (const char *str)
1070 cost = 0;
1071 if (str)
1072 tputs (str, 0, evalcost);
1073 return cost;
1076 /* Compute cost of sending "str", in characters,
1077 counting any line-dependent padding at one line. */
1079 static int
1080 string_cost_one_line (const char *str)
1082 cost = 0;
1083 if (str)
1084 tputs (str, 1, evalcost);
1085 return cost;
1088 /* Compute per line amount of line-dependent padding,
1089 in tenths of characters. */
1092 per_line_cost (const char *str)
1094 cost = 0;
1095 if (str)
1096 tputs (str, 0, evalcost);
1097 cost = - cost;
1098 if (str)
1099 tputs (str, 10, evalcost);
1100 return cost;
1103 /* char_ins_del_cost[n] is cost of inserting N characters.
1104 char_ins_del_cost[-n] is cost of deleting N characters.
1105 The length of this vector is based on max_frame_cols. */
1107 int *char_ins_del_vector;
1109 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
1111 /* ARGSUSED */
1112 static void
1113 calculate_ins_del_char_costs (struct frame *f)
1115 struct tty_display_info *tty = FRAME_TTY (f);
1116 int ins_startup_cost, del_startup_cost;
1117 int ins_cost_per_char, del_cost_per_char;
1118 register int i;
1119 register int *p;
1121 if (tty->TS_ins_multi_chars)
1123 ins_cost_per_char = 0;
1124 ins_startup_cost = string_cost_one_line (tty->TS_ins_multi_chars);
1126 else if (tty->TS_ins_char || tty->TS_pad_inserted_char
1127 || (tty->TS_insert_mode && tty->TS_end_insert_mode))
1129 ins_startup_cost = (30 * (string_cost (tty->TS_insert_mode)
1130 + string_cost (tty->TS_end_insert_mode))) / 100;
1131 ins_cost_per_char = (string_cost_one_line (tty->TS_ins_char)
1132 + string_cost_one_line (tty->TS_pad_inserted_char));
1134 else
1136 ins_startup_cost = 9999;
1137 ins_cost_per_char = 0;
1140 if (tty->TS_del_multi_chars)
1142 del_cost_per_char = 0;
1143 del_startup_cost = string_cost_one_line (tty->TS_del_multi_chars);
1145 else if (tty->TS_del_char)
1147 del_startup_cost = (string_cost (tty->TS_delete_mode)
1148 + string_cost (tty->TS_end_delete_mode));
1149 if (tty->delete_in_insert_mode)
1150 del_startup_cost /= 2;
1151 del_cost_per_char = string_cost_one_line (tty->TS_del_char);
1153 else
1155 del_startup_cost = 9999;
1156 del_cost_per_char = 0;
1159 /* Delete costs are at negative offsets */
1160 p = &char_ins_del_cost (f)[0];
1161 for (i = FRAME_COLS (f); --i >= 0;)
1162 *--p = (del_startup_cost += del_cost_per_char);
1164 /* Doing nothing is free */
1165 p = &char_ins_del_cost (f)[0];
1166 *p++ = 0;
1168 /* Insert costs are at positive offsets */
1169 for (i = FRAME_COLS (f); --i >= 0;)
1170 *p++ = (ins_startup_cost += ins_cost_per_char);
1173 void
1174 calculate_costs (struct frame *frame)
1176 FRAME_COST_BAUD_RATE (frame) = baud_rate;
1178 if (FRAME_TERMCAP_P (frame))
1180 struct tty_display_info *tty = FRAME_TTY (frame);
1181 register char *f = (tty->TS_set_scroll_region
1182 ? tty->TS_set_scroll_region
1183 : tty->TS_set_scroll_region_1);
1185 FRAME_SCROLL_REGION_COST (frame) = string_cost (f);
1187 tty->costs_set = 1;
1189 /* These variables are only used for terminal stuff. They are
1190 allocated once for the terminal frame of X-windows emacs, but not
1191 used afterwards.
1193 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1194 X turns off char_ins_del_ok. */
1196 max_frame_lines = max (max_frame_lines, FRAME_LINES (frame));
1197 max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
1199 if (char_ins_del_vector != 0)
1200 char_ins_del_vector
1201 = (int *) xrealloc (char_ins_del_vector,
1202 (sizeof (int)
1203 + 2 * max_frame_cols * sizeof (int)));
1204 else
1205 char_ins_del_vector
1206 = (int *) xmalloc (sizeof (int)
1207 + 2 * max_frame_cols * sizeof (int));
1209 memset (char_ins_del_vector, 0,
1210 (sizeof (int) + 2 * max_frame_cols * sizeof (int)));
1213 if (f && (!tty->TS_ins_line && !tty->TS_del_line))
1214 do_line_insertion_deletion_costs (frame,
1215 tty->TS_rev_scroll, tty->TS_ins_multi_lines,
1216 tty->TS_fwd_scroll, tty->TS_del_multi_lines,
1217 f, f, 1);
1218 else
1219 do_line_insertion_deletion_costs (frame,
1220 tty->TS_ins_line, tty->TS_ins_multi_lines,
1221 tty->TS_del_line, tty->TS_del_multi_lines,
1222 0, 0, 1);
1224 calculate_ins_del_char_costs (frame);
1226 /* Don't use TS_repeat if its padding is worse than sending the chars */
1227 if (tty->TS_repeat && per_line_cost (tty->TS_repeat) * baud_rate < 9000)
1228 tty->RPov = string_cost (tty->TS_repeat);
1229 else
1230 tty->RPov = FRAME_COLS (frame) * 2;
1232 cmcostinit (FRAME_TTY (frame)); /* set up cursor motion costs */
1236 struct fkey_table {
1237 char *cap, *name;
1240 /* Termcap capability names that correspond directly to X keysyms.
1241 Some of these (marked "terminfo") aren't supplied by old-style
1242 (Berkeley) termcap entries. They're listed in X keysym order;
1243 except we put the keypad keys first, so that if they clash with
1244 other keys (as on the IBM PC keyboard) they get overridden.
1247 static const struct fkey_table keys[] =
1249 {"kh", "home"}, /* termcap */
1250 {"kl", "left"}, /* termcap */
1251 {"ku", "up"}, /* termcap */
1252 {"kr", "right"}, /* termcap */
1253 {"kd", "down"}, /* termcap */
1254 {"%8", "prior"}, /* terminfo */
1255 {"%5", "next"}, /* terminfo */
1256 {"@7", "end"}, /* terminfo */
1257 {"@1", "begin"}, /* terminfo */
1258 {"*6", "select"}, /* terminfo */
1259 {"%9", "print"}, /* terminfo */
1260 {"@4", "execute"}, /* terminfo --- actually the `command' key */
1262 * "insert" --- see below
1264 {"&8", "undo"}, /* terminfo */
1265 {"%0", "redo"}, /* terminfo */
1266 {"%7", "menu"}, /* terminfo --- actually the `options' key */
1267 {"@0", "find"}, /* terminfo */
1268 {"@2", "cancel"}, /* terminfo */
1269 {"%1", "help"}, /* terminfo */
1271 * "break" goes here, but can't be reliably intercepted with termcap
1273 {"&4", "reset"}, /* terminfo --- actually `restart' */
1275 * "system" and "user" --- no termcaps
1277 {"kE", "clearline"}, /* terminfo */
1278 {"kA", "insertline"}, /* terminfo */
1279 {"kL", "deleteline"}, /* terminfo */
1280 {"kI", "insertchar"}, /* terminfo */
1281 {"kD", "deletechar"}, /* terminfo */
1282 {"kB", "backtab"}, /* terminfo */
1284 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1286 {"@8", "kp-enter"}, /* terminfo */
1288 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1289 * "kp-multiply", "kp-add", "kp-separator",
1290 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1291 * --- no termcaps for any of these.
1293 {"K4", "kp-1"}, /* terminfo */
1295 * "kp-2" --- no termcap
1297 {"K5", "kp-3"}, /* terminfo */
1299 * "kp-4" --- no termcap
1301 {"K2", "kp-5"}, /* terminfo */
1303 * "kp-6" --- no termcap
1305 {"K1", "kp-7"}, /* terminfo */
1307 * "kp-8" --- no termcap
1309 {"K3", "kp-9"}, /* terminfo */
1311 * "kp-equal" --- no termcap
1313 {"k1", "f1"},
1314 {"k2", "f2"},
1315 {"k3", "f3"},
1316 {"k4", "f4"},
1317 {"k5", "f5"},
1318 {"k6", "f6"},
1319 {"k7", "f7"},
1320 {"k8", "f8"},
1321 {"k9", "f9"},
1323 {"&0", "S-cancel"}, /*shifted cancel key*/
1324 {"&9", "S-begin"}, /*shifted begin key*/
1325 {"*0", "S-find"}, /*shifted find key*/
1326 {"*1", "S-execute"}, /*shifted execute? actually shifted command key*/
1327 {"*4", "S-delete"}, /*shifted delete-character key*/
1328 {"*7", "S-end"}, /*shifted end key*/
1329 {"*8", "S-clearline"}, /*shifted clear-to end-of-line key*/
1330 {"#1", "S-help"}, /*shifted help key*/
1331 {"#2", "S-home"}, /*shifted home key*/
1332 {"#3", "S-insert"}, /*shifted insert-character key*/
1333 {"#4", "S-left"}, /*shifted left-arrow key*/
1334 {"%d", "S-menu"}, /*shifted menu? actually shifted options key*/
1335 {"%c", "S-next"}, /*shifted next key*/
1336 {"%e", "S-prior"}, /*shifted previous key*/
1337 {"%f", "S-print"}, /*shifted print key*/
1338 {"%g", "S-redo"}, /*shifted redo key*/
1339 {"%i", "S-right"}, /*shifted right-arrow key*/
1340 {"!3", "S-undo"} /*shifted undo key*/
1343 #ifndef DOS_NT
1344 static char **term_get_fkeys_address;
1345 static KBOARD *term_get_fkeys_kboard;
1346 static Lisp_Object term_get_fkeys_1 (void);
1348 /* Find the escape codes sent by the function keys for Vinput_decode_map.
1349 This function scans the termcap function key sequence entries, and
1350 adds entries to Vinput_decode_map for each function key it finds. */
1352 static void
1353 term_get_fkeys (char **address, KBOARD *kboard)
1355 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1356 errors during the call. The only errors should be from Fdefine_key
1357 when given a key sequence containing an invalid prefix key. If the
1358 termcap defines function keys which use a prefix that is already bound
1359 to a command by the default bindings, we should silently ignore that
1360 function key specification, rather than giving the user an error and
1361 refusing to run at all on such a terminal. */
1363 term_get_fkeys_address = address;
1364 term_get_fkeys_kboard = kboard;
1365 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1368 static Lisp_Object
1369 term_get_fkeys_1 (void)
1371 int i;
1373 char **address = term_get_fkeys_address;
1374 KBOARD *kboard = term_get_fkeys_kboard;
1376 /* This can happen if CANNOT_DUMP or with strange options. */
1377 if (!KEYMAPP (kboard->Vinput_decode_map))
1378 kboard->Vinput_decode_map = Fmake_sparse_keymap (Qnil);
1380 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1382 char *sequence = tgetstr (keys[i].cap, address);
1383 if (sequence)
1384 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence),
1385 Fmake_vector (make_number (1),
1386 intern (keys[i].name)));
1389 /* The uses of the "k0" capability are inconsistent; sometimes it
1390 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1391 We will attempt to politely accommodate both systems by testing for
1392 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1395 char *k_semi = tgetstr ("k;", address);
1396 char *k0 = tgetstr ("k0", address);
1397 char *k0_name = "f10";
1399 if (k_semi)
1401 if (k0)
1402 /* Define f0 first, so that f10 takes precedence in case the
1403 key sequences happens to be the same. */
1404 Fdefine_key (kboard->Vinput_decode_map, build_string (k0),
1405 Fmake_vector (make_number (1), intern ("f0")));
1406 Fdefine_key (kboard->Vinput_decode_map, build_string (k_semi),
1407 Fmake_vector (make_number (1), intern ("f10")));
1409 else if (k0)
1410 Fdefine_key (kboard->Vinput_decode_map, build_string (k0),
1411 Fmake_vector (make_number (1), intern (k0_name)));
1414 /* Set up cookies for numbered function keys above f10. */
1416 char fcap[3], fkey[4];
1418 fcap[0] = 'F'; fcap[2] = '\0';
1419 for (i = 11; i < 64; i++)
1421 if (i <= 19)
1422 fcap[1] = '1' + i - 11;
1423 else if (i <= 45)
1424 fcap[1] = 'A' + i - 20;
1425 else
1426 fcap[1] = 'a' + i - 46;
1429 char *sequence = tgetstr (fcap, address);
1430 if (sequence)
1432 sprintf (fkey, "f%d", i);
1433 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence),
1434 Fmake_vector (make_number (1),
1435 intern (fkey)));
1442 * Various mappings to try and get a better fit.
1445 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1446 if (!tgetstr (cap1, address)) \
1448 char *sequence = tgetstr (cap2, address); \
1449 if (sequence) \
1450 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence), \
1451 Fmake_vector (make_number (1), \
1452 intern (sym))); \
1455 /* if there's no key_next keycap, map key_npage to `next' keysym */
1456 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1457 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1458 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1459 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1460 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1461 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1462 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1464 /* IBM has their own non-standard dialect of terminfo.
1465 If the standard name isn't found, try the IBM name. */
1466 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1467 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1468 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1469 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1470 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1471 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1472 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1473 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1474 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1475 #undef CONDITIONAL_REASSIGN
1478 return Qnil;
1480 #endif /* not DOS_NT */
1483 /***********************************************************************
1484 Character Display Information
1485 ***********************************************************************/
1486 static void append_glyph (struct it *);
1487 static void produce_stretch_glyph (struct it *);
1488 static void append_composite_glyph (struct it *);
1489 static void produce_composite_glyph (struct it *);
1490 static void append_glyphless_glyph (struct it *, int, char *);
1491 static void produce_glyphless_glyph (struct it *, int, Lisp_Object);
1493 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1494 terminal frames if IT->glyph_row != NULL. IT->char_to_display is
1495 the character for which to produce glyphs; IT->face_id contains the
1496 character's face. Padding glyphs are appended if IT->c has a
1497 IT->pixel_width > 1. */
1499 static void
1500 append_glyph (struct it *it)
1502 struct glyph *glyph, *end;
1503 int i;
1505 xassert (it->glyph_row);
1506 glyph = (it->glyph_row->glyphs[it->area]
1507 + it->glyph_row->used[it->area]);
1508 end = it->glyph_row->glyphs[1 + it->area];
1510 /* If the glyph row is reversed, we need to prepend the glyph rather
1511 than append it. */
1512 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1514 struct glyph *g;
1515 int move_by = it->pixel_width;
1517 /* Make room for the new glyphs. */
1518 if (move_by > end - glyph) /* don't overstep end of this area */
1519 move_by = end - glyph;
1520 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1521 g[move_by] = *g;
1522 glyph = it->glyph_row->glyphs[it->area];
1523 end = glyph + move_by;
1526 /* BIDI Note: we put the glyphs of a "multi-pixel" character left to
1527 right, even in the REVERSED_P case, since (a) all of its u.ch are
1528 identical, and (b) the PADDING_P flag needs to be set for the
1529 leftmost one, because we write to the terminal left-to-right. */
1530 for (i = 0;
1531 i < it->pixel_width && glyph < end;
1532 ++i)
1534 glyph->type = CHAR_GLYPH;
1535 glyph->pixel_width = 1;
1536 glyph->u.ch = it->char_to_display;
1537 glyph->face_id = it->face_id;
1538 glyph->padding_p = i > 0;
1539 glyph->charpos = CHARPOS (it->position);
1540 glyph->object = it->object;
1541 if (it->bidi_p)
1543 glyph->resolved_level = it->bidi_it.resolved_level;
1544 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1545 abort ();
1546 glyph->bidi_type = it->bidi_it.type;
1548 else
1550 glyph->resolved_level = 0;
1551 glyph->bidi_type = UNKNOWN_BT;
1554 ++it->glyph_row->used[it->area];
1555 ++glyph;
1559 /* Produce glyphs for the display element described by IT. *IT
1560 specifies what we want to produce a glyph for (character, image, ...),
1561 and where in the glyph matrix we currently are (glyph row and hpos).
1562 produce_glyphs fills in output fields of *IT with information such as the
1563 pixel width and height of a character, and maybe output actual glyphs at
1564 the same time if IT->glyph_row is non-null. For an overview, see
1565 the explanation in dispextern.h, before the definition of the
1566 display_element_type enumeration.
1568 produce_glyphs also stores the result of glyph width, ascent
1569 etc. computations in *IT.
1571 IT->glyph_row may be null, in which case produce_glyphs does not
1572 actually fill in the glyphs. This is used in the move_* functions
1573 in xdisp.c for text width and height computations.
1575 Callers usually don't call produce_glyphs directly;
1576 instead they use the macro PRODUCE_GLYPHS. */
1578 void
1579 produce_glyphs (struct it *it)
1581 /* If a hook is installed, let it do the work. */
1583 /* Nothing but characters are supported on terminal frames. */
1584 xassert (it->what == IT_CHARACTER
1585 || it->what == IT_COMPOSITION
1586 || it->what == IT_STRETCH);
1588 if (it->what == IT_STRETCH)
1590 produce_stretch_glyph (it);
1591 goto done;
1594 if (it->what == IT_COMPOSITION)
1596 produce_composite_glyph (it);
1597 goto done;
1600 if (it->what == IT_GLYPHLESS)
1602 produce_glyphless_glyph (it, 0, Qnil);
1603 goto done;
1606 if (it->char_to_display >= 040 && it->char_to_display < 0177)
1608 it->pixel_width = it->nglyphs = 1;
1609 if (it->glyph_row)
1610 append_glyph (it);
1612 else if (it->char_to_display == '\n')
1613 it->pixel_width = it->nglyphs = 0;
1614 else if (it->char_to_display == '\t')
1616 int absolute_x = (it->current_x
1617 + it->continuation_lines_width);
1618 int next_tab_x
1619 = (((1 + absolute_x + it->tab_width - 1)
1620 / it->tab_width)
1621 * it->tab_width);
1622 int nspaces;
1624 /* If part of the TAB has been displayed on the previous line
1625 which is continued now, continuation_lines_width will have
1626 been incremented already by the part that fitted on the
1627 continued line. So, we will get the right number of spaces
1628 here. */
1629 nspaces = next_tab_x - absolute_x;
1631 if (it->glyph_row)
1633 int n = nspaces;
1635 it->char_to_display = ' ';
1636 it->pixel_width = it->len = 1;
1638 while (n--)
1639 append_glyph (it);
1642 it->pixel_width = nspaces;
1643 it->nglyphs = nspaces;
1645 else if (CHAR_BYTE8_P (it->char_to_display))
1647 /* Coming here means that we must send the raw 8-bit byte as is
1648 to the terminal. Although there's no way to know how many
1649 columns it occupies on a screen, it is a good assumption that
1650 a single byte code has 1-column width. */
1651 it->pixel_width = it->nglyphs = 1;
1652 if (it->glyph_row)
1653 append_glyph (it);
1655 else
1657 Lisp_Object charset_list = FRAME_TERMINAL (it->f)->charset_list;
1659 if (char_charset (it->char_to_display, charset_list, NULL))
1661 it->pixel_width = CHAR_WIDTH (it->char_to_display);
1662 it->nglyphs = it->pixel_width;
1663 if (it->glyph_row)
1664 append_glyph (it);
1666 else
1668 Lisp_Object acronym = lookup_glyphless_char_display (-1, it);
1670 xassert (it->what == IT_GLYPHLESS);
1671 produce_glyphless_glyph (it, 1, acronym);
1675 done:
1676 /* Advance current_x by the pixel width as a convenience for
1677 the caller. */
1678 if (it->area == TEXT_AREA)
1679 it->current_x += it->pixel_width;
1680 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1681 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
1685 /* Produce a stretch glyph for iterator IT. IT->object is the value
1686 of the glyph property displayed. The value must be a list
1687 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1688 being recognized:
1690 1. `:width WIDTH' specifies that the space should be WIDTH *
1691 canonical char width wide. WIDTH may be an integer or floating
1692 point number.
1694 2. `:align-to HPOS' specifies that the space should be wide enough
1695 to reach HPOS, a value in canonical character units. */
1697 static void
1698 produce_stretch_glyph (struct it *it)
1700 /* (space :width WIDTH ...) */
1701 Lisp_Object prop, plist;
1702 int width = 0, align_to = -1;
1703 int zero_width_ok_p = 0;
1704 double tem;
1706 /* List should start with `space'. */
1707 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1708 plist = XCDR (it->object);
1710 /* Compute the width of the stretch. */
1711 if ((prop = Fplist_get (plist, QCwidth), !NILP (prop))
1712 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, 0))
1714 /* Absolute width `:width WIDTH' specified and valid. */
1715 zero_width_ok_p = 1;
1716 width = (int)(tem + 0.5);
1718 else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
1719 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, &align_to))
1721 if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
1722 align_to = (align_to < 0
1724 : align_to - window_box_left_offset (it->w, TEXT_AREA));
1725 else if (align_to < 0)
1726 align_to = window_box_left_offset (it->w, TEXT_AREA);
1727 width = max (0, (int)(tem + 0.5) + align_to - it->current_x);
1728 zero_width_ok_p = 1;
1730 else
1731 /* Nothing specified -> width defaults to canonical char width. */
1732 width = FRAME_COLUMN_WIDTH (it->f);
1734 if (width <= 0 && (width < 0 || !zero_width_ok_p))
1735 width = 1;
1737 if (width > 0 && it->line_wrap != TRUNCATE
1738 && it->current_x + width > it->last_visible_x)
1739 width = it->last_visible_x - it->current_x - 1;
1741 if (width > 0 && it->glyph_row)
1743 Lisp_Object o_object = it->object;
1744 Lisp_Object object = it->stack[it->sp - 1].string;
1745 int n = width;
1747 if (!STRINGP (object))
1748 object = it->w->buffer;
1749 it->object = object;
1750 it->char_to_display = ' ';
1751 it->pixel_width = it->len = 1;
1752 while (n--)
1753 append_glyph (it);
1754 it->object = o_object;
1756 it->pixel_width = width;
1757 it->nglyphs = width;
1761 /* Append glyphs to IT's glyph_row for the composition IT->cmp_id.
1762 Called from produce_composite_glyph for terminal frames if
1763 IT->glyph_row != NULL. IT->face_id contains the character's
1764 face. */
1766 static void
1767 append_composite_glyph (struct it *it)
1769 struct glyph *glyph;
1771 xassert (it->glyph_row);
1772 glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
1773 if (glyph < it->glyph_row->glyphs[1 + it->area])
1775 /* If the glyph row is reversed, we need to prepend the glyph
1776 rather than append it. */
1777 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1779 struct glyph *g;
1781 /* Make room for the new glyph. */
1782 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1783 g[1] = *g;
1784 glyph = it->glyph_row->glyphs[it->area];
1786 glyph->type = COMPOSITE_GLYPH;
1787 glyph->pixel_width = it->pixel_width;
1788 glyph->u.cmp.id = it->cmp_it.id;
1789 if (it->cmp_it.ch < 0)
1791 glyph->u.cmp.automatic = 0;
1792 glyph->u.cmp.id = it->cmp_it.id;
1794 else
1796 glyph->u.cmp.automatic = 1;
1797 glyph->u.cmp.id = it->cmp_it.id;
1798 glyph->slice.cmp.from = it->cmp_it.from;
1799 glyph->slice.cmp.to = it->cmp_it.to - 1;
1802 glyph->face_id = it->face_id;
1803 glyph->padding_p = 0;
1804 glyph->charpos = CHARPOS (it->position);
1805 glyph->object = it->object;
1806 if (it->bidi_p)
1808 glyph->resolved_level = it->bidi_it.resolved_level;
1809 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1810 abort ();
1811 glyph->bidi_type = it->bidi_it.type;
1813 else
1815 glyph->resolved_level = 0;
1816 glyph->bidi_type = UNKNOWN_BT;
1819 ++it->glyph_row->used[it->area];
1820 ++glyph;
1825 /* Produce a composite glyph for iterator IT. IT->cmp_id is the ID of
1826 the composition. We simply produces components of the composition
1827 assuming that the terminal has a capability to layout/render it
1828 correctly. */
1830 static void
1831 produce_composite_glyph (struct it *it)
1833 if (it->cmp_it.ch < 0)
1835 struct composition *cmp = composition_table[it->cmp_it.id];
1837 it->pixel_width = cmp->width;
1839 else
1841 Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id);
1843 it->pixel_width = composition_gstring_width (gstring, it->cmp_it.from,
1844 it->cmp_it.to, NULL);
1846 it->nglyphs = 1;
1847 if (it->glyph_row)
1848 append_composite_glyph (it);
1852 /* Append a glyph for a glyphless character to IT->glyph_row. FACE_ID
1853 is a face ID to be used for the glyph. What is actually appended
1854 are glyphs of type CHAR_GLYPH whose characters are in STR (which
1855 comes from it->nglyphs bytes). */
1857 static void
1858 append_glyphless_glyph (struct it *it, int face_id, char *str)
1860 struct glyph *glyph, *end;
1861 int i;
1863 xassert (it->glyph_row);
1864 glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
1865 end = it->glyph_row->glyphs[1 + it->area];
1867 /* If the glyph row is reversed, we need to prepend the glyph rather
1868 than append it. */
1869 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1871 struct glyph *g;
1872 int move_by = it->pixel_width;
1874 /* Make room for the new glyphs. */
1875 if (move_by > end - glyph) /* don't overstep end of this area */
1876 move_by = end - glyph;
1877 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1878 g[move_by] = *g;
1879 glyph = it->glyph_row->glyphs[it->area];
1880 end = glyph + move_by;
1883 if (glyph >= end)
1884 return;
1885 glyph->type = CHAR_GLYPH;
1886 glyph->pixel_width = 1;
1887 glyph->face_id = face_id;
1888 glyph->padding_p = 0;
1889 glyph->charpos = CHARPOS (it->position);
1890 glyph->object = it->object;
1891 if (it->bidi_p)
1893 glyph->resolved_level = it->bidi_it.resolved_level;
1894 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1895 abort ();
1896 glyph->bidi_type = it->bidi_it.type;
1898 else
1900 glyph->resolved_level = 0;
1901 glyph->bidi_type = UNKNOWN_BT;
1904 /* BIDI Note: we put the glyphs of characters left to right, even in
1905 the REVERSED_P case because we write to the terminal
1906 left-to-right. */
1907 for (i = 0; i < it->nglyphs && glyph < end; ++i)
1909 if (i > 0)
1910 glyph[0] = glyph[-1];
1911 glyph->u.ch = str[i];
1912 ++it->glyph_row->used[it->area];
1913 ++glyph;
1917 /* Declared in xdisp.c */
1918 extern struct frame *last_glyphless_glyph_frame;
1919 extern unsigned last_glyphless_glyph_face_id;
1920 extern int last_glyphless_glyph_merged_face_id;
1921 extern Lisp_Object Qglyphless_char;
1923 /* Produce glyphs for a glyphless character for iterator IT.
1924 IT->glyphless_method specifies which method to use for displaying
1925 the character. See the description of enum
1926 glyphless_display_method in dispextern.h for the details.
1928 FOR_NO_FONT is nonzero if and only if this is for a character that
1929 is not supproted by the coding system of the terminal. ACRONYM, if
1930 non-nil, is an acronym string for the character.
1932 The glyphs actually produced are of type CHAR_GLYPH. */
1934 static void
1935 produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym)
1937 int face_id;
1938 int len;
1939 char buf[11], *str = " ";
1941 /* Get a face ID for the glyph by utilizing a cache (the same way as
1942 done for `escape-glyph' in get_next_display_element). */
1943 if (it->f == last_glyphless_glyph_frame
1944 && it->face_id == last_glyphless_glyph_face_id)
1946 face_id = last_glyphless_glyph_merged_face_id;
1948 else
1950 /* Merge the `glyphless-char' face into the current face. */
1951 face_id = merge_faces (it->f, Qglyphless_char, 0, it->face_id);
1952 last_glyphless_glyph_frame = it->f;
1953 last_glyphless_glyph_face_id = it->face_id;
1954 last_glyphless_glyph_merged_face_id = face_id;
1957 if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE)
1959 /* As there's no way to produce a thin space, we produce a space
1960 of canonical width. */
1961 len = 1;
1963 else if (it->glyphless_method == GLYPHLESS_DISPLAY_EMPTY_BOX)
1965 len = CHAR_WIDTH (it->c);
1966 if (len == 0)
1967 len = 1;
1968 else if (len > 4)
1969 len = 4;
1970 sprintf (buf, "[%.*s]", len, str);
1971 len += 2;
1972 str = buf;
1974 else
1976 if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM)
1978 if (! STRINGP (acronym) && CHAR_TABLE_P (Vglyphless_char_display))
1979 acronym = CHAR_TABLE_REF (Vglyphless_char_display, it->c);
1980 buf[0] = '[';
1981 str = STRINGP (acronym) ? (char *) SDATA (acronym) : "";
1982 for (len = 0; len < 6 && str[len] && ASCII_BYTE_P (str[len]); len++)
1983 buf[1 + len] = str[len];
1984 buf[1 + len] = ']';
1985 len += 2;
1987 else
1989 xassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEX_CODE);
1990 len = (it->c < 0x100 ? sprintf (buf, "[U+%02X]", it->c)
1991 : it->c < 0x10000 ? sprintf (buf, "[U+%04X]", it->c)
1992 : it->c <= MAX_UNICODE_CHAR ? sprintf (buf, "[U+%06X]", it->c)
1993 : sprintf (buf, "[E+%06X]", it->c));
1995 str = buf;
1998 it->pixel_width = len;
1999 it->nglyphs = len;
2000 if (len > 0 && it->glyph_row)
2001 append_glyphless_glyph (it, face_id, str);
2005 /* Get information about special display element WHAT in an
2006 environment described by IT. WHAT is one of IT_TRUNCATION or
2007 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
2008 non-null glyph_row member. This function ensures that fields like
2009 face_id, c, len of IT are left untouched. */
2011 void
2012 produce_special_glyphs (struct it *it, enum display_element_type what)
2014 struct it temp_it;
2015 Lisp_Object gc;
2016 GLYPH glyph;
2018 temp_it = *it;
2019 temp_it.dp = NULL;
2020 temp_it.what = IT_CHARACTER;
2021 temp_it.len = 1;
2022 temp_it.object = make_number (0);
2023 memset (&temp_it.current, 0, sizeof temp_it.current);
2025 if (what == IT_CONTINUATION)
2027 /* Continuation glyph. For R2L lines, we mirror it by hand. */
2028 if (it->bidi_it.paragraph_dir == R2L)
2029 SET_GLYPH_FROM_CHAR (glyph, '/');
2030 else
2031 SET_GLYPH_FROM_CHAR (glyph, '\\');
2032 if (it->dp
2033 && (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc))
2034 && GLYPH_CODE_CHAR_VALID_P (gc))
2036 /* FIXME: Should we mirror GC for R2L lines? */
2037 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
2038 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
2041 else if (what == IT_TRUNCATION)
2043 /* Truncation glyph. */
2044 SET_GLYPH_FROM_CHAR (glyph, '$');
2045 if (it->dp
2046 && (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc))
2047 && GLYPH_CODE_CHAR_VALID_P (gc))
2049 /* FIXME: Should we mirror GC for R2L lines? */
2050 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
2051 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
2054 else
2055 abort ();
2057 temp_it.c = temp_it.char_to_display = GLYPH_CHAR (glyph);
2058 temp_it.face_id = GLYPH_FACE (glyph);
2059 temp_it.len = CHAR_BYTES (temp_it.c);
2061 produce_glyphs (&temp_it);
2062 it->pixel_width = temp_it.pixel_width;
2063 it->nglyphs = temp_it.pixel_width;
2068 /***********************************************************************
2069 Faces
2070 ***********************************************************************/
2072 /* Value is non-zero if attribute ATTR may be used. ATTR should be
2073 one of the enumerators from enum no_color_bit, or a bit set built
2074 from them. Some display attributes may not be used together with
2075 color; the termcap capability `NC' specifies which ones. */
2077 #define MAY_USE_WITH_COLORS_P(tty, ATTR) \
2078 (tty->TN_max_colors > 0 \
2079 ? (tty->TN_no_color_video & (ATTR)) == 0 \
2080 : 1)
2082 /* Turn appearances of face FACE_ID on tty frame F on.
2083 FACE_ID is a realized face ID number, in the face cache. */
2085 static void
2086 turn_on_face (struct frame *f, int face_id)
2088 struct face *face = FACE_FROM_ID (f, face_id);
2089 long fg = face->foreground;
2090 long bg = face->background;
2091 struct tty_display_info *tty = FRAME_TTY (f);
2093 /* Do this first because TS_end_standout_mode may be the same
2094 as TS_exit_attribute_mode, which turns all appearances off. */
2095 if (MAY_USE_WITH_COLORS_P (tty, NC_REVERSE))
2097 if (tty->TN_max_colors > 0)
2099 if (fg >= 0 && bg >= 0)
2101 /* If the terminal supports colors, we can set them
2102 below without using reverse video. The face's fg
2103 and bg colors are set as they should appear on
2104 the screen, i.e. they take the inverse-video'ness
2105 of the face already into account. */
2107 else if (inverse_video)
2109 if (fg == FACE_TTY_DEFAULT_FG_COLOR
2110 || bg == FACE_TTY_DEFAULT_BG_COLOR)
2111 tty_toggle_highlight (tty);
2113 else
2115 if (fg == FACE_TTY_DEFAULT_BG_COLOR
2116 || bg == FACE_TTY_DEFAULT_FG_COLOR)
2117 tty_toggle_highlight (tty);
2120 else
2122 /* If we can't display colors, use reverse video
2123 if the face specifies that. */
2124 if (inverse_video)
2126 if (fg == FACE_TTY_DEFAULT_FG_COLOR
2127 || bg == FACE_TTY_DEFAULT_BG_COLOR)
2128 tty_toggle_highlight (tty);
2130 else
2132 if (fg == FACE_TTY_DEFAULT_BG_COLOR
2133 || bg == FACE_TTY_DEFAULT_FG_COLOR)
2134 tty_toggle_highlight (tty);
2139 if (face->tty_bold_p && MAY_USE_WITH_COLORS_P (tty, NC_BOLD))
2140 OUTPUT1_IF (tty, tty->TS_enter_bold_mode);
2142 if (face->tty_dim_p && MAY_USE_WITH_COLORS_P (tty, NC_DIM))
2143 OUTPUT1_IF (tty, tty->TS_enter_dim_mode);
2145 /* Alternate charset and blinking not yet used. */
2146 if (face->tty_alt_charset_p
2147 && MAY_USE_WITH_COLORS_P (tty, NC_ALT_CHARSET))
2148 OUTPUT1_IF (tty, tty->TS_enter_alt_charset_mode);
2150 if (face->tty_blinking_p
2151 && MAY_USE_WITH_COLORS_P (tty, NC_BLINK))
2152 OUTPUT1_IF (tty, tty->TS_enter_blink_mode);
2154 if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (tty, NC_UNDERLINE))
2155 OUTPUT1_IF (tty, tty->TS_enter_underline_mode);
2157 if (tty->TN_max_colors > 0)
2159 char *ts, *p;
2161 ts = tty->standout_mode ? tty->TS_set_background : tty->TS_set_foreground;
2162 if (fg >= 0 && ts)
2164 p = tparam (ts, NULL, 0, (int) fg);
2165 OUTPUT (tty, p);
2166 xfree (p);
2169 ts = tty->standout_mode ? tty->TS_set_foreground : tty->TS_set_background;
2170 if (bg >= 0 && ts)
2172 p = tparam (ts, NULL, 0, (int) bg);
2173 OUTPUT (tty, p);
2174 xfree (p);
2180 /* Turn off appearances of face FACE_ID on tty frame F. */
2182 static void
2183 turn_off_face (struct frame *f, int face_id)
2185 struct face *face = FACE_FROM_ID (f, face_id);
2186 struct tty_display_info *tty = FRAME_TTY (f);
2188 xassert (face != NULL);
2190 if (tty->TS_exit_attribute_mode)
2192 /* Capability "me" will turn off appearance modes double-bright,
2193 half-bright, reverse-video, standout, underline. It may or
2194 may not turn off alt-char-mode. */
2195 if (face->tty_bold_p
2196 || face->tty_dim_p
2197 || face->tty_reverse_p
2198 || face->tty_alt_charset_p
2199 || face->tty_blinking_p
2200 || face->tty_underline_p)
2202 OUTPUT1_IF (tty, tty->TS_exit_attribute_mode);
2203 if (strcmp (tty->TS_exit_attribute_mode, tty->TS_end_standout_mode) == 0)
2204 tty->standout_mode = 0;
2207 if (face->tty_alt_charset_p)
2208 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
2210 else
2212 /* If we don't have "me" we can only have those appearances
2213 that have exit sequences defined. */
2214 if (face->tty_alt_charset_p)
2215 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
2217 if (face->tty_underline_p)
2218 OUTPUT_IF (tty, tty->TS_exit_underline_mode);
2221 /* Switch back to default colors. */
2222 if (tty->TN_max_colors > 0
2223 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
2224 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
2225 || (face->background != FACE_TTY_DEFAULT_COLOR
2226 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
2227 OUTPUT1_IF (tty, tty->TS_orig_pair);
2231 /* Return non-zero if the terminal on frame F supports all of the
2232 capabilities in CAPS simultaneously, with foreground and background
2233 colors FG and BG. */
2236 tty_capable_p (struct tty_display_info *tty, unsigned int caps,
2237 unsigned long fg, unsigned long bg)
2239 #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
2240 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
2241 return 0;
2243 TTY_CAPABLE_P_TRY (tty, TTY_CAP_INVERSE, tty->TS_standout_mode, NC_REVERSE);
2244 TTY_CAPABLE_P_TRY (tty, TTY_CAP_UNDERLINE, tty->TS_enter_underline_mode, NC_UNDERLINE);
2245 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BOLD, tty->TS_enter_bold_mode, NC_BOLD);
2246 TTY_CAPABLE_P_TRY (tty, TTY_CAP_DIM, tty->TS_enter_dim_mode, NC_DIM);
2247 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BLINK, tty->TS_enter_blink_mode, NC_BLINK);
2248 TTY_CAPABLE_P_TRY (tty, TTY_CAP_ALT_CHARSET, tty->TS_enter_alt_charset_mode, NC_ALT_CHARSET);
2250 /* We can do it! */
2251 return 1;
2254 /* Return non-zero if the terminal is capable to display colors. */
2256 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
2257 0, 1, 0,
2258 doc: /* Return non-nil if the tty device TERMINAL can display colors.
2260 TERMINAL can be a terminal object, a frame, or nil (meaning the
2261 selected frame's terminal). This function always returns nil if
2262 TERMINAL does not refer to a text-only terminal. */)
2263 (Lisp_Object terminal)
2265 struct terminal *t = get_tty_terminal (terminal, 0);
2266 if (!t)
2267 return Qnil;
2268 else
2269 return t->display_info.tty->TN_max_colors > 0 ? Qt : Qnil;
2272 /* Return the number of supported colors. */
2273 DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
2274 Stty_display_color_cells, 0, 1, 0,
2275 doc: /* Return the number of colors supported by the tty device TERMINAL.
2277 TERMINAL can be a terminal object, a frame, or nil (meaning the
2278 selected frame's terminal). This function always returns 0 if
2279 TERMINAL does not refer to a text-only terminal. */)
2280 (Lisp_Object terminal)
2282 struct terminal *t = get_tty_terminal (terminal, 0);
2283 if (!t)
2284 return make_number (0);
2285 else
2286 return make_number (t->display_info.tty->TN_max_colors);
2289 #ifndef DOS_NT
2291 /* Declare here rather than in the function, as in the rest of Emacs,
2292 to work around an HPUX compiler bug (?). See
2293 http://lists.gnu.org/archive/html/emacs-devel/2007-08/msg00410.html */
2294 static int default_max_colors;
2295 static int default_max_pairs;
2296 static int default_no_color_video;
2297 static char *default_orig_pair;
2298 static char *default_set_foreground;
2299 static char *default_set_background;
2301 /* Save or restore the default color-related capabilities of this
2302 terminal. */
2303 static void
2304 tty_default_color_capabilities (struct tty_display_info *tty, int save)
2307 if (save)
2309 xfree (default_orig_pair);
2310 default_orig_pair = tty->TS_orig_pair ? xstrdup (tty->TS_orig_pair) : NULL;
2312 xfree (default_set_foreground);
2313 default_set_foreground = tty->TS_set_foreground ? xstrdup (tty->TS_set_foreground)
2314 : NULL;
2316 xfree (default_set_background);
2317 default_set_background = tty->TS_set_background ? xstrdup (tty->TS_set_background)
2318 : NULL;
2320 default_max_colors = tty->TN_max_colors;
2321 default_max_pairs = tty->TN_max_pairs;
2322 default_no_color_video = tty->TN_no_color_video;
2324 else
2326 tty->TS_orig_pair = default_orig_pair;
2327 tty->TS_set_foreground = default_set_foreground;
2328 tty->TS_set_background = default_set_background;
2329 tty->TN_max_colors = default_max_colors;
2330 tty->TN_max_pairs = default_max_pairs;
2331 tty->TN_no_color_video = default_no_color_video;
2335 /* Setup one of the standard tty color schemes according to MODE.
2336 MODE's value is generally the number of colors which we want to
2337 support; zero means set up for the default capabilities, the ones
2338 we saw at init_tty time; -1 means turn off color support. */
2339 static void
2340 tty_setup_colors (struct tty_display_info *tty, int mode)
2342 /* Canonicalize all negative values of MODE. */
2343 if (mode < -1)
2344 mode = -1;
2346 switch (mode)
2348 case -1: /* no colors at all */
2349 tty->TN_max_colors = 0;
2350 tty->TN_max_pairs = 0;
2351 tty->TN_no_color_video = 0;
2352 tty->TS_set_foreground = tty->TS_set_background = tty->TS_orig_pair = NULL;
2353 break;
2354 case 0: /* default colors, if any */
2355 default:
2356 tty_default_color_capabilities (tty, 0);
2357 break;
2358 case 8: /* 8 standard ANSI colors */
2359 tty->TS_orig_pair = "\033[0m";
2360 #ifdef TERMINFO
2361 tty->TS_set_foreground = "\033[3%p1%dm";
2362 tty->TS_set_background = "\033[4%p1%dm";
2363 #else
2364 tty->TS_set_foreground = "\033[3%dm";
2365 tty->TS_set_background = "\033[4%dm";
2366 #endif
2367 tty->TN_max_colors = 8;
2368 tty->TN_max_pairs = 64;
2369 tty->TN_no_color_video = 0;
2370 break;
2374 void
2375 set_tty_color_mode (struct tty_display_info *tty, struct frame *f)
2377 Lisp_Object tem, val;
2378 Lisp_Object color_mode;
2379 int mode;
2380 Lisp_Object tty_color_mode_alist
2381 = Fintern_soft (build_string ("tty-color-mode-alist"), Qnil);
2383 tem = assq_no_quit (Qtty_color_mode, f->param_alist);
2384 val = CONSP (tem) ? XCDR (tem) : Qnil;
2386 if (INTEGERP (val))
2387 color_mode = val;
2388 else if (SYMBOLP (tty_color_mode_alist))
2390 tem = Fassq (val, Fsymbol_value (tty_color_mode_alist));
2391 color_mode = CONSP (tem) ? XCDR (tem) : Qnil;
2393 else
2394 color_mode = Qnil;
2396 mode = INTEGERP (color_mode) ? XINT (color_mode) : 0;
2398 if (mode != tty->previous_color_mode)
2400 Lisp_Object funsym = intern ("tty-set-up-initial-frame-faces");
2401 tty->previous_color_mode = mode;
2402 tty_setup_colors (tty , mode);
2403 /* This recomputes all the faces given the new color definitions. */
2404 safe_call (1, &funsym);
2408 #endif /* !DOS_NT */
2412 /* Return the tty display object specified by TERMINAL. */
2414 struct terminal *
2415 get_tty_terminal (Lisp_Object terminal, int throw)
2417 struct terminal *t = get_terminal (terminal, throw);
2419 if (t && t->type != output_termcap && t->type != output_msdos_raw)
2421 if (throw)
2422 error ("Device %d is not a termcap terminal device", t->id);
2423 else
2424 return NULL;
2427 return t;
2430 /* Return an active termcap device that uses the tty device with the
2431 given name.
2433 This function ignores suspended devices.
2435 Returns NULL if the named terminal device is not opened. */
2437 struct terminal *
2438 get_named_tty (const char *name)
2440 struct terminal *t;
2442 if (!name)
2443 abort ();
2445 for (t = terminal_list; t; t = t->next_terminal)
2447 if ((t->type == output_termcap || t->type == output_msdos_raw)
2448 && !strcmp (t->display_info.tty->name, name)
2449 && TERMINAL_ACTIVE_P (t))
2450 return t;
2453 return 0;
2457 DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0,
2458 doc: /* Return the type of the tty device that TERMINAL uses.
2459 Returns nil if TERMINAL is not on a tty device.
2461 TERMINAL can be a terminal object, a frame, or nil (meaning the
2462 selected frame's terminal). */)
2463 (Lisp_Object terminal)
2465 struct terminal *t = get_terminal (terminal, 1);
2467 if (t->type != output_termcap && t->type != output_msdos_raw)
2468 return Qnil;
2470 if (t->display_info.tty->type)
2471 return build_string (t->display_info.tty->type);
2472 else
2473 return Qnil;
2476 DEFUN ("controlling-tty-p", Fcontrolling_tty_p, Scontrolling_tty_p, 0, 1, 0,
2477 doc: /* Return non-nil if TERMINAL is the controlling tty of the Emacs process.
2479 TERMINAL can be a terminal object, a frame, or nil (meaning the
2480 selected frame's terminal). This function always returns nil if
2481 TERMINAL is not on a tty device. */)
2482 (Lisp_Object terminal)
2484 struct terminal *t = get_terminal (terminal, 1);
2486 if ((t->type != output_termcap && t->type != output_msdos_raw)
2487 || strcmp (t->display_info.tty->name, DEV_TTY) != 0)
2488 return Qnil;
2489 else
2490 return Qt;
2493 DEFUN ("tty-no-underline", Ftty_no_underline, Stty_no_underline, 0, 1, 0,
2494 doc: /* Declare that the tty used by TERMINAL does not handle underlining.
2495 This is used to override the terminfo data, for certain terminals that
2496 do not really do underlining, but say that they do. This function has
2497 no effect if used on a non-tty terminal.
2499 TERMINAL can be a terminal object, a frame or nil (meaning the
2500 selected frame's terminal). This function always returns nil if
2501 TERMINAL does not refer to a text-only terminal. */)
2502 (Lisp_Object terminal)
2504 struct terminal *t = get_terminal (terminal, 1);
2506 if (t->type == output_termcap)
2507 t->display_info.tty->TS_enter_underline_mode = 0;
2508 return Qnil;
2513 DEFUN ("suspend-tty", Fsuspend_tty, Ssuspend_tty, 0, 1, 0,
2514 doc: /* Suspend the terminal device TTY.
2516 The device is restored to its default state, and Emacs ceases all
2517 access to the tty device. Frames that use the device are not deleted,
2518 but input is not read from them and if they change, their display is
2519 not updated.
2521 TTY may be a terminal object, a frame, or nil for the terminal device
2522 of the currently selected frame.
2524 This function runs `suspend-tty-functions' after suspending the
2525 device. The functions are run with one arg, the id of the suspended
2526 terminal device.
2528 `suspend-tty' does nothing if it is called on a device that is already
2529 suspended.
2531 A suspended tty may be resumed by calling `resume-tty' on it. */)
2532 (Lisp_Object tty)
2534 struct terminal *t = get_tty_terminal (tty, 1);
2535 FILE *f;
2537 if (!t)
2538 error ("Unknown tty device");
2540 f = t->display_info.tty->input;
2542 if (f)
2544 /* First run `suspend-tty-functions' and then clean up the tty
2545 state because `suspend-tty-functions' might need to change
2546 the tty state. */
2547 if (!NILP (Vrun_hooks))
2549 Lisp_Object args[2];
2550 args[0] = intern ("suspend-tty-functions");
2551 XSETTERMINAL (args[1], t);
2552 Frun_hook_with_args (2, args);
2555 reset_sys_modes (t->display_info.tty);
2556 delete_keyboard_wait_descriptor (fileno (f));
2558 #ifndef MSDOS
2559 fclose (f);
2560 if (f != t->display_info.tty->output)
2561 fclose (t->display_info.tty->output);
2562 #endif
2564 t->display_info.tty->input = 0;
2565 t->display_info.tty->output = 0;
2567 if (FRAMEP (t->display_info.tty->top_frame))
2568 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0);
2572 /* Clear display hooks to prevent further output. */
2573 clear_tty_hooks (t);
2575 return Qnil;
2578 DEFUN ("resume-tty", Fresume_tty, Sresume_tty, 0, 1, 0,
2579 doc: /* Resume the previously suspended terminal device TTY.
2580 The terminal is opened and reinitialized. Frames that are on the
2581 suspended terminal are revived.
2583 It is an error to resume a terminal while another terminal is active
2584 on the same device.
2586 This function runs `resume-tty-functions' after resuming the terminal.
2587 The functions are run with one arg, the id of the resumed terminal
2588 device.
2590 `resume-tty' does nothing if it is called on a device that is not
2591 suspended.
2593 TTY may be a terminal object, a frame, or nil (meaning the selected
2594 frame's terminal). */)
2595 (Lisp_Object tty)
2597 struct terminal *t = get_tty_terminal (tty, 1);
2598 int fd;
2600 if (!t)
2601 error ("Unknown tty device");
2603 if (!t->display_info.tty->input)
2605 if (get_named_tty (t->display_info.tty->name))
2606 error ("Cannot resume display while another display is active on the same device");
2608 #ifdef MSDOS
2609 t->display_info.tty->output = stdout;
2610 t->display_info.tty->input = stdin;
2611 #else /* !MSDOS */
2612 fd = emacs_open (t->display_info.tty->name, O_RDWR | O_NOCTTY, 0);
2614 if (fd == -1)
2615 error ("Can not reopen tty device %s: %s", t->display_info.tty->name, strerror (errno));
2617 if (strcmp (t->display_info.tty->name, DEV_TTY))
2618 dissociate_if_controlling_tty (fd);
2620 t->display_info.tty->output = fdopen (fd, "w+");
2621 t->display_info.tty->input = t->display_info.tty->output;
2622 #endif
2624 add_keyboard_wait_descriptor (fd);
2626 if (FRAMEP (t->display_info.tty->top_frame))
2628 struct frame *f = XFRAME (t->display_info.tty->top_frame);
2629 int width, height;
2630 int old_height = FRAME_COLS (f);
2631 int old_width = FRAME_LINES (f);
2633 /* Check if terminal/window size has changed while the frame
2634 was suspended. */
2635 get_tty_size (fileno (t->display_info.tty->input), &width, &height);
2636 if (width != old_width || height != old_height)
2637 change_frame_size (f, height, width, 0, 0, 0);
2638 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
2641 init_sys_modes (t->display_info.tty);
2643 /* Run `resume-tty-functions'. */
2644 if (!NILP (Vrun_hooks))
2646 Lisp_Object args[2];
2647 args[0] = intern ("resume-tty-functions");
2648 XSETTERMINAL (args[1], t);
2649 Frun_hook_with_args (2, args);
2653 set_tty_hooks (t);
2655 return Qnil;
2659 /***********************************************************************
2660 Mouse
2661 ***********************************************************************/
2663 #ifdef HAVE_GPM
2664 void
2665 term_mouse_moveto (int x, int y)
2667 /* TODO: how to set mouse position?
2668 const char *name;
2669 int fd;
2670 name = (const char *) ttyname (0);
2671 fd = open (name, O_WRONLY);
2672 SOME_FUNCTION (x, y, fd);
2673 close (fd);
2674 last_mouse_x = x;
2675 last_mouse_y = y; */
2678 /* Implementation of draw_row_with_mouse_face for TTY/GPM. */
2679 void
2680 tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *row,
2681 int start_hpos, int end_hpos,
2682 enum draw_glyphs_face draw)
2684 int nglyphs = end_hpos - start_hpos;
2685 struct frame *f = XFRAME (WINDOW_FRAME (w));
2686 struct tty_display_info *tty = FRAME_TTY (f);
2687 int face_id = tty->mouse_highlight.mouse_face_face_id;
2688 int save_x, save_y, pos_x, pos_y;
2690 if (end_hpos >= row->used[TEXT_AREA])
2691 nglyphs = row->used[TEXT_AREA] - start_hpos;
2693 pos_y = row->y + WINDOW_TOP_EDGE_Y (w);
2694 pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos + WINDOW_LEFT_EDGE_X (w);
2696 /* Save current cursor co-ordinates. */
2697 save_y = curY (tty);
2698 save_x = curX (tty);
2699 cursor_to (f, pos_y, pos_x);
2701 if (draw == DRAW_MOUSE_FACE)
2702 tty_write_glyphs_with_face (f, row->glyphs[TEXT_AREA] + start_hpos,
2703 nglyphs, face_id);
2704 else if (draw == DRAW_NORMAL_TEXT)
2705 write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
2707 cursor_to (f, save_y, save_x);
2710 static int
2711 term_mouse_movement (FRAME_PTR frame, Gpm_Event *event)
2713 /* Has the mouse moved off the glyph it was on at the last sighting? */
2714 if (event->x != last_mouse_x || event->y != last_mouse_y)
2716 frame->mouse_moved = 1;
2717 note_mouse_highlight (frame, event->x, event->y);
2718 /* Remember which glyph we're now on. */
2719 last_mouse_x = event->x;
2720 last_mouse_y = event->y;
2721 return 1;
2723 return 0;
2726 /* Return the current position of the mouse.
2728 Set *f to the frame the mouse is in, or zero if the mouse is in no
2729 Emacs frame. If it is set to zero, all the other arguments are
2730 garbage.
2732 Set *bar_window to Qnil, and *x and *y to the column and
2733 row of the character cell the mouse is over.
2735 Set *time to the time the mouse was at the returned position.
2737 This clears mouse_moved until the next motion
2738 event arrives. */
2739 static void
2740 term_mouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
2741 enum scroll_bar_part *part, Lisp_Object *x,
2742 Lisp_Object *y, unsigned long *time)
2744 struct timeval now;
2746 *fp = SELECTED_FRAME ();
2747 (*fp)->mouse_moved = 0;
2749 *bar_window = Qnil;
2750 *part = 0;
2752 XSETINT (*x, last_mouse_x);
2753 XSETINT (*y, last_mouse_y);
2754 gettimeofday(&now, 0);
2755 *time = (now.tv_sec * 1000) + (now.tv_usec / 1000);
2758 /* Prepare a mouse-event in *RESULT for placement in the input queue.
2760 If the event is a button press, then note that we have grabbed
2761 the mouse. */
2763 static Lisp_Object
2764 term_mouse_click (struct input_event *result, Gpm_Event *event,
2765 struct frame *f)
2767 struct timeval now;
2768 int i, j;
2770 result->kind = GPM_CLICK_EVENT;
2771 for (i = 0, j = GPM_B_LEFT; i < 3; i++, j >>= 1 )
2773 if (event->buttons & j) {
2774 result->code = i; /* button number */
2775 break;
2778 gettimeofday(&now, 0);
2779 result->timestamp = (now.tv_sec * 1000) + (now.tv_usec / 1000);
2781 if (event->type & GPM_UP)
2782 result->modifiers = up_modifier;
2783 else if (event->type & GPM_DOWN)
2784 result->modifiers = down_modifier;
2785 else
2786 result->modifiers = 0;
2788 if (event->type & GPM_SINGLE)
2789 result->modifiers |= click_modifier;
2791 if (event->type & GPM_DOUBLE)
2792 result->modifiers |= double_modifier;
2794 if (event->type & GPM_TRIPLE)
2795 result->modifiers |= triple_modifier;
2797 if (event->type & GPM_DRAG)
2798 result->modifiers |= drag_modifier;
2800 if (!(event->type & (GPM_MOVE | GPM_DRAG))) {
2802 /* 1 << KG_SHIFT */
2803 if (event->modifiers & (1 << 0))
2804 result->modifiers |= shift_modifier;
2806 /* 1 << KG_CTRL */
2807 if (event->modifiers & (1 << 2))
2808 result->modifiers |= ctrl_modifier;
2810 /* 1 << KG_ALT || KG_ALTGR */
2811 if (event->modifiers & (1 << 3)
2812 || event->modifiers & (1 << 1))
2813 result->modifiers |= meta_modifier;
2816 XSETINT (result->x, event->x);
2817 XSETINT (result->y, event->y);
2818 XSETFRAME (result->frame_or_window, f);
2819 result->arg = Qnil;
2820 return Qnil;
2824 handle_one_term_event (struct tty_display_info *tty, Gpm_Event *event, struct input_event* hold_quit)
2826 struct frame *f = XFRAME (tty->top_frame);
2827 struct input_event ie;
2828 int do_help = 0;
2829 int count = 0;
2831 EVENT_INIT (ie);
2832 ie.kind = NO_EVENT;
2833 ie.arg = Qnil;
2835 if (event->type & (GPM_MOVE | GPM_DRAG)) {
2836 previous_help_echo_string = help_echo_string;
2837 help_echo_string = Qnil;
2839 Gpm_DrawPointer (event->x, event->y, fileno (tty->output));
2841 if (!term_mouse_movement (f, event))
2842 help_echo_string = previous_help_echo_string;
2844 /* If the contents of the global variable help_echo_string
2845 has changed, generate a HELP_EVENT. */
2846 if (!NILP (help_echo_string)
2847 || !NILP (previous_help_echo_string))
2848 do_help = 1;
2850 goto done;
2852 else {
2853 f->mouse_moved = 0;
2854 term_mouse_click (&ie, event, f);
2857 done:
2858 if (ie.kind != NO_EVENT)
2860 kbd_buffer_store_event_hold (&ie, hold_quit);
2861 count++;
2864 if (do_help
2865 && !(hold_quit && hold_quit->kind != NO_EVENT))
2867 Lisp_Object frame;
2869 if (f)
2870 XSETFRAME (frame, f);
2871 else
2872 frame = Qnil;
2874 gen_help_event (help_echo_string, frame, help_echo_window,
2875 help_echo_object, help_echo_pos);
2876 count++;
2879 return count;
2882 DEFUN ("gpm-mouse-start", Fgpm_mouse_start, Sgpm_mouse_start,
2883 0, 0, 0,
2884 doc: /* Open a connection to Gpm.
2885 Gpm-mouse can only be activated for one tty at a time. */)
2886 (void)
2888 struct frame *f = SELECTED_FRAME ();
2889 struct tty_display_info *tty
2890 = ((f)->output_method == output_termcap
2891 ? (f)->terminal->display_info.tty : NULL);
2892 Gpm_Connect connection;
2894 if (!tty)
2895 error ("Gpm-mouse only works in the GNU/Linux console");
2896 if (gpm_tty == tty)
2897 return Qnil; /* Already activated, nothing to do. */
2898 if (gpm_tty)
2899 error ("Gpm-mouse can only be activated for one tty at a time");
2901 connection.eventMask = ~0;
2902 connection.defaultMask = ~GPM_HARD;
2903 connection.maxMod = ~0;
2904 connection.minMod = 0;
2905 gpm_zerobased = 1;
2907 if (Gpm_Open (&connection, 0) < 0)
2908 error ("Gpm-mouse failed to connect to the gpm daemon");
2909 else
2911 gpm_tty = tty;
2912 /* `init_sys_modes' arranges for mouse movements sent through gpm_fd
2913 to generate SIGIOs. Apparently we need to call reset_sys_modes
2914 before calling init_sys_modes. */
2915 reset_sys_modes (tty);
2916 init_sys_modes (tty);
2917 add_gpm_wait_descriptor (gpm_fd);
2918 return Qnil;
2922 void
2923 close_gpm (int fd)
2925 if (fd >= 0)
2926 delete_gpm_wait_descriptor (fd);
2927 while (Gpm_Close()); /* close all the stack */
2928 gpm_tty = NULL;
2931 DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop, Sgpm_mouse_stop,
2932 0, 0, 0,
2933 doc: /* Close a connection to Gpm. */)
2934 (void)
2936 struct frame *f = SELECTED_FRAME ();
2937 struct tty_display_info *tty
2938 = ((f)->output_method == output_termcap
2939 ? (f)->terminal->display_info.tty : NULL);
2941 if (!tty || gpm_tty != tty)
2942 return Qnil; /* Not activated on this terminal, nothing to do. */
2944 close_gpm (gpm_fd);
2945 return Qnil;
2947 #endif /* HAVE_GPM */
2950 #ifndef MSDOS
2951 /***********************************************************************
2952 Initialization
2953 ***********************************************************************/
2955 /* Initialize the tty-dependent part of frame F. The frame must
2956 already have its device initialized. */
2958 void
2959 create_tty_output (struct frame *f)
2961 struct tty_output *t;
2963 if (! FRAME_TERMCAP_P (f))
2964 abort ();
2966 t = xmalloc (sizeof (struct tty_output));
2967 memset (t, 0, sizeof (struct tty_output));
2969 t->display_info = FRAME_TERMINAL (f)->display_info.tty;
2971 f->output_data.tty = t;
2974 /* Delete frame F's face cache, and its tty-dependent part. */
2976 static void
2977 tty_free_frame_resources (struct frame *f)
2979 if (! FRAME_TERMCAP_P (f))
2980 abort ();
2982 if (FRAME_FACE_CACHE (f))
2983 free_frame_faces (f);
2985 xfree (f->output_data.tty);
2988 #else /* MSDOS */
2990 /* Delete frame F's face cache. */
2992 static void
2993 tty_free_frame_resources (struct frame *f)
2995 if (! FRAME_TERMCAP_P (f) && ! FRAME_MSDOS_P (f))
2996 abort ();
2998 if (FRAME_FACE_CACHE (f))
2999 free_frame_faces (f);
3001 #endif /* MSDOS */
3003 /* Reset the hooks in TERMINAL. */
3005 static void
3006 clear_tty_hooks (struct terminal *terminal)
3008 terminal->rif = 0;
3009 terminal->cursor_to_hook = 0;
3010 terminal->raw_cursor_to_hook = 0;
3011 terminal->clear_to_end_hook = 0;
3012 terminal->clear_frame_hook = 0;
3013 terminal->clear_end_of_line_hook = 0;
3014 terminal->ins_del_lines_hook = 0;
3015 terminal->insert_glyphs_hook = 0;
3016 terminal->write_glyphs_hook = 0;
3017 terminal->delete_glyphs_hook = 0;
3018 terminal->ring_bell_hook = 0;
3019 terminal->reset_terminal_modes_hook = 0;
3020 terminal->set_terminal_modes_hook = 0;
3021 terminal->update_begin_hook = 0;
3022 terminal->update_end_hook = 0;
3023 terminal->set_terminal_window_hook = 0;
3024 terminal->mouse_position_hook = 0;
3025 terminal->frame_rehighlight_hook = 0;
3026 terminal->frame_raise_lower_hook = 0;
3027 terminal->fullscreen_hook = 0;
3028 terminal->set_vertical_scroll_bar_hook = 0;
3029 terminal->condemn_scroll_bars_hook = 0;
3030 terminal->redeem_scroll_bar_hook = 0;
3031 terminal->judge_scroll_bars_hook = 0;
3032 terminal->read_socket_hook = 0;
3033 terminal->frame_up_to_date_hook = 0;
3035 /* Leave these two set, or suspended frames are not deleted
3036 correctly. */
3037 terminal->delete_frame_hook = &tty_free_frame_resources;
3038 terminal->delete_terminal_hook = &delete_tty;
3041 /* Initialize hooks in TERMINAL with the values needed for a tty. */
3043 static void
3044 set_tty_hooks (struct terminal *terminal)
3046 terminal->rif = 0; /* ttys don't support window-based redisplay. */
3048 terminal->cursor_to_hook = &tty_cursor_to;
3049 terminal->raw_cursor_to_hook = &tty_raw_cursor_to;
3051 terminal->clear_to_end_hook = &tty_clear_to_end;
3052 terminal->clear_frame_hook = &tty_clear_frame;
3053 terminal->clear_end_of_line_hook = &tty_clear_end_of_line;
3055 terminal->ins_del_lines_hook = &tty_ins_del_lines;
3057 terminal->insert_glyphs_hook = &tty_insert_glyphs;
3058 terminal->write_glyphs_hook = &tty_write_glyphs;
3059 terminal->delete_glyphs_hook = &tty_delete_glyphs;
3061 terminal->ring_bell_hook = &tty_ring_bell;
3063 terminal->reset_terminal_modes_hook = &tty_reset_terminal_modes;
3064 terminal->set_terminal_modes_hook = &tty_set_terminal_modes;
3065 terminal->update_begin_hook = 0; /* Not needed. */
3066 terminal->update_end_hook = &tty_update_end;
3067 terminal->set_terminal_window_hook = &tty_set_terminal_window;
3069 terminal->mouse_position_hook = 0; /* Not needed. */
3070 terminal->frame_rehighlight_hook = 0; /* Not needed. */
3071 terminal->frame_raise_lower_hook = 0; /* Not needed. */
3073 terminal->set_vertical_scroll_bar_hook = 0; /* Not needed. */
3074 terminal->condemn_scroll_bars_hook = 0; /* Not needed. */
3075 terminal->redeem_scroll_bar_hook = 0; /* Not needed. */
3076 terminal->judge_scroll_bars_hook = 0; /* Not needed. */
3078 terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */
3079 terminal->frame_up_to_date_hook = 0; /* Not needed. */
3081 terminal->delete_frame_hook = &tty_free_frame_resources;
3082 terminal->delete_terminal_hook = &delete_tty;
3085 /* Drop the controlling terminal if fd is the same device. */
3086 static void
3087 dissociate_if_controlling_tty (int fd)
3089 #ifndef DOS_NT
3090 int pgid = tcgetpgrp (fd); /* If tcgetpgrp succeeds, fd is the ctty. */
3091 if (pgid != -1)
3093 #if defined (USG5)
3094 setpgrp ();
3095 no_controlling_tty = 1;
3096 #elif defined (CYGWIN)
3097 setsid ();
3098 no_controlling_tty = 1;
3099 #else
3100 #ifdef TIOCNOTTY /* Try BSD ioctls. */
3101 sigblock (sigmask (SIGTTOU));
3102 fd = emacs_open (DEV_TTY, O_RDWR, 0);
3103 if (fd != -1 && ioctl (fd, TIOCNOTTY, 0) != -1)
3105 no_controlling_tty = 1;
3107 if (fd != -1)
3108 emacs_close (fd);
3109 sigunblock (sigmask (SIGTTOU));
3110 #else
3111 /* Unknown system. */
3112 croak ();
3113 #endif /* ! TIOCNOTTY */
3114 #endif /* ! USG */
3116 #endif /* !DOS_NT */
3119 /* Create a termcap display on the tty device with the given name and
3120 type.
3122 If NAME is NULL, then use the controlling tty, i.e., "/dev/tty".
3123 Otherwise NAME should be a path to the tty device file,
3124 e.g. "/dev/pts/7".
3126 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
3128 If MUST_SUCCEED is true, then all errors are fatal. */
3130 struct terminal *
3131 init_tty (const char *name, const char *terminal_type, int must_succeed)
3133 char *area = NULL;
3134 char **address = &area;
3135 int buffer_size = 4096;
3136 register char *p = NULL;
3137 int status;
3138 struct tty_display_info *tty = NULL;
3139 struct terminal *terminal = NULL;
3140 int ctty = 0; /* 1 if asked to open controlling tty. */
3142 if (!terminal_type)
3143 maybe_fatal (must_succeed, 0,
3144 "Unknown terminal type",
3145 "Unknown terminal type");
3147 if (name == NULL)
3148 name = DEV_TTY;
3149 if (!strcmp (name, DEV_TTY))
3150 ctty = 1;
3152 /* If we already have a terminal on the given device, use that. If
3153 all such terminals are suspended, create a new one instead. */
3154 /* XXX Perhaps this should be made explicit by having init_tty
3155 always create a new terminal and separating terminal and frame
3156 creation on Lisp level. */
3157 terminal = get_named_tty (name);
3158 if (terminal)
3159 return terminal;
3161 terminal = create_terminal ();
3162 #ifdef MSDOS
3163 if (been_here > 0)
3164 maybe_fatal (1, 0, "Attempt to create another terminal %s", "",
3165 name, "");
3166 been_here = 1;
3167 tty = &the_only_display_info;
3168 #else
3169 tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info));
3170 #endif
3171 memset (tty, 0, sizeof (struct tty_display_info));
3172 tty->next = tty_list;
3173 tty_list = tty;
3175 terminal->type = output_termcap;
3176 terminal->display_info.tty = tty;
3177 tty->terminal = terminal;
3179 tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
3180 Wcm_clear (tty);
3182 encode_terminal_src_size = 0;
3183 encode_terminal_dst_size = 0;
3185 #ifdef HAVE_GPM
3186 terminal->mouse_position_hook = term_mouse_position;
3187 tty->mouse_highlight.mouse_face_window = Qnil;
3188 #endif
3191 #ifndef DOS_NT
3192 set_tty_hooks (terminal);
3195 int fd;
3196 FILE *file;
3198 #ifdef O_IGNORE_CTTY
3199 if (!ctty)
3200 /* Open the terminal device. Don't recognize it as our
3201 controlling terminal, and don't make it the controlling tty
3202 if we don't have one at the moment. */
3203 fd = emacs_open (name, O_RDWR | O_IGNORE_CTTY | O_NOCTTY, 0);
3204 else
3205 #else
3206 /* Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
3207 defined on Hurd. On other systems, we need to explicitly
3208 dissociate ourselves from the controlling tty when we want to
3209 open a frame on the same terminal. */
3210 fd = emacs_open (name, O_RDWR | O_NOCTTY, 0);
3211 #endif /* O_IGNORE_CTTY */
3213 tty->name = xstrdup (name);
3214 terminal->name = xstrdup (name);
3216 if (fd < 0)
3217 maybe_fatal (must_succeed, terminal,
3218 "Could not open file: %s",
3219 "Could not open file: %s",
3220 name);
3221 if (!isatty (fd))
3223 close (fd);
3224 maybe_fatal (must_succeed, terminal,
3225 "Not a tty device: %s",
3226 "Not a tty device: %s",
3227 name);
3230 #ifndef O_IGNORE_CTTY
3231 if (!ctty)
3232 dissociate_if_controlling_tty (fd);
3233 #endif
3235 file = fdopen (fd, "w+");
3236 tty->input = file;
3237 tty->output = file;
3240 tty->type = xstrdup (terminal_type);
3242 add_keyboard_wait_descriptor (fileno (tty->input));
3244 Wcm_clear (tty);
3246 tty->termcap_term_buffer = (char *) xmalloc (buffer_size);
3248 /* On some systems, tgetent tries to access the controlling
3249 terminal. */
3250 sigblock (sigmask (SIGTTOU));
3251 status = tgetent (tty->termcap_term_buffer, terminal_type);
3252 sigunblock (sigmask (SIGTTOU));
3254 if (status < 0)
3256 #ifdef TERMINFO
3257 maybe_fatal (must_succeed, terminal,
3258 "Cannot open terminfo database file",
3259 "Cannot open terminfo database file");
3260 #else
3261 maybe_fatal (must_succeed, terminal,
3262 "Cannot open termcap database file",
3263 "Cannot open termcap database file");
3264 #endif
3266 if (status == 0)
3268 maybe_fatal (must_succeed, terminal,
3269 "Terminal type %s is not defined",
3270 "Terminal type %s is not defined.\n\
3271 If that is not the actual type of terminal you have,\n\
3272 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3273 `setenv TERM ...') to specify the correct type. It may be necessary\n"
3274 #ifdef TERMINFO
3275 "to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3276 #else
3277 "to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3278 #endif
3279 terminal_type);
3282 #ifndef TERMINFO
3283 if (strlen (tty->termcap_term_buffer) >= buffer_size)
3284 abort ();
3285 buffer_size = strlen (tty->termcap_term_buffer);
3286 #endif
3287 tty->termcap_strings_buffer = area = (char *) xmalloc (buffer_size);
3288 tty->TS_ins_line = tgetstr ("al", address);
3289 tty->TS_ins_multi_lines = tgetstr ("AL", address);
3290 tty->TS_bell = tgetstr ("bl", address);
3291 BackTab (tty) = tgetstr ("bt", address);
3292 tty->TS_clr_to_bottom = tgetstr ("cd", address);
3293 tty->TS_clr_line = tgetstr ("ce", address);
3294 tty->TS_clr_frame = tgetstr ("cl", address);
3295 ColPosition (tty) = NULL; /* tgetstr ("ch", address); */
3296 AbsPosition (tty) = tgetstr ("cm", address);
3297 CR (tty) = tgetstr ("cr", address);
3298 tty->TS_set_scroll_region = tgetstr ("cs", address);
3299 tty->TS_set_scroll_region_1 = tgetstr ("cS", address);
3300 RowPosition (tty) = tgetstr ("cv", address);
3301 tty->TS_del_char = tgetstr ("dc", address);
3302 tty->TS_del_multi_chars = tgetstr ("DC", address);
3303 tty->TS_del_line = tgetstr ("dl", address);
3304 tty->TS_del_multi_lines = tgetstr ("DL", address);
3305 tty->TS_delete_mode = tgetstr ("dm", address);
3306 tty->TS_end_delete_mode = tgetstr ("ed", address);
3307 tty->TS_end_insert_mode = tgetstr ("ei", address);
3308 Home (tty) = tgetstr ("ho", address);
3309 tty->TS_ins_char = tgetstr ("ic", address);
3310 tty->TS_ins_multi_chars = tgetstr ("IC", address);
3311 tty->TS_insert_mode = tgetstr ("im", address);
3312 tty->TS_pad_inserted_char = tgetstr ("ip", address);
3313 tty->TS_end_keypad_mode = tgetstr ("ke", address);
3314 tty->TS_keypad_mode = tgetstr ("ks", address);
3315 LastLine (tty) = tgetstr ("ll", address);
3316 Right (tty) = tgetstr ("nd", address);
3317 Down (tty) = tgetstr ("do", address);
3318 if (!Down (tty))
3319 Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do" */
3320 if (tgetflag ("bs"))
3321 Left (tty) = "\b"; /* can't possibly be longer! */
3322 else /* (Actually, "bs" is obsolete...) */
3323 Left (tty) = tgetstr ("le", address);
3324 if (!Left (tty))
3325 Left (tty) = tgetstr ("bc", address); /* Obsolete name for "le" */
3326 tty->TS_pad_char = tgetstr ("pc", address);
3327 tty->TS_repeat = tgetstr ("rp", address);
3328 tty->TS_end_standout_mode = tgetstr ("se", address);
3329 tty->TS_fwd_scroll = tgetstr ("sf", address);
3330 tty->TS_standout_mode = tgetstr ("so", address);
3331 tty->TS_rev_scroll = tgetstr ("sr", address);
3332 tty->Wcm->cm_tab = tgetstr ("ta", address);
3333 tty->TS_end_termcap_modes = tgetstr ("te", address);
3334 tty->TS_termcap_modes = tgetstr ("ti", address);
3335 Up (tty) = tgetstr ("up", address);
3336 tty->TS_visible_bell = tgetstr ("vb", address);
3337 tty->TS_cursor_normal = tgetstr ("ve", address);
3338 tty->TS_cursor_visible = tgetstr ("vs", address);
3339 tty->TS_cursor_invisible = tgetstr ("vi", address);
3340 tty->TS_set_window = tgetstr ("wi", address);
3342 tty->TS_enter_underline_mode = tgetstr ("us", address);
3343 tty->TS_exit_underline_mode = tgetstr ("ue", address);
3344 tty->TS_enter_bold_mode = tgetstr ("md", address);
3345 tty->TS_enter_dim_mode = tgetstr ("mh", address);
3346 tty->TS_enter_blink_mode = tgetstr ("mb", address);
3347 tty->TS_enter_reverse_mode = tgetstr ("mr", address);
3348 tty->TS_enter_alt_charset_mode = tgetstr ("as", address);
3349 tty->TS_exit_alt_charset_mode = tgetstr ("ae", address);
3350 tty->TS_exit_attribute_mode = tgetstr ("me", address);
3352 MultiUp (tty) = tgetstr ("UP", address);
3353 MultiDown (tty) = tgetstr ("DO", address);
3354 MultiLeft (tty) = tgetstr ("LE", address);
3355 MultiRight (tty) = tgetstr ("RI", address);
3357 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
3358 color because we can't switch back to the default foreground and
3359 background. */
3360 tty->TS_orig_pair = tgetstr ("op", address);
3361 if (tty->TS_orig_pair)
3363 tty->TS_set_foreground = tgetstr ("AF", address);
3364 tty->TS_set_background = tgetstr ("AB", address);
3365 if (!tty->TS_set_foreground)
3367 /* SVr4. */
3368 tty->TS_set_foreground = tgetstr ("Sf", address);
3369 tty->TS_set_background = tgetstr ("Sb", address);
3372 tty->TN_max_colors = tgetnum ("Co");
3373 tty->TN_max_pairs = tgetnum ("pa");
3375 tty->TN_no_color_video = tgetnum ("NC");
3376 if (tty->TN_no_color_video == -1)
3377 tty->TN_no_color_video = 0;
3380 tty_default_color_capabilities (tty, 1);
3382 MagicWrap (tty) = tgetflag ("xn");
3383 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
3384 the former flag imply the latter. */
3385 AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
3386 terminal->memory_below_frame = tgetflag ("db");
3387 tty->TF_hazeltine = tgetflag ("hz");
3388 terminal->must_write_spaces = tgetflag ("in");
3389 tty->meta_key = tgetflag ("km") || tgetflag ("MT");
3390 tty->TF_insmode_motion = tgetflag ("mi");
3391 tty->TF_standout_motion = tgetflag ("ms");
3392 tty->TF_underscore = tgetflag ("ul");
3393 tty->TF_teleray = tgetflag ("xt");
3395 #else /* DOS_NT */
3396 #ifdef WINDOWSNT
3398 struct frame *f = XFRAME (selected_frame);
3400 initialize_w32_display (terminal);
3402 FrameRows (tty) = FRAME_LINES (f);
3403 FrameCols (tty) = FRAME_COLS (f);
3404 tty->specified_window = FRAME_LINES (f);
3406 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
3407 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
3408 terminal->char_ins_del_ok = 1;
3409 baud_rate = 19200;
3411 #else /* MSDOS */
3413 int height, width;
3414 if (strcmp (terminal_type, "internal") == 0)
3415 terminal->type = output_msdos_raw;
3416 initialize_msdos_display (terminal);
3418 get_tty_size (fileno (tty->input), &width, &height);
3419 FrameCols (tty) = width;
3420 FrameRows (tty) = height;
3421 terminal->char_ins_del_ok = 0;
3422 init_baud_rate (fileno (tty->input));
3424 #endif /* MSDOS */
3425 tty->output = stdout;
3426 tty->input = stdin;
3427 /* The following two are inaccessible from w32console.c. */
3428 terminal->delete_frame_hook = &tty_free_frame_resources;
3429 terminal->delete_terminal_hook = &delete_tty;
3431 tty->name = xstrdup (name);
3432 terminal->name = xstrdup (name);
3433 tty->type = xstrdup (terminal_type);
3435 add_keyboard_wait_descriptor (0);
3437 tty->delete_in_insert_mode = 1;
3439 UseTabs (tty) = 0;
3440 terminal->scroll_region_ok = 0;
3442 /* Seems to insert lines when it's not supposed to, messing up the
3443 display. In doing a trace, it didn't seem to be called much, so I
3444 don't think we're losing anything by turning it off. */
3445 terminal->line_ins_del_ok = 0;
3447 tty->TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
3448 #endif /* DOS_NT */
3450 terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
3451 init_kboard (terminal->kboard);
3452 terminal->kboard->Vwindow_system = Qnil;
3453 terminal->kboard->next_kboard = all_kboards;
3454 all_kboards = terminal->kboard;
3455 terminal->kboard->reference_count++;
3456 /* Don't let the initial kboard remain current longer than necessary.
3457 That would cause problems if a file loaded on startup tries to
3458 prompt in the mini-buffer. */
3459 if (current_kboard == initial_kboard)
3460 current_kboard = terminal->kboard;
3461 #ifndef DOS_NT
3462 term_get_fkeys (address, terminal->kboard);
3464 /* Get frame size from system, or else from termcap. */
3466 int height, width;
3467 get_tty_size (fileno (tty->input), &width, &height);
3468 FrameCols (tty) = width;
3469 FrameRows (tty) = height;
3472 if (FrameCols (tty) <= 0)
3473 FrameCols (tty) = tgetnum ("co");
3474 if (FrameRows (tty) <= 0)
3475 FrameRows (tty) = tgetnum ("li");
3477 if (FrameRows (tty) < 3 || FrameCols (tty) < 3)
3478 maybe_fatal (must_succeed, terminal,
3479 "Screen size %dx%d is too small",
3480 "Screen size %dx%d is too small",
3481 FrameCols (tty), FrameRows (tty));
3483 TabWidth (tty) = tgetnum ("tw");
3485 if (!tty->TS_bell)
3486 tty->TS_bell = "\07";
3488 if (!tty->TS_fwd_scroll)
3489 tty->TS_fwd_scroll = Down (tty);
3491 PC = tty->TS_pad_char ? *tty->TS_pad_char : 0;
3493 if (TabWidth (tty) < 0)
3494 TabWidth (tty) = 8;
3496 /* Turned off since /etc/termcap seems to have :ta= for most terminals
3497 and newer termcap doc does not seem to say there is a default.
3498 if (!tty->Wcm->cm_tab)
3499 tty->Wcm->cm_tab = "\t";
3502 /* We don't support standout modes that use `magic cookies', so
3503 turn off any that do. */
3504 if (tty->TS_standout_mode && tgetnum ("sg") >= 0)
3506 tty->TS_standout_mode = 0;
3507 tty->TS_end_standout_mode = 0;
3509 if (tty->TS_enter_underline_mode && tgetnum ("ug") >= 0)
3511 tty->TS_enter_underline_mode = 0;
3512 tty->TS_exit_underline_mode = 0;
3515 /* If there's no standout mode, try to use underlining instead. */
3516 if (tty->TS_standout_mode == 0)
3518 tty->TS_standout_mode = tty->TS_enter_underline_mode;
3519 tty->TS_end_standout_mode = tty->TS_exit_underline_mode;
3522 /* If no `se' string, try using a `me' string instead.
3523 If that fails, we can't use standout mode at all. */
3524 if (tty->TS_end_standout_mode == 0)
3526 char *s = tgetstr ("me", address);
3527 if (s != 0)
3528 tty->TS_end_standout_mode = s;
3529 else
3530 tty->TS_standout_mode = 0;
3533 if (tty->TF_teleray)
3535 tty->Wcm->cm_tab = 0;
3536 /* We can't support standout mode, because it uses magic cookies. */
3537 tty->TS_standout_mode = 0;
3538 /* But that means we cannot rely on ^M to go to column zero! */
3539 CR (tty) = 0;
3540 /* LF can't be trusted either -- can alter hpos */
3541 /* if move at column 0 thru a line with TS_standout_mode */
3542 Down (tty) = 0;
3545 /* Special handling for certain terminal types known to need it */
3547 if (!strcmp (terminal_type, "supdup"))
3549 terminal->memory_below_frame = 1;
3550 tty->Wcm->cm_losewrap = 1;
3552 if (!strncmp (terminal_type, "c10", 3)
3553 || !strcmp (terminal_type, "perq"))
3555 /* Supply a makeshift :wi string.
3556 This string is not valid in general since it works only
3557 for windows starting at the upper left corner;
3558 but that is all Emacs uses.
3560 This string works only if the frame is using
3561 the top of the video memory, because addressing is memory-relative.
3562 So first check the :ti string to see if that is true.
3564 It would be simpler if the :wi string could go in the termcap
3565 entry, but it can't because it is not fully valid.
3566 If it were in the termcap entry, it would confuse other programs. */
3567 if (!tty->TS_set_window)
3569 p = tty->TS_termcap_modes;
3570 while (*p && strcmp (p, "\033v "))
3571 p++;
3572 if (*p)
3573 tty->TS_set_window = "\033v%C %C %C %C ";
3575 /* Termcap entry often fails to have :in: flag */
3576 terminal->must_write_spaces = 1;
3577 /* :ti string typically fails to have \E^G! in it */
3578 /* This limits scope of insert-char to one line. */
3579 strcpy (area, tty->TS_termcap_modes);
3580 strcat (area, "\033\007!");
3581 tty->TS_termcap_modes = area;
3582 area += strlen (area) + 1;
3583 p = AbsPosition (tty);
3584 /* Change all %+ parameters to %C, to handle
3585 values above 96 correctly for the C100. */
3586 while (*p)
3588 if (p[0] == '%' && p[1] == '+')
3589 p[1] = 'C';
3590 p++;
3594 tty->specified_window = FrameRows (tty);
3596 if (Wcm_init (tty) == -1) /* can't do cursor motion */
3598 maybe_fatal (must_succeed, terminal,
3599 "Terminal type \"%s\" is not powerful enough to run Emacs",
3600 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3601 It lacks the ability to position the cursor.\n\
3602 If that is not the actual type of terminal you have,\n\
3603 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3604 `setenv TERM ...') to specify the correct type. It may be necessary\n"
3605 # ifdef TERMINFO
3606 "to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3607 # else /* TERMCAP */
3608 "to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3609 # endif /* TERMINFO */
3610 terminal_type);
3613 if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
3614 maybe_fatal (must_succeed, terminal,
3615 "Could not determine the frame size",
3616 "Could not determine the frame size");
3618 tty->delete_in_insert_mode
3619 = tty->TS_delete_mode && tty->TS_insert_mode
3620 && !strcmp (tty->TS_delete_mode, tty->TS_insert_mode);
3622 tty->se_is_so = (tty->TS_standout_mode
3623 && tty->TS_end_standout_mode
3624 && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode));
3626 UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8;
3628 terminal->scroll_region_ok
3629 = (tty->Wcm->cm_abs
3630 && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
3632 terminal->line_ins_del_ok
3633 = (((tty->TS_ins_line || tty->TS_ins_multi_lines)
3634 && (tty->TS_del_line || tty->TS_del_multi_lines))
3635 || (terminal->scroll_region_ok
3636 && tty->TS_fwd_scroll && tty->TS_rev_scroll));
3638 terminal->char_ins_del_ok
3639 = ((tty->TS_ins_char || tty->TS_insert_mode
3640 || tty->TS_pad_inserted_char || tty->TS_ins_multi_chars)
3641 && (tty->TS_del_char || tty->TS_del_multi_chars));
3643 terminal->fast_clear_end_of_line = tty->TS_clr_line != 0;
3645 init_baud_rate (fileno (tty->input));
3647 #endif /* not DOS_NT */
3649 /* Init system terminal modes (RAW or CBREAK, etc.). */
3650 init_sys_modes (tty);
3652 return terminal;
3656 static void
3657 vfatal (const char *str, va_list ap)
3659 fprintf (stderr, "emacs: ");
3660 vfprintf (stderr, str, ap);
3661 if (!(strlen (str) > 0 && str[strlen (str) - 1] == '\n'))
3662 fprintf (stderr, "\n");
3663 va_end (ap);
3664 fflush (stderr);
3665 exit (1);
3669 /* Auxiliary error-handling function for init_tty.
3670 Delete TERMINAL, then call error or fatal with str1 or str2,
3671 respectively, according to MUST_SUCCEED. */
3673 static void
3674 maybe_fatal (int must_succeed, struct terminal *terminal,
3675 const char *str1, const char *str2, ...)
3677 va_list ap;
3678 va_start (ap, str2);
3679 if (terminal)
3680 delete_tty (terminal);
3682 if (must_succeed)
3683 vfatal (str2, ap);
3684 else
3685 verror (str1, ap);
3687 va_end (ap);
3688 abort ();
3691 void
3692 fatal (const char *str, ...)
3694 va_list ap;
3695 va_start (ap, str);
3696 vfatal (str, ap);
3697 va_end (ap);
3702 /* Delete the given tty terminal, closing all frames on it. */
3704 static void
3705 delete_tty (struct terminal *terminal)
3707 struct tty_display_info *tty;
3709 /* Protect against recursive calls. delete_frame in
3710 delete_terminal calls us back when it deletes our last frame. */
3711 if (!terminal->name)
3712 return;
3714 if (terminal->type != output_termcap)
3715 abort ();
3717 tty = terminal->display_info.tty;
3719 if (tty == tty_list)
3720 tty_list = tty->next;
3721 else
3723 struct tty_display_info *p;
3724 for (p = tty_list; p && p->next != tty; p = p->next)
3727 if (! p)
3728 /* This should not happen. */
3729 abort ();
3731 p->next = tty->next;
3732 tty->next = 0;
3735 /* reset_sys_modes needs a valid device, so this call needs to be
3736 before delete_terminal. */
3737 reset_sys_modes (tty);
3739 delete_terminal (terminal);
3741 xfree (tty->name);
3742 xfree (tty->type);
3744 if (tty->input)
3746 delete_keyboard_wait_descriptor (fileno (tty->input));
3747 if (tty->input != stdin)
3748 fclose (tty->input);
3750 if (tty->output && tty->output != stdout && tty->output != tty->input)
3751 fclose (tty->output);
3752 if (tty->termscript)
3753 fclose (tty->termscript);
3755 xfree (tty->old_tty);
3756 xfree (tty->Wcm);
3757 xfree (tty->termcap_strings_buffer);
3758 xfree (tty->termcap_term_buffer);
3760 memset (tty, 0, sizeof (struct tty_display_info));
3761 xfree (tty);
3766 /* Mark the pointers in the tty_display_info objects.
3767 Called by the Fgarbage_collector. */
3769 void
3770 mark_ttys (void)
3772 struct tty_display_info *tty;
3774 for (tty = tty_list; tty; tty = tty->next)
3775 mark_object (tty->top_frame);
3780 void
3781 syms_of_term (void)
3783 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
3784 doc: /* Non-nil means the system uses terminfo rather than termcap.
3785 This variable can be used by terminal emulator packages. */);
3786 #ifdef TERMINFO
3787 system_uses_terminfo = 1;
3788 #else
3789 system_uses_terminfo = 0;
3790 #endif
3792 DEFVAR_LISP ("suspend-tty-functions", &Vsuspend_tty_functions,
3793 doc: /* Functions to be run after suspending a tty.
3794 The functions are run with one argument, the terminal object to be suspended.
3795 See `suspend-tty'. */);
3796 Vsuspend_tty_functions = Qnil;
3799 DEFVAR_LISP ("resume-tty-functions", &Vresume_tty_functions,
3800 doc: /* Functions to be run after resuming a tty.
3801 The functions are run with one argument, the terminal object that was revived.
3802 See `resume-tty'. */);
3803 Vresume_tty_functions = Qnil;
3805 DEFVAR_BOOL ("visible-cursor", &visible_cursor,
3806 doc: /* Non-nil means to make the cursor very visible.
3807 This only has an effect when running in a text terminal.
3808 What means \"very visible\" is up to your terminal. It may make the cursor
3809 bigger, or it may make it blink, or it may do nothing at all. */);
3810 visible_cursor = 1;
3812 defsubr (&Stty_display_color_p);
3813 defsubr (&Stty_display_color_cells);
3814 defsubr (&Stty_no_underline);
3815 defsubr (&Stty_type);
3816 defsubr (&Scontrolling_tty_p);
3817 defsubr (&Ssuspend_tty);
3818 defsubr (&Sresume_tty);
3819 #ifdef HAVE_GPM
3820 defsubr (&Sgpm_mouse_start);
3821 defsubr (&Sgpm_mouse_stop);
3822 #endif /* HAVE_GPM */
3824 #ifndef DOS_NT
3825 default_orig_pair = NULL;
3826 default_set_foreground = NULL;
3827 default_set_background = NULL;
3828 #endif /* !DOS_NT */
3830 encode_terminal_src = NULL;
3831 encode_terminal_dst = NULL;