(check-declare-verify): Tweak regexp for end of function-name. Handle
[emacs.git] / src / term.c
blobcdf84eef0911016b9e51daea9084a78d0644323a
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 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 /* New redisplay, TTY faces by Gerd Moellmann <gerd@gnu.org>. */
24 #include <config.h>
25 #include <stdio.h>
26 #include <ctype.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <sys/file.h>
31 #ifdef HAVE_UNISTD_H
32 #include <unistd.h>
33 #endif
35 #if HAVE_TERMIOS_H
36 #include <termios.h> /* For TIOCNOTTY. */
37 #endif
39 #include <signal.h>
41 #include "lisp.h"
42 #include "termchar.h"
43 #include "termopts.h"
44 #include "charset.h"
45 #include "coding.h"
46 #include "keyboard.h"
47 #include "frame.h"
48 #include "disptab.h"
49 #include "termhooks.h"
50 #include "dispextern.h"
51 #include "window.h"
52 #include "keymap.h"
53 #include "blockinput.h"
54 #include "syssignal.h"
55 #include "systty.h"
56 #include "intervals.h"
58 /* For now, don't try to include termcap.h. On some systems,
59 configure finds a non-standard termcap.h that the main build
60 won't find. */
62 #if defined HAVE_TERMCAP_H && 0
63 #include <termcap.h>
64 #else
65 extern void tputs P_ ((const char *, int, int (*)(int)));
66 extern int tgetent P_ ((char *, const char *));
67 extern int tgetflag P_ ((char *id));
68 extern int tgetnum P_ ((char *id));
69 #endif
71 #include "cm.h"
72 #ifdef HAVE_X_WINDOWS
73 #include "xterm.h"
74 #endif
75 #ifdef MAC_OS
76 #include "macterm.h"
77 #endif
79 #ifndef O_RDWR
80 #define O_RDWR 2
81 #endif
83 #ifndef O_NOCTTY
84 #define O_NOCTTY 0
85 #endif
87 /* The name of the default console device. */
88 #ifdef WINDOWSNT
89 #define DEV_TTY "CONOUT$"
90 #else
91 #define DEV_TTY "/dev/tty"
92 #endif
94 static void tty_set_scroll_region P_ ((struct frame *f, int start, int stop));
95 static void turn_on_face P_ ((struct frame *, int face_id));
96 static void turn_off_face P_ ((struct frame *, int face_id));
97 static void tty_show_cursor P_ ((struct tty_display_info *));
98 static void tty_hide_cursor P_ ((struct tty_display_info *));
99 static void tty_background_highlight P_ ((struct tty_display_info *tty));
100 static void clear_tty_hooks P_ ((struct terminal *terminal));
101 static void set_tty_hooks P_ ((struct terminal *terminal));
102 static void dissociate_if_controlling_tty P_ ((int fd));
103 static void delete_tty P_ ((struct terminal *));
105 #define OUTPUT(tty, a) \
106 emacs_tputs ((tty), a, \
107 (int) (FRAME_LINES (XFRAME (selected_frame)) \
108 - curY (tty)), \
109 cmputc)
111 #define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
112 #define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
114 #define OUTPUT_IF(tty, a) \
115 do { \
116 if (a) \
117 emacs_tputs ((tty), a, \
118 (int) (FRAME_LINES (XFRAME (selected_frame)) \
119 - curY (tty) ), \
120 cmputc); \
121 } while (0)
123 #define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
125 /* If true, use "vs", otherwise use "ve" to make the cursor visible. */
127 static int visible_cursor;
129 /* Display space properties */
131 extern Lisp_Object Qspace, QCalign_to, QCwidth;
133 /* Functions to call after suspending a tty. */
134 Lisp_Object Vsuspend_tty_functions;
136 /* Functions to call after resuming a tty. */
137 Lisp_Object Vresume_tty_functions;
139 /* Chain of all tty device parameters. */
140 struct tty_display_info *tty_list;
142 /* Nonzero means no need to redraw the entire frame on resuming a
143 suspended Emacs. This is useful on terminals with multiple
144 pages, where one page is used for Emacs and another for all
145 else. */
146 int no_redraw_on_reenter;
148 /* Meaning of bits in no_color_video. Each bit set means that the
149 corresponding attribute cannot be combined with colors. */
151 enum no_color_bit
153 NC_STANDOUT = 1 << 0,
154 NC_UNDERLINE = 1 << 1,
155 NC_REVERSE = 1 << 2,
156 NC_BLINK = 1 << 3,
157 NC_DIM = 1 << 4,
158 NC_BOLD = 1 << 5,
159 NC_INVIS = 1 << 6,
160 NC_PROTECT = 1 << 7,
161 NC_ALT_CHARSET = 1 << 8
164 /* internal state */
166 /* The largest frame width in any call to calculate_costs. */
168 int max_frame_cols;
170 /* The largest frame height in any call to calculate_costs. */
172 int max_frame_lines;
174 /* Non-zero if we have dropped our controlling tty and therefore
175 should not open a frame on stdout. */
176 static int no_controlling_tty;
178 /* Provided for lisp packages. */
180 static int system_uses_terminfo;
182 char *tparam ();
184 extern char *tgetstr ();
187 #ifdef HAVE_GPM
188 #include <sys/fcntl.h>
189 #include "buffer.h"
191 static void term_clear_mouse_face ();
192 static void term_mouse_highlight (struct frame *f, int x, int y);
194 /* The device for which we have enabled gpm support (or NULL). */
195 struct tty_display_info *gpm_tty = NULL;
197 /* These variables describe the range of text currently shown in its
198 mouse-face, together with the window they apply to. As long as
199 the mouse stays within this range, we need not redraw anything on
200 its account. Rows and columns are glyph matrix positions in
201 MOUSE_FACE_WINDOW. */
202 static int mouse_face_beg_row, mouse_face_beg_col;
203 static int mouse_face_end_row, mouse_face_end_col;
204 static int mouse_face_past_end;
205 static Lisp_Object mouse_face_window;
206 static int mouse_face_face_id;
208 static int pos_x, pos_y;
209 static int last_mouse_x, last_mouse_y;
210 #endif /* HAVE_GPM */
212 /* Ring the bell on a tty. */
214 static void
215 tty_ring_bell (struct frame *f)
217 struct tty_display_info *tty = FRAME_TTY (f);
219 if (tty->output)
221 OUTPUT (tty, (tty->TS_visible_bell && visible_bell
222 ? tty->TS_visible_bell
223 : tty->TS_bell));
224 fflush (tty->output);
228 /* Set up termcap modes for Emacs. */
230 void
231 tty_set_terminal_modes (struct terminal *terminal)
233 struct tty_display_info *tty = terminal->display_info.tty;
235 if (tty->output)
237 if (tty->TS_termcap_modes)
238 OUTPUT (tty, tty->TS_termcap_modes);
239 else
241 /* Output enough newlines to scroll all the old screen contents
242 off the screen, so it won't be overwritten and lost. */
243 int i;
244 current_tty = tty;
245 for (i = 0; i < FRAME_LINES (XFRAME (selected_frame)); i++)
246 cmputc ('\n');
249 OUTPUT_IF (tty, tty->TS_termcap_modes);
250 OUTPUT_IF (tty, visible_cursor ? tty->TS_cursor_visible : tty->TS_cursor_normal);
251 OUTPUT_IF (tty, tty->TS_keypad_mode);
252 losecursor (tty);
253 fflush (tty->output);
257 /* Reset termcap modes before exiting Emacs. */
259 void
260 tty_reset_terminal_modes (struct terminal *terminal)
262 struct tty_display_info *tty = terminal->display_info.tty;
264 if (tty->output)
266 tty_turn_off_highlight (tty);
267 tty_turn_off_insert (tty);
268 OUTPUT_IF (tty, tty->TS_end_keypad_mode);
269 OUTPUT_IF (tty, tty->TS_cursor_normal);
270 OUTPUT_IF (tty, tty->TS_end_termcap_modes);
271 OUTPUT_IF (tty, tty->TS_orig_pair);
272 /* Output raw CR so kernel can track the cursor hpos. */
273 current_tty = tty;
274 cmputc ('\r');
275 fflush (tty->output);
279 /* Flag the end of a display update on a termcap terminal. */
281 static void
282 tty_update_end (struct frame *f)
284 struct tty_display_info *tty = FRAME_TTY (f);
286 if (!XWINDOW (selected_window)->cursor_off_p)
287 tty_show_cursor (tty);
288 tty_turn_off_insert (tty);
289 tty_background_highlight (tty);
292 /* The implementation of set_terminal_window for termcap frames. */
294 static void
295 tty_set_terminal_window (struct frame *f, int size)
297 struct tty_display_info *tty = FRAME_TTY (f);
299 tty->specified_window = size ? size : FRAME_LINES (f);
300 if (FRAME_SCROLL_REGION_OK (f))
301 tty_set_scroll_region (f, 0, tty->specified_window);
304 static void
305 tty_set_scroll_region (struct frame *f, int start, int stop)
307 char *buf;
308 struct tty_display_info *tty = FRAME_TTY (f);
310 if (tty->TS_set_scroll_region)
311 buf = tparam (tty->TS_set_scroll_region, 0, 0, start, stop - 1);
312 else if (tty->TS_set_scroll_region_1)
313 buf = tparam (tty->TS_set_scroll_region_1, 0, 0,
314 FRAME_LINES (f), start,
315 FRAME_LINES (f) - stop,
316 FRAME_LINES (f));
317 else
318 buf = tparam (tty->TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (f));
320 OUTPUT (tty, buf);
321 xfree (buf);
322 losecursor (tty);
326 static void
327 tty_turn_on_insert (struct tty_display_info *tty)
329 if (!tty->insert_mode)
330 OUTPUT (tty, tty->TS_insert_mode);
331 tty->insert_mode = 1;
334 void
335 tty_turn_off_insert (struct tty_display_info *tty)
337 if (tty->insert_mode)
338 OUTPUT (tty, tty->TS_end_insert_mode);
339 tty->insert_mode = 0;
342 /* Handle highlighting. */
344 void
345 tty_turn_off_highlight (struct tty_display_info *tty)
347 if (tty->standout_mode)
348 OUTPUT_IF (tty, tty->TS_end_standout_mode);
349 tty->standout_mode = 0;
352 static void
353 tty_turn_on_highlight (struct tty_display_info *tty)
355 if (!tty->standout_mode)
356 OUTPUT_IF (tty, tty->TS_standout_mode);
357 tty->standout_mode = 1;
360 static void
361 tty_toggle_highlight (struct tty_display_info *tty)
363 if (tty->standout_mode)
364 tty_turn_off_highlight (tty);
365 else
366 tty_turn_on_highlight (tty);
370 /* Make cursor invisible. */
372 static void
373 tty_hide_cursor (struct tty_display_info *tty)
375 if (tty->cursor_hidden == 0)
377 tty->cursor_hidden = 1;
378 OUTPUT_IF (tty, tty->TS_cursor_invisible);
383 /* Ensure that cursor is visible. */
385 static void
386 tty_show_cursor (struct tty_display_info *tty)
388 if (tty->cursor_hidden)
390 tty->cursor_hidden = 0;
391 OUTPUT_IF (tty, tty->TS_cursor_normal);
392 if (visible_cursor)
393 OUTPUT_IF (tty, tty->TS_cursor_visible);
398 /* Set standout mode to the state it should be in for
399 empty space inside windows. What this is,
400 depends on the user option inverse-video. */
402 static void
403 tty_background_highlight (struct tty_display_info *tty)
405 if (inverse_video)
406 tty_turn_on_highlight (tty);
407 else
408 tty_turn_off_highlight (tty);
411 /* Set standout mode to the mode specified for the text to be output. */
413 static void
414 tty_highlight_if_desired (struct tty_display_info *tty)
416 if (inverse_video)
417 tty_turn_on_highlight (tty);
418 else
419 tty_turn_off_highlight (tty);
423 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
424 frame-relative coordinates. */
426 static void
427 tty_cursor_to (struct frame *f, int vpos, int hpos)
429 struct tty_display_info *tty = FRAME_TTY (f);
431 /* Detect the case where we are called from reset_sys_modes
432 and the costs have never been calculated. Do nothing. */
433 if (! tty->costs_set)
434 return;
436 if (curY (tty) == vpos
437 && curX (tty) == hpos)
438 return;
439 if (!tty->TF_standout_motion)
440 tty_background_highlight (tty);
441 if (!tty->TF_insmode_motion)
442 tty_turn_off_insert (tty);
443 cmgoto (tty, vpos, hpos);
446 /* Similar but don't take any account of the wasted characters. */
448 static void
449 tty_raw_cursor_to (struct frame *f, int row, int col)
451 struct tty_display_info *tty = FRAME_TTY (f);
453 if (curY (tty) == row
454 && curX (tty) == col)
455 return;
456 if (!tty->TF_standout_motion)
457 tty_background_highlight (tty);
458 if (!tty->TF_insmode_motion)
459 tty_turn_off_insert (tty);
460 cmgoto (tty, row, col);
463 /* Erase operations */
465 /* Clear from cursor to end of frame on a termcap device. */
467 static void
468 tty_clear_to_end (struct frame *f)
470 register int i;
471 struct tty_display_info *tty = FRAME_TTY (f);
473 if (tty->TS_clr_to_bottom)
475 tty_background_highlight (tty);
476 OUTPUT (tty, tty->TS_clr_to_bottom);
478 else
480 for (i = curY (tty); i < FRAME_LINES (f); i++)
482 cursor_to (f, i, 0);
483 clear_end_of_line (f, FRAME_COLS (f));
488 /* Clear an entire termcap frame. */
490 static void
491 tty_clear_frame (struct frame *f)
493 struct tty_display_info *tty = FRAME_TTY (f);
495 if (tty->TS_clr_frame)
497 tty_background_highlight (tty);
498 OUTPUT (tty, tty->TS_clr_frame);
499 cmat (tty, 0, 0);
501 else
503 cursor_to (f, 0, 0);
504 clear_to_end (f);
508 /* An implementation of clear_end_of_line for termcap frames.
510 Note that the cursor may be moved, on terminals lacking a `ce' string. */
512 static void
513 tty_clear_end_of_line (struct frame *f, int first_unused_hpos)
515 register int i;
516 struct tty_display_info *tty = FRAME_TTY (f);
518 /* Detect the case where we are called from reset_sys_modes
519 and the costs have never been calculated. Do nothing. */
520 if (! tty->costs_set)
521 return;
523 if (curX (tty) >= first_unused_hpos)
524 return;
525 tty_background_highlight (tty);
526 if (tty->TS_clr_line)
528 OUTPUT1 (tty, tty->TS_clr_line);
530 else
531 { /* have to do it the hard way */
532 tty_turn_off_insert (tty);
534 /* Do not write in last row last col with Auto-wrap on. */
535 if (AutoWrap (tty)
536 && curY (tty) == FrameRows (tty) - 1
537 && first_unused_hpos == FrameCols (tty))
538 first_unused_hpos--;
540 for (i = curX (tty); i < first_unused_hpos; i++)
542 if (tty->termscript)
543 fputc (' ', tty->termscript);
544 fputc (' ', tty->output);
546 cmplus (tty, first_unused_hpos - curX (tty));
550 /* Buffer to store the source and result of code conversion for terminal. */
551 static unsigned char *encode_terminal_buf;
552 /* Allocated size of the above buffer. */
553 static int encode_terminal_bufsize;
555 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes.
556 Set CODING->produced to the byte-length of the resulting byte
557 sequence, and return a pointer to that byte sequence. */
559 unsigned char *
560 encode_terminal_code (src, src_len, coding)
561 struct glyph *src;
562 int src_len;
563 struct coding_system *coding;
565 struct glyph *src_end = src + src_len;
566 register GLYPH g;
567 unsigned char *buf;
568 int nchars, nbytes, required;
569 register int tlen = GLYPH_TABLE_LENGTH;
570 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
572 /* Allocate sufficient size of buffer to store all characters in
573 multibyte-form. But, it may be enlarged on demand if
574 Vglyph_table contains a string. */
575 required = MAX_MULTIBYTE_LENGTH * src_len;
576 if (encode_terminal_bufsize < required)
578 if (encode_terminal_bufsize == 0)
579 encode_terminal_buf = xmalloc (required);
580 else
581 encode_terminal_buf = xrealloc (encode_terminal_buf, required);
582 encode_terminal_bufsize = required;
585 buf = encode_terminal_buf;
586 nchars = 0;
587 while (src < src_end)
589 /* We must skip glyphs to be padded for a wide character. */
590 if (! CHAR_GLYPH_PADDING_P (*src))
592 g = GLYPH_FROM_CHAR_GLYPH (src[0]);
594 if (g < 0 || g >= tlen)
596 /* This glyph doesn't has an entry in Vglyph_table. */
597 if (CHAR_VALID_P (src->u.ch, 0))
598 buf += CHAR_STRING (src->u.ch, buf);
599 else
600 *buf++ = SPACEGLYPH;
601 nchars++;
603 else
605 /* This glyph has an entry in Vglyph_table,
606 so process any alias before testing for simpleness. */
607 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
609 if (GLYPH_SIMPLE_P (tbase, tlen, g))
611 int c = FAST_GLYPH_CHAR (g);
613 if (CHAR_VALID_P (c, 0))
614 buf += CHAR_STRING (c, buf);
615 else
616 *buf++ = SPACEGLYPH;
617 nchars++;
619 else
621 /* We have a string in Vglyph_table. */
622 Lisp_Object string;
624 string = tbase[g];
625 if (! STRING_MULTIBYTE (string))
626 string = string_to_multibyte (string);
627 nbytes = buf - encode_terminal_buf;
628 if (encode_terminal_bufsize < nbytes + SBYTES (string))
630 encode_terminal_bufsize = nbytes + SBYTES (string);
631 encode_terminal_buf = xrealloc (encode_terminal_buf,
632 encode_terminal_bufsize);
633 buf = encode_terminal_buf + nbytes;
635 bcopy (SDATA (string), buf, SBYTES (string));
636 buf += SBYTES (string);
637 nchars += SCHARS (string);
641 src++;
644 nbytes = buf - encode_terminal_buf;
645 coding->src_multibyte = 1;
646 coding->dst_multibyte = 0;
647 if (SYMBOLP (coding->pre_write_conversion)
648 && ! NILP (Ffboundp (coding->pre_write_conversion)))
650 run_pre_write_conversin_on_c_str (&encode_terminal_buf,
651 &encode_terminal_bufsize,
652 nchars, nbytes, coding);
653 nchars = coding->produced_char;
654 nbytes = coding->produced;
656 required = nbytes + encoding_buffer_size (coding, nbytes);
657 if (encode_terminal_bufsize < required)
659 encode_terminal_bufsize = required;
660 encode_terminal_buf = xrealloc (encode_terminal_buf, required);
663 encode_coding (coding, encode_terminal_buf, encode_terminal_buf + nbytes,
664 nbytes, encode_terminal_bufsize - nbytes);
665 return encode_terminal_buf + nbytes;
669 /* An implementation of write_glyphs for termcap frames. */
671 static void
672 tty_write_glyphs (struct frame *f, struct glyph *string, int len)
674 unsigned char *conversion_buffer;
675 struct coding_system *coding;
677 struct tty_display_info *tty = FRAME_TTY (f);
679 tty_turn_off_insert (tty);
680 tty_hide_cursor (tty);
682 /* Don't dare write in last column of bottom line, if Auto-Wrap,
683 since that would scroll the whole frame on some terminals. */
685 if (AutoWrap (tty)
686 && curY (tty) + 1 == FRAME_LINES (f)
687 && (curX (tty) + len) == FRAME_COLS (f))
688 len --;
689 if (len <= 0)
690 return;
692 cmplus (tty, len);
694 /* If terminal_coding does any conversion, use it, otherwise use
695 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
696 because it always return 1 if the member src_multibyte is 1. */
697 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
698 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
699 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
700 the tail. */
701 coding->mode &= ~CODING_MODE_LAST_BLOCK;
703 while (len > 0)
705 /* Identify a run of glyphs with the same face. */
706 int face_id = string->face_id;
707 int n;
709 for (n = 1; n < len; ++n)
710 if (string[n].face_id != face_id)
711 break;
713 /* Turn appearance modes of the face of the run on. */
714 tty_highlight_if_desired (tty);
715 turn_on_face (f, face_id);
717 if (n == len)
718 /* This is the last run. */
719 coding->mode |= CODING_MODE_LAST_BLOCK;
720 conversion_buffer = encode_terminal_code (string, n, coding);
721 if (coding->produced > 0)
723 BLOCK_INPUT;
724 fwrite (conversion_buffer, 1, coding->produced, tty->output);
725 if (ferror (tty->output))
726 clearerr (tty->output);
727 if (tty->termscript)
728 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
729 UNBLOCK_INPUT;
731 len -= n;
732 string += n;
734 /* Turn appearance modes off. */
735 turn_off_face (f, face_id);
736 tty_turn_off_highlight (tty);
739 cmcheckmagic (tty);
742 #ifdef HAVE_GPM /* Only used by GPM code. */
744 static void
745 tty_write_glyphs_with_face (f, string, len, face_id)
746 register struct frame *f;
747 register struct glyph *string;
748 register int len, face_id;
750 unsigned char *conversion_buffer;
751 struct coding_system *coding;
753 struct tty_display_info *tty = FRAME_TTY (f);
755 tty_turn_off_insert (tty);
756 tty_hide_cursor (tty);
758 /* Don't dare write in last column of bottom line, if Auto-Wrap,
759 since that would scroll the whole frame on some terminals. */
761 if (AutoWrap (tty)
762 && curY (tty) + 1 == FRAME_LINES (f)
763 && (curX (tty) + len) == FRAME_COLS (f))
764 len --;
765 if (len <= 0)
766 return;
768 cmplus (tty, len);
770 /* If terminal_coding does any conversion, use it, otherwise use
771 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
772 because it always return 1 if the member src_multibyte is 1. */
773 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
774 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
775 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
776 the tail. */
777 coding->mode &= ~CODING_MODE_LAST_BLOCK;
779 /* Turn appearance modes of the face. */
780 tty_highlight_if_desired (tty);
781 turn_on_face (f, face_id);
783 coding->mode |= CODING_MODE_LAST_BLOCK;
784 conversion_buffer = encode_terminal_code (string, len, coding);
785 if (coding->produced > 0)
787 BLOCK_INPUT;
788 fwrite (conversion_buffer, 1, coding->produced, tty->output);
789 if (ferror (tty->output))
790 clearerr (tty->output);
791 if (tty->termscript)
792 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
793 UNBLOCK_INPUT;
796 /* Turn appearance modes off. */
797 turn_off_face (f, face_id);
798 tty_turn_off_highlight (tty);
800 cmcheckmagic (tty);
802 #endif
804 /* An implementation of insert_glyphs for termcap frames. */
806 static void
807 tty_insert_glyphs (struct frame *f, struct glyph *start, int len)
809 char *buf;
810 struct glyph *glyph = NULL;
811 unsigned char *conversion_buffer;
812 unsigned char space[1];
813 struct coding_system *coding;
815 struct tty_display_info *tty = FRAME_TTY (f);
817 if (tty->TS_ins_multi_chars)
819 buf = tparam (tty->TS_ins_multi_chars, 0, 0, len);
820 OUTPUT1 (tty, buf);
821 xfree (buf);
822 if (start)
823 write_glyphs (f, start, len);
824 return;
827 tty_turn_on_insert (tty);
828 cmplus (tty, len);
830 if (! start)
831 space[0] = SPACEGLYPH;
833 /* If terminal_coding does any conversion, use it, otherwise use
834 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
835 because it always return 1 if the member src_multibyte is 1. */
836 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
837 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
838 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
839 the tail. */
840 coding->mode &= ~CODING_MODE_LAST_BLOCK;
842 while (len-- > 0)
844 OUTPUT1_IF (tty, tty->TS_ins_char);
845 if (!start)
847 conversion_buffer = space;
848 coding->produced = 1;
850 else
852 tty_highlight_if_desired (tty);
853 turn_on_face (f, start->face_id);
854 glyph = start;
855 ++start;
856 /* We must open sufficient space for a character which
857 occupies more than one column. */
858 while (len && CHAR_GLYPH_PADDING_P (*start))
860 OUTPUT1_IF (tty, tty->TS_ins_char);
861 start++, len--;
864 if (len <= 0)
865 /* This is the last glyph. */
866 coding->mode |= CODING_MODE_LAST_BLOCK;
868 conversion_buffer = encode_terminal_code (glyph, 1, coding);
871 if (coding->produced > 0)
873 BLOCK_INPUT;
874 fwrite (conversion_buffer, 1, coding->produced, tty->output);
875 if (ferror (tty->output))
876 clearerr (tty->output);
877 if (tty->termscript)
878 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
879 UNBLOCK_INPUT;
882 OUTPUT1_IF (tty, tty->TS_pad_inserted_char);
883 if (start)
885 turn_off_face (f, glyph->face_id);
886 tty_turn_off_highlight (tty);
890 cmcheckmagic (tty);
893 /* An implementation of delete_glyphs for termcap frames. */
895 static void
896 tty_delete_glyphs (struct frame *f, int n)
898 char *buf;
899 register int i;
901 struct tty_display_info *tty = FRAME_TTY (f);
903 if (tty->delete_in_insert_mode)
905 tty_turn_on_insert (tty);
907 else
909 tty_turn_off_insert (tty);
910 OUTPUT_IF (tty, tty->TS_delete_mode);
913 if (tty->TS_del_multi_chars)
915 buf = tparam (tty->TS_del_multi_chars, 0, 0, n);
916 OUTPUT1 (tty, buf);
917 xfree (buf);
919 else
920 for (i = 0; i < n; i++)
921 OUTPUT1 (tty, tty->TS_del_char);
922 if (!tty->delete_in_insert_mode)
923 OUTPUT_IF (tty, tty->TS_end_delete_mode);
926 /* An implementation of ins_del_lines for termcap frames. */
928 static void
929 tty_ins_del_lines (struct frame *f, int vpos, int n)
931 struct tty_display_info *tty = FRAME_TTY (f);
932 char *multi = n > 0 ? tty->TS_ins_multi_lines : tty->TS_del_multi_lines;
933 char *single = n > 0 ? tty->TS_ins_line : tty->TS_del_line;
934 char *scroll = n > 0 ? tty->TS_rev_scroll : tty->TS_fwd_scroll;
936 register int i = n > 0 ? n : -n;
937 register char *buf;
939 /* If the lines below the insertion are being pushed
940 into the end of the window, this is the same as clearing;
941 and we know the lines are already clear, since the matching
942 deletion has already been done. So can ignore this. */
943 /* If the lines below the deletion are blank lines coming
944 out of the end of the window, don't bother,
945 as there will be a matching inslines later that will flush them. */
946 if (FRAME_SCROLL_REGION_OK (f)
947 && vpos + i >= tty->specified_window)
948 return;
949 if (!FRAME_MEMORY_BELOW_FRAME (f)
950 && vpos + i >= FRAME_LINES (f))
951 return;
953 if (multi)
955 raw_cursor_to (f, vpos, 0);
956 tty_background_highlight (tty);
957 buf = tparam (multi, 0, 0, i);
958 OUTPUT (tty, buf);
959 xfree (buf);
961 else if (single)
963 raw_cursor_to (f, vpos, 0);
964 tty_background_highlight (tty);
965 while (--i >= 0)
966 OUTPUT (tty, single);
967 if (tty->TF_teleray)
968 curX (tty) = 0;
970 else
972 tty_set_scroll_region (f, vpos, tty->specified_window);
973 if (n < 0)
974 raw_cursor_to (f, tty->specified_window - 1, 0);
975 else
976 raw_cursor_to (f, vpos, 0);
977 tty_background_highlight (tty);
978 while (--i >= 0)
979 OUTPUTL (tty, scroll, tty->specified_window - vpos);
980 tty_set_scroll_region (f, 0, tty->specified_window);
983 if (!FRAME_SCROLL_REGION_OK (f)
984 && FRAME_MEMORY_BELOW_FRAME (f)
985 && n < 0)
987 cursor_to (f, FRAME_LINES (f) + n, 0);
988 clear_to_end (f);
992 /* Compute cost of sending "str", in characters,
993 not counting any line-dependent padding. */
996 string_cost (char *str)
998 cost = 0;
999 if (str)
1000 tputs (str, 0, evalcost);
1001 return cost;
1004 /* Compute cost of sending "str", in characters,
1005 counting any line-dependent padding at one line. */
1007 static int
1008 string_cost_one_line (char *str)
1010 cost = 0;
1011 if (str)
1012 tputs (str, 1, evalcost);
1013 return cost;
1016 /* Compute per line amount of line-dependent padding,
1017 in tenths of characters. */
1020 per_line_cost (char *str)
1022 cost = 0;
1023 if (str)
1024 tputs (str, 0, evalcost);
1025 cost = - cost;
1026 if (str)
1027 tputs (str, 10, evalcost);
1028 return cost;
1031 #ifndef old
1032 /* char_ins_del_cost[n] is cost of inserting N characters.
1033 char_ins_del_cost[-n] is cost of deleting N characters.
1034 The length of this vector is based on max_frame_cols. */
1036 int *char_ins_del_vector;
1038 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
1039 #endif
1041 /* ARGSUSED */
1042 static void
1043 calculate_ins_del_char_costs (struct frame *f)
1045 struct tty_display_info *tty = FRAME_TTY (f);
1046 int ins_startup_cost, del_startup_cost;
1047 int ins_cost_per_char, del_cost_per_char;
1048 register int i;
1049 register int *p;
1051 if (tty->TS_ins_multi_chars)
1053 ins_cost_per_char = 0;
1054 ins_startup_cost = string_cost_one_line (tty->TS_ins_multi_chars);
1056 else if (tty->TS_ins_char || tty->TS_pad_inserted_char
1057 || (tty->TS_insert_mode && tty->TS_end_insert_mode))
1059 ins_startup_cost = (30 * (string_cost (tty->TS_insert_mode)
1060 + string_cost (tty->TS_end_insert_mode))) / 100;
1061 ins_cost_per_char = (string_cost_one_line (tty->TS_ins_char)
1062 + string_cost_one_line (tty->TS_pad_inserted_char));
1064 else
1066 ins_startup_cost = 9999;
1067 ins_cost_per_char = 0;
1070 if (tty->TS_del_multi_chars)
1072 del_cost_per_char = 0;
1073 del_startup_cost = string_cost_one_line (tty->TS_del_multi_chars);
1075 else if (tty->TS_del_char)
1077 del_startup_cost = (string_cost (tty->TS_delete_mode)
1078 + string_cost (tty->TS_end_delete_mode));
1079 if (tty->delete_in_insert_mode)
1080 del_startup_cost /= 2;
1081 del_cost_per_char = string_cost_one_line (tty->TS_del_char);
1083 else
1085 del_startup_cost = 9999;
1086 del_cost_per_char = 0;
1089 /* Delete costs are at negative offsets */
1090 p = &char_ins_del_cost (f)[0];
1091 for (i = FRAME_COLS (f); --i >= 0;)
1092 *--p = (del_startup_cost += del_cost_per_char);
1094 /* Doing nothing is free */
1095 p = &char_ins_del_cost (f)[0];
1096 *p++ = 0;
1098 /* Insert costs are at positive offsets */
1099 for (i = FRAME_COLS (f); --i >= 0;)
1100 *p++ = (ins_startup_cost += ins_cost_per_char);
1103 void
1104 calculate_costs (struct frame *frame)
1106 FRAME_COST_BAUD_RATE (frame) = baud_rate;
1108 if (FRAME_TERMCAP_P (frame))
1110 struct tty_display_info *tty = FRAME_TTY (frame);
1111 register char *f = (tty->TS_set_scroll_region
1112 ? tty->TS_set_scroll_region
1113 : tty->TS_set_scroll_region_1);
1115 FRAME_SCROLL_REGION_COST (frame) = string_cost (f);
1117 tty->costs_set = 1;
1119 /* These variables are only used for terminal stuff. They are
1120 allocated once for the terminal frame of X-windows emacs, but not
1121 used afterwards.
1123 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1124 X turns off char_ins_del_ok. */
1126 max_frame_lines = max (max_frame_lines, FRAME_LINES (frame));
1127 max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
1129 if (char_ins_del_vector != 0)
1130 char_ins_del_vector
1131 = (int *) xrealloc (char_ins_del_vector,
1132 (sizeof (int)
1133 + 2 * max_frame_cols * sizeof (int)));
1134 else
1135 char_ins_del_vector
1136 = (int *) xmalloc (sizeof (int)
1137 + 2 * max_frame_cols * sizeof (int));
1139 bzero (char_ins_del_vector, (sizeof (int)
1140 + 2 * max_frame_cols * sizeof (int)));
1143 if (f && (!tty->TS_ins_line && !tty->TS_del_line))
1144 do_line_insertion_deletion_costs (frame,
1145 tty->TS_rev_scroll, tty->TS_ins_multi_lines,
1146 tty->TS_fwd_scroll, tty->TS_del_multi_lines,
1147 f, f, 1);
1148 else
1149 do_line_insertion_deletion_costs (frame,
1150 tty->TS_ins_line, tty->TS_ins_multi_lines,
1151 tty->TS_del_line, tty->TS_del_multi_lines,
1152 0, 0, 1);
1154 calculate_ins_del_char_costs (frame);
1156 /* Don't use TS_repeat if its padding is worse than sending the chars */
1157 if (tty->TS_repeat && per_line_cost (tty->TS_repeat) * baud_rate < 9000)
1158 tty->RPov = string_cost (tty->TS_repeat);
1159 else
1160 tty->RPov = FRAME_COLS (frame) * 2;
1162 cmcostinit (FRAME_TTY (frame)); /* set up cursor motion costs */
1166 struct fkey_table {
1167 char *cap, *name;
1170 /* Termcap capability names that correspond directly to X keysyms.
1171 Some of these (marked "terminfo") aren't supplied by old-style
1172 (Berkeley) termcap entries. They're listed in X keysym order;
1173 except we put the keypad keys first, so that if they clash with
1174 other keys (as on the IBM PC keyboard) they get overridden.
1177 static struct fkey_table keys[] =
1179 {"kh", "home"}, /* termcap */
1180 {"kl", "left"}, /* termcap */
1181 {"ku", "up"}, /* termcap */
1182 {"kr", "right"}, /* termcap */
1183 {"kd", "down"}, /* termcap */
1184 {"%8", "prior"}, /* terminfo */
1185 {"%5", "next"}, /* terminfo */
1186 {"@7", "end"}, /* terminfo */
1187 {"@1", "begin"}, /* terminfo */
1188 {"*6", "select"}, /* terminfo */
1189 {"%9", "print"}, /* terminfo */
1190 {"@4", "execute"}, /* terminfo --- actually the `command' key */
1192 * "insert" --- see below
1194 {"&8", "undo"}, /* terminfo */
1195 {"%0", "redo"}, /* terminfo */
1196 {"%7", "menu"}, /* terminfo --- actually the `options' key */
1197 {"@0", "find"}, /* terminfo */
1198 {"@2", "cancel"}, /* terminfo */
1199 {"%1", "help"}, /* terminfo */
1201 * "break" goes here, but can't be reliably intercepted with termcap
1203 {"&4", "reset"}, /* terminfo --- actually `restart' */
1205 * "system" and "user" --- no termcaps
1207 {"kE", "clearline"}, /* terminfo */
1208 {"kA", "insertline"}, /* terminfo */
1209 {"kL", "deleteline"}, /* terminfo */
1210 {"kI", "insertchar"}, /* terminfo */
1211 {"kD", "deletechar"}, /* terminfo */
1212 {"kB", "backtab"}, /* terminfo */
1214 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1216 {"@8", "kp-enter"}, /* terminfo */
1218 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1219 * "kp-multiply", "kp-add", "kp-separator",
1220 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1221 * --- no termcaps for any of these.
1223 {"K4", "kp-1"}, /* terminfo */
1225 * "kp-2" --- no termcap
1227 {"K5", "kp-3"}, /* terminfo */
1229 * "kp-4" --- no termcap
1231 {"K2", "kp-5"}, /* terminfo */
1233 * "kp-6" --- no termcap
1235 {"K1", "kp-7"}, /* terminfo */
1237 * "kp-8" --- no termcap
1239 {"K3", "kp-9"}, /* terminfo */
1241 * "kp-equal" --- no termcap
1243 {"k1", "f1"},
1244 {"k2", "f2"},
1245 {"k3", "f3"},
1246 {"k4", "f4"},
1247 {"k5", "f5"},
1248 {"k6", "f6"},
1249 {"k7", "f7"},
1250 {"k8", "f8"},
1251 {"k9", "f9"},
1253 {"&0", "S-cancel"}, /*shifted cancel key*/
1254 {"&9", "S-begin"}, /*shifted begin key*/
1255 {"*0", "S-find"}, /*shifted find key*/
1256 {"*1", "S-execute"}, /*shifted execute? actually shifted command key*/
1257 {"*4", "S-delete"}, /*shifted delete-character key*/
1258 {"*7", "S-end"}, /*shifted end key*/
1259 {"*8", "S-clearline"}, /*shifted clear-to end-of-line key*/
1260 {"#1", "S-help"}, /*shifted help key*/
1261 {"#2", "S-home"}, /*shifted home key*/
1262 {"#3", "S-insert"}, /*shifted insert-character key*/
1263 {"#4", "S-left"}, /*shifted left-arrow key*/
1264 {"%d", "S-menu"}, /*shifted menu? actually shifted options key*/
1265 {"%c", "S-next"}, /*shifted next key*/
1266 {"%e", "S-prior"}, /*shifted previous key*/
1267 {"%f", "S-print"}, /*shifted print key*/
1268 {"%g", "S-redo"}, /*shifted redo key*/
1269 {"%i", "S-right"}, /*shifted right-arrow key*/
1270 {"!3", "S-undo"} /*shifted undo key*/
1273 static char **term_get_fkeys_address;
1274 static KBOARD *term_get_fkeys_kboard;
1275 static Lisp_Object term_get_fkeys_1 ();
1277 /* Find the escape codes sent by the function keys for Vinput_decode_map.
1278 This function scans the termcap function key sequence entries, and
1279 adds entries to Vinput_decode_map for each function key it finds. */
1281 static void
1282 term_get_fkeys (address, kboard)
1283 char **address;
1284 KBOARD *kboard;
1286 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1287 errors during the call. The only errors should be from Fdefine_key
1288 when given a key sequence containing an invalid prefix key. If the
1289 termcap defines function keys which use a prefix that is already bound
1290 to a command by the default bindings, we should silently ignore that
1291 function key specification, rather than giving the user an error and
1292 refusing to run at all on such a terminal. */
1294 extern Lisp_Object Fidentity ();
1295 term_get_fkeys_address = address;
1296 term_get_fkeys_kboard = kboard;
1297 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1300 static Lisp_Object
1301 term_get_fkeys_1 ()
1303 int i;
1305 char **address = term_get_fkeys_address;
1306 KBOARD *kboard = term_get_fkeys_kboard;
1308 /* This can happen if CANNOT_DUMP or with strange options. */
1309 if (!KEYMAPP (kboard->Vinput_decode_map))
1310 kboard->Vinput_decode_map = Fmake_sparse_keymap (Qnil);
1312 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1314 char *sequence = tgetstr (keys[i].cap, address);
1315 if (sequence)
1316 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence),
1317 Fmake_vector (make_number (1),
1318 intern (keys[i].name)));
1321 /* The uses of the "k0" capability are inconsistent; sometimes it
1322 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1323 We will attempt to politely accommodate both systems by testing for
1324 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1327 char *k_semi = tgetstr ("k;", address);
1328 char *k0 = tgetstr ("k0", address);
1329 char *k0_name = "f10";
1331 if (k_semi)
1333 if (k0)
1334 /* Define f0 first, so that f10 takes precedence in case the
1335 key sequences happens to be the same. */
1336 Fdefine_key (kboard->Vinput_decode_map, build_string (k0),
1337 Fmake_vector (make_number (1), intern ("f0")));
1338 Fdefine_key (kboard->Vinput_decode_map, build_string (k_semi),
1339 Fmake_vector (make_number (1), intern ("f10")));
1341 else if (k0)
1342 Fdefine_key (kboard->Vinput_decode_map, build_string (k0),
1343 Fmake_vector (make_number (1), intern (k0_name)));
1346 /* Set up cookies for numbered function keys above f10. */
1348 char fcap[3], fkey[4];
1350 fcap[0] = 'F'; fcap[2] = '\0';
1351 for (i = 11; i < 64; i++)
1353 if (i <= 19)
1354 fcap[1] = '1' + i - 11;
1355 else if (i <= 45)
1356 fcap[1] = 'A' + i - 20;
1357 else
1358 fcap[1] = 'a' + i - 46;
1361 char *sequence = tgetstr (fcap, address);
1362 if (sequence)
1364 sprintf (fkey, "f%d", i);
1365 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence),
1366 Fmake_vector (make_number (1),
1367 intern (fkey)));
1374 * Various mappings to try and get a better fit.
1377 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1378 if (!tgetstr (cap1, address)) \
1380 char *sequence = tgetstr (cap2, address); \
1381 if (sequence) \
1382 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence), \
1383 Fmake_vector (make_number (1), \
1384 intern (sym))); \
1387 /* if there's no key_next keycap, map key_npage to `next' keysym */
1388 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1389 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1390 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1391 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1392 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1393 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1394 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1396 /* IBM has their own non-standard dialect of terminfo.
1397 If the standard name isn't found, try the IBM name. */
1398 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1399 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1400 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1401 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1402 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1403 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1404 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1405 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1406 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1407 #undef CONDITIONAL_REASSIGN
1410 return Qnil;
1414 /***********************************************************************
1415 Character Display Information
1416 ***********************************************************************/
1418 /* Avoid name clash with functions defined in xterm.c */
1419 #ifdef static
1420 #define append_glyph append_glyph_term
1421 #define produce_stretch_glyph produce_stretch_glyph_term
1422 #endif
1424 static void append_glyph P_ ((struct it *));
1425 static void produce_stretch_glyph P_ ((struct it *));
1428 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1429 terminal frames if IT->glyph_row != NULL. IT->char_to_display is
1430 the character for which to produce glyphs; IT->face_id contains the
1431 character's face. Padding glyphs are appended if IT->c has a
1432 IT->pixel_width > 1. */
1434 static void
1435 append_glyph (it)
1436 struct it *it;
1438 struct glyph *glyph, *end;
1439 int i;
1441 xassert (it->glyph_row);
1442 glyph = (it->glyph_row->glyphs[it->area]
1443 + it->glyph_row->used[it->area]);
1444 end = it->glyph_row->glyphs[1 + it->area];
1446 for (i = 0;
1447 i < it->pixel_width && glyph < end;
1448 ++i)
1450 glyph->type = CHAR_GLYPH;
1451 glyph->pixel_width = 1;
1452 glyph->u.ch = it->char_to_display;
1453 glyph->face_id = it->face_id;
1454 glyph->padding_p = i > 0;
1455 glyph->charpos = CHARPOS (it->position);
1456 glyph->object = it->object;
1458 ++it->glyph_row->used[it->area];
1459 ++glyph;
1464 /* Produce glyphs for the display element described by IT. *IT
1465 specifies what we want to produce a glyph for (character, image, ...),
1466 and where in the glyph matrix we currently are (glyph row and hpos).
1467 produce_glyphs fills in output fields of *IT with information such as the
1468 pixel width and height of a character, and maybe output actual glyphs at
1469 the same time if IT->glyph_row is non-null. See the explanation of
1470 struct display_iterator in dispextern.h for an overview.
1472 produce_glyphs also stores the result of glyph width, ascent
1473 etc. computations in *IT.
1475 IT->glyph_row may be null, in which case produce_glyphs does not
1476 actually fill in the glyphs. This is used in the move_* functions
1477 in xdisp.c for text width and height computations.
1479 Callers usually don't call produce_glyphs directly;
1480 instead they use the macro PRODUCE_GLYPHS. */
1482 void
1483 produce_glyphs (it)
1484 struct it *it;
1486 /* If a hook is installed, let it do the work. */
1487 xassert (it->what == IT_CHARACTER
1488 || it->what == IT_COMPOSITION
1489 || it->what == IT_STRETCH);
1491 if (it->what == IT_STRETCH)
1493 produce_stretch_glyph (it);
1494 goto done;
1497 /* Nothing but characters are supported on terminal frames. For a
1498 composition sequence, it->c is the first character of the
1499 sequence. */
1500 xassert (it->what == IT_CHARACTER
1501 || it->what == IT_COMPOSITION);
1503 /* Maybe translate single-byte characters to multibyte. */
1504 it->char_to_display = it->c;
1506 if (it->c >= 040 && it->c < 0177)
1508 it->pixel_width = it->nglyphs = 1;
1509 if (it->glyph_row)
1510 append_glyph (it);
1512 else if (it->c == '\n')
1513 it->pixel_width = it->nglyphs = 0;
1514 else if (it->c == '\t')
1516 int absolute_x = (it->current_x
1517 + it->continuation_lines_width);
1518 int next_tab_x
1519 = (((1 + absolute_x + it->tab_width - 1)
1520 / it->tab_width)
1521 * it->tab_width);
1522 int nspaces;
1524 /* If part of the TAB has been displayed on the previous line
1525 which is continued now, continuation_lines_width will have
1526 been incremented already by the part that fitted on the
1527 continued line. So, we will get the right number of spaces
1528 here. */
1529 nspaces = next_tab_x - absolute_x;
1531 if (it->glyph_row)
1533 int n = nspaces;
1535 it->char_to_display = ' ';
1536 it->pixel_width = it->len = 1;
1538 while (n--)
1539 append_glyph (it);
1542 it->pixel_width = nspaces;
1543 it->nglyphs = nspaces;
1545 else if (SINGLE_BYTE_CHAR_P (it->c))
1547 if (unibyte_display_via_language_environment
1548 && (it->c >= 0240
1549 || !NILP (Vnonascii_translation_table)))
1551 int charset;
1553 it->char_to_display = unibyte_char_to_multibyte (it->c);
1554 charset = CHAR_CHARSET (it->char_to_display);
1555 it->pixel_width = CHARSET_WIDTH (charset);
1556 it->nglyphs = it->pixel_width;
1557 if (it->glyph_row)
1558 append_glyph (it);
1560 else
1562 /* Coming here means that it->c is from display table, thus we
1563 must send the code as is to the terminal. Although there's
1564 no way to know how many columns it occupies on a screen, it
1565 is a good assumption that a single byte code has 1-column
1566 width. */
1567 it->pixel_width = it->nglyphs = 1;
1568 if (it->glyph_row)
1569 append_glyph (it);
1572 else
1574 /* A multi-byte character. The display width is fixed for all
1575 characters of the set. Some of the glyphs may have to be
1576 ignored because they are already displayed in a continued
1577 line. */
1578 int charset = CHAR_CHARSET (it->c);
1580 it->pixel_width = CHARSET_WIDTH (charset);
1581 it->nglyphs = it->pixel_width;
1583 if (it->glyph_row)
1584 append_glyph (it);
1587 done:
1588 /* Advance current_x by the pixel width as a convenience for
1589 the caller. */
1590 if (it->area == TEXT_AREA)
1591 it->current_x += it->pixel_width;
1592 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1593 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
1597 /* Produce a stretch glyph for iterator IT. IT->object is the value
1598 of the glyph property displayed. The value must be a list
1599 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1600 being recognized:
1602 1. `:width WIDTH' specifies that the space should be WIDTH *
1603 canonical char width wide. WIDTH may be an integer or floating
1604 point number.
1606 2. `:align-to HPOS' specifies that the space should be wide enough
1607 to reach HPOS, a value in canonical character units. */
1609 static void
1610 produce_stretch_glyph (it)
1611 struct it *it;
1613 /* (space :width WIDTH ...) */
1614 Lisp_Object prop, plist;
1615 int width = 0, align_to = -1;
1616 int zero_width_ok_p = 0;
1617 double tem;
1619 /* List should start with `space'. */
1620 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1621 plist = XCDR (it->object);
1623 /* Compute the width of the stretch. */
1624 if ((prop = Fplist_get (plist, QCwidth), !NILP (prop))
1625 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, 0))
1627 /* Absolute width `:width WIDTH' specified and valid. */
1628 zero_width_ok_p = 1;
1629 width = (int)(tem + 0.5);
1631 else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
1632 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, &align_to))
1634 if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
1635 align_to = (align_to < 0
1637 : align_to - window_box_left_offset (it->w, TEXT_AREA));
1638 else if (align_to < 0)
1639 align_to = window_box_left_offset (it->w, TEXT_AREA);
1640 width = max (0, (int)(tem + 0.5) + align_to - it->current_x);
1641 zero_width_ok_p = 1;
1643 else
1644 /* Nothing specified -> width defaults to canonical char width. */
1645 width = FRAME_COLUMN_WIDTH (it->f);
1647 if (width <= 0 && (width < 0 || !zero_width_ok_p))
1648 width = 1;
1650 if (width > 0 && it->glyph_row)
1652 Lisp_Object o_object = it->object;
1653 Lisp_Object object = it->stack[it->sp - 1].string;
1654 int n = width;
1656 if (!STRINGP (object))
1657 object = it->w->buffer;
1658 it->object = object;
1659 it->char_to_display = ' ';
1660 it->pixel_width = it->len = 1;
1661 while (n--)
1662 append_glyph (it);
1663 it->object = o_object;
1665 it->pixel_width = width;
1666 it->nglyphs = width;
1670 /* Get information about special display element WHAT in an
1671 environment described by IT. WHAT is one of IT_TRUNCATION or
1672 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1673 non-null glyph_row member. This function ensures that fields like
1674 face_id, c, len of IT are left untouched. */
1676 void
1677 produce_special_glyphs (it, what)
1678 struct it *it;
1679 enum display_element_type what;
1681 struct it temp_it;
1682 GLYPH glyph;
1684 temp_it = *it;
1685 temp_it.dp = NULL;
1686 temp_it.what = IT_CHARACTER;
1687 temp_it.len = 1;
1688 temp_it.object = make_number (0);
1689 bzero (&temp_it.current, sizeof temp_it.current);
1691 if (what == IT_CONTINUATION)
1693 /* Continuation glyph. */
1694 if (it->dp
1695 && INTEGERP (DISP_CONTINUE_GLYPH (it->dp))
1696 && GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (it->dp))))
1698 glyph = XINT (DISP_CONTINUE_GLYPH (it->dp));
1699 glyph = spec_glyph_lookup_face (XWINDOW (it->window), glyph);
1701 else
1702 glyph = '\\';
1704 else if (what == IT_TRUNCATION)
1706 /* Truncation glyph. */
1707 if (it->dp
1708 && INTEGERP (DISP_TRUNC_GLYPH (it->dp))
1709 && GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (it->dp))))
1711 glyph = XINT (DISP_TRUNC_GLYPH (it->dp));
1712 glyph = spec_glyph_lookup_face (XWINDOW (it->window), glyph);
1714 else
1715 glyph = '$';
1717 else
1718 abort ();
1720 temp_it.c = FAST_GLYPH_CHAR (glyph);
1721 temp_it.face_id = FAST_GLYPH_FACE (glyph);
1722 temp_it.len = CHAR_BYTES (temp_it.c);
1724 produce_glyphs (&temp_it);
1725 it->pixel_width = temp_it.pixel_width;
1726 it->nglyphs = temp_it.pixel_width;
1731 /***********************************************************************
1732 Faces
1733 ***********************************************************************/
1735 /* Value is non-zero if attribute ATTR may be used. ATTR should be
1736 one of the enumerators from enum no_color_bit, or a bit set built
1737 from them. Some display attributes may not be used together with
1738 color; the termcap capability `NC' specifies which ones. */
1740 #define MAY_USE_WITH_COLORS_P(tty, ATTR) \
1741 (tty->TN_max_colors > 0 \
1742 ? (tty->TN_no_color_video & (ATTR)) == 0 \
1743 : 1)
1745 /* Turn appearances of face FACE_ID on tty frame F on.
1746 FACE_ID is a realized face ID number, in the face cache. */
1748 static void
1749 turn_on_face (f, face_id)
1750 struct frame *f;
1751 int face_id;
1753 struct face *face = FACE_FROM_ID (f, face_id);
1754 long fg = face->foreground;
1755 long bg = face->background;
1756 struct tty_display_info *tty = FRAME_TTY (f);
1758 /* Do this first because TS_end_standout_mode may be the same
1759 as TS_exit_attribute_mode, which turns all appearances off. */
1760 if (MAY_USE_WITH_COLORS_P (tty, NC_REVERSE))
1762 if (tty->TN_max_colors > 0)
1764 if (fg >= 0 && bg >= 0)
1766 /* If the terminal supports colors, we can set them
1767 below without using reverse video. The face's fg
1768 and bg colors are set as they should appear on
1769 the screen, i.e. they take the inverse-video'ness
1770 of the face already into account. */
1772 else if (inverse_video)
1774 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1775 || bg == FACE_TTY_DEFAULT_BG_COLOR)
1776 tty_toggle_highlight (tty);
1778 else
1780 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1781 || bg == FACE_TTY_DEFAULT_FG_COLOR)
1782 tty_toggle_highlight (tty);
1785 else
1787 /* If we can't display colors, use reverse video
1788 if the face specifies that. */
1789 if (inverse_video)
1791 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1792 || bg == FACE_TTY_DEFAULT_BG_COLOR)
1793 tty_toggle_highlight (tty);
1795 else
1797 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1798 || bg == FACE_TTY_DEFAULT_FG_COLOR)
1799 tty_toggle_highlight (tty);
1804 if (face->tty_bold_p)
1806 if (MAY_USE_WITH_COLORS_P (tty, NC_BOLD))
1807 OUTPUT1_IF (tty, tty->TS_enter_bold_mode);
1809 else if (face->tty_dim_p)
1810 if (MAY_USE_WITH_COLORS_P (tty, NC_DIM))
1811 OUTPUT1_IF (tty, tty->TS_enter_dim_mode);
1813 /* Alternate charset and blinking not yet used. */
1814 if (face->tty_alt_charset_p
1815 && MAY_USE_WITH_COLORS_P (tty, NC_ALT_CHARSET))
1816 OUTPUT1_IF (tty, tty->TS_enter_alt_charset_mode);
1818 if (face->tty_blinking_p
1819 && MAY_USE_WITH_COLORS_P (tty, NC_BLINK))
1820 OUTPUT1_IF (tty, tty->TS_enter_blink_mode);
1822 if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (tty, NC_UNDERLINE))
1823 OUTPUT1_IF (tty, tty->TS_enter_underline_mode);
1825 if (tty->TN_max_colors > 0)
1827 char *ts, *p;
1829 ts = tty->standout_mode ? tty->TS_set_background : tty->TS_set_foreground;
1830 if (fg >= 0 && ts)
1832 p = tparam (ts, NULL, 0, (int) fg);
1833 OUTPUT (tty, p);
1834 xfree (p);
1837 ts = tty->standout_mode ? tty->TS_set_foreground : tty->TS_set_background;
1838 if (bg >= 0 && ts)
1840 p = tparam (ts, NULL, 0, (int) bg);
1841 OUTPUT (tty, p);
1842 xfree (p);
1848 /* Turn off appearances of face FACE_ID on tty frame F. */
1850 static void
1851 turn_off_face (f, face_id)
1852 struct frame *f;
1853 int face_id;
1855 struct face *face = FACE_FROM_ID (f, face_id);
1856 struct tty_display_info *tty = FRAME_TTY (f);
1858 xassert (face != NULL);
1860 if (tty->TS_exit_attribute_mode)
1862 /* Capability "me" will turn off appearance modes double-bright,
1863 half-bright, reverse-video, standout, underline. It may or
1864 may not turn off alt-char-mode. */
1865 if (face->tty_bold_p
1866 || face->tty_dim_p
1867 || face->tty_reverse_p
1868 || face->tty_alt_charset_p
1869 || face->tty_blinking_p
1870 || face->tty_underline_p)
1872 OUTPUT1_IF (tty, tty->TS_exit_attribute_mode);
1873 if (strcmp (tty->TS_exit_attribute_mode, tty->TS_end_standout_mode) == 0)
1874 tty->standout_mode = 0;
1877 if (face->tty_alt_charset_p)
1878 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
1880 else
1882 /* If we don't have "me" we can only have those appearances
1883 that have exit sequences defined. */
1884 if (face->tty_alt_charset_p)
1885 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
1887 if (face->tty_underline_p)
1888 OUTPUT_IF (tty, tty->TS_exit_underline_mode);
1891 /* Switch back to default colors. */
1892 if (tty->TN_max_colors > 0
1893 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
1894 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
1895 || (face->background != FACE_TTY_DEFAULT_COLOR
1896 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
1897 OUTPUT1_IF (tty, tty->TS_orig_pair);
1901 /* Return non-zero if the terminal on frame F supports all of the
1902 capabilities in CAPS simultaneously, with foreground and background
1903 colors FG and BG. */
1906 tty_capable_p (tty, caps, fg, bg)
1907 struct tty_display_info *tty;
1908 unsigned caps;
1909 unsigned long fg, bg;
1911 #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
1912 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
1913 return 0;
1915 TTY_CAPABLE_P_TRY (tty, TTY_CAP_INVERSE, tty->TS_standout_mode, NC_REVERSE);
1916 TTY_CAPABLE_P_TRY (tty, TTY_CAP_UNDERLINE, tty->TS_enter_underline_mode, NC_UNDERLINE);
1917 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BOLD, tty->TS_enter_bold_mode, NC_BOLD);
1918 TTY_CAPABLE_P_TRY (tty, TTY_CAP_DIM, tty->TS_enter_dim_mode, NC_DIM);
1919 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BLINK, tty->TS_enter_blink_mode, NC_BLINK);
1920 TTY_CAPABLE_P_TRY (tty, TTY_CAP_ALT_CHARSET, tty->TS_enter_alt_charset_mode, NC_ALT_CHARSET);
1922 /* We can do it! */
1923 return 1;
1926 /* Return non-zero if the terminal is capable to display colors. */
1928 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
1929 0, 1, 0,
1930 doc: /* Return non-nil if the tty device TERMINAL can display colors.
1932 TERMINAL can be a terminal id, a frame or nil (meaning the selected
1933 frame's terminal). This function always returns nil if TERMINAL
1934 is not on a tty device. */)
1935 (terminal)
1936 Lisp_Object terminal;
1938 struct terminal *t = get_tty_terminal (terminal, 0);
1939 if (!t)
1940 return Qnil;
1941 else
1942 return t->display_info.tty->TN_max_colors > 0 ? Qt : Qnil;
1945 /* Return the number of supported colors. */
1946 DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
1947 Stty_display_color_cells, 0, 1, 0,
1948 doc: /* Return the number of colors supported by the tty device TERMINAL.
1950 TERMINAL can be a terminal id, a frame or nil (meaning the selected
1951 frame's terminal). This function always returns 0 if TERMINAL
1952 is not on a tty device. */)
1953 (terminal)
1954 Lisp_Object terminal;
1956 struct terminal *t = get_tty_terminal (terminal, 0);
1957 if (!t)
1958 return make_number (0);
1959 else
1960 return make_number (t->display_info.tty->TN_max_colors);
1963 #ifndef WINDOWSNT
1965 /* Declare here rather than in the function, as in the rest of Emacs,
1966 to work around an HPUX compiler bug (?). See
1967 http://lists.gnu.org/archive/html/emacs-devel/2007-08/msg00410.html */
1968 static int default_max_colors;
1969 static int default_max_pairs;
1970 static int default_no_color_video;
1971 static char *default_orig_pair;
1972 static char *default_set_foreground;
1973 static char *default_set_background;
1975 /* Save or restore the default color-related capabilities of this
1976 terminal. */
1977 static void
1978 tty_default_color_capabilities (struct tty_display_info *tty, int save)
1981 if (save)
1983 if (default_orig_pair)
1984 xfree (default_orig_pair);
1985 default_orig_pair = tty->TS_orig_pair ? xstrdup (tty->TS_orig_pair) : NULL;
1987 if (default_set_foreground)
1988 xfree (default_set_foreground);
1989 default_set_foreground = tty->TS_set_foreground ? xstrdup (tty->TS_set_foreground)
1990 : NULL;
1992 if (default_set_background)
1993 xfree (default_set_background);
1994 default_set_background = tty->TS_set_background ? xstrdup (tty->TS_set_background)
1995 : NULL;
1997 default_max_colors = tty->TN_max_colors;
1998 default_max_pairs = tty->TN_max_pairs;
1999 default_no_color_video = tty->TN_no_color_video;
2001 else
2003 tty->TS_orig_pair = default_orig_pair;
2004 tty->TS_set_foreground = default_set_foreground;
2005 tty->TS_set_background = default_set_background;
2006 tty->TN_max_colors = default_max_colors;
2007 tty->TN_max_pairs = default_max_pairs;
2008 tty->TN_no_color_video = default_no_color_video;
2012 /* Setup one of the standard tty color schemes according to MODE.
2013 MODE's value is generally the number of colors which we want to
2014 support; zero means set up for the default capabilities, the ones
2015 we saw at init_tty time; -1 means turn off color support. */
2016 static void
2017 tty_setup_colors (struct tty_display_info *tty, int mode)
2019 /* Canonicalize all negative values of MODE. */
2020 if (mode < -1)
2021 mode = -1;
2023 switch (mode)
2025 case -1: /* no colors at all */
2026 tty->TN_max_colors = 0;
2027 tty->TN_max_pairs = 0;
2028 tty->TN_no_color_video = 0;
2029 tty->TS_set_foreground = tty->TS_set_background = tty->TS_orig_pair = NULL;
2030 break;
2031 case 0: /* default colors, if any */
2032 default:
2033 tty_default_color_capabilities (tty, 0);
2034 break;
2035 case 8: /* 8 standard ANSI colors */
2036 tty->TS_orig_pair = "\033[0m";
2037 #ifdef TERMINFO
2038 tty->TS_set_foreground = "\033[3%p1%dm";
2039 tty->TS_set_background = "\033[4%p1%dm";
2040 #else
2041 tty->TS_set_foreground = "\033[3%dm";
2042 tty->TS_set_background = "\033[4%dm";
2043 #endif
2044 tty->TN_max_colors = 8;
2045 tty->TN_max_pairs = 64;
2046 tty->TN_no_color_video = 0;
2047 break;
2051 void
2052 set_tty_color_mode (f, val)
2053 struct frame *f;
2054 Lisp_Object val;
2056 Lisp_Object color_mode_spec, current_mode_spec;
2057 Lisp_Object color_mode, current_mode;
2058 int mode, old_mode;
2059 extern Lisp_Object Qtty_color_mode;
2060 Lisp_Object tty_color_mode_alist;
2062 tty_color_mode_alist = Fintern_soft (build_string ("tty-color-mode-alist"),
2063 Qnil);
2065 if (INTEGERP (val))
2066 color_mode = val;
2067 else
2069 if (NILP (tty_color_mode_alist))
2070 color_mode_spec = Qnil;
2071 else
2072 color_mode_spec = Fassq (val, XSYMBOL (tty_color_mode_alist)->value);
2074 if (CONSP (color_mode_spec))
2075 color_mode = XCDR (color_mode_spec);
2076 else
2077 color_mode = Qnil;
2080 current_mode_spec = assq_no_quit (Qtty_color_mode, f->param_alist);
2082 if (CONSP (current_mode_spec))
2083 current_mode = XCDR (current_mode_spec);
2084 else
2085 current_mode = Qnil;
2086 if (INTEGERP (color_mode))
2087 mode = XINT (color_mode);
2088 else
2089 mode = 0; /* meaning default */
2090 if (INTEGERP (current_mode))
2091 old_mode = XINT (current_mode);
2092 else
2093 old_mode = 0;
2095 if (mode != old_mode)
2097 tty_setup_colors (FRAME_TTY (f), mode);
2098 /* This recomputes all the faces given the new color
2099 definitions. */
2100 call0 (intern ("tty-set-up-initial-frame-faces"));
2101 redraw_frame (f);
2105 #endif /* !WINDOWSNT */
2109 /* Return the tty display object specified by TERMINAL. */
2111 struct terminal *
2112 get_tty_terminal (Lisp_Object terminal, int throw)
2114 struct terminal *t = get_terminal (terminal, throw);
2116 if (t && t->type != output_termcap)
2118 if (throw)
2119 error ("Device %d is not a termcap terminal device", t->id);
2120 else
2121 return NULL;
2124 return t;
2127 /* Return an active termcap device that uses the tty device with the
2128 given name.
2130 This function ignores suspended devices.
2132 Returns NULL if the named terminal device is not opened. */
2134 struct terminal *
2135 get_named_tty (name)
2136 char *name;
2138 struct terminal *t;
2140 if (!name)
2141 abort ();
2143 for (t = terminal_list; t; t = t->next_terminal)
2145 if (t->type == output_termcap
2146 && !strcmp (t->display_info.tty->name, name)
2147 && TERMINAL_ACTIVE_P (t))
2148 return t;
2151 return 0;
2155 DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0,
2156 doc: /* Return the type of the tty device that TERMINAL uses.
2157 Returns nil if TERMINAL is not on a tty device.
2159 TERMINAL can be a terminal id, a frame or nil (meaning the selected
2160 frame's terminal). */)
2161 (terminal)
2162 Lisp_Object terminal;
2164 struct terminal *t = get_terminal (terminal, 1);
2166 if (t->type != output_termcap)
2167 return Qnil;
2169 if (t->display_info.tty->type)
2170 return build_string (t->display_info.tty->type);
2171 else
2172 return Qnil;
2175 DEFUN ("controlling-tty-p", Fcontrolling_tty_p, Scontrolling_tty_p, 0, 1, 0,
2176 doc: /* Return non-nil if TERMINAL is on the controlling tty of the Emacs process.
2178 TERMINAL can be a terminal id, a frame or nil (meaning the selected
2179 frame's terminal). This function always returns nil if TERMINAL
2180 is not on a tty device. */)
2181 (terminal)
2182 Lisp_Object terminal;
2184 struct terminal *t = get_terminal (terminal, 1);
2186 if (t->type != output_termcap || strcmp (t->display_info.tty->name, DEV_TTY))
2187 return Qnil;
2188 else
2189 return Qt;
2192 DEFUN ("tty-no-underline", Ftty_no_underline, Stty_no_underline, 0, 1, 0,
2193 doc: /* Declare that the tty used by TERMINAL does not handle underlining.
2194 This is used to override the terminfo data, for certain terminals that
2195 do not really do underlining, but say that they do. This function has
2196 no effect if used on a non-tty terminal.
2198 TERMINAL can be a terminal id, a frame or nil (meaning the selected
2199 frame's terminal). This function always returns nil if TERMINAL
2200 is not on a tty device. */)
2201 (terminal)
2202 Lisp_Object terminal;
2204 struct terminal *t = get_terminal (terminal, 1);
2206 if (t->type == output_termcap)
2207 t->display_info.tty->TS_enter_underline_mode = 0;
2208 return Qnil;
2213 DEFUN ("suspend-tty", Fsuspend_tty, Ssuspend_tty, 0, 1, 0,
2214 doc: /* Suspend the terminal device TTY.
2216 The device is restored to its default state, and Emacs ceases all
2217 access to the tty device. Frames that use the device are not deleted,
2218 but input is not read from them and if they change, their display is
2219 not updated.
2221 TTY may be a terminal id, a frame, or nil for the terminal device of
2222 the currently selected frame.
2224 This function runs `suspend-tty-functions' after suspending the
2225 device. The functions are run with one arg, the id of the suspended
2226 terminal device.
2228 `suspend-tty' does nothing if it is called on a device that is already
2229 suspended.
2231 A suspended tty may be resumed by calling `resume-tty' on it. */)
2232 (tty)
2233 Lisp_Object tty;
2235 struct terminal *t = get_tty_terminal (tty, 1);
2236 FILE *f;
2238 if (!t)
2239 error ("Unknown tty device");
2241 f = t->display_info.tty->input;
2243 if (f)
2245 /* First run `suspend-tty-functions' and then clean up the tty
2246 state because `suspend-tty-functions' might need to change
2247 the tty state. */
2248 if (!NILP (Vrun_hooks))
2250 Lisp_Object args[2];
2251 args[0] = intern ("suspend-tty-functions");
2252 XSETTERMINAL (args[1], t);
2253 Frun_hook_with_args (2, args);
2256 reset_sys_modes (t->display_info.tty);
2258 delete_keyboard_wait_descriptor (fileno (f));
2260 fclose (f);
2261 if (f != t->display_info.tty->output)
2262 fclose (t->display_info.tty->output);
2264 t->display_info.tty->input = 0;
2265 t->display_info.tty->output = 0;
2267 if (FRAMEP (t->display_info.tty->top_frame))
2268 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0);
2272 /* Clear display hooks to prevent further output. */
2273 clear_tty_hooks (t);
2275 return Qnil;
2278 DEFUN ("resume-tty", Fresume_tty, Sresume_tty, 0, 1, 0,
2279 doc: /* Resume the previously suspended terminal device TTY.
2280 The terminal is opened and reinitialized. Frames that are on the
2281 suspended terminal are revived.
2283 It is an error to resume a terminal while another terminal is active
2284 on the same device.
2286 This function runs `resume-tty-functions' after resuming the terminal.
2287 The functions are run with one arg, the id of the resumed terminal
2288 device.
2290 `resume-tty' does nothing if it is called on a device that is not
2291 suspended.
2293 TTY may be a terminal id, a frame, or nil for the terminal device of
2294 the currently selected frame. */)
2295 (tty)
2296 Lisp_Object tty;
2298 struct terminal *t = get_tty_terminal (tty, 1);
2299 int fd;
2301 if (!t)
2302 error ("Unknown tty device");
2304 if (!t->display_info.tty->input)
2306 if (get_named_tty (t->display_info.tty->name))
2307 error ("Cannot resume display while another display is active on the same device");
2309 fd = emacs_open (t->display_info.tty->name, O_RDWR | O_NOCTTY, 0);
2311 if (fd == -1)
2312 error ("Can not reopen tty device %s: %s", t->display_info.tty->name, strerror (errno));
2314 if (strcmp (t->display_info.tty->name, DEV_TTY))
2315 dissociate_if_controlling_tty (fd);
2317 t->display_info.tty->output = fdopen (fd, "w+");
2318 t->display_info.tty->input = t->display_info.tty->output;
2320 add_keyboard_wait_descriptor (fd);
2322 if (FRAMEP (t->display_info.tty->top_frame))
2323 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
2325 init_sys_modes (t->display_info.tty);
2327 /* Run `resume-tty-functions'. */
2328 if (!NILP (Vrun_hooks))
2330 Lisp_Object args[2];
2331 args[0] = intern ("resume-tty-functions");
2332 XSETTERMINAL (args[1], t);
2333 Frun_hook_with_args (2, args);
2337 set_tty_hooks (t);
2339 return Qnil;
2343 /***********************************************************************
2344 Mouse
2345 ***********************************************************************/
2347 #ifdef HAVE_GPM
2348 void
2349 term_mouse_moveto (int x, int y)
2351 /* TODO: how to set mouse position?
2352 const char *name;
2353 int fd;
2354 name = (const char *) ttyname (0);
2355 fd = open (name, O_WRONLY);
2356 SOME_FUNCTION (x, y, fd);
2357 close (fd);
2358 last_mouse_x = x;
2359 last_mouse_y = y; */
2362 static void
2363 term_show_mouse_face (enum draw_glyphs_face draw)
2365 struct window *w = XWINDOW (mouse_face_window);
2366 int save_x, save_y;
2367 int i;
2369 struct frame *f = XFRAME (w->frame);
2370 struct tty_display_info *tty = FRAME_TTY (f);
2372 if (/* If window is in the process of being destroyed, don't bother
2373 to do anything. */
2374 w->current_matrix != NULL
2375 /* Recognize when we are called to operate on rows that don't exist
2376 anymore. This can happen when a window is split. */
2377 && mouse_face_end_row < w->current_matrix->nrows)
2379 /* write_glyphs writes at cursor position, so we need to
2380 temporarily move cursor coordinates to the beginning of
2381 the highlight region. */
2383 /* Save current cursor co-ordinates */
2384 save_y = curY (tty);
2385 save_x = curX (tty);
2387 /* Note that mouse_face_beg_row etc. are window relative. */
2388 for (i = mouse_face_beg_row; i <= mouse_face_end_row; i++)
2390 int start_hpos, end_hpos, nglyphs;
2391 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
2393 /* Don't do anything if row doesn't have valid contents. */
2394 if (!row->enabled_p)
2395 continue;
2397 /* For all but the first row, the highlight starts at column 0. */
2398 if (i == mouse_face_beg_row)
2399 start_hpos = mouse_face_beg_col;
2400 else
2401 start_hpos = 0;
2403 if (i == mouse_face_end_row)
2404 end_hpos = mouse_face_end_col;
2405 else
2407 end_hpos = row->used[TEXT_AREA];
2408 if (draw == DRAW_NORMAL_TEXT)
2409 row->fill_line_p = 1; /* Clear to end of line */
2412 if (end_hpos <= start_hpos)
2413 continue;
2414 /* Record that some glyphs of this row are displayed in
2415 mouse-face. */
2416 row->mouse_face_p = draw > 0;
2418 nglyphs = end_hpos - start_hpos;
2420 if (end_hpos >= row->used[TEXT_AREA])
2421 nglyphs = row->used[TEXT_AREA] - start_hpos;
2423 pos_y = row->y + WINDOW_TOP_EDGE_Y (w);
2424 pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos
2425 + WINDOW_LEFT_EDGE_X (w);
2427 cursor_to (f, pos_y, pos_x);
2429 if (draw == DRAW_MOUSE_FACE)
2431 tty_write_glyphs_with_face (f, row->glyphs[TEXT_AREA] + start_hpos,
2432 nglyphs, mouse_face_face_id);
2434 else /* draw == DRAW_NORMAL_TEXT */
2435 write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
2437 cursor_to (f, save_y, save_x);
2441 static void
2442 term_clear_mouse_face ()
2444 if (!NILP (mouse_face_window))
2445 term_show_mouse_face (DRAW_NORMAL_TEXT);
2447 mouse_face_beg_row = mouse_face_beg_col = -1;
2448 mouse_face_end_row = mouse_face_end_col = -1;
2449 mouse_face_window = Qnil;
2452 /* Find the glyph matrix position of buffer position POS in window W.
2453 *HPOS and *VPOS are set to the positions found. W's current glyphs
2454 must be up to date. If POS is above window start return (0, 0).
2455 If POS is after end of W, return end of last line in W.
2456 - taken from msdos.c */
2457 static int
2458 fast_find_position (struct window *w, int pos, int *hpos, int *vpos)
2460 int i, lastcol, line_start_position, maybe_next_line_p = 0;
2461 int yb = window_text_bottom_y (w);
2462 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0), *best_row = row;
2464 while (row->y < yb)
2466 if (row->used[TEXT_AREA])
2467 line_start_position = row->glyphs[TEXT_AREA]->charpos;
2468 else
2469 line_start_position = 0;
2471 if (line_start_position > pos)
2472 break;
2473 /* If the position sought is the end of the buffer,
2474 don't include the blank lines at the bottom of the window. */
2475 else if (line_start_position == pos
2476 && pos == BUF_ZV (XBUFFER (w->buffer)))
2478 maybe_next_line_p = 1;
2479 break;
2481 else if (line_start_position > 0)
2482 best_row = row;
2484 /* Don't overstep the last matrix row, lest we get into the
2485 never-never land... */
2486 if (row->y + 1 >= yb)
2487 break;
2489 ++row;
2492 /* Find the right column within BEST_ROW. */
2493 lastcol = 0;
2494 row = best_row;
2495 for (i = 0; i < row->used[TEXT_AREA]; i++)
2497 struct glyph *glyph = row->glyphs[TEXT_AREA] + i;
2498 int charpos;
2500 charpos = glyph->charpos;
2501 if (charpos == pos)
2503 *hpos = i;
2504 *vpos = row->y;
2505 return 1;
2507 else if (charpos > pos)
2508 break;
2509 else if (charpos > 0)
2510 lastcol = i;
2513 /* If we're looking for the end of the buffer,
2514 and we didn't find it in the line we scanned,
2515 use the start of the following line. */
2516 if (maybe_next_line_p)
2518 ++row;
2519 lastcol = 0;
2522 *vpos = row->y;
2523 *hpos = lastcol + 1;
2524 return 0;
2527 static void
2528 term_mouse_highlight (struct frame *f, int x, int y)
2530 enum window_part part;
2531 Lisp_Object window;
2532 struct window *w;
2533 struct buffer *b;
2535 if (NILP (Vmouse_highlight)
2536 || !f->glyphs_initialized_p)
2537 return;
2539 /* Which window is that in? */
2540 window = window_from_coordinates (f, x, y, &part, &x, &y, 0);
2542 /* Not on a window -> return. */
2543 if (!WINDOWP (window))
2544 return;
2546 if (!EQ (window, mouse_face_window))
2547 term_clear_mouse_face ();
2549 w = XWINDOW (window);
2551 /* Are we in a window whose display is up to date?
2552 And verify the buffer's text has not changed. */
2553 b = XBUFFER (w->buffer);
2554 if (part == ON_TEXT
2555 && EQ (w->window_end_valid, w->buffer)
2556 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
2557 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
2559 int pos, i, nrows = w->current_matrix->nrows;
2560 struct glyph_row *row;
2561 struct glyph *glyph;
2563 /* Find the glyph under X/Y. */
2564 glyph = NULL;
2565 if (y >= 0 && y < nrows)
2567 row = MATRIX_ROW (w->current_matrix, y);
2568 /* Give up if some row before the one we are looking for is
2569 not enabled. */
2570 for (i = 0; i <= y; i++)
2571 if (!MATRIX_ROW (w->current_matrix, i)->enabled_p)
2572 break;
2573 if (i > y /* all rows upto and including the one at Y are enabled */
2574 && row->displays_text_p
2575 && x < window_box_width (w, TEXT_AREA))
2577 glyph = row->glyphs[TEXT_AREA];
2578 if (x >= row->used[TEXT_AREA])
2579 glyph = NULL;
2580 else
2582 glyph += x;
2583 if (!BUFFERP (glyph->object))
2584 glyph = NULL;
2589 /* Clear mouse face if X/Y not over text. */
2590 if (glyph == NULL)
2592 term_clear_mouse_face ();
2593 return;
2596 if (!BUFFERP (glyph->object))
2597 abort ();
2598 pos = glyph->charpos;
2600 /* Check for mouse-face. */
2602 extern Lisp_Object Qmouse_face;
2603 Lisp_Object mouse_face, overlay, position, *overlay_vec;
2604 int noverlays, obegv, ozv;
2605 struct buffer *obuf;
2607 /* If we get an out-of-range value, return now; avoid an error. */
2608 if (pos > BUF_Z (b))
2609 return;
2611 /* Make the window's buffer temporarily current for
2612 overlays_at and compute_char_face. */
2613 obuf = current_buffer;
2614 current_buffer = b;
2615 obegv = BEGV;
2616 ozv = ZV;
2617 BEGV = BEG;
2618 ZV = Z;
2620 /* Is this char mouse-active? */
2621 XSETINT (position, pos);
2623 /* Put all the overlays we want in a vector in overlay_vec. */
2624 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL, 0);
2625 /* Sort overlays into increasing priority order. */
2626 noverlays = sort_overlays (overlay_vec, noverlays, w);
2628 /* Check mouse-face highlighting. */
2629 if (!(EQ (window, mouse_face_window)
2630 && y >= mouse_face_beg_row
2631 && y <= mouse_face_end_row
2632 && (y > mouse_face_beg_row
2633 || x >= mouse_face_beg_col)
2634 && (y < mouse_face_end_row
2635 || x < mouse_face_end_col
2636 || mouse_face_past_end)))
2638 /* Clear the display of the old active region, if any. */
2639 term_clear_mouse_face ();
2641 /* Find the highest priority overlay that has a mouse-face
2642 property. */
2643 overlay = Qnil;
2644 for (i = noverlays - 1; i >= 0; --i)
2646 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
2647 if (!NILP (mouse_face))
2649 overlay = overlay_vec[i];
2650 break;
2654 /* If no overlay applies, get a text property. */
2655 if (NILP (overlay))
2656 mouse_face = Fget_text_property (position, Qmouse_face,
2657 w->buffer);
2659 /* Handle the overlay case. */
2660 if (!NILP (overlay))
2662 /* Find the range of text around this char that
2663 should be active. */
2664 Lisp_Object before, after;
2665 int ignore;
2668 before = Foverlay_start (overlay);
2669 after = Foverlay_end (overlay);
2670 /* Record this as the current active region. */
2671 fast_find_position (w, XFASTINT (before),
2672 &mouse_face_beg_col,
2673 &mouse_face_beg_row);
2675 mouse_face_past_end
2676 = !fast_find_position (w, XFASTINT (after),
2677 &mouse_face_end_col,
2678 &mouse_face_end_row);
2679 mouse_face_window = window;
2681 mouse_face_face_id
2682 = face_at_buffer_position (w, pos, 0, 0,
2683 &ignore, pos + 1, 1);
2685 /* Display it as active. */
2686 term_show_mouse_face (DRAW_MOUSE_FACE);
2688 /* Handle the text property case. */
2689 else if (!NILP (mouse_face))
2691 /* Find the range of text around this char that
2692 should be active. */
2693 Lisp_Object before, after, beginning, end;
2694 int ignore;
2696 beginning = Fmarker_position (w->start);
2697 XSETINT (end, (BUF_Z (b) - XFASTINT (w->window_end_pos)));
2698 before
2699 = Fprevious_single_property_change (make_number (pos + 1),
2700 Qmouse_face,
2701 w->buffer, beginning);
2702 after
2703 = Fnext_single_property_change (position, Qmouse_face,
2704 w->buffer, end);
2706 /* Record this as the current active region. */
2707 fast_find_position (w, XFASTINT (before),
2708 &mouse_face_beg_col,
2709 &mouse_face_beg_row);
2710 mouse_face_past_end
2711 = !fast_find_position (w, XFASTINT (after),
2712 &mouse_face_end_col,
2713 &mouse_face_end_row);
2714 mouse_face_window = window;
2716 mouse_face_face_id
2717 = face_at_buffer_position (w, pos, 0, 0,
2718 &ignore, pos + 1, 1);
2720 /* Display it as active. */
2721 term_show_mouse_face (DRAW_MOUSE_FACE);
2725 /* Look for a `help-echo' property. */
2727 Lisp_Object help;
2728 extern Lisp_Object Qhelp_echo;
2730 /* Check overlays first. */
2731 help = Qnil;
2732 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
2734 overlay = overlay_vec[i];
2735 help = Foverlay_get (overlay, Qhelp_echo);
2738 if (!NILP (help))
2740 help_echo_string = help;
2741 help_echo_window = window;
2742 help_echo_object = overlay;
2743 help_echo_pos = pos;
2745 /* Try text properties. */
2746 else if (NILP (help)
2747 && ((STRINGP (glyph->object)
2748 && glyph->charpos >= 0
2749 && glyph->charpos < SCHARS (glyph->object))
2750 || (BUFFERP (glyph->object)
2751 && glyph->charpos >= BEGV
2752 && glyph->charpos < ZV)))
2754 help = Fget_text_property (make_number (glyph->charpos),
2755 Qhelp_echo, glyph->object);
2756 if (!NILP (help))
2758 help_echo_string = help;
2759 help_echo_window = window;
2760 help_echo_object = glyph->object;
2761 help_echo_pos = glyph->charpos;
2766 BEGV = obegv;
2767 ZV = ozv;
2768 current_buffer = obuf;
2773 static int
2774 term_mouse_movement (FRAME_PTR frame, Gpm_Event *event)
2776 /* Has the mouse moved off the glyph it was on at the last sighting? */
2777 if (event->x != last_mouse_x || event->y != last_mouse_y)
2779 frame->mouse_moved = 1;
2780 term_mouse_highlight (frame, event->x, event->y);
2781 /* Remember which glyph we're now on. */
2782 last_mouse_x = event->x;
2783 last_mouse_y = event->y;
2784 return 1;
2786 return 0;
2789 /* Return the current position of the mouse.
2791 Set *f to the frame the mouse is in, or zero if the mouse is in no
2792 Emacs frame. If it is set to zero, all the other arguments are
2793 garbage.
2795 Set *bar_window to Qnil, and *x and *y to the column and
2796 row of the character cell the mouse is over.
2798 Set *time to the time the mouse was at the returned position.
2800 This clears mouse_moved until the next motion
2801 event arrives. */
2802 static void
2803 term_mouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
2804 enum scroll_bar_part *part, Lisp_Object *x,
2805 Lisp_Object *y, unsigned long *time)
2807 struct timeval now;
2809 *fp = SELECTED_FRAME ();
2810 (*fp)->mouse_moved = 0;
2812 *bar_window = Qnil;
2813 *part = 0;
2815 XSETINT (*x, last_mouse_x);
2816 XSETINT (*y, last_mouse_y);
2817 gettimeofday(&now, 0);
2818 *time = (now.tv_sec * 1000) + (now.tv_usec / 1000);
2821 /* Prepare a mouse-event in *RESULT for placement in the input queue.
2823 If the event is a button press, then note that we have grabbed
2824 the mouse. */
2826 static Lisp_Object
2827 term_mouse_click (struct input_event *result, Gpm_Event *event,
2828 struct frame *f)
2830 struct timeval now;
2831 int i, j;
2833 result->kind = GPM_CLICK_EVENT;
2834 for (i = 0, j = GPM_B_LEFT; i < 3; i++, j >>= 1 )
2836 if (event->buttons & j) {
2837 result->code = i; /* button number */
2838 break;
2841 gettimeofday(&now, 0);
2842 result->timestamp = (now.tv_sec * 1000) + (now.tv_usec / 1000);
2844 if (event->type & GPM_UP)
2845 result->modifiers = up_modifier;
2846 else if (event->type & GPM_DOWN)
2847 result->modifiers = down_modifier;
2848 else
2849 result->modifiers = 0;
2851 if (event->type & GPM_SINGLE)
2852 result->modifiers |= click_modifier;
2854 if (event->type & GPM_DOUBLE)
2855 result->modifiers |= double_modifier;
2857 if (event->type & GPM_TRIPLE)
2858 result->modifiers |= triple_modifier;
2860 if (event->type & GPM_DRAG)
2861 result->modifiers |= drag_modifier;
2863 if (!(event->type & (GPM_MOVE | GPM_DRAG))) {
2865 /* 1 << KG_SHIFT */
2866 if (event->modifiers & (1 << 0))
2867 result->modifiers |= shift_modifier;
2869 /* 1 << KG_CTRL */
2870 if (event->modifiers & (1 << 2))
2871 result->modifiers |= ctrl_modifier;
2873 /* 1 << KG_ALT || KG_ALTGR */
2874 if (event->modifiers & (1 << 3)
2875 || event->modifiers & (1 << 1))
2876 result->modifiers |= meta_modifier;
2879 XSETINT (result->x, event->x);
2880 XSETINT (result->y, event->y);
2881 XSETFRAME (result->frame_or_window, f);
2882 result->arg = Qnil;
2883 return Qnil;
2886 int
2887 handle_one_term_event (struct tty_display_info *tty, Gpm_Event *event, struct input_event* hold_quit)
2889 struct frame *f = XFRAME (tty->top_frame);
2890 struct input_event ie;
2891 int do_help = 0;
2892 int count = 0;
2894 EVENT_INIT (ie);
2895 ie.kind = NO_EVENT;
2896 ie.arg = Qnil;
2898 if (event->type & (GPM_MOVE | GPM_DRAG)) {
2899 previous_help_echo_string = help_echo_string;
2900 help_echo_string = Qnil;
2902 Gpm_DrawPointer (event->x, event->y, fileno (tty->output));
2904 if (!term_mouse_movement (f, event))
2905 help_echo_string = previous_help_echo_string;
2907 /* If the contents of the global variable help_echo_string
2908 has changed, generate a HELP_EVENT. */
2909 if (!NILP (help_echo_string)
2910 || !NILP (previous_help_echo_string))
2911 do_help = 1;
2913 goto done;
2915 else {
2916 f->mouse_moved = 0;
2917 term_mouse_click (&ie, event, f);
2920 done:
2921 if (ie.kind != NO_EVENT)
2923 kbd_buffer_store_event_hold (&ie, hold_quit);
2924 count++;
2927 if (do_help
2928 && !(hold_quit && hold_quit->kind != NO_EVENT))
2930 Lisp_Object frame;
2932 if (f)
2933 XSETFRAME (frame, f);
2934 else
2935 frame = Qnil;
2937 gen_help_event (help_echo_string, frame, help_echo_window,
2938 help_echo_object, help_echo_pos);
2939 count++;
2942 return count;
2945 DEFUN ("gpm-mouse-start", Fgpm_mouse_start, Sgpm_mouse_start,
2946 0, 0, 0,
2947 doc: /* Open a connection to Gpm.
2948 Gpm-mouse can only be activated for one tty at a time. */)
2951 struct frame *f = SELECTED_FRAME ();
2952 struct tty_display_info *tty
2953 = ((f)->output_method == output_termcap
2954 ? (f)->terminal->display_info.tty : NULL);
2955 Gpm_Connect connection;
2957 if (!tty)
2958 error ("Gpm-mouse only works in the GNU/Linux console");
2959 if (gpm_tty == tty)
2960 return Qnil; /* Already activated, nothing to do. */
2961 if (gpm_tty)
2962 error ("Gpm-mouse can only be activated for one tty at a time");
2964 connection.eventMask = ~0;
2965 connection.defaultMask = ~GPM_HARD;
2966 connection.maxMod = ~0;
2967 connection.minMod = 0;
2968 gpm_zerobased = 1;
2970 if (Gpm_Open (&connection, 0) < 0)
2971 error ("Gpm-mouse failed to connect to the gpm daemon");
2972 else
2974 gpm_tty = tty;
2975 /* `init_sys_modes' arranges for mouse movements sent through gpm_fd
2976 to generate SIGIOs. Apparently we need to call reset_sys_modes
2977 before calling init_sys_modes. */
2978 reset_sys_modes (tty);
2979 init_sys_modes (tty);
2980 add_gpm_wait_descriptor (gpm_fd);
2981 return Qnil;
2985 DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop, Sgpm_mouse_stop,
2986 0, 0, 0,
2987 doc: /* Close a connection to Gpm. */)
2990 struct frame *f = SELECTED_FRAME ();
2991 struct tty_display_info *tty
2992 = ((f)->output_method == output_termcap
2993 ? (f)->terminal->display_info.tty : NULL);
2995 if (!tty || gpm_tty != tty)
2996 return Qnil; /* Not activated on this terminal, nothing to do. */
2998 if (gpm_fd >= 0)
2999 delete_gpm_wait_descriptor (gpm_fd);
3000 while (Gpm_Close()); /* close all the stack */
3001 gpm_tty = NULL;
3002 return Qnil;
3004 #endif /* HAVE_GPM */
3007 /***********************************************************************
3008 Initialization
3009 ***********************************************************************/
3011 /* Initialize the tty-dependent part of frame F. The frame must
3012 already have its device initialized. */
3014 void
3015 create_tty_output (struct frame *f)
3017 struct tty_output *t;
3019 if (! FRAME_TERMCAP_P (f))
3020 abort ();
3022 t = xmalloc (sizeof (struct tty_output));
3023 bzero (t, sizeof (struct tty_output));
3025 t->display_info = FRAME_TERMINAL (f)->display_info.tty;
3027 f->output_data.tty = t;
3030 /* Delete the tty-dependent part of frame F. */
3032 static void
3033 delete_tty_output (struct frame *f)
3035 if (! FRAME_TERMCAP_P (f))
3036 abort ();
3038 xfree (f->output_data.tty);
3042 /* Reset the hooks in TERMINAL. */
3044 static void
3045 clear_tty_hooks (struct terminal *terminal)
3047 terminal->rif = 0;
3048 terminal->cursor_to_hook = 0;
3049 terminal->raw_cursor_to_hook = 0;
3050 terminal->clear_to_end_hook = 0;
3051 terminal->clear_frame_hook = 0;
3052 terminal->clear_end_of_line_hook = 0;
3053 terminal->ins_del_lines_hook = 0;
3054 terminal->insert_glyphs_hook = 0;
3055 terminal->write_glyphs_hook = 0;
3056 terminal->delete_glyphs_hook = 0;
3057 terminal->ring_bell_hook = 0;
3058 terminal->reset_terminal_modes_hook = 0;
3059 terminal->set_terminal_modes_hook = 0;
3060 terminal->update_begin_hook = 0;
3061 terminal->update_end_hook = 0;
3062 terminal->set_terminal_window_hook = 0;
3063 terminal->mouse_position_hook = 0;
3064 terminal->frame_rehighlight_hook = 0;
3065 terminal->frame_raise_lower_hook = 0;
3066 terminal->fullscreen_hook = 0;
3067 terminal->set_vertical_scroll_bar_hook = 0;
3068 terminal->condemn_scroll_bars_hook = 0;
3069 terminal->redeem_scroll_bar_hook = 0;
3070 terminal->judge_scroll_bars_hook = 0;
3071 terminal->read_socket_hook = 0;
3072 terminal->frame_up_to_date_hook = 0;
3074 /* Leave these two set, or suspended frames are not deleted
3075 correctly. */
3076 terminal->delete_frame_hook = &delete_tty_output;
3077 terminal->delete_terminal_hook = &delete_tty;
3080 /* Initialize hooks in TERMINAL with the values needed for a tty. */
3082 static void
3083 set_tty_hooks (struct terminal *terminal)
3085 terminal->rif = 0; /* ttys don't support window-based redisplay. */
3087 terminal->cursor_to_hook = &tty_cursor_to;
3088 terminal->raw_cursor_to_hook = &tty_raw_cursor_to;
3090 terminal->clear_to_end_hook = &tty_clear_to_end;
3091 terminal->clear_frame_hook = &tty_clear_frame;
3092 terminal->clear_end_of_line_hook = &tty_clear_end_of_line;
3094 terminal->ins_del_lines_hook = &tty_ins_del_lines;
3096 terminal->insert_glyphs_hook = &tty_insert_glyphs;
3097 terminal->write_glyphs_hook = &tty_write_glyphs;
3098 terminal->delete_glyphs_hook = &tty_delete_glyphs;
3100 terminal->ring_bell_hook = &tty_ring_bell;
3102 terminal->reset_terminal_modes_hook = &tty_reset_terminal_modes;
3103 terminal->set_terminal_modes_hook = &tty_set_terminal_modes;
3104 terminal->update_begin_hook = 0; /* Not needed. */
3105 terminal->update_end_hook = &tty_update_end;
3106 terminal->set_terminal_window_hook = &tty_set_terminal_window;
3108 terminal->mouse_position_hook = 0; /* Not needed. */
3109 terminal->frame_rehighlight_hook = 0; /* Not needed. */
3110 terminal->frame_raise_lower_hook = 0; /* Not needed. */
3112 terminal->set_vertical_scroll_bar_hook = 0; /* Not needed. */
3113 terminal->condemn_scroll_bars_hook = 0; /* Not needed. */
3114 terminal->redeem_scroll_bar_hook = 0; /* Not needed. */
3115 terminal->judge_scroll_bars_hook = 0; /* Not needed. */
3117 terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */
3118 terminal->frame_up_to_date_hook = 0; /* Not needed. */
3120 terminal->delete_frame_hook = &delete_tty_output;
3121 terminal->delete_terminal_hook = &delete_tty;
3124 /* Drop the controlling terminal if fd is the same device. */
3125 static void
3126 dissociate_if_controlling_tty (int fd)
3128 #ifndef WINDOWSNT
3129 int pgid;
3130 EMACS_GET_TTY_PGRP (fd, &pgid); /* If tcgetpgrp succeeds, fd is the ctty. */
3131 if (pgid != -1)
3133 #if defined (USG) && !defined (BSD_PGRPS)
3134 setpgrp ();
3135 no_controlling_tty = 1;
3136 #elif defined (CYGWIN)
3137 setsid ();
3138 no_controlling_tty = 1;
3139 #else
3140 #ifdef TIOCNOTTY /* Try BSD ioctls. */
3141 sigblock (sigmask (SIGTTOU));
3142 fd = emacs_open (DEV_TTY, O_RDWR, 0);
3143 if (fd != -1 && ioctl (fd, TIOCNOTTY, 0) != -1)
3145 no_controlling_tty = 1;
3147 if (fd != -1)
3148 emacs_close (fd);
3149 sigunblock (sigmask (SIGTTOU));
3150 #else
3151 /* Unknown system. */
3152 croak ();
3153 #endif /* ! TIOCNOTTY */
3154 #endif /* ! USG */
3156 #endif /* !WINDOWSNT */
3159 static void maybe_fatal();
3161 /* Create a termcap display on the tty device with the given name and
3162 type.
3164 If NAME is NULL, then use the controlling tty, i.e., "/dev/tty".
3165 Otherwise NAME should be a path to the tty device file,
3166 e.g. "/dev/pts/7".
3168 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
3170 If MUST_SUCCEED is true, then all errors are fatal. */
3172 struct terminal *
3173 init_tty (char *name, char *terminal_type, int must_succeed)
3175 char *area = NULL;
3176 char **address = &area;
3177 char *buffer = NULL;
3178 int buffer_size = 4096;
3179 register char *p = NULL;
3180 int status;
3181 struct tty_display_info *tty = NULL;
3182 struct terminal *terminal = NULL;
3183 int ctty = 0; /* 1 if asked to open controlling tty. */
3185 if (!terminal_type)
3186 maybe_fatal (must_succeed, 0, 0,
3187 "Unknown terminal type",
3188 "Unknown terminal type");
3190 if (name == NULL)
3191 name = DEV_TTY;
3192 if (!strcmp (name, DEV_TTY))
3193 ctty = 1;
3195 /* If we already have a terminal on the given device, use that. If
3196 all such terminals are suspended, create a new one instead. */
3197 /* XXX Perhaps this should be made explicit by having init_tty
3198 always create a new terminal and separating terminal and frame
3199 creation on Lisp level. */
3200 terminal = get_named_tty (name);
3201 if (terminal)
3202 return terminal;
3204 terminal = create_terminal ();
3205 tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info));
3206 bzero (tty, sizeof (struct tty_display_info));
3207 tty->next = tty_list;
3208 tty_list = tty;
3210 terminal->type = output_termcap;
3211 terminal->display_info.tty = tty;
3212 tty->terminal = terminal;
3214 tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
3215 Wcm_clear (tty);
3217 #ifndef WINDOWSNT
3218 set_tty_hooks (terminal);
3221 int fd;
3222 FILE *file;
3224 #ifdef O_IGNORE_CTTY
3225 if (!ctty)
3226 /* Open the terminal device. Don't recognize it as our
3227 controlling terminal, and don't make it the controlling tty
3228 if we don't have one at the moment. */
3229 fd = emacs_open (name, O_RDWR | O_IGNORE_CTTY | O_NOCTTY, 0);
3230 else
3231 #else
3232 /* Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
3233 defined on Hurd. On other systems, we need to explicitly
3234 dissociate ourselves from the controlling tty when we want to
3235 open a frame on the same terminal. */
3236 fd = emacs_open (name, O_RDWR | O_NOCTTY, 0);
3237 #endif /* O_IGNORE_CTTY */
3239 if (fd < 0)
3240 maybe_fatal (must_succeed, buffer, terminal,
3241 "Could not open file: %s",
3242 "Could not open file: %s",
3243 name);
3244 if (!isatty (fd))
3246 close (fd);
3247 maybe_fatal (must_succeed, buffer, terminal,
3248 "Not a tty device: %s",
3249 "Not a tty device: %s",
3250 name);
3253 #ifndef O_IGNORE_CTTY
3254 if (!ctty)
3255 dissociate_if_controlling_tty (fd);
3256 #endif
3258 file = fdopen (fd, "w+");
3259 tty->name = xstrdup (name);
3260 terminal->name = xstrdup (name);
3261 tty->input = file;
3262 tty->output = file;
3265 tty->type = xstrdup (terminal_type);
3267 add_keyboard_wait_descriptor (fileno (tty->input));
3269 #endif
3271 encode_terminal_bufsize = 0;
3273 #ifdef HAVE_GPM
3274 terminal->mouse_position_hook = term_mouse_position;
3275 mouse_face_window = Qnil;
3276 #endif
3278 #ifdef WINDOWSNT
3279 initialize_w32_display (terminal);
3280 /* The following two are inaccessible from w32console.c. */
3281 terminal->delete_frame_hook = &delete_tty_output;
3282 terminal->delete_terminal_hook = &delete_tty;
3284 tty->name = xstrdup (name);
3285 terminal->name = xstrdup (name);
3286 tty->type = xstrdup (terminal_type);
3288 tty->output = stdout;
3289 tty->input = stdin;
3290 add_keyboard_wait_descriptor (0);
3292 Wcm_clear (tty);
3295 struct frame *f = XFRAME (selected_frame);
3297 FrameRows (tty) = FRAME_LINES (f);
3298 FrameCols (tty) = FRAME_COLS (f);
3299 tty->specified_window = FRAME_LINES (f);
3301 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
3302 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
3304 tty->delete_in_insert_mode = 1;
3306 UseTabs (tty) = 0;
3307 terminal->scroll_region_ok = 0;
3309 /* Seems to insert lines when it's not supposed to, messing up the
3310 display. In doing a trace, it didn't seem to be called much, so I
3311 don't think we're losing anything by turning it off. */
3312 terminal->line_ins_del_ok = 0;
3313 terminal->char_ins_del_ok = 1;
3315 baud_rate = 19200;
3317 tty->TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
3319 #else /* not WINDOWSNT */
3321 Wcm_clear (tty);
3323 buffer = (char *) xmalloc (buffer_size);
3325 /* On some systems, tgetent tries to access the controlling
3326 terminal. */
3327 sigblock (sigmask (SIGTTOU));
3328 status = tgetent (buffer, terminal_type);
3329 sigunblock (sigmask (SIGTTOU));
3331 if (status < 0)
3333 #ifdef TERMINFO
3334 maybe_fatal (must_succeed, buffer, terminal,
3335 "Cannot open terminfo database file",
3336 "Cannot open terminfo database file");
3337 #else
3338 maybe_fatal (must_succeed, buffer, terminal,
3339 "Cannot open termcap database file",
3340 "Cannot open termcap database file");
3341 #endif
3343 if (status == 0)
3345 #ifdef TERMINFO
3346 maybe_fatal (must_succeed, buffer, terminal,
3347 "Terminal type %s is not defined",
3348 "Terminal type %s is not defined.\n\
3349 If that is not the actual type of terminal you have,\n\
3350 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3351 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3352 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3353 terminal_type);
3354 #else
3355 maybe_fatal (must_succeed, buffer, terminal,
3356 "Terminal type %s is not defined",
3357 "Terminal type %s is not defined.\n\
3358 If that is not the actual type of terminal you have,\n\
3359 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3360 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3361 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3362 terminal_type);
3363 #endif
3366 #ifndef TERMINFO
3367 if (strlen (buffer) >= buffer_size)
3368 abort ();
3369 buffer_size = strlen (buffer);
3370 #endif
3371 area = (char *) xmalloc (buffer_size);
3373 tty->TS_ins_line = tgetstr ("al", address);
3374 tty->TS_ins_multi_lines = tgetstr ("AL", address);
3375 tty->TS_bell = tgetstr ("bl", address);
3376 BackTab (tty) = tgetstr ("bt", address);
3377 tty->TS_clr_to_bottom = tgetstr ("cd", address);
3378 tty->TS_clr_line = tgetstr ("ce", address);
3379 tty->TS_clr_frame = tgetstr ("cl", address);
3380 ColPosition (tty) = NULL; /* tgetstr ("ch", address); */
3381 AbsPosition (tty) = tgetstr ("cm", address);
3382 CR (tty) = tgetstr ("cr", address);
3383 tty->TS_set_scroll_region = tgetstr ("cs", address);
3384 tty->TS_set_scroll_region_1 = tgetstr ("cS", address);
3385 RowPosition (tty) = tgetstr ("cv", address);
3386 tty->TS_del_char = tgetstr ("dc", address);
3387 tty->TS_del_multi_chars = tgetstr ("DC", address);
3388 tty->TS_del_line = tgetstr ("dl", address);
3389 tty->TS_del_multi_lines = tgetstr ("DL", address);
3390 tty->TS_delete_mode = tgetstr ("dm", address);
3391 tty->TS_end_delete_mode = tgetstr ("ed", address);
3392 tty->TS_end_insert_mode = tgetstr ("ei", address);
3393 Home (tty) = tgetstr ("ho", address);
3394 tty->TS_ins_char = tgetstr ("ic", address);
3395 tty->TS_ins_multi_chars = tgetstr ("IC", address);
3396 tty->TS_insert_mode = tgetstr ("im", address);
3397 tty->TS_pad_inserted_char = tgetstr ("ip", address);
3398 tty->TS_end_keypad_mode = tgetstr ("ke", address);
3399 tty->TS_keypad_mode = tgetstr ("ks", address);
3400 LastLine (tty) = tgetstr ("ll", address);
3401 Right (tty) = tgetstr ("nd", address);
3402 Down (tty) = tgetstr ("do", address);
3403 if (!Down (tty))
3404 Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do" */
3405 #ifdef VMS
3406 /* VMS puts a carriage return before each linefeed,
3407 so it is not safe to use linefeeds. */
3408 if (Down (tty) && Down (tty)[0] == '\n' && Down (tty)[1] == '\0')
3409 Down (tty) = 0;
3410 #endif /* VMS */
3411 if (tgetflag ("bs"))
3412 Left (tty) = "\b"; /* can't possibly be longer! */
3413 else /* (Actually, "bs" is obsolete...) */
3414 Left (tty) = tgetstr ("le", address);
3415 if (!Left (tty))
3416 Left (tty) = tgetstr ("bc", address); /* Obsolete name for "le" */
3417 tty->TS_pad_char = tgetstr ("pc", address);
3418 tty->TS_repeat = tgetstr ("rp", address);
3419 tty->TS_end_standout_mode = tgetstr ("se", address);
3420 tty->TS_fwd_scroll = tgetstr ("sf", address);
3421 tty->TS_standout_mode = tgetstr ("so", address);
3422 tty->TS_rev_scroll = tgetstr ("sr", address);
3423 tty->Wcm->cm_tab = tgetstr ("ta", address);
3424 tty->TS_end_termcap_modes = tgetstr ("te", address);
3425 tty->TS_termcap_modes = tgetstr ("ti", address);
3426 Up (tty) = tgetstr ("up", address);
3427 tty->TS_visible_bell = tgetstr ("vb", address);
3428 tty->TS_cursor_normal = tgetstr ("ve", address);
3429 tty->TS_cursor_visible = tgetstr ("vs", address);
3430 tty->TS_cursor_invisible = tgetstr ("vi", address);
3431 tty->TS_set_window = tgetstr ("wi", address);
3433 tty->TS_enter_underline_mode = tgetstr ("us", address);
3434 tty->TS_exit_underline_mode = tgetstr ("ue", address);
3435 tty->TS_enter_bold_mode = tgetstr ("md", address);
3436 tty->TS_enter_dim_mode = tgetstr ("mh", address);
3437 tty->TS_enter_blink_mode = tgetstr ("mb", address);
3438 tty->TS_enter_reverse_mode = tgetstr ("mr", address);
3439 tty->TS_enter_alt_charset_mode = tgetstr ("as", address);
3440 tty->TS_exit_alt_charset_mode = tgetstr ("ae", address);
3441 tty->TS_exit_attribute_mode = tgetstr ("me", address);
3443 MultiUp (tty) = tgetstr ("UP", address);
3444 MultiDown (tty) = tgetstr ("DO", address);
3445 MultiLeft (tty) = tgetstr ("LE", address);
3446 MultiRight (tty) = tgetstr ("RI", address);
3448 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
3449 color because we can't switch back to the default foreground and
3450 background. */
3451 tty->TS_orig_pair = tgetstr ("op", address);
3452 if (tty->TS_orig_pair)
3454 tty->TS_set_foreground = tgetstr ("AF", address);
3455 tty->TS_set_background = tgetstr ("AB", address);
3456 if (!tty->TS_set_foreground)
3458 /* SVr4. */
3459 tty->TS_set_foreground = tgetstr ("Sf", address);
3460 tty->TS_set_background = tgetstr ("Sb", address);
3463 tty->TN_max_colors = tgetnum ("Co");
3464 tty->TN_max_pairs = tgetnum ("pa");
3466 tty->TN_no_color_video = tgetnum ("NC");
3467 if (tty->TN_no_color_video == -1)
3468 tty->TN_no_color_video = 0;
3471 tty_default_color_capabilities (tty, 1);
3473 MagicWrap (tty) = tgetflag ("xn");
3474 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
3475 the former flag imply the latter. */
3476 AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
3477 terminal->memory_below_frame = tgetflag ("db");
3478 tty->TF_hazeltine = tgetflag ("hz");
3479 terminal->must_write_spaces = tgetflag ("in");
3480 tty->meta_key = tgetflag ("km") || tgetflag ("MT");
3481 tty->TF_insmode_motion = tgetflag ("mi");
3482 tty->TF_standout_motion = tgetflag ("ms");
3483 tty->TF_underscore = tgetflag ("ul");
3484 tty->TF_teleray = tgetflag ("xt");
3486 #endif /* !WINDOWSNT */
3487 #ifdef MULTI_KBOARD
3488 terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
3489 init_kboard (terminal->kboard);
3490 terminal->kboard->Vwindow_system = Qnil;
3491 terminal->kboard->next_kboard = all_kboards;
3492 all_kboards = terminal->kboard;
3493 terminal->kboard->reference_count++;
3494 /* Don't let the initial kboard remain current longer than necessary.
3495 That would cause problems if a file loaded on startup tries to
3496 prompt in the mini-buffer. */
3497 if (current_kboard == initial_kboard)
3498 current_kboard = terminal->kboard;
3499 #ifndef WINDOWSNT
3500 term_get_fkeys (address, terminal->kboard);
3501 #endif
3502 #endif
3504 #ifndef WINDOWSNT
3505 /* Get frame size from system, or else from termcap. */
3507 int height, width;
3508 get_tty_size (fileno (tty->input), &width, &height);
3509 FrameCols (tty) = width;
3510 FrameRows (tty) = height;
3513 if (FrameCols (tty) <= 0)
3514 FrameCols (tty) = tgetnum ("co");
3515 if (FrameRows (tty) <= 0)
3516 FrameRows (tty) = tgetnum ("li");
3518 if (FrameRows (tty) < 3 || FrameCols (tty) < 3)
3519 maybe_fatal (must_succeed, NULL, terminal,
3520 "Screen size %dx%d is too small"
3521 "Screen size %dx%d is too small",
3522 FrameCols (tty), FrameRows (tty));
3524 #if 0 /* This is not used anywhere. */
3525 tty->terminal->min_padding_speed = tgetnum ("pb");
3526 #endif
3528 TabWidth (tty) = tgetnum ("tw");
3530 #ifdef VMS
3531 /* These capabilities commonly use ^J.
3532 I don't know why, but sending them on VMS does not work;
3533 it causes following spaces to be lost, sometimes.
3534 For now, the simplest fix is to avoid using these capabilities ever. */
3535 if (Down (tty) && Down (tty)[0] == '\n')
3536 Down (tty) = 0;
3537 #endif /* VMS */
3539 if (!tty->TS_bell)
3540 tty->TS_bell = "\07";
3542 if (!tty->TS_fwd_scroll)
3543 tty->TS_fwd_scroll = Down (tty);
3545 PC = tty->TS_pad_char ? *tty->TS_pad_char : 0;
3547 if (TabWidth (tty) < 0)
3548 TabWidth (tty) = 8;
3550 /* Turned off since /etc/termcap seems to have :ta= for most terminals
3551 and newer termcap doc does not seem to say there is a default.
3552 if (!tty->Wcm->cm_tab)
3553 tty->Wcm->cm_tab = "\t";
3556 /* We don't support standout modes that use `magic cookies', so
3557 turn off any that do. */
3558 if (tty->TS_standout_mode && tgetnum ("sg") >= 0)
3560 tty->TS_standout_mode = 0;
3561 tty->TS_end_standout_mode = 0;
3563 if (tty->TS_enter_underline_mode && tgetnum ("ug") >= 0)
3565 tty->TS_enter_underline_mode = 0;
3566 tty->TS_exit_underline_mode = 0;
3569 /* If there's no standout mode, try to use underlining instead. */
3570 if (tty->TS_standout_mode == 0)
3572 tty->TS_standout_mode = tty->TS_enter_underline_mode;
3573 tty->TS_end_standout_mode = tty->TS_exit_underline_mode;
3576 /* If no `se' string, try using a `me' string instead.
3577 If that fails, we can't use standout mode at all. */
3578 if (tty->TS_end_standout_mode == 0)
3580 char *s = tgetstr ("me", address);
3581 if (s != 0)
3582 tty->TS_end_standout_mode = s;
3583 else
3584 tty->TS_standout_mode = 0;
3587 if (tty->TF_teleray)
3589 tty->Wcm->cm_tab = 0;
3590 /* We can't support standout mode, because it uses magic cookies. */
3591 tty->TS_standout_mode = 0;
3592 /* But that means we cannot rely on ^M to go to column zero! */
3593 CR (tty) = 0;
3594 /* LF can't be trusted either -- can alter hpos */
3595 /* if move at column 0 thru a line with TS_standout_mode */
3596 Down (tty) = 0;
3599 /* Special handling for certain terminal types known to need it */
3601 if (!strcmp (terminal_type, "supdup"))
3603 terminal->memory_below_frame = 1;
3604 tty->Wcm->cm_losewrap = 1;
3606 if (!strncmp (terminal_type, "c10", 3)
3607 || !strcmp (terminal_type, "perq"))
3609 /* Supply a makeshift :wi string.
3610 This string is not valid in general since it works only
3611 for windows starting at the upper left corner;
3612 but that is all Emacs uses.
3614 This string works only if the frame is using
3615 the top of the video memory, because addressing is memory-relative.
3616 So first check the :ti string to see if that is true.
3618 It would be simpler if the :wi string could go in the termcap
3619 entry, but it can't because it is not fully valid.
3620 If it were in the termcap entry, it would confuse other programs. */
3621 if (!tty->TS_set_window)
3623 p = tty->TS_termcap_modes;
3624 while (*p && strcmp (p, "\033v "))
3625 p++;
3626 if (*p)
3627 tty->TS_set_window = "\033v%C %C %C %C ";
3629 /* Termcap entry often fails to have :in: flag */
3630 terminal->must_write_spaces = 1;
3631 /* :ti string typically fails to have \E^G! in it */
3632 /* This limits scope of insert-char to one line. */
3633 strcpy (area, tty->TS_termcap_modes);
3634 strcat (area, "\033\007!");
3635 tty->TS_termcap_modes = area;
3636 area += strlen (area) + 1;
3637 p = AbsPosition (tty);
3638 /* Change all %+ parameters to %C, to handle
3639 values above 96 correctly for the C100. */
3640 while (*p)
3642 if (p[0] == '%' && p[1] == '+')
3643 p[1] = 'C';
3644 p++;
3648 tty->specified_window = FrameRows (tty);
3650 if (Wcm_init (tty) == -1) /* can't do cursor motion */
3652 maybe_fatal (must_succeed, NULL, terminal,
3653 "Terminal type \"%s\" is not powerful enough to run Emacs",
3654 #ifdef VMS
3655 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3656 It lacks the ability to position the cursor.\n\
3657 If that is not the actual type of terminal you have, use either the\n\
3658 DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
3659 or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
3660 #else /* not VMS */
3661 # ifdef TERMINFO
3662 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3663 It lacks the ability to position the cursor.\n\
3664 If that is not the actual type of terminal you have,\n\
3665 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3666 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3667 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3668 # else /* TERMCAP */
3669 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3670 It lacks the ability to position the cursor.\n\
3671 If that is not the actual type of terminal you have,\n\
3672 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3673 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3674 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3675 # endif /* TERMINFO */
3676 #endif /*VMS */
3677 terminal_type);
3680 if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
3681 maybe_fatal (must_succeed, NULL, terminal,
3682 "Could not determine the frame size",
3683 "Could not determine the frame size");
3685 tty->delete_in_insert_mode
3686 = tty->TS_delete_mode && tty->TS_insert_mode
3687 && !strcmp (tty->TS_delete_mode, tty->TS_insert_mode);
3689 tty->se_is_so = (tty->TS_standout_mode
3690 && tty->TS_end_standout_mode
3691 && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode));
3693 UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8;
3695 terminal->scroll_region_ok
3696 = (tty->Wcm->cm_abs
3697 && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
3699 terminal->line_ins_del_ok
3700 = (((tty->TS_ins_line || tty->TS_ins_multi_lines)
3701 && (tty->TS_del_line || tty->TS_del_multi_lines))
3702 || (terminal->scroll_region_ok
3703 && tty->TS_fwd_scroll && tty->TS_rev_scroll));
3705 terminal->char_ins_del_ok
3706 = ((tty->TS_ins_char || tty->TS_insert_mode
3707 || tty->TS_pad_inserted_char || tty->TS_ins_multi_chars)
3708 && (tty->TS_del_char || tty->TS_del_multi_chars));
3710 terminal->fast_clear_end_of_line = tty->TS_clr_line != 0;
3712 init_baud_rate (fileno (tty->input));
3714 #ifdef AIXHFT
3715 /* The HFT system on AIX doesn't optimize for scrolling, so it's
3716 really ugly at times. */
3717 terminal->line_ins_del_ok = 0;
3718 terminal->char_ins_del_ok = 0;
3719 #endif
3721 /* Don't do this. I think termcap may still need the buffer. */
3722 /* xfree (buffer); */
3724 #endif /* not WINDOWSNT */
3726 /* Init system terminal modes (RAW or CBREAK, etc.). */
3727 init_sys_modes (tty);
3729 return terminal;
3732 /* Auxiliary error-handling function for init_tty.
3733 Free BUFFER and delete TERMINAL, then call error or fatal
3734 with str1 or str2, respectively, according to MUST_SUCCEED. */
3736 static void
3737 maybe_fatal (must_succeed, buffer, terminal, str1, str2, arg1, arg2)
3738 int must_succeed;
3739 char *buffer;
3740 struct terminal *terminal;
3741 char *str1, *str2, *arg1, *arg2;
3743 if (buffer)
3744 xfree (buffer);
3746 if (terminal)
3747 delete_tty (terminal);
3749 if (must_succeed)
3750 fatal (str2, arg1, arg2);
3751 else
3752 error (str1, arg1, arg2);
3754 abort ();
3757 /* VARARGS 1 */
3758 void
3759 fatal (str, arg1, arg2)
3760 char *str, *arg1, *arg2;
3762 fprintf (stderr, "emacs: ");
3763 fprintf (stderr, str, arg1, arg2);
3764 fprintf (stderr, "\n");
3765 fflush (stderr);
3766 exit (1);
3771 /* Delete the given tty terminal, closing all frames on it. */
3773 static void
3774 delete_tty (struct terminal *terminal)
3776 struct tty_display_info *tty;
3777 Lisp_Object tail, frame;
3778 int last_terminal;
3780 /* Protect against recursive calls. Fdelete_frame in
3781 delete_terminal calls us back when it deletes our last frame. */
3782 if (!terminal->name)
3783 return;
3785 if (terminal->type != output_termcap)
3786 abort ();
3788 tty = terminal->display_info.tty;
3790 last_terminal = 1;
3791 FOR_EACH_FRAME (tail, frame)
3793 struct frame *f = XFRAME (frame);
3794 if (FRAME_LIVE_P (f) && (!FRAME_TERMCAP_P (f) || FRAME_TTY (f) != tty))
3796 last_terminal = 0;
3797 break;
3800 if (last_terminal)
3801 error ("Attempt to delete the sole terminal device with live frames");
3803 if (tty == tty_list)
3804 tty_list = tty->next;
3805 else
3807 struct tty_display_info *p;
3808 for (p = tty_list; p && p->next != tty; p = p->next)
3811 if (! p)
3812 /* This should not happen. */
3813 abort ();
3815 p->next = tty->next;
3816 tty->next = 0;
3819 /* reset_sys_modes needs a valid device, so this call needs to be
3820 before delete_terminal. */
3821 reset_sys_modes (tty);
3823 delete_terminal (terminal);
3825 if (tty->name)
3826 xfree (tty->name);
3828 if (tty->type)
3829 xfree (tty->type);
3831 if (tty->input)
3833 delete_keyboard_wait_descriptor (fileno (tty->input));
3834 if (tty->input != stdin)
3835 fclose (tty->input);
3837 if (tty->output && tty->output != stdout && tty->output != tty->input)
3838 fclose (tty->output);
3839 if (tty->termscript)
3840 fclose (tty->termscript);
3842 if (tty->old_tty)
3843 xfree (tty->old_tty);
3845 if (tty->Wcm)
3846 xfree (tty->Wcm);
3848 bzero (tty, sizeof (struct tty_display_info));
3849 xfree (tty);
3854 /* Mark the pointers in the tty_display_info objects.
3855 Called by the Fgarbage_collector. */
3857 void
3858 mark_ttys (void)
3860 struct tty_display_info *tty;
3862 for (tty = tty_list; tty; tty = tty->next)
3863 mark_object (tty->top_frame);
3868 void
3869 syms_of_term ()
3871 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
3872 doc: /* Non-nil means the system uses terminfo rather than termcap.
3873 This variable can be used by terminal emulator packages. */);
3874 #ifdef TERMINFO
3875 system_uses_terminfo = 1;
3876 #else
3877 system_uses_terminfo = 0;
3878 #endif
3880 DEFVAR_LISP ("suspend-tty-functions", &Vsuspend_tty_functions,
3881 doc: /* Functions to be run after suspending a tty.
3882 The functions are run with one argument, the terminal id to be suspended.
3883 See `suspend-tty'. */);
3884 Vsuspend_tty_functions = Qnil;
3887 DEFVAR_LISP ("resume-tty-functions", &Vresume_tty_functions,
3888 doc: /* Functions to be run after resuming a tty.
3889 The functions are run with one argument, the terminal id that was revived.
3890 See `resume-tty'. */);
3891 Vresume_tty_functions = Qnil;
3893 DEFVAR_BOOL ("visible-cursor", &visible_cursor,
3894 doc: /* Non-nil means to make the cursor very visible.
3895 This only has an effect when running in a text terminal.
3896 What means \"very visible\" is up to your terminal. It may make the cursor
3897 bigger, or it may make it blink, or it may do nothing at all. */);
3898 visible_cursor = 1;
3900 defsubr (&Stty_display_color_p);
3901 defsubr (&Stty_display_color_cells);
3902 defsubr (&Stty_no_underline);
3903 defsubr (&Stty_type);
3904 defsubr (&Scontrolling_tty_p);
3905 defsubr (&Ssuspend_tty);
3906 defsubr (&Sresume_tty);
3907 #ifdef HAVE_GPM
3908 defsubr (&Sgpm_mouse_start);
3909 defsubr (&Sgpm_mouse_stop);
3911 staticpro (&mouse_face_window);
3912 #endif /* HAVE_GPM */
3917 /* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193
3918 (do not change this comment) */