Fix comment typo.
[emacs.git] / src / term.c
blob4e63568213dcbee780ccfaed0b23544cf33ecff0
1 /* Terminal control module for terminals described by TERMCAP
2 Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1998, 2000, 2001,
3 2002, 2003, 2004, 2005, 2006, 2007, 2008
4 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
23 /* New redisplay, TTY faces by Gerd Moellmann <gerd@gnu.org>. */
25 #include <config.h>
26 #include <stdio.h>
27 #include <ctype.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <sys/file.h>
32 #ifdef HAVE_UNISTD_H
33 #include <unistd.h>
34 #endif
36 #if HAVE_TERMIOS_H
37 #include <termios.h> /* For TIOCNOTTY. */
38 #endif
40 #include <signal.h>
41 #include <stdarg.h>
43 #include "lisp.h"
44 #include "termchar.h"
45 #include "termopts.h"
46 #include "buffer.h"
47 #include "character.h"
48 #include "charset.h"
49 #include "coding.h"
50 #include "composite.h"
51 #include "keyboard.h"
52 #include "frame.h"
53 #include "disptab.h"
54 #include "termhooks.h"
55 #include "dispextern.h"
56 #include "window.h"
57 #include "keymap.h"
58 #include "blockinput.h"
59 #include "syssignal.h"
60 #include "systty.h"
61 #include "intervals.h"
63 /* For now, don't try to include termcap.h. On some systems,
64 configure finds a non-standard termcap.h that the main build
65 won't find. */
67 #if defined HAVE_TERMCAP_H && 0
68 #include <termcap.h>
69 #else
70 extern void tputs P_ ((const char *, int, int (*)(int)));
71 extern int tgetent P_ ((char *, const char *));
72 extern int tgetflag P_ ((char *id));
73 extern int tgetnum P_ ((char *id));
74 #endif
76 #include "cm.h"
77 #ifdef HAVE_X_WINDOWS
78 #include "xterm.h"
79 #endif
80 #ifdef MAC_OS
81 #include "macterm.h"
82 #endif
84 #ifndef O_RDWR
85 #define O_RDWR 2
86 #endif
88 #ifndef O_NOCTTY
89 #define O_NOCTTY 0
90 #endif
92 /* The name of the default console device. */
93 #ifdef WINDOWSNT
94 #define DEV_TTY "CONOUT$"
95 #else
96 #define DEV_TTY "/dev/tty"
97 #endif
99 static void tty_set_scroll_region P_ ((struct frame *f, int start, int stop));
100 static void turn_on_face P_ ((struct frame *, int face_id));
101 static void turn_off_face P_ ((struct frame *, int face_id));
102 static void tty_show_cursor P_ ((struct tty_display_info *));
103 static void tty_hide_cursor P_ ((struct tty_display_info *));
104 static void tty_background_highlight P_ ((struct tty_display_info *tty));
105 static void clear_tty_hooks P_ ((struct terminal *terminal));
106 static void set_tty_hooks P_ ((struct terminal *terminal));
107 static void dissociate_if_controlling_tty P_ ((int fd));
108 static void delete_tty P_ ((struct terminal *));
110 #define OUTPUT(tty, a) \
111 emacs_tputs ((tty), a, \
112 (int) (FRAME_LINES (XFRAME (selected_frame)) \
113 - curY (tty)), \
114 cmputc)
116 #define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
117 #define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
119 #define OUTPUT_IF(tty, a) \
120 do { \
121 if (a) \
122 emacs_tputs ((tty), a, \
123 (int) (FRAME_LINES (XFRAME (selected_frame)) \
124 - curY (tty) ), \
125 cmputc); \
126 } while (0)
128 #define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
130 /* If true, use "vs", otherwise use "ve" to make the cursor visible. */
132 static int visible_cursor;
134 /* Display space properties */
136 extern Lisp_Object Qspace, QCalign_to, QCwidth;
138 /* Functions to call after suspending a tty. */
139 Lisp_Object Vsuspend_tty_functions;
141 /* Functions to call after resuming a tty. */
142 Lisp_Object Vresume_tty_functions;
144 /* Chain of all tty device parameters. */
145 struct tty_display_info *tty_list;
147 /* Nonzero means no need to redraw the entire frame on resuming a
148 suspended Emacs. This is useful on terminals with multiple
149 pages, where one page is used for Emacs and another for all
150 else. */
151 int no_redraw_on_reenter;
153 /* Meaning of bits in no_color_video. Each bit set means that the
154 corresponding attribute cannot be combined with colors. */
156 enum no_color_bit
158 NC_STANDOUT = 1 << 0,
159 NC_UNDERLINE = 1 << 1,
160 NC_REVERSE = 1 << 2,
161 NC_BLINK = 1 << 3,
162 NC_DIM = 1 << 4,
163 NC_BOLD = 1 << 5,
164 NC_INVIS = 1 << 6,
165 NC_PROTECT = 1 << 7,
166 NC_ALT_CHARSET = 1 << 8
169 /* internal state */
171 /* The largest frame width in any call to calculate_costs. */
173 int max_frame_cols;
175 /* The largest frame height in any call to calculate_costs. */
177 int max_frame_lines;
179 /* Non-zero if we have dropped our controlling tty and therefore
180 should not open a frame on stdout. */
181 static int no_controlling_tty;
183 /* Provided for lisp packages. */
185 static int system_uses_terminfo;
187 char *tparam ();
189 extern char *tgetstr ();
192 #ifdef HAVE_GPM
193 #include <sys/fcntl.h>
195 static void term_clear_mouse_face ();
196 static void term_mouse_highlight (struct frame *f, int x, int y);
198 /* The device for which we have enabled gpm support (or NULL). */
199 struct tty_display_info *gpm_tty = NULL;
201 /* These variables describe the range of text currently shown in its
202 mouse-face, together with the window they apply to. As long as
203 the mouse stays within this range, we need not redraw anything on
204 its account. Rows and columns are glyph matrix positions in
205 MOUSE_FACE_WINDOW. */
206 static int mouse_face_beg_row, mouse_face_beg_col;
207 static int mouse_face_end_row, mouse_face_end_col;
208 static int mouse_face_past_end;
209 static Lisp_Object mouse_face_window;
210 static int mouse_face_face_id;
212 static int pos_x, pos_y;
213 static int last_mouse_x, last_mouse_y;
214 #endif /* HAVE_GPM */
216 /* Ring the bell on a tty. */
218 static void
219 tty_ring_bell (struct frame *f)
221 struct tty_display_info *tty = FRAME_TTY (f);
223 if (tty->output)
225 OUTPUT (tty, (tty->TS_visible_bell && visible_bell
226 ? tty->TS_visible_bell
227 : tty->TS_bell));
228 fflush (tty->output);
232 /* Set up termcap modes for Emacs. */
234 void
235 tty_set_terminal_modes (struct terminal *terminal)
237 struct tty_display_info *tty = terminal->display_info.tty;
239 if (tty->output)
241 if (tty->TS_termcap_modes)
242 OUTPUT (tty, tty->TS_termcap_modes);
243 else
245 /* Output enough newlines to scroll all the old screen contents
246 off the screen, so it won't be overwritten and lost. */
247 int i;
248 current_tty = tty;
249 for (i = 0; i < FRAME_LINES (XFRAME (selected_frame)); i++)
250 cmputc ('\n');
253 OUTPUT_IF (tty, tty->TS_termcap_modes);
254 OUTPUT_IF (tty, visible_cursor ? tty->TS_cursor_visible : tty->TS_cursor_normal);
255 OUTPUT_IF (tty, tty->TS_keypad_mode);
256 losecursor (tty);
257 fflush (tty->output);
261 /* Reset termcap modes before exiting Emacs. */
263 void
264 tty_reset_terminal_modes (struct terminal *terminal)
266 struct tty_display_info *tty = terminal->display_info.tty;
268 if (tty->output)
270 tty_turn_off_highlight (tty);
271 tty_turn_off_insert (tty);
272 OUTPUT_IF (tty, tty->TS_end_keypad_mode);
273 OUTPUT_IF (tty, tty->TS_cursor_normal);
274 OUTPUT_IF (tty, tty->TS_end_termcap_modes);
275 OUTPUT_IF (tty, tty->TS_orig_pair);
276 /* Output raw CR so kernel can track the cursor hpos. */
277 current_tty = tty;
278 cmputc ('\r');
279 fflush (tty->output);
283 /* Flag the end of a display update on a termcap terminal. */
285 static void
286 tty_update_end (struct frame *f)
288 struct tty_display_info *tty = FRAME_TTY (f);
290 if (!XWINDOW (selected_window)->cursor_off_p)
291 tty_show_cursor (tty);
292 tty_turn_off_insert (tty);
293 tty_background_highlight (tty);
296 /* The implementation of set_terminal_window for termcap frames. */
298 static void
299 tty_set_terminal_window (struct frame *f, int size)
301 struct tty_display_info *tty = FRAME_TTY (f);
303 tty->specified_window = size ? size : FRAME_LINES (f);
304 if (FRAME_SCROLL_REGION_OK (f))
305 tty_set_scroll_region (f, 0, tty->specified_window);
308 static void
309 tty_set_scroll_region (struct frame *f, int start, int stop)
311 char *buf;
312 struct tty_display_info *tty = FRAME_TTY (f);
314 if (tty->TS_set_scroll_region)
315 buf = tparam (tty->TS_set_scroll_region, 0, 0, start, stop - 1);
316 else if (tty->TS_set_scroll_region_1)
317 buf = tparam (tty->TS_set_scroll_region_1, 0, 0,
318 FRAME_LINES (f), start,
319 FRAME_LINES (f) - stop,
320 FRAME_LINES (f));
321 else
322 buf = tparam (tty->TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (f));
324 OUTPUT (tty, buf);
325 xfree (buf);
326 losecursor (tty);
330 static void
331 tty_turn_on_insert (struct tty_display_info *tty)
333 if (!tty->insert_mode)
334 OUTPUT (tty, tty->TS_insert_mode);
335 tty->insert_mode = 1;
338 void
339 tty_turn_off_insert (struct tty_display_info *tty)
341 if (tty->insert_mode)
342 OUTPUT (tty, tty->TS_end_insert_mode);
343 tty->insert_mode = 0;
346 /* Handle highlighting. */
348 void
349 tty_turn_off_highlight (struct tty_display_info *tty)
351 if (tty->standout_mode)
352 OUTPUT_IF (tty, tty->TS_end_standout_mode);
353 tty->standout_mode = 0;
356 static void
357 tty_turn_on_highlight (struct tty_display_info *tty)
359 if (!tty->standout_mode)
360 OUTPUT_IF (tty, tty->TS_standout_mode);
361 tty->standout_mode = 1;
364 static void
365 tty_toggle_highlight (struct tty_display_info *tty)
367 if (tty->standout_mode)
368 tty_turn_off_highlight (tty);
369 else
370 tty_turn_on_highlight (tty);
374 /* Make cursor invisible. */
376 static void
377 tty_hide_cursor (struct tty_display_info *tty)
379 if (tty->cursor_hidden == 0)
381 tty->cursor_hidden = 1;
382 OUTPUT_IF (tty, tty->TS_cursor_invisible);
387 /* Ensure that cursor is visible. */
389 static void
390 tty_show_cursor (struct tty_display_info *tty)
392 if (tty->cursor_hidden)
394 tty->cursor_hidden = 0;
395 OUTPUT_IF (tty, tty->TS_cursor_normal);
396 if (visible_cursor)
397 OUTPUT_IF (tty, tty->TS_cursor_visible);
402 /* Set standout mode to the state it should be in for
403 empty space inside windows. What this is,
404 depends on the user option inverse-video. */
406 static void
407 tty_background_highlight (struct tty_display_info *tty)
409 if (inverse_video)
410 tty_turn_on_highlight (tty);
411 else
412 tty_turn_off_highlight (tty);
415 /* Set standout mode to the mode specified for the text to be output. */
417 static void
418 tty_highlight_if_desired (struct tty_display_info *tty)
420 if (inverse_video)
421 tty_turn_on_highlight (tty);
422 else
423 tty_turn_off_highlight (tty);
427 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
428 frame-relative coordinates. */
430 static void
431 tty_cursor_to (struct frame *f, int vpos, int hpos)
433 struct tty_display_info *tty = FRAME_TTY (f);
435 /* Detect the case where we are called from reset_sys_modes
436 and the costs have never been calculated. Do nothing. */
437 if (! tty->costs_set)
438 return;
440 if (curY (tty) == vpos
441 && curX (tty) == hpos)
442 return;
443 if (!tty->TF_standout_motion)
444 tty_background_highlight (tty);
445 if (!tty->TF_insmode_motion)
446 tty_turn_off_insert (tty);
447 cmgoto (tty, vpos, hpos);
450 /* Similar but don't take any account of the wasted characters. */
452 static void
453 tty_raw_cursor_to (struct frame *f, int row, int col)
455 struct tty_display_info *tty = FRAME_TTY (f);
457 if (curY (tty) == row
458 && curX (tty) == col)
459 return;
460 if (!tty->TF_standout_motion)
461 tty_background_highlight (tty);
462 if (!tty->TF_insmode_motion)
463 tty_turn_off_insert (tty);
464 cmgoto (tty, row, col);
467 /* Erase operations */
469 /* Clear from cursor to end of frame on a termcap device. */
471 static void
472 tty_clear_to_end (struct frame *f)
474 register int i;
475 struct tty_display_info *tty = FRAME_TTY (f);
477 if (tty->TS_clr_to_bottom)
479 tty_background_highlight (tty);
480 OUTPUT (tty, tty->TS_clr_to_bottom);
482 else
484 for (i = curY (tty); i < FRAME_LINES (f); i++)
486 cursor_to (f, i, 0);
487 clear_end_of_line (f, FRAME_COLS (f));
492 /* Clear an entire termcap frame. */
494 static void
495 tty_clear_frame (struct frame *f)
497 struct tty_display_info *tty = FRAME_TTY (f);
499 if (tty->TS_clr_frame)
501 tty_background_highlight (tty);
502 OUTPUT (tty, tty->TS_clr_frame);
503 cmat (tty, 0, 0);
505 else
507 cursor_to (f, 0, 0);
508 clear_to_end (f);
512 /* An implementation of clear_end_of_line for termcap frames.
514 Note that the cursor may be moved, on terminals lacking a `ce' string. */
516 static void
517 tty_clear_end_of_line (struct frame *f, int first_unused_hpos)
519 register int i;
520 struct tty_display_info *tty = FRAME_TTY (f);
522 /* Detect the case where we are called from reset_sys_modes
523 and the costs have never been calculated. Do nothing. */
524 if (! tty->costs_set)
525 return;
527 if (curX (tty) >= first_unused_hpos)
528 return;
529 tty_background_highlight (tty);
530 if (tty->TS_clr_line)
532 OUTPUT1 (tty, tty->TS_clr_line);
534 else
535 { /* have to do it the hard way */
536 tty_turn_off_insert (tty);
538 /* Do not write in last row last col with Auto-wrap on. */
539 if (AutoWrap (tty)
540 && curY (tty) == FrameRows (tty) - 1
541 && first_unused_hpos == FrameCols (tty))
542 first_unused_hpos--;
544 for (i = curX (tty); i < first_unused_hpos; i++)
546 if (tty->termscript)
547 fputc (' ', tty->termscript);
548 fputc (' ', tty->output);
550 cmplus (tty, first_unused_hpos - curX (tty));
554 /* Buffers to store the source and result of code conversion for terminal. */
555 static unsigned char *encode_terminal_src;
556 static unsigned char *encode_terminal_dst;
557 /* Allocated sizes of the above buffers. */
558 static int encode_terminal_src_size;
559 static int encode_terminal_dst_size;
561 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes.
562 Set CODING->produced to the byte-length of the resulting byte
563 sequence, and return a pointer to that byte sequence. */
565 unsigned char *
566 encode_terminal_code (src, src_len, coding)
567 struct glyph *src;
568 int src_len;
569 struct coding_system *coding;
571 struct glyph *src_end = src + src_len;
572 unsigned char *buf;
573 int nchars, nbytes, required;
574 register int tlen = GLYPH_TABLE_LENGTH;
575 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
576 Lisp_Object charset_list;
578 /* Allocate sufficient size of buffer to store all characters in
579 multibyte-form. But, it may be enlarged on demand if
580 Vglyph_table contains a string or a composite glyph is
581 encountered. */
582 required = MAX_MULTIBYTE_LENGTH * src_len;
583 if (encode_terminal_src_size < required)
585 if (encode_terminal_src_size == 0)
586 encode_terminal_src = xmalloc (required);
587 else
588 encode_terminal_src = xrealloc (encode_terminal_src, required);
589 encode_terminal_src_size = required;
592 charset_list = coding_charset_list (coding);
594 buf = encode_terminal_src;
595 nchars = 0;
596 while (src < src_end)
598 if (src->type == COMPOSITE_GLYPH)
600 struct composition *cmp = composition_table[src->u.cmp_id];
601 int i;
603 nbytes = buf - encode_terminal_src;
604 required = MAX_MULTIBYTE_LENGTH * cmp->glyph_len;
606 if (encode_terminal_src_size < nbytes + required)
608 encode_terminal_src_size = nbytes + required;
609 encode_terminal_src = xrealloc (encode_terminal_src,
610 encode_terminal_src_size);
611 buf = encode_terminal_src + nbytes;
614 for (i = 0; i < cmp->glyph_len; i++)
616 int c = COMPOSITION_GLYPH (cmp, i);
618 if (! char_charset (c, charset_list, NULL))
619 break;
620 buf += CHAR_STRING (c, buf);
621 nchars++;
623 if (i == 0)
625 /* The first character of the composition is not encodable. */
626 *buf++ = '?';
627 nchars++;
630 /* We must skip glyphs to be padded for a wide character. */
631 else if (! CHAR_GLYPH_PADDING_P (*src))
633 GLYPH g;
634 int c;
635 Lisp_Object string;
637 string = Qnil;
638 SET_GLYPH_FROM_CHAR_GLYPH (g, src[0]);
640 if (GLYPH_INVALID_P (g) || GLYPH_SIMPLE_P (tbase, tlen, g))
642 /* This glyph doesn't has an entry in Vglyph_table. */
643 c = src->u.ch;
645 else
647 /* This glyph has an entry in Vglyph_table,
648 so process any alias before testing for simpleness. */
649 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
651 if (GLYPH_SIMPLE_P (tbase, tlen, g))
652 /* We set the multi-byte form of a character in G
653 (that should be an ASCII character) at WORKBUF. */
654 c = GLYPH_CHAR (g);
655 else
656 /* We have a string in Vglyph_table. */
657 string = tbase[GLYPH_CHAR (g)];
660 if (NILP (string))
662 nbytes = buf - encode_terminal_src;
663 if (encode_terminal_src_size < nbytes + MAX_MULTIBYTE_LENGTH)
665 encode_terminal_src_size = nbytes + MAX_MULTIBYTE_LENGTH;
666 encode_terminal_src = xrealloc (encode_terminal_src,
667 encode_terminal_src_size);
668 buf = encode_terminal_src + nbytes;
670 if (char_charset (c, charset_list, NULL))
672 /* Store the multibyte form of C at BUF. */
673 buf += CHAR_STRING (c, buf);
674 nchars++;
676 else
678 /* C is not encodable. */
679 *buf++ = '?';
680 nchars++;
681 while (src + 1 < src_end && CHAR_GLYPH_PADDING_P (src[1]))
683 *buf++ = '?';
684 nchars++;
685 src++;
689 else
691 unsigned char *p = SDATA (string), *pend = p + SBYTES (string);
693 if (! STRING_MULTIBYTE (string))
694 string = string_to_multibyte (string);
695 nbytes = buf - encode_terminal_src;
696 if (encode_terminal_src_size < nbytes + SBYTES (string))
698 encode_terminal_src_size = nbytes + SBYTES (string);
699 encode_terminal_src = xrealloc (encode_terminal_src,
700 encode_terminal_src_size);
701 buf = encode_terminal_src + nbytes;
703 bcopy (SDATA (string), buf, SBYTES (string));
704 buf += SBYTES (string);
705 nchars += SCHARS (string);
708 src++;
711 if (nchars == 0)
713 coding->produced = 0;
714 return NULL;
717 nbytes = buf - encode_terminal_src;
718 coding->source = encode_terminal_src;
719 if (encode_terminal_dst_size == 0)
721 encode_terminal_dst_size = encode_terminal_src_size;
722 encode_terminal_dst = xmalloc (encode_terminal_dst_size);
724 coding->destination = encode_terminal_dst;
725 coding->dst_bytes = encode_terminal_dst_size;
726 encode_coding_object (coding, Qnil, 0, 0, nchars, nbytes, Qnil);
727 /* coding->destination may have been reallocated. */
728 encode_terminal_dst = coding->destination;
729 encode_terminal_dst_size = coding->dst_bytes;
731 return (encode_terminal_dst);
736 /* An implementation of write_glyphs for termcap frames. */
738 static void
739 tty_write_glyphs (struct frame *f, struct glyph *string, int len)
741 unsigned char *conversion_buffer;
742 struct coding_system *coding;
744 struct tty_display_info *tty = FRAME_TTY (f);
746 tty_turn_off_insert (tty);
747 tty_hide_cursor (tty);
749 /* Don't dare write in last column of bottom line, if Auto-Wrap,
750 since that would scroll the whole frame on some terminals. */
752 if (AutoWrap (tty)
753 && curY (tty) + 1 == FRAME_LINES (f)
754 && (curX (tty) + len) == FRAME_COLS (f))
755 len --;
756 if (len <= 0)
757 return;
759 cmplus (tty, len);
761 /* If terminal_coding does any conversion, use it, otherwise use
762 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
763 because it always return 1 if the member src_multibyte is 1. */
764 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
765 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
766 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
767 the tail. */
768 coding->mode &= ~CODING_MODE_LAST_BLOCK;
770 while (len > 0)
772 /* Identify a run of glyphs with the same face. */
773 int face_id = string->face_id;
774 int n;
776 for (n = 1; n < len; ++n)
777 if (string[n].face_id != face_id)
778 break;
780 /* Turn appearance modes of the face of the run on. */
781 tty_highlight_if_desired (tty);
782 turn_on_face (f, face_id);
784 if (n == len)
785 /* This is the last run. */
786 coding->mode |= CODING_MODE_LAST_BLOCK;
787 conversion_buffer = encode_terminal_code (string, n, coding);
788 if (coding->produced > 0)
790 BLOCK_INPUT;
791 fwrite (conversion_buffer, 1, coding->produced, tty->output);
792 if (ferror (tty->output))
793 clearerr (tty->output);
794 if (tty->termscript)
795 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
796 UNBLOCK_INPUT;
798 len -= n;
799 string += n;
801 /* Turn appearance modes off. */
802 turn_off_face (f, face_id);
803 tty_turn_off_highlight (tty);
806 cmcheckmagic (tty);
809 #ifdef HAVE_GPM /* Only used by GPM code. */
811 static void
812 tty_write_glyphs_with_face (f, string, len, face_id)
813 register struct frame *f;
814 register struct glyph *string;
815 register int len, face_id;
817 unsigned char *conversion_buffer;
818 struct coding_system *coding;
820 struct tty_display_info *tty = FRAME_TTY (f);
822 tty_turn_off_insert (tty);
823 tty_hide_cursor (tty);
825 /* Don't dare write in last column of bottom line, if Auto-Wrap,
826 since that would scroll the whole frame on some terminals. */
828 if (AutoWrap (tty)
829 && curY (tty) + 1 == FRAME_LINES (f)
830 && (curX (tty) + len) == FRAME_COLS (f))
831 len --;
832 if (len <= 0)
833 return;
835 cmplus (tty, len);
837 /* If terminal_coding does any conversion, use it, otherwise use
838 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
839 because it always return 1 if the member src_multibyte is 1. */
840 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
841 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
842 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
843 the tail. */
844 coding->mode &= ~CODING_MODE_LAST_BLOCK;
846 /* Turn appearance modes of the face. */
847 tty_highlight_if_desired (tty);
848 turn_on_face (f, face_id);
850 coding->mode |= CODING_MODE_LAST_BLOCK;
851 conversion_buffer = encode_terminal_code (string, len, coding);
852 if (coding->produced > 0)
854 BLOCK_INPUT;
855 fwrite (conversion_buffer, 1, coding->produced, tty->output);
856 if (ferror (tty->output))
857 clearerr (tty->output);
858 if (tty->termscript)
859 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
860 UNBLOCK_INPUT;
863 /* Turn appearance modes off. */
864 turn_off_face (f, face_id);
865 tty_turn_off_highlight (tty);
867 cmcheckmagic (tty);
869 #endif
871 /* An implementation of insert_glyphs for termcap frames. */
873 static void
874 tty_insert_glyphs (struct frame *f, struct glyph *start, int len)
876 char *buf;
877 struct glyph *glyph = NULL;
878 unsigned char *conversion_buffer;
879 unsigned char space[1];
880 struct coding_system *coding;
882 struct tty_display_info *tty = FRAME_TTY (f);
884 if (tty->TS_ins_multi_chars)
886 buf = tparam (tty->TS_ins_multi_chars, 0, 0, len);
887 OUTPUT1 (tty, buf);
888 xfree (buf);
889 if (start)
890 write_glyphs (f, start, len);
891 return;
894 tty_turn_on_insert (tty);
895 cmplus (tty, len);
897 if (! start)
898 space[0] = SPACEGLYPH;
900 /* If terminal_coding does any conversion, use it, otherwise use
901 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
902 because it always return 1 if the member src_multibyte is 1. */
903 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
904 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
905 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
906 the tail. */
907 coding->mode &= ~CODING_MODE_LAST_BLOCK;
909 while (len-- > 0)
911 OUTPUT1_IF (tty, tty->TS_ins_char);
912 if (!start)
914 conversion_buffer = space;
915 coding->produced = 1;
917 else
919 tty_highlight_if_desired (tty);
920 turn_on_face (f, start->face_id);
921 glyph = start;
922 ++start;
923 /* We must open sufficient space for a character which
924 occupies more than one column. */
925 while (len && CHAR_GLYPH_PADDING_P (*start))
927 OUTPUT1_IF (tty, tty->TS_ins_char);
928 start++, len--;
931 if (len <= 0)
932 /* This is the last glyph. */
933 coding->mode |= CODING_MODE_LAST_BLOCK;
935 conversion_buffer = encode_terminal_code (glyph, 1, coding);
938 if (coding->produced > 0)
940 BLOCK_INPUT;
941 fwrite (conversion_buffer, 1, coding->produced, tty->output);
942 if (ferror (tty->output))
943 clearerr (tty->output);
944 if (tty->termscript)
945 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
946 UNBLOCK_INPUT;
949 OUTPUT1_IF (tty, tty->TS_pad_inserted_char);
950 if (start)
952 turn_off_face (f, glyph->face_id);
953 tty_turn_off_highlight (tty);
957 cmcheckmagic (tty);
960 /* An implementation of delete_glyphs for termcap frames. */
962 static void
963 tty_delete_glyphs (struct frame *f, int n)
965 char *buf;
966 register int i;
968 struct tty_display_info *tty = FRAME_TTY (f);
970 if (tty->delete_in_insert_mode)
972 tty_turn_on_insert (tty);
974 else
976 tty_turn_off_insert (tty);
977 OUTPUT_IF (tty, tty->TS_delete_mode);
980 if (tty->TS_del_multi_chars)
982 buf = tparam (tty->TS_del_multi_chars, 0, 0, n);
983 OUTPUT1 (tty, buf);
984 xfree (buf);
986 else
987 for (i = 0; i < n; i++)
988 OUTPUT1 (tty, tty->TS_del_char);
989 if (!tty->delete_in_insert_mode)
990 OUTPUT_IF (tty, tty->TS_end_delete_mode);
993 /* An implementation of ins_del_lines for termcap frames. */
995 static void
996 tty_ins_del_lines (struct frame *f, int vpos, int n)
998 struct tty_display_info *tty = FRAME_TTY (f);
999 char *multi = n > 0 ? tty->TS_ins_multi_lines : tty->TS_del_multi_lines;
1000 char *single = n > 0 ? tty->TS_ins_line : tty->TS_del_line;
1001 char *scroll = n > 0 ? tty->TS_rev_scroll : tty->TS_fwd_scroll;
1003 register int i = n > 0 ? n : -n;
1004 register char *buf;
1006 /* If the lines below the insertion are being pushed
1007 into the end of the window, this is the same as clearing;
1008 and we know the lines are already clear, since the matching
1009 deletion has already been done. So can ignore this. */
1010 /* If the lines below the deletion are blank lines coming
1011 out of the end of the window, don't bother,
1012 as there will be a matching inslines later that will flush them. */
1013 if (FRAME_SCROLL_REGION_OK (f)
1014 && vpos + i >= tty->specified_window)
1015 return;
1016 if (!FRAME_MEMORY_BELOW_FRAME (f)
1017 && vpos + i >= FRAME_LINES (f))
1018 return;
1020 if (multi)
1022 raw_cursor_to (f, vpos, 0);
1023 tty_background_highlight (tty);
1024 buf = tparam (multi, 0, 0, i);
1025 OUTPUT (tty, buf);
1026 xfree (buf);
1028 else if (single)
1030 raw_cursor_to (f, vpos, 0);
1031 tty_background_highlight (tty);
1032 while (--i >= 0)
1033 OUTPUT (tty, single);
1034 if (tty->TF_teleray)
1035 curX (tty) = 0;
1037 else
1039 tty_set_scroll_region (f, vpos, tty->specified_window);
1040 if (n < 0)
1041 raw_cursor_to (f, tty->specified_window - 1, 0);
1042 else
1043 raw_cursor_to (f, vpos, 0);
1044 tty_background_highlight (tty);
1045 while (--i >= 0)
1046 OUTPUTL (tty, scroll, tty->specified_window - vpos);
1047 tty_set_scroll_region (f, 0, tty->specified_window);
1050 if (!FRAME_SCROLL_REGION_OK (f)
1051 && FRAME_MEMORY_BELOW_FRAME (f)
1052 && n < 0)
1054 cursor_to (f, FRAME_LINES (f) + n, 0);
1055 clear_to_end (f);
1059 /* Compute cost of sending "str", in characters,
1060 not counting any line-dependent padding. */
1063 string_cost (char *str)
1065 cost = 0;
1066 if (str)
1067 tputs (str, 0, evalcost);
1068 return cost;
1071 /* Compute cost of sending "str", in characters,
1072 counting any line-dependent padding at one line. */
1074 static int
1075 string_cost_one_line (char *str)
1077 cost = 0;
1078 if (str)
1079 tputs (str, 1, evalcost);
1080 return cost;
1083 /* Compute per line amount of line-dependent padding,
1084 in tenths of characters. */
1087 per_line_cost (char *str)
1089 cost = 0;
1090 if (str)
1091 tputs (str, 0, evalcost);
1092 cost = - cost;
1093 if (str)
1094 tputs (str, 10, evalcost);
1095 return cost;
1098 #ifndef old
1099 /* char_ins_del_cost[n] is cost of inserting N characters.
1100 char_ins_del_cost[-n] is cost of deleting N characters.
1101 The length of this vector is based on max_frame_cols. */
1103 int *char_ins_del_vector;
1105 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
1106 #endif
1108 /* ARGSUSED */
1109 static void
1110 calculate_ins_del_char_costs (struct frame *f)
1112 struct tty_display_info *tty = FRAME_TTY (f);
1113 int ins_startup_cost, del_startup_cost;
1114 int ins_cost_per_char, del_cost_per_char;
1115 register int i;
1116 register int *p;
1118 if (tty->TS_ins_multi_chars)
1120 ins_cost_per_char = 0;
1121 ins_startup_cost = string_cost_one_line (tty->TS_ins_multi_chars);
1123 else if (tty->TS_ins_char || tty->TS_pad_inserted_char
1124 || (tty->TS_insert_mode && tty->TS_end_insert_mode))
1126 ins_startup_cost = (30 * (string_cost (tty->TS_insert_mode)
1127 + string_cost (tty->TS_end_insert_mode))) / 100;
1128 ins_cost_per_char = (string_cost_one_line (tty->TS_ins_char)
1129 + string_cost_one_line (tty->TS_pad_inserted_char));
1131 else
1133 ins_startup_cost = 9999;
1134 ins_cost_per_char = 0;
1137 if (tty->TS_del_multi_chars)
1139 del_cost_per_char = 0;
1140 del_startup_cost = string_cost_one_line (tty->TS_del_multi_chars);
1142 else if (tty->TS_del_char)
1144 del_startup_cost = (string_cost (tty->TS_delete_mode)
1145 + string_cost (tty->TS_end_delete_mode));
1146 if (tty->delete_in_insert_mode)
1147 del_startup_cost /= 2;
1148 del_cost_per_char = string_cost_one_line (tty->TS_del_char);
1150 else
1152 del_startup_cost = 9999;
1153 del_cost_per_char = 0;
1156 /* Delete costs are at negative offsets */
1157 p = &char_ins_del_cost (f)[0];
1158 for (i = FRAME_COLS (f); --i >= 0;)
1159 *--p = (del_startup_cost += del_cost_per_char);
1161 /* Doing nothing is free */
1162 p = &char_ins_del_cost (f)[0];
1163 *p++ = 0;
1165 /* Insert costs are at positive offsets */
1166 for (i = FRAME_COLS (f); --i >= 0;)
1167 *p++ = (ins_startup_cost += ins_cost_per_char);
1170 void
1171 calculate_costs (struct frame *frame)
1173 FRAME_COST_BAUD_RATE (frame) = baud_rate;
1175 if (FRAME_TERMCAP_P (frame))
1177 struct tty_display_info *tty = FRAME_TTY (frame);
1178 register char *f = (tty->TS_set_scroll_region
1179 ? tty->TS_set_scroll_region
1180 : tty->TS_set_scroll_region_1);
1182 FRAME_SCROLL_REGION_COST (frame) = string_cost (f);
1184 tty->costs_set = 1;
1186 /* These variables are only used for terminal stuff. They are
1187 allocated once for the terminal frame of X-windows emacs, but not
1188 used afterwards.
1190 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1191 X turns off char_ins_del_ok. */
1193 max_frame_lines = max (max_frame_lines, FRAME_LINES (frame));
1194 max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
1196 if (char_ins_del_vector != 0)
1197 char_ins_del_vector
1198 = (int *) xrealloc (char_ins_del_vector,
1199 (sizeof (int)
1200 + 2 * max_frame_cols * sizeof (int)));
1201 else
1202 char_ins_del_vector
1203 = (int *) xmalloc (sizeof (int)
1204 + 2 * max_frame_cols * sizeof (int));
1206 bzero (char_ins_del_vector, (sizeof (int)
1207 + 2 * max_frame_cols * sizeof (int)));
1210 if (f && (!tty->TS_ins_line && !tty->TS_del_line))
1211 do_line_insertion_deletion_costs (frame,
1212 tty->TS_rev_scroll, tty->TS_ins_multi_lines,
1213 tty->TS_fwd_scroll, tty->TS_del_multi_lines,
1214 f, f, 1);
1215 else
1216 do_line_insertion_deletion_costs (frame,
1217 tty->TS_ins_line, tty->TS_ins_multi_lines,
1218 tty->TS_del_line, tty->TS_del_multi_lines,
1219 0, 0, 1);
1221 calculate_ins_del_char_costs (frame);
1223 /* Don't use TS_repeat if its padding is worse than sending the chars */
1224 if (tty->TS_repeat && per_line_cost (tty->TS_repeat) * baud_rate < 9000)
1225 tty->RPov = string_cost (tty->TS_repeat);
1226 else
1227 tty->RPov = FRAME_COLS (frame) * 2;
1229 cmcostinit (FRAME_TTY (frame)); /* set up cursor motion costs */
1233 struct fkey_table {
1234 char *cap, *name;
1237 /* Termcap capability names that correspond directly to X keysyms.
1238 Some of these (marked "terminfo") aren't supplied by old-style
1239 (Berkeley) termcap entries. They're listed in X keysym order;
1240 except we put the keypad keys first, so that if they clash with
1241 other keys (as on the IBM PC keyboard) they get overridden.
1244 static struct fkey_table keys[] =
1246 {"kh", "home"}, /* termcap */
1247 {"kl", "left"}, /* termcap */
1248 {"ku", "up"}, /* termcap */
1249 {"kr", "right"}, /* termcap */
1250 {"kd", "down"}, /* termcap */
1251 {"%8", "prior"}, /* terminfo */
1252 {"%5", "next"}, /* terminfo */
1253 {"@7", "end"}, /* terminfo */
1254 {"@1", "begin"}, /* terminfo */
1255 {"*6", "select"}, /* terminfo */
1256 {"%9", "print"}, /* terminfo */
1257 {"@4", "execute"}, /* terminfo --- actually the `command' key */
1259 * "insert" --- see below
1261 {"&8", "undo"}, /* terminfo */
1262 {"%0", "redo"}, /* terminfo */
1263 {"%7", "menu"}, /* terminfo --- actually the `options' key */
1264 {"@0", "find"}, /* terminfo */
1265 {"@2", "cancel"}, /* terminfo */
1266 {"%1", "help"}, /* terminfo */
1268 * "break" goes here, but can't be reliably intercepted with termcap
1270 {"&4", "reset"}, /* terminfo --- actually `restart' */
1272 * "system" and "user" --- no termcaps
1274 {"kE", "clearline"}, /* terminfo */
1275 {"kA", "insertline"}, /* terminfo */
1276 {"kL", "deleteline"}, /* terminfo */
1277 {"kI", "insertchar"}, /* terminfo */
1278 {"kD", "deletechar"}, /* terminfo */
1279 {"kB", "backtab"}, /* terminfo */
1281 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1283 {"@8", "kp-enter"}, /* terminfo */
1285 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1286 * "kp-multiply", "kp-add", "kp-separator",
1287 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1288 * --- no termcaps for any of these.
1290 {"K4", "kp-1"}, /* terminfo */
1292 * "kp-2" --- no termcap
1294 {"K5", "kp-3"}, /* terminfo */
1296 * "kp-4" --- no termcap
1298 {"K2", "kp-5"}, /* terminfo */
1300 * "kp-6" --- no termcap
1302 {"K1", "kp-7"}, /* terminfo */
1304 * "kp-8" --- no termcap
1306 {"K3", "kp-9"}, /* terminfo */
1308 * "kp-equal" --- no termcap
1310 {"k1", "f1"},
1311 {"k2", "f2"},
1312 {"k3", "f3"},
1313 {"k4", "f4"},
1314 {"k5", "f5"},
1315 {"k6", "f6"},
1316 {"k7", "f7"},
1317 {"k8", "f8"},
1318 {"k9", "f9"},
1320 {"&0", "S-cancel"}, /*shifted cancel key*/
1321 {"&9", "S-begin"}, /*shifted begin key*/
1322 {"*0", "S-find"}, /*shifted find key*/
1323 {"*1", "S-execute"}, /*shifted execute? actually shifted command key*/
1324 {"*4", "S-delete"}, /*shifted delete-character key*/
1325 {"*7", "S-end"}, /*shifted end key*/
1326 {"*8", "S-clearline"}, /*shifted clear-to end-of-line key*/
1327 {"#1", "S-help"}, /*shifted help key*/
1328 {"#2", "S-home"}, /*shifted home key*/
1329 {"#3", "S-insert"}, /*shifted insert-character key*/
1330 {"#4", "S-left"}, /*shifted left-arrow key*/
1331 {"%d", "S-menu"}, /*shifted menu? actually shifted options key*/
1332 {"%c", "S-next"}, /*shifted next key*/
1333 {"%e", "S-prior"}, /*shifted previous key*/
1334 {"%f", "S-print"}, /*shifted print key*/
1335 {"%g", "S-redo"}, /*shifted redo key*/
1336 {"%i", "S-right"}, /*shifted right-arrow key*/
1337 {"!3", "S-undo"} /*shifted undo key*/
1340 static char **term_get_fkeys_address;
1341 static KBOARD *term_get_fkeys_kboard;
1342 static Lisp_Object term_get_fkeys_1 ();
1344 /* Find the escape codes sent by the function keys for Vinput_decode_map.
1345 This function scans the termcap function key sequence entries, and
1346 adds entries to Vinput_decode_map for each function key it finds. */
1348 static void
1349 term_get_fkeys (address, kboard)
1350 char **address;
1351 KBOARD *kboard;
1353 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1354 errors during the call. The only errors should be from Fdefine_key
1355 when given a key sequence containing an invalid prefix key. If the
1356 termcap defines function keys which use a prefix that is already bound
1357 to a command by the default bindings, we should silently ignore that
1358 function key specification, rather than giving the user an error and
1359 refusing to run at all on such a terminal. */
1361 extern Lisp_Object Fidentity ();
1362 term_get_fkeys_address = address;
1363 term_get_fkeys_kboard = kboard;
1364 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1367 static Lisp_Object
1368 term_get_fkeys_1 ()
1370 int i;
1372 char **address = term_get_fkeys_address;
1373 KBOARD *kboard = term_get_fkeys_kboard;
1375 /* This can happen if CANNOT_DUMP or with strange options. */
1376 if (!KEYMAPP (kboard->Vinput_decode_map))
1377 kboard->Vinput_decode_map = Fmake_sparse_keymap (Qnil);
1379 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1381 char *sequence = tgetstr (keys[i].cap, address);
1382 if (sequence)
1383 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence),
1384 Fmake_vector (make_number (1),
1385 intern (keys[i].name)));
1388 /* The uses of the "k0" capability are inconsistent; sometimes it
1389 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1390 We will attempt to politely accommodate both systems by testing for
1391 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1394 char *k_semi = tgetstr ("k;", address);
1395 char *k0 = tgetstr ("k0", address);
1396 char *k0_name = "f10";
1398 if (k_semi)
1400 if (k0)
1401 /* Define f0 first, so that f10 takes precedence in case the
1402 key sequences happens to be the same. */
1403 Fdefine_key (kboard->Vinput_decode_map, build_string (k0),
1404 Fmake_vector (make_number (1), intern ("f0")));
1405 Fdefine_key (kboard->Vinput_decode_map, build_string (k_semi),
1406 Fmake_vector (make_number (1), intern ("f10")));
1408 else if (k0)
1409 Fdefine_key (kboard->Vinput_decode_map, build_string (k0),
1410 Fmake_vector (make_number (1), intern (k0_name)));
1413 /* Set up cookies for numbered function keys above f10. */
1415 char fcap[3], fkey[4];
1417 fcap[0] = 'F'; fcap[2] = '\0';
1418 for (i = 11; i < 64; i++)
1420 if (i <= 19)
1421 fcap[1] = '1' + i - 11;
1422 else if (i <= 45)
1423 fcap[1] = 'A' + i - 20;
1424 else
1425 fcap[1] = 'a' + i - 46;
1428 char *sequence = tgetstr (fcap, address);
1429 if (sequence)
1431 sprintf (fkey, "f%d", i);
1432 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence),
1433 Fmake_vector (make_number (1),
1434 intern (fkey)));
1441 * Various mappings to try and get a better fit.
1444 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1445 if (!tgetstr (cap1, address)) \
1447 char *sequence = tgetstr (cap2, address); \
1448 if (sequence) \
1449 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence), \
1450 Fmake_vector (make_number (1), \
1451 intern (sym))); \
1454 /* if there's no key_next keycap, map key_npage to `next' keysym */
1455 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1456 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1457 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1458 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1459 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1460 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1461 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1463 /* IBM has their own non-standard dialect of terminfo.
1464 If the standard name isn't found, try the IBM name. */
1465 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1466 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1467 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1468 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1469 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1470 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1471 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1472 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1473 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1474 #undef CONDITIONAL_REASSIGN
1477 return Qnil;
1481 /***********************************************************************
1482 Character Display Information
1483 ***********************************************************************/
1485 /* Avoid name clash with functions defined in xterm.c */
1486 #ifdef static
1487 #define append_glyph append_glyph_term
1488 #define produce_stretch_glyph produce_stretch_glyph_term
1489 #define append_composite_glyph append_composite_glyph_term
1490 #define produce_composite_glyph produce_composite_glyph_term
1491 #endif
1493 static void append_glyph P_ ((struct it *));
1494 static void produce_stretch_glyph P_ ((struct it *));
1495 static void append_composite_glyph P_ ((struct it *));
1496 static void produce_composite_glyph P_ ((struct it *));
1498 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1499 terminal frames if IT->glyph_row != NULL. IT->char_to_display is
1500 the character for which to produce glyphs; IT->face_id contains the
1501 character's face. Padding glyphs are appended if IT->c has a
1502 IT->pixel_width > 1. */
1504 static void
1505 append_glyph (it)
1506 struct it *it;
1508 struct glyph *glyph, *end;
1509 int i;
1511 xassert (it->glyph_row);
1512 glyph = (it->glyph_row->glyphs[it->area]
1513 + it->glyph_row->used[it->area]);
1514 end = it->glyph_row->glyphs[1 + it->area];
1516 for (i = 0;
1517 i < it->pixel_width && glyph < end;
1518 ++i)
1520 glyph->type = CHAR_GLYPH;
1521 glyph->pixel_width = 1;
1522 glyph->u.ch = it->char_to_display;
1523 glyph->face_id = it->face_id;
1524 glyph->padding_p = i > 0;
1525 glyph->charpos = CHARPOS (it->position);
1526 glyph->object = it->object;
1528 ++it->glyph_row->used[it->area];
1529 ++glyph;
1534 /* Produce glyphs for the display element described by IT. *IT
1535 specifies what we want to produce a glyph for (character, image, ...),
1536 and where in the glyph matrix we currently are (glyph row and hpos).
1537 produce_glyphs fills in output fields of *IT with information such as the
1538 pixel width and height of a character, and maybe output actual glyphs at
1539 the same time if IT->glyph_row is non-null. See the explanation of
1540 struct display_iterator in dispextern.h for an overview.
1542 produce_glyphs also stores the result of glyph width, ascent
1543 etc. computations in *IT.
1545 IT->glyph_row may be null, in which case produce_glyphs does not
1546 actually fill in the glyphs. This is used in the move_* functions
1547 in xdisp.c for text width and height computations.
1549 Callers usually don't call produce_glyphs directly;
1550 instead they use the macro PRODUCE_GLYPHS. */
1552 void
1553 produce_glyphs (it)
1554 struct it *it;
1556 /* If a hook is installed, let it do the work. */
1558 /* Nothing but characters are supported on terminal frames. */
1559 xassert (it->what == IT_CHARACTER
1560 || it->what == IT_COMPOSITION
1561 || it->what == IT_STRETCH);
1563 if (it->what == IT_STRETCH)
1565 produce_stretch_glyph (it);
1566 goto done;
1569 if (it->what == IT_COMPOSITION)
1571 produce_composite_glyph (it);
1572 goto done;
1575 /* Maybe translate single-byte characters to multibyte. */
1576 it->char_to_display = it->c;
1578 if (it->c >= 040 && it->c < 0177)
1580 it->pixel_width = it->nglyphs = 1;
1581 if (it->glyph_row)
1582 append_glyph (it);
1584 else if (it->c == '\n')
1585 it->pixel_width = it->nglyphs = 0;
1586 else if (it->c == '\t')
1588 int absolute_x = (it->current_x
1589 + it->continuation_lines_width);
1590 int next_tab_x
1591 = (((1 + absolute_x + it->tab_width - 1)
1592 / it->tab_width)
1593 * it->tab_width);
1594 int nspaces;
1596 /* If part of the TAB has been displayed on the previous line
1597 which is continued now, continuation_lines_width will have
1598 been incremented already by the part that fitted on the
1599 continued line. So, we will get the right number of spaces
1600 here. */
1601 nspaces = next_tab_x - absolute_x;
1603 if (it->glyph_row)
1605 int n = nspaces;
1607 it->char_to_display = ' ';
1608 it->pixel_width = it->len = 1;
1610 while (n--)
1611 append_glyph (it);
1614 it->pixel_width = nspaces;
1615 it->nglyphs = nspaces;
1617 else if (CHAR_BYTE8_P (it->c))
1619 if (unibyte_display_via_language_environment
1620 && (it->c >= 0240))
1622 it->char_to_display = unibyte_char_to_multibyte (it->c);
1623 it->pixel_width = CHAR_WIDTH (it->char_to_display);
1624 it->nglyphs = it->pixel_width;
1625 if (it->glyph_row)
1626 append_glyph (it);
1628 else
1630 /* Coming here means that it->c is from display table, thus
1631 we must send the raw 8-bit byte as is to the terminal.
1632 Although there's no way to know how many columns it
1633 occupies on a screen, it is a good assumption that a
1634 single byte code has 1-column width. */
1635 it->pixel_width = it->nglyphs = 1;
1636 if (it->glyph_row)
1637 append_glyph (it);
1640 else
1642 it->pixel_width = CHAR_WIDTH (it->c);
1643 it->nglyphs = it->pixel_width;
1645 if (it->glyph_row)
1646 append_glyph (it);
1649 done:
1650 /* Advance current_x by the pixel width as a convenience for
1651 the caller. */
1652 if (it->area == TEXT_AREA)
1653 it->current_x += it->pixel_width;
1654 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1655 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
1659 /* Produce a stretch glyph for iterator IT. IT->object is the value
1660 of the glyph property displayed. The value must be a list
1661 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1662 being recognized:
1664 1. `:width WIDTH' specifies that the space should be WIDTH *
1665 canonical char width wide. WIDTH may be an integer or floating
1666 point number.
1668 2. `:align-to HPOS' specifies that the space should be wide enough
1669 to reach HPOS, a value in canonical character units. */
1671 static void
1672 produce_stretch_glyph (it)
1673 struct it *it;
1675 /* (space :width WIDTH ...) */
1676 Lisp_Object prop, plist;
1677 int width = 0, align_to = -1;
1678 int zero_width_ok_p = 0;
1679 double tem;
1681 /* List should start with `space'. */
1682 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1683 plist = XCDR (it->object);
1685 /* Compute the width of the stretch. */
1686 if ((prop = Fplist_get (plist, QCwidth), !NILP (prop))
1687 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, 0))
1689 /* Absolute width `:width WIDTH' specified and valid. */
1690 zero_width_ok_p = 1;
1691 width = (int)(tem + 0.5);
1693 else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
1694 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, &align_to))
1696 if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
1697 align_to = (align_to < 0
1699 : align_to - window_box_left_offset (it->w, TEXT_AREA));
1700 else if (align_to < 0)
1701 align_to = window_box_left_offset (it->w, TEXT_AREA);
1702 width = max (0, (int)(tem + 0.5) + align_to - it->current_x);
1703 zero_width_ok_p = 1;
1705 else
1706 /* Nothing specified -> width defaults to canonical char width. */
1707 width = FRAME_COLUMN_WIDTH (it->f);
1709 if (width <= 0 && (width < 0 || !zero_width_ok_p))
1710 width = 1;
1712 if (width > 0 && it->glyph_row)
1714 Lisp_Object o_object = it->object;
1715 Lisp_Object object = it->stack[it->sp - 1].string;
1716 int n = width;
1718 if (!STRINGP (object))
1719 object = it->w->buffer;
1720 it->object = object;
1721 it->char_to_display = ' ';
1722 it->pixel_width = it->len = 1;
1723 while (n--)
1724 append_glyph (it);
1725 it->object = o_object;
1727 it->pixel_width = width;
1728 it->nglyphs = width;
1732 /* Append glyphs to IT's glyph_row for the composition IT->cmp_id.
1733 Called from produce_composite_glyph for terminal frames if
1734 IT->glyph_row != NULL. IT->face_id contains the character's
1735 face. */
1737 static void
1738 append_composite_glyph (it)
1739 struct it *it;
1741 struct glyph *glyph;
1743 xassert (it->glyph_row);
1744 glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
1745 if (glyph < it->glyph_row->glyphs[1 + it->area])
1747 glyph->type = COMPOSITE_GLYPH;
1748 glyph->pixel_width = it->pixel_width;
1749 glyph->u.cmp_id = it->cmp_id;
1750 glyph->face_id = it->face_id;
1751 glyph->padding_p = 0;
1752 glyph->charpos = CHARPOS (it->position);
1753 glyph->object = it->object;
1755 ++it->glyph_row->used[it->area];
1756 ++glyph;
1761 /* Produce a composite glyph for iterator IT. IT->cmp_id is the ID of
1762 the composition. We simply produces components of the composition
1763 assuming that that the terminal has a capability to layout/render
1764 it correctly. */
1766 static void
1767 produce_composite_glyph (it)
1768 struct it *it;
1770 struct composition *cmp = composition_table[it->cmp_id];
1771 int c;
1773 xassert (cmp->glyph_len > 0);
1774 c = COMPOSITION_GLYPH (cmp, 0);
1775 it->pixel_width = CHAR_WIDTH (it->c);
1776 it->nglyphs = 1;
1778 if (it->glyph_row)
1779 append_composite_glyph (it);
1783 /* Get information about special display element WHAT in an
1784 environment described by IT. WHAT is one of IT_TRUNCATION or
1785 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1786 non-null glyph_row member. This function ensures that fields like
1787 face_id, c, len of IT are left untouched. */
1789 void
1790 produce_special_glyphs (it, what)
1791 struct it *it;
1792 enum display_element_type what;
1794 struct it temp_it;
1795 Lisp_Object gc;
1796 GLYPH glyph;
1798 temp_it = *it;
1799 temp_it.dp = NULL;
1800 temp_it.what = IT_CHARACTER;
1801 temp_it.len = 1;
1802 temp_it.object = make_number (0);
1803 bzero (&temp_it.current, sizeof temp_it.current);
1805 if (what == IT_CONTINUATION)
1807 /* Continuation glyph. */
1808 SET_GLYPH_FROM_CHAR (glyph, '\\');
1809 if (it->dp
1810 && (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc))
1811 && GLYPH_CODE_CHAR_VALID_P (gc))
1813 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
1814 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
1817 else if (what == IT_TRUNCATION)
1819 /* Truncation glyph. */
1820 SET_GLYPH_FROM_CHAR (glyph, '$');
1821 if (it->dp
1822 && (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc))
1823 && GLYPH_CODE_CHAR_VALID_P (gc))
1825 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
1826 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
1829 else
1830 abort ();
1832 temp_it.c = GLYPH_CHAR (glyph);
1833 temp_it.face_id = GLYPH_FACE (glyph);
1834 temp_it.len = CHAR_BYTES (temp_it.c);
1836 produce_glyphs (&temp_it);
1837 it->pixel_width = temp_it.pixel_width;
1838 it->nglyphs = temp_it.pixel_width;
1843 /***********************************************************************
1844 Faces
1845 ***********************************************************************/
1847 /* Value is non-zero if attribute ATTR may be used. ATTR should be
1848 one of the enumerators from enum no_color_bit, or a bit set built
1849 from them. Some display attributes may not be used together with
1850 color; the termcap capability `NC' specifies which ones. */
1852 #define MAY_USE_WITH_COLORS_P(tty, ATTR) \
1853 (tty->TN_max_colors > 0 \
1854 ? (tty->TN_no_color_video & (ATTR)) == 0 \
1855 : 1)
1857 /* Turn appearances of face FACE_ID on tty frame F on.
1858 FACE_ID is a realized face ID number, in the face cache. */
1860 static void
1861 turn_on_face (f, face_id)
1862 struct frame *f;
1863 int face_id;
1865 struct face *face = FACE_FROM_ID (f, face_id);
1866 long fg = face->foreground;
1867 long bg = face->background;
1868 struct tty_display_info *tty = FRAME_TTY (f);
1870 /* Do this first because TS_end_standout_mode may be the same
1871 as TS_exit_attribute_mode, which turns all appearances off. */
1872 if (MAY_USE_WITH_COLORS_P (tty, NC_REVERSE))
1874 if (tty->TN_max_colors > 0)
1876 if (fg >= 0 && bg >= 0)
1878 /* If the terminal supports colors, we can set them
1879 below without using reverse video. The face's fg
1880 and bg colors are set as they should appear on
1881 the screen, i.e. they take the inverse-video'ness
1882 of the face already into account. */
1884 else if (inverse_video)
1886 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1887 || bg == FACE_TTY_DEFAULT_BG_COLOR)
1888 tty_toggle_highlight (tty);
1890 else
1892 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1893 || bg == FACE_TTY_DEFAULT_FG_COLOR)
1894 tty_toggle_highlight (tty);
1897 else
1899 /* If we can't display colors, use reverse video
1900 if the face specifies that. */
1901 if (inverse_video)
1903 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1904 || bg == FACE_TTY_DEFAULT_BG_COLOR)
1905 tty_toggle_highlight (tty);
1907 else
1909 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1910 || bg == FACE_TTY_DEFAULT_FG_COLOR)
1911 tty_toggle_highlight (tty);
1916 if (face->tty_bold_p)
1918 if (MAY_USE_WITH_COLORS_P (tty, NC_BOLD))
1919 OUTPUT1_IF (tty, tty->TS_enter_bold_mode);
1921 else if (face->tty_dim_p)
1922 if (MAY_USE_WITH_COLORS_P (tty, NC_DIM))
1923 OUTPUT1_IF (tty, tty->TS_enter_dim_mode);
1925 /* Alternate charset and blinking not yet used. */
1926 if (face->tty_alt_charset_p
1927 && MAY_USE_WITH_COLORS_P (tty, NC_ALT_CHARSET))
1928 OUTPUT1_IF (tty, tty->TS_enter_alt_charset_mode);
1930 if (face->tty_blinking_p
1931 && MAY_USE_WITH_COLORS_P (tty, NC_BLINK))
1932 OUTPUT1_IF (tty, tty->TS_enter_blink_mode);
1934 if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (tty, NC_UNDERLINE))
1935 OUTPUT1_IF (tty, tty->TS_enter_underline_mode);
1937 if (tty->TN_max_colors > 0)
1939 char *ts, *p;
1941 ts = tty->standout_mode ? tty->TS_set_background : tty->TS_set_foreground;
1942 if (fg >= 0 && ts)
1944 p = tparam (ts, NULL, 0, (int) fg);
1945 OUTPUT (tty, p);
1946 xfree (p);
1949 ts = tty->standout_mode ? tty->TS_set_foreground : tty->TS_set_background;
1950 if (bg >= 0 && ts)
1952 p = tparam (ts, NULL, 0, (int) bg);
1953 OUTPUT (tty, p);
1954 xfree (p);
1960 /* Turn off appearances of face FACE_ID on tty frame F. */
1962 static void
1963 turn_off_face (f, face_id)
1964 struct frame *f;
1965 int face_id;
1967 struct face *face = FACE_FROM_ID (f, face_id);
1968 struct tty_display_info *tty = FRAME_TTY (f);
1970 xassert (face != NULL);
1972 if (tty->TS_exit_attribute_mode)
1974 /* Capability "me" will turn off appearance modes double-bright,
1975 half-bright, reverse-video, standout, underline. It may or
1976 may not turn off alt-char-mode. */
1977 if (face->tty_bold_p
1978 || face->tty_dim_p
1979 || face->tty_reverse_p
1980 || face->tty_alt_charset_p
1981 || face->tty_blinking_p
1982 || face->tty_underline_p)
1984 OUTPUT1_IF (tty, tty->TS_exit_attribute_mode);
1985 if (strcmp (tty->TS_exit_attribute_mode, tty->TS_end_standout_mode) == 0)
1986 tty->standout_mode = 0;
1989 if (face->tty_alt_charset_p)
1990 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
1992 else
1994 /* If we don't have "me" we can only have those appearances
1995 that have exit sequences defined. */
1996 if (face->tty_alt_charset_p)
1997 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
1999 if (face->tty_underline_p)
2000 OUTPUT_IF (tty, tty->TS_exit_underline_mode);
2003 /* Switch back to default colors. */
2004 if (tty->TN_max_colors > 0
2005 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
2006 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
2007 || (face->background != FACE_TTY_DEFAULT_COLOR
2008 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
2009 OUTPUT1_IF (tty, tty->TS_orig_pair);
2013 /* Return non-zero if the terminal on frame F supports all of the
2014 capabilities in CAPS simultaneously, with foreground and background
2015 colors FG and BG. */
2018 tty_capable_p (tty, caps, fg, bg)
2019 struct tty_display_info *tty;
2020 unsigned caps;
2021 unsigned long fg, bg;
2023 #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
2024 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
2025 return 0;
2027 TTY_CAPABLE_P_TRY (tty, TTY_CAP_INVERSE, tty->TS_standout_mode, NC_REVERSE);
2028 TTY_CAPABLE_P_TRY (tty, TTY_CAP_UNDERLINE, tty->TS_enter_underline_mode, NC_UNDERLINE);
2029 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BOLD, tty->TS_enter_bold_mode, NC_BOLD);
2030 TTY_CAPABLE_P_TRY (tty, TTY_CAP_DIM, tty->TS_enter_dim_mode, NC_DIM);
2031 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BLINK, tty->TS_enter_blink_mode, NC_BLINK);
2032 TTY_CAPABLE_P_TRY (tty, TTY_CAP_ALT_CHARSET, tty->TS_enter_alt_charset_mode, NC_ALT_CHARSET);
2034 /* We can do it! */
2035 return 1;
2038 /* Return non-zero if the terminal is capable to display colors. */
2040 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
2041 0, 1, 0,
2042 doc: /* Return non-nil if the tty device TERMINAL can display colors.
2044 TERMINAL can be a terminal id, a frame or nil (meaning the selected
2045 frame's terminal). This function always returns nil if TERMINAL
2046 is not on a tty device. */)
2047 (terminal)
2048 Lisp_Object terminal;
2050 struct terminal *t = get_tty_terminal (terminal, 0);
2051 if (!t)
2052 return Qnil;
2053 else
2054 return t->display_info.tty->TN_max_colors > 0 ? Qt : Qnil;
2057 /* Return the number of supported colors. */
2058 DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
2059 Stty_display_color_cells, 0, 1, 0,
2060 doc: /* Return the number of colors supported by the tty device TERMINAL.
2062 TERMINAL can be a terminal id, a frame or nil (meaning the selected
2063 frame's terminal). This function always returns 0 if TERMINAL
2064 is not on a tty device. */)
2065 (terminal)
2066 Lisp_Object terminal;
2068 struct terminal *t = get_tty_terminal (terminal, 0);
2069 if (!t)
2070 return make_number (0);
2071 else
2072 return make_number (t->display_info.tty->TN_max_colors);
2075 #ifndef WINDOWSNT
2077 /* Declare here rather than in the function, as in the rest of Emacs,
2078 to work around an HPUX compiler bug (?). See
2079 http://lists.gnu.org/archive/html/emacs-devel/2007-08/msg00410.html */
2080 static int default_max_colors;
2081 static int default_max_pairs;
2082 static int default_no_color_video;
2083 static char *default_orig_pair;
2084 static char *default_set_foreground;
2085 static char *default_set_background;
2087 /* Save or restore the default color-related capabilities of this
2088 terminal. */
2089 static void
2090 tty_default_color_capabilities (struct tty_display_info *tty, int save)
2093 if (save)
2095 if (default_orig_pair)
2096 xfree (default_orig_pair);
2097 default_orig_pair = tty->TS_orig_pair ? xstrdup (tty->TS_orig_pair) : NULL;
2099 if (default_set_foreground)
2100 xfree (default_set_foreground);
2101 default_set_foreground = tty->TS_set_foreground ? xstrdup (tty->TS_set_foreground)
2102 : NULL;
2104 if (default_set_background)
2105 xfree (default_set_background);
2106 default_set_background = tty->TS_set_background ? xstrdup (tty->TS_set_background)
2107 : NULL;
2109 default_max_colors = tty->TN_max_colors;
2110 default_max_pairs = tty->TN_max_pairs;
2111 default_no_color_video = tty->TN_no_color_video;
2113 else
2115 tty->TS_orig_pair = default_orig_pair;
2116 tty->TS_set_foreground = default_set_foreground;
2117 tty->TS_set_background = default_set_background;
2118 tty->TN_max_colors = default_max_colors;
2119 tty->TN_max_pairs = default_max_pairs;
2120 tty->TN_no_color_video = default_no_color_video;
2124 /* Setup one of the standard tty color schemes according to MODE.
2125 MODE's value is generally the number of colors which we want to
2126 support; zero means set up for the default capabilities, the ones
2127 we saw at init_tty time; -1 means turn off color support. */
2128 static void
2129 tty_setup_colors (struct tty_display_info *tty, int mode)
2131 /* Canonicalize all negative values of MODE. */
2132 if (mode < -1)
2133 mode = -1;
2135 switch (mode)
2137 case -1: /* no colors at all */
2138 tty->TN_max_colors = 0;
2139 tty->TN_max_pairs = 0;
2140 tty->TN_no_color_video = 0;
2141 tty->TS_set_foreground = tty->TS_set_background = tty->TS_orig_pair = NULL;
2142 break;
2143 case 0: /* default colors, if any */
2144 default:
2145 tty_default_color_capabilities (tty, 0);
2146 break;
2147 case 8: /* 8 standard ANSI colors */
2148 tty->TS_orig_pair = "\033[0m";
2149 #ifdef TERMINFO
2150 tty->TS_set_foreground = "\033[3%p1%dm";
2151 tty->TS_set_background = "\033[4%p1%dm";
2152 #else
2153 tty->TS_set_foreground = "\033[3%dm";
2154 tty->TS_set_background = "\033[4%dm";
2155 #endif
2156 tty->TN_max_colors = 8;
2157 tty->TN_max_pairs = 64;
2158 tty->TN_no_color_video = 0;
2159 break;
2163 void
2164 set_tty_color_mode (tty, f)
2165 struct tty_display_info *tty;
2166 struct frame *f;
2168 Lisp_Object tem, val, color_mode_spec;
2169 Lisp_Object color_mode;
2170 int mode;
2171 extern Lisp_Object Qtty_color_mode;
2172 Lisp_Object tty_color_mode_alist
2173 = Fintern_soft (build_string ("tty-color-mode-alist"), Qnil);
2175 tem = assq_no_quit (Qtty_color_mode, f->param_alist);
2176 val = CONSP (tem) ? XCDR (tem) : Qnil;
2178 if (INTEGERP (val))
2179 color_mode = val;
2180 else
2182 tem = (NILP (tty_color_mode_alist) ? Qnil
2183 : Fassq (val, XSYMBOL (tty_color_mode_alist)->value));
2184 color_mode = CONSP (tem) ? XCDR (tem) : Qnil;
2187 mode = INTEGERP (color_mode) ? XINT (color_mode) : 0;
2189 if (mode != tty->previous_color_mode)
2191 Lisp_Object funsym = intern ("tty-set-up-initial-frame-faces");
2192 tty->previous_color_mode = mode;
2193 tty_setup_colors (tty , mode);
2194 /* This recomputes all the faces given the new color definitions. */
2195 safe_call (1, &funsym);
2199 #endif /* !WINDOWSNT */
2203 /* Return the tty display object specified by TERMINAL. */
2205 struct terminal *
2206 get_tty_terminal (Lisp_Object terminal, int throw)
2208 struct terminal *t = get_terminal (terminal, throw);
2210 if (t && t->type != output_termcap)
2212 if (throw)
2213 error ("Device %d is not a termcap terminal device", t->id);
2214 else
2215 return NULL;
2218 return t;
2221 /* Return an active termcap device that uses the tty device with the
2222 given name.
2224 This function ignores suspended devices.
2226 Returns NULL if the named terminal device is not opened. */
2228 struct terminal *
2229 get_named_tty (name)
2230 char *name;
2232 struct terminal *t;
2234 if (!name)
2235 abort ();
2237 for (t = terminal_list; t; t = t->next_terminal)
2239 if (t->type == output_termcap
2240 && !strcmp (t->display_info.tty->name, name)
2241 && TERMINAL_ACTIVE_P (t))
2242 return t;
2245 return 0;
2249 DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0,
2250 doc: /* Return the type of the tty device that TERMINAL uses.
2251 Returns nil if TERMINAL is not on a tty device.
2253 TERMINAL can be a terminal id, a frame or nil (meaning the selected
2254 frame's terminal). */)
2255 (terminal)
2256 Lisp_Object terminal;
2258 struct terminal *t = get_terminal (terminal, 1);
2260 if (t->type != output_termcap)
2261 return Qnil;
2263 if (t->display_info.tty->type)
2264 return build_string (t->display_info.tty->type);
2265 else
2266 return Qnil;
2269 DEFUN ("controlling-tty-p", Fcontrolling_tty_p, Scontrolling_tty_p, 0, 1, 0,
2270 doc: /* Return non-nil if TERMINAL is on the controlling tty of the Emacs process.
2272 TERMINAL can be a terminal id, a frame or nil (meaning the selected
2273 frame's terminal). This function always returns nil if TERMINAL
2274 is not on a tty device. */)
2275 (terminal)
2276 Lisp_Object terminal;
2278 struct terminal *t = get_terminal (terminal, 1);
2280 if (t->type != output_termcap || strcmp (t->display_info.tty->name, DEV_TTY))
2281 return Qnil;
2282 else
2283 return Qt;
2286 DEFUN ("tty-no-underline", Ftty_no_underline, Stty_no_underline, 0, 1, 0,
2287 doc: /* Declare that the tty used by TERMINAL does not handle underlining.
2288 This is used to override the terminfo data, for certain terminals that
2289 do not really do underlining, but say that they do. This function has
2290 no effect if used on a non-tty terminal.
2292 TERMINAL can be a terminal id, a frame or nil (meaning the selected
2293 frame's terminal). This function always returns nil if TERMINAL
2294 is not on a tty device. */)
2295 (terminal)
2296 Lisp_Object terminal;
2298 struct terminal *t = get_terminal (terminal, 1);
2300 if (t->type == output_termcap)
2301 t->display_info.tty->TS_enter_underline_mode = 0;
2302 return Qnil;
2307 DEFUN ("suspend-tty", Fsuspend_tty, Ssuspend_tty, 0, 1, 0,
2308 doc: /* Suspend the terminal device TTY.
2310 The device is restored to its default state, and Emacs ceases all
2311 access to the tty device. Frames that use the device are not deleted,
2312 but input is not read from them and if they change, their display is
2313 not updated.
2315 TTY may be a terminal id, a frame, or nil for the terminal device of
2316 the currently selected frame.
2318 This function runs `suspend-tty-functions' after suspending the
2319 device. The functions are run with one arg, the id of the suspended
2320 terminal device.
2322 `suspend-tty' does nothing if it is called on a device that is already
2323 suspended.
2325 A suspended tty may be resumed by calling `resume-tty' on it. */)
2326 (tty)
2327 Lisp_Object tty;
2329 struct terminal *t = get_tty_terminal (tty, 1);
2330 FILE *f;
2332 if (!t)
2333 error ("Unknown tty device");
2335 f = t->display_info.tty->input;
2337 if (f)
2339 /* First run `suspend-tty-functions' and then clean up the tty
2340 state because `suspend-tty-functions' might need to change
2341 the tty state. */
2342 if (!NILP (Vrun_hooks))
2344 Lisp_Object args[2];
2345 args[0] = intern ("suspend-tty-functions");
2346 XSETTERMINAL (args[1], t);
2347 Frun_hook_with_args (2, args);
2350 reset_sys_modes (t->display_info.tty);
2352 delete_keyboard_wait_descriptor (fileno (f));
2354 fclose (f);
2355 if (f != t->display_info.tty->output)
2356 fclose (t->display_info.tty->output);
2358 t->display_info.tty->input = 0;
2359 t->display_info.tty->output = 0;
2361 if (FRAMEP (t->display_info.tty->top_frame))
2362 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0);
2366 /* Clear display hooks to prevent further output. */
2367 clear_tty_hooks (t);
2369 return Qnil;
2372 DEFUN ("resume-tty", Fresume_tty, Sresume_tty, 0, 1, 0,
2373 doc: /* Resume the previously suspended terminal device TTY.
2374 The terminal is opened and reinitialized. Frames that are on the
2375 suspended terminal are revived.
2377 It is an error to resume a terminal while another terminal is active
2378 on the same device.
2380 This function runs `resume-tty-functions' after resuming the terminal.
2381 The functions are run with one arg, the id of the resumed terminal
2382 device.
2384 `resume-tty' does nothing if it is called on a device that is not
2385 suspended.
2387 TTY may be a terminal id, a frame, or nil for the terminal device of
2388 the currently selected frame. */)
2389 (tty)
2390 Lisp_Object tty;
2392 struct terminal *t = get_tty_terminal (tty, 1);
2393 int fd;
2395 if (!t)
2396 error ("Unknown tty device");
2398 if (!t->display_info.tty->input)
2400 if (get_named_tty (t->display_info.tty->name))
2401 error ("Cannot resume display while another display is active on the same device");
2403 fd = emacs_open (t->display_info.tty->name, O_RDWR | O_NOCTTY, 0);
2405 if (fd == -1)
2406 error ("Can not reopen tty device %s: %s", t->display_info.tty->name, strerror (errno));
2408 if (strcmp (t->display_info.tty->name, DEV_TTY))
2409 dissociate_if_controlling_tty (fd);
2411 t->display_info.tty->output = fdopen (fd, "w+");
2412 t->display_info.tty->input = t->display_info.tty->output;
2414 add_keyboard_wait_descriptor (fd);
2416 if (FRAMEP (t->display_info.tty->top_frame))
2417 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
2419 init_sys_modes (t->display_info.tty);
2421 /* Run `resume-tty-functions'. */
2422 if (!NILP (Vrun_hooks))
2424 Lisp_Object args[2];
2425 args[0] = intern ("resume-tty-functions");
2426 XSETTERMINAL (args[1], t);
2427 Frun_hook_with_args (2, args);
2431 set_tty_hooks (t);
2433 return Qnil;
2437 /***********************************************************************
2438 Mouse
2439 ***********************************************************************/
2441 #ifdef HAVE_GPM
2442 void
2443 term_mouse_moveto (int x, int y)
2445 /* TODO: how to set mouse position?
2446 const char *name;
2447 int fd;
2448 name = (const char *) ttyname (0);
2449 fd = open (name, O_WRONLY);
2450 SOME_FUNCTION (x, y, fd);
2451 close (fd);
2452 last_mouse_x = x;
2453 last_mouse_y = y; */
2456 static void
2457 term_show_mouse_face (enum draw_glyphs_face draw)
2459 struct window *w = XWINDOW (mouse_face_window);
2460 int save_x, save_y;
2461 int i;
2463 struct frame *f = XFRAME (w->frame);
2464 struct tty_display_info *tty = FRAME_TTY (f);
2466 if (/* If window is in the process of being destroyed, don't bother
2467 to do anything. */
2468 w->current_matrix != NULL
2469 /* Recognize when we are called to operate on rows that don't exist
2470 anymore. This can happen when a window is split. */
2471 && mouse_face_end_row < w->current_matrix->nrows)
2473 /* write_glyphs writes at cursor position, so we need to
2474 temporarily move cursor coordinates to the beginning of
2475 the highlight region. */
2477 /* Save current cursor co-ordinates */
2478 save_y = curY (tty);
2479 save_x = curX (tty);
2481 /* Note that mouse_face_beg_row etc. are window relative. */
2482 for (i = mouse_face_beg_row; i <= mouse_face_end_row; i++)
2484 int start_hpos, end_hpos, nglyphs;
2485 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
2487 /* Don't do anything if row doesn't have valid contents. */
2488 if (!row->enabled_p)
2489 continue;
2491 /* For all but the first row, the highlight starts at column 0. */
2492 if (i == mouse_face_beg_row)
2493 start_hpos = mouse_face_beg_col;
2494 else
2495 start_hpos = 0;
2497 if (i == mouse_face_end_row)
2498 end_hpos = mouse_face_end_col;
2499 else
2501 end_hpos = row->used[TEXT_AREA];
2502 if (draw == DRAW_NORMAL_TEXT)
2503 row->fill_line_p = 1; /* Clear to end of line */
2506 if (end_hpos <= start_hpos)
2507 continue;
2508 /* Record that some glyphs of this row are displayed in
2509 mouse-face. */
2510 row->mouse_face_p = draw > 0;
2512 nglyphs = end_hpos - start_hpos;
2514 if (end_hpos >= row->used[TEXT_AREA])
2515 nglyphs = row->used[TEXT_AREA] - start_hpos;
2517 pos_y = row->y + WINDOW_TOP_EDGE_Y (w);
2518 pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos
2519 + WINDOW_LEFT_EDGE_X (w);
2521 cursor_to (f, pos_y, pos_x);
2523 if (draw == DRAW_MOUSE_FACE)
2525 tty_write_glyphs_with_face (f, row->glyphs[TEXT_AREA] + start_hpos,
2526 nglyphs, mouse_face_face_id);
2528 else /* draw == DRAW_NORMAL_TEXT */
2529 write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
2531 cursor_to (f, save_y, save_x);
2535 static void
2536 term_clear_mouse_face ()
2538 if (!NILP (mouse_face_window))
2539 term_show_mouse_face (DRAW_NORMAL_TEXT);
2541 mouse_face_beg_row = mouse_face_beg_col = -1;
2542 mouse_face_end_row = mouse_face_end_col = -1;
2543 mouse_face_window = Qnil;
2546 /* Find the glyph matrix position of buffer position POS in window W.
2547 *HPOS and *VPOS are set to the positions found. W's current glyphs
2548 must be up to date. If POS is above window start return (0, 0).
2549 If POS is after end of W, return end of last line in W.
2550 - taken from msdos.c */
2551 static int
2552 fast_find_position (struct window *w, int pos, int *hpos, int *vpos)
2554 int i, lastcol, line_start_position, maybe_next_line_p = 0;
2555 int yb = window_text_bottom_y (w);
2556 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0), *best_row = row;
2558 while (row->y < yb)
2560 if (row->used[TEXT_AREA])
2561 line_start_position = row->glyphs[TEXT_AREA]->charpos;
2562 else
2563 line_start_position = 0;
2565 if (line_start_position > pos)
2566 break;
2567 /* If the position sought is the end of the buffer,
2568 don't include the blank lines at the bottom of the window. */
2569 else if (line_start_position == pos
2570 && pos == BUF_ZV (XBUFFER (w->buffer)))
2572 maybe_next_line_p = 1;
2573 break;
2575 else if (line_start_position > 0)
2576 best_row = row;
2578 /* Don't overstep the last matrix row, lest we get into the
2579 never-never land... */
2580 if (row->y + 1 >= yb)
2581 break;
2583 ++row;
2586 /* Find the right column within BEST_ROW. */
2587 lastcol = 0;
2588 row = best_row;
2589 for (i = 0; i < row->used[TEXT_AREA]; i++)
2591 struct glyph *glyph = row->glyphs[TEXT_AREA] + i;
2592 int charpos;
2594 charpos = glyph->charpos;
2595 if (charpos == pos)
2597 *hpos = i;
2598 *vpos = row->y;
2599 return 1;
2601 else if (charpos > pos)
2602 break;
2603 else if (charpos > 0)
2604 lastcol = i;
2607 /* If we're looking for the end of the buffer,
2608 and we didn't find it in the line we scanned,
2609 use the start of the following line. */
2610 if (maybe_next_line_p)
2612 ++row;
2613 lastcol = 0;
2616 *vpos = row->y;
2617 *hpos = lastcol + 1;
2618 return 0;
2621 static void
2622 term_mouse_highlight (struct frame *f, int x, int y)
2624 enum window_part part;
2625 Lisp_Object window;
2626 struct window *w;
2627 struct buffer *b;
2629 if (NILP (Vmouse_highlight)
2630 || !f->glyphs_initialized_p)
2631 return;
2633 /* Which window is that in? */
2634 window = window_from_coordinates (f, x, y, &part, &x, &y, 0);
2636 /* Not on a window -> return. */
2637 if (!WINDOWP (window))
2638 return;
2640 if (!EQ (window, mouse_face_window))
2641 term_clear_mouse_face ();
2643 w = XWINDOW (window);
2645 /* Are we in a window whose display is up to date?
2646 And verify the buffer's text has not changed. */
2647 b = XBUFFER (w->buffer);
2648 if (part == ON_TEXT
2649 && EQ (w->window_end_valid, w->buffer)
2650 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
2651 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
2653 int pos, i, nrows = w->current_matrix->nrows;
2654 struct glyph_row *row;
2655 struct glyph *glyph;
2657 /* Find the glyph under X/Y. */
2658 glyph = NULL;
2659 if (y >= 0 && y < nrows)
2661 row = MATRIX_ROW (w->current_matrix, y);
2662 /* Give up if some row before the one we are looking for is
2663 not enabled. */
2664 for (i = 0; i <= y; i++)
2665 if (!MATRIX_ROW (w->current_matrix, i)->enabled_p)
2666 break;
2667 if (i > y /* all rows upto and including the one at Y are enabled */
2668 && row->displays_text_p
2669 && x < window_box_width (w, TEXT_AREA))
2671 glyph = row->glyphs[TEXT_AREA];
2672 if (x >= row->used[TEXT_AREA])
2673 glyph = NULL;
2674 else
2676 glyph += x;
2677 if (!BUFFERP (glyph->object))
2678 glyph = NULL;
2683 /* Clear mouse face if X/Y not over text. */
2684 if (glyph == NULL)
2686 term_clear_mouse_face ();
2687 return;
2690 if (!BUFFERP (glyph->object))
2691 abort ();
2692 pos = glyph->charpos;
2694 /* Check for mouse-face. */
2696 extern Lisp_Object Qmouse_face;
2697 Lisp_Object mouse_face, overlay, position, *overlay_vec;
2698 int noverlays, obegv, ozv;
2699 struct buffer *obuf;
2701 /* If we get an out-of-range value, return now; avoid an error. */
2702 if (pos > BUF_Z (b))
2703 return;
2705 /* Make the window's buffer temporarily current for
2706 overlays_at and compute_char_face. */
2707 obuf = current_buffer;
2708 current_buffer = b;
2709 obegv = BEGV;
2710 ozv = ZV;
2711 BEGV = BEG;
2712 ZV = Z;
2714 /* Is this char mouse-active? */
2715 XSETINT (position, pos);
2717 /* Put all the overlays we want in a vector in overlay_vec. */
2718 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL, 0);
2719 /* Sort overlays into increasing priority order. */
2720 noverlays = sort_overlays (overlay_vec, noverlays, w);
2722 /* Check mouse-face highlighting. */
2723 if (!(EQ (window, mouse_face_window)
2724 && y >= mouse_face_beg_row
2725 && y <= mouse_face_end_row
2726 && (y > mouse_face_beg_row
2727 || x >= mouse_face_beg_col)
2728 && (y < mouse_face_end_row
2729 || x < mouse_face_end_col
2730 || mouse_face_past_end)))
2732 /* Clear the display of the old active region, if any. */
2733 term_clear_mouse_face ();
2735 /* Find the highest priority overlay that has a mouse-face
2736 property. */
2737 overlay = Qnil;
2738 for (i = noverlays - 1; i >= 0; --i)
2740 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
2741 if (!NILP (mouse_face))
2743 overlay = overlay_vec[i];
2744 break;
2748 /* If no overlay applies, get a text property. */
2749 if (NILP (overlay))
2750 mouse_face = Fget_text_property (position, Qmouse_face,
2751 w->buffer);
2753 /* Handle the overlay case. */
2754 if (!NILP (overlay))
2756 /* Find the range of text around this char that
2757 should be active. */
2758 Lisp_Object before, after;
2759 EMACS_INT ignore;
2762 before = Foverlay_start (overlay);
2763 after = Foverlay_end (overlay);
2764 /* Record this as the current active region. */
2765 fast_find_position (w, XFASTINT (before),
2766 &mouse_face_beg_col,
2767 &mouse_face_beg_row);
2769 mouse_face_past_end
2770 = !fast_find_position (w, XFASTINT (after),
2771 &mouse_face_end_col,
2772 &mouse_face_end_row);
2773 mouse_face_window = window;
2775 mouse_face_face_id
2776 = face_at_buffer_position (w, pos, 0, 0,
2777 &ignore, pos + 1, 1);
2779 /* Display it as active. */
2780 term_show_mouse_face (DRAW_MOUSE_FACE);
2782 /* Handle the text property case. */
2783 else if (!NILP (mouse_face))
2785 /* Find the range of text around this char that
2786 should be active. */
2787 Lisp_Object before, after, beginning, end;
2788 EMACS_INT ignore;
2790 beginning = Fmarker_position (w->start);
2791 XSETINT (end, (BUF_Z (b) - XFASTINT (w->window_end_pos)));
2792 before
2793 = Fprevious_single_property_change (make_number (pos + 1),
2794 Qmouse_face,
2795 w->buffer, beginning);
2796 after
2797 = Fnext_single_property_change (position, Qmouse_face,
2798 w->buffer, end);
2800 /* Record this as the current active region. */
2801 fast_find_position (w, XFASTINT (before),
2802 &mouse_face_beg_col,
2803 &mouse_face_beg_row);
2804 mouse_face_past_end
2805 = !fast_find_position (w, XFASTINT (after),
2806 &mouse_face_end_col,
2807 &mouse_face_end_row);
2808 mouse_face_window = window;
2810 mouse_face_face_id
2811 = face_at_buffer_position (w, pos, 0, 0,
2812 &ignore, pos + 1, 1);
2814 /* Display it as active. */
2815 term_show_mouse_face (DRAW_MOUSE_FACE);
2819 /* Look for a `help-echo' property. */
2821 Lisp_Object help;
2822 extern Lisp_Object Qhelp_echo;
2824 /* Check overlays first. */
2825 help = Qnil;
2826 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
2828 overlay = overlay_vec[i];
2829 help = Foverlay_get (overlay, Qhelp_echo);
2832 if (!NILP (help))
2834 help_echo_string = help;
2835 help_echo_window = window;
2836 help_echo_object = overlay;
2837 help_echo_pos = pos;
2839 /* Try text properties. */
2840 else if (NILP (help)
2841 && ((STRINGP (glyph->object)
2842 && glyph->charpos >= 0
2843 && glyph->charpos < SCHARS (glyph->object))
2844 || (BUFFERP (glyph->object)
2845 && glyph->charpos >= BEGV
2846 && glyph->charpos < ZV)))
2848 help = Fget_text_property (make_number (glyph->charpos),
2849 Qhelp_echo, glyph->object);
2850 if (!NILP (help))
2852 help_echo_string = help;
2853 help_echo_window = window;
2854 help_echo_object = glyph->object;
2855 help_echo_pos = glyph->charpos;
2860 BEGV = obegv;
2861 ZV = ozv;
2862 current_buffer = obuf;
2867 static int
2868 term_mouse_movement (FRAME_PTR frame, Gpm_Event *event)
2870 /* Has the mouse moved off the glyph it was on at the last sighting? */
2871 if (event->x != last_mouse_x || event->y != last_mouse_y)
2873 frame->mouse_moved = 1;
2874 term_mouse_highlight (frame, event->x, event->y);
2875 /* Remember which glyph we're now on. */
2876 last_mouse_x = event->x;
2877 last_mouse_y = event->y;
2878 return 1;
2880 return 0;
2883 /* Return the current position of the mouse.
2885 Set *f to the frame the mouse is in, or zero if the mouse is in no
2886 Emacs frame. If it is set to zero, all the other arguments are
2887 garbage.
2889 Set *bar_window to Qnil, and *x and *y to the column and
2890 row of the character cell the mouse is over.
2892 Set *time to the time the mouse was at the returned position.
2894 This clears mouse_moved until the next motion
2895 event arrives. */
2896 static void
2897 term_mouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
2898 enum scroll_bar_part *part, Lisp_Object *x,
2899 Lisp_Object *y, unsigned long *time)
2901 struct timeval now;
2903 *fp = SELECTED_FRAME ();
2904 (*fp)->mouse_moved = 0;
2906 *bar_window = Qnil;
2907 *part = 0;
2909 XSETINT (*x, last_mouse_x);
2910 XSETINT (*y, last_mouse_y);
2911 gettimeofday(&now, 0);
2912 *time = (now.tv_sec * 1000) + (now.tv_usec / 1000);
2915 /* Prepare a mouse-event in *RESULT for placement in the input queue.
2917 If the event is a button press, then note that we have grabbed
2918 the mouse. */
2920 static Lisp_Object
2921 term_mouse_click (struct input_event *result, Gpm_Event *event,
2922 struct frame *f)
2924 struct timeval now;
2925 int i, j;
2927 result->kind = GPM_CLICK_EVENT;
2928 for (i = 0, j = GPM_B_LEFT; i < 3; i++, j >>= 1 )
2930 if (event->buttons & j) {
2931 result->code = i; /* button number */
2932 break;
2935 gettimeofday(&now, 0);
2936 result->timestamp = (now.tv_sec * 1000) + (now.tv_usec / 1000);
2938 if (event->type & GPM_UP)
2939 result->modifiers = up_modifier;
2940 else if (event->type & GPM_DOWN)
2941 result->modifiers = down_modifier;
2942 else
2943 result->modifiers = 0;
2945 if (event->type & GPM_SINGLE)
2946 result->modifiers |= click_modifier;
2948 if (event->type & GPM_DOUBLE)
2949 result->modifiers |= double_modifier;
2951 if (event->type & GPM_TRIPLE)
2952 result->modifiers |= triple_modifier;
2954 if (event->type & GPM_DRAG)
2955 result->modifiers |= drag_modifier;
2957 if (!(event->type & (GPM_MOVE | GPM_DRAG))) {
2959 /* 1 << KG_SHIFT */
2960 if (event->modifiers & (1 << 0))
2961 result->modifiers |= shift_modifier;
2963 /* 1 << KG_CTRL */
2964 if (event->modifiers & (1 << 2))
2965 result->modifiers |= ctrl_modifier;
2967 /* 1 << KG_ALT || KG_ALTGR */
2968 if (event->modifiers & (1 << 3)
2969 || event->modifiers & (1 << 1))
2970 result->modifiers |= meta_modifier;
2973 XSETINT (result->x, event->x);
2974 XSETINT (result->y, event->y);
2975 XSETFRAME (result->frame_or_window, f);
2976 result->arg = Qnil;
2977 return Qnil;
2981 handle_one_term_event (struct tty_display_info *tty, Gpm_Event *event, struct input_event* hold_quit)
2983 struct frame *f = XFRAME (tty->top_frame);
2984 struct input_event ie;
2985 int do_help = 0;
2986 int count = 0;
2988 EVENT_INIT (ie);
2989 ie.kind = NO_EVENT;
2990 ie.arg = Qnil;
2992 if (event->type & (GPM_MOVE | GPM_DRAG)) {
2993 previous_help_echo_string = help_echo_string;
2994 help_echo_string = Qnil;
2996 Gpm_DrawPointer (event->x, event->y, fileno (tty->output));
2998 if (!term_mouse_movement (f, event))
2999 help_echo_string = previous_help_echo_string;
3001 /* If the contents of the global variable help_echo_string
3002 has changed, generate a HELP_EVENT. */
3003 if (!NILP (help_echo_string)
3004 || !NILP (previous_help_echo_string))
3005 do_help = 1;
3007 goto done;
3009 else {
3010 f->mouse_moved = 0;
3011 term_mouse_click (&ie, event, f);
3014 done:
3015 if (ie.kind != NO_EVENT)
3017 kbd_buffer_store_event_hold (&ie, hold_quit);
3018 count++;
3021 if (do_help
3022 && !(hold_quit && hold_quit->kind != NO_EVENT))
3024 Lisp_Object frame;
3026 if (f)
3027 XSETFRAME (frame, f);
3028 else
3029 frame = Qnil;
3031 gen_help_event (help_echo_string, frame, help_echo_window,
3032 help_echo_object, help_echo_pos);
3033 count++;
3036 return count;
3039 DEFUN ("gpm-mouse-start", Fgpm_mouse_start, Sgpm_mouse_start,
3040 0, 0, 0,
3041 doc: /* Open a connection to Gpm.
3042 Gpm-mouse can only be activated for one tty at a time. */)
3045 struct frame *f = SELECTED_FRAME ();
3046 struct tty_display_info *tty
3047 = ((f)->output_method == output_termcap
3048 ? (f)->terminal->display_info.tty : NULL);
3049 Gpm_Connect connection;
3051 if (!tty)
3052 error ("Gpm-mouse only works in the GNU/Linux console");
3053 if (gpm_tty == tty)
3054 return Qnil; /* Already activated, nothing to do. */
3055 if (gpm_tty)
3056 error ("Gpm-mouse can only be activated for one tty at a time");
3058 connection.eventMask = ~0;
3059 connection.defaultMask = ~GPM_HARD;
3060 connection.maxMod = ~0;
3061 connection.minMod = 0;
3062 gpm_zerobased = 1;
3064 if (Gpm_Open (&connection, 0) < 0)
3065 error ("Gpm-mouse failed to connect to the gpm daemon");
3066 else
3068 gpm_tty = tty;
3069 /* `init_sys_modes' arranges for mouse movements sent through gpm_fd
3070 to generate SIGIOs. Apparently we need to call reset_sys_modes
3071 before calling init_sys_modes. */
3072 reset_sys_modes (tty);
3073 init_sys_modes (tty);
3074 add_gpm_wait_descriptor (gpm_fd);
3075 return Qnil;
3079 DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop, Sgpm_mouse_stop,
3080 0, 0, 0,
3081 doc: /* Close a connection to Gpm. */)
3084 struct frame *f = SELECTED_FRAME ();
3085 struct tty_display_info *tty
3086 = ((f)->output_method == output_termcap
3087 ? (f)->terminal->display_info.tty : NULL);
3089 if (!tty || gpm_tty != tty)
3090 return Qnil; /* Not activated on this terminal, nothing to do. */
3092 if (gpm_fd >= 0)
3093 delete_gpm_wait_descriptor (gpm_fd);
3094 while (Gpm_Close()); /* close all the stack */
3095 gpm_tty = NULL;
3096 return Qnil;
3098 #endif /* HAVE_GPM */
3101 /***********************************************************************
3102 Initialization
3103 ***********************************************************************/
3105 /* Initialize the tty-dependent part of frame F. The frame must
3106 already have its device initialized. */
3108 void
3109 create_tty_output (struct frame *f)
3111 struct tty_output *t;
3113 if (! FRAME_TERMCAP_P (f))
3114 abort ();
3116 t = xmalloc (sizeof (struct tty_output));
3117 bzero (t, sizeof (struct tty_output));
3119 t->display_info = FRAME_TERMINAL (f)->display_info.tty;
3121 f->output_data.tty = t;
3124 /* Delete the tty-dependent part of frame F. */
3126 static void
3127 delete_tty_output (struct frame *f)
3129 if (! FRAME_TERMCAP_P (f))
3130 abort ();
3132 xfree (f->output_data.tty);
3136 /* Reset the hooks in TERMINAL. */
3138 static void
3139 clear_tty_hooks (struct terminal *terminal)
3141 terminal->rif = 0;
3142 terminal->cursor_to_hook = 0;
3143 terminal->raw_cursor_to_hook = 0;
3144 terminal->clear_to_end_hook = 0;
3145 terminal->clear_frame_hook = 0;
3146 terminal->clear_end_of_line_hook = 0;
3147 terminal->ins_del_lines_hook = 0;
3148 terminal->insert_glyphs_hook = 0;
3149 terminal->write_glyphs_hook = 0;
3150 terminal->delete_glyphs_hook = 0;
3151 terminal->ring_bell_hook = 0;
3152 terminal->reset_terminal_modes_hook = 0;
3153 terminal->set_terminal_modes_hook = 0;
3154 terminal->update_begin_hook = 0;
3155 terminal->update_end_hook = 0;
3156 terminal->set_terminal_window_hook = 0;
3157 terminal->mouse_position_hook = 0;
3158 terminal->frame_rehighlight_hook = 0;
3159 terminal->frame_raise_lower_hook = 0;
3160 terminal->fullscreen_hook = 0;
3161 terminal->set_vertical_scroll_bar_hook = 0;
3162 terminal->condemn_scroll_bars_hook = 0;
3163 terminal->redeem_scroll_bar_hook = 0;
3164 terminal->judge_scroll_bars_hook = 0;
3165 terminal->read_socket_hook = 0;
3166 terminal->frame_up_to_date_hook = 0;
3168 /* Leave these two set, or suspended frames are not deleted
3169 correctly. */
3170 terminal->delete_frame_hook = &delete_tty_output;
3171 terminal->delete_terminal_hook = &delete_tty;
3174 /* Initialize hooks in TERMINAL with the values needed for a tty. */
3176 static void
3177 set_tty_hooks (struct terminal *terminal)
3179 terminal->rif = 0; /* ttys don't support window-based redisplay. */
3181 terminal->cursor_to_hook = &tty_cursor_to;
3182 terminal->raw_cursor_to_hook = &tty_raw_cursor_to;
3184 terminal->clear_to_end_hook = &tty_clear_to_end;
3185 terminal->clear_frame_hook = &tty_clear_frame;
3186 terminal->clear_end_of_line_hook = &tty_clear_end_of_line;
3188 terminal->ins_del_lines_hook = &tty_ins_del_lines;
3190 terminal->insert_glyphs_hook = &tty_insert_glyphs;
3191 terminal->write_glyphs_hook = &tty_write_glyphs;
3192 terminal->delete_glyphs_hook = &tty_delete_glyphs;
3194 terminal->ring_bell_hook = &tty_ring_bell;
3196 terminal->reset_terminal_modes_hook = &tty_reset_terminal_modes;
3197 terminal->set_terminal_modes_hook = &tty_set_terminal_modes;
3198 terminal->update_begin_hook = 0; /* Not needed. */
3199 terminal->update_end_hook = &tty_update_end;
3200 terminal->set_terminal_window_hook = &tty_set_terminal_window;
3202 terminal->mouse_position_hook = 0; /* Not needed. */
3203 terminal->frame_rehighlight_hook = 0; /* Not needed. */
3204 terminal->frame_raise_lower_hook = 0; /* Not needed. */
3206 terminal->set_vertical_scroll_bar_hook = 0; /* Not needed. */
3207 terminal->condemn_scroll_bars_hook = 0; /* Not needed. */
3208 terminal->redeem_scroll_bar_hook = 0; /* Not needed. */
3209 terminal->judge_scroll_bars_hook = 0; /* Not needed. */
3211 terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */
3212 terminal->frame_up_to_date_hook = 0; /* Not needed. */
3214 terminal->delete_frame_hook = &delete_tty_output;
3215 terminal->delete_terminal_hook = &delete_tty;
3218 /* Drop the controlling terminal if fd is the same device. */
3219 static void
3220 dissociate_if_controlling_tty (int fd)
3222 #ifndef WINDOWSNT
3223 int pgid;
3224 EMACS_GET_TTY_PGRP (fd, &pgid); /* If tcgetpgrp succeeds, fd is the ctty. */
3225 if (pgid != -1)
3227 #if defined (USG) && !defined (BSD_PGRPS)
3228 setpgrp ();
3229 no_controlling_tty = 1;
3230 #elif defined (CYGWIN)
3231 setsid ();
3232 no_controlling_tty = 1;
3233 #else
3234 #ifdef TIOCNOTTY /* Try BSD ioctls. */
3235 sigblock (sigmask (SIGTTOU));
3236 fd = emacs_open (DEV_TTY, O_RDWR, 0);
3237 if (fd != -1 && ioctl (fd, TIOCNOTTY, 0) != -1)
3239 no_controlling_tty = 1;
3241 if (fd != -1)
3242 emacs_close (fd);
3243 sigunblock (sigmask (SIGTTOU));
3244 #else
3245 /* Unknown system. */
3246 croak ();
3247 #endif /* ! TIOCNOTTY */
3248 #endif /* ! USG */
3250 #endif /* !WINDOWSNT */
3253 static void maybe_fatal();
3255 /* Create a termcap display on the tty device with the given name and
3256 type.
3258 If NAME is NULL, then use the controlling tty, i.e., "/dev/tty".
3259 Otherwise NAME should be a path to the tty device file,
3260 e.g. "/dev/pts/7".
3262 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
3264 If MUST_SUCCEED is true, then all errors are fatal. */
3266 struct terminal *
3267 init_tty (char *name, char *terminal_type, int must_succeed)
3269 char *area = NULL;
3270 char **address = &area;
3271 char *buffer = NULL;
3272 int buffer_size = 4096;
3273 register char *p = NULL;
3274 int status;
3275 struct tty_display_info *tty = NULL;
3276 struct terminal *terminal = NULL;
3277 int ctty = 0; /* 1 if asked to open controlling tty. */
3279 if (!terminal_type)
3280 maybe_fatal (must_succeed, 0, 0,
3281 "Unknown terminal type",
3282 "Unknown terminal type");
3284 if (name == NULL)
3285 name = DEV_TTY;
3286 if (!strcmp (name, DEV_TTY))
3287 ctty = 1;
3289 /* If we already have a terminal on the given device, use that. If
3290 all such terminals are suspended, create a new one instead. */
3291 /* XXX Perhaps this should be made explicit by having init_tty
3292 always create a new terminal and separating terminal and frame
3293 creation on Lisp level. */
3294 terminal = get_named_tty (name);
3295 if (terminal)
3296 return terminal;
3298 terminal = create_terminal ();
3299 tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info));
3300 bzero (tty, sizeof (struct tty_display_info));
3301 tty->next = tty_list;
3302 tty_list = tty;
3304 terminal->type = output_termcap;
3305 terminal->display_info.tty = tty;
3306 tty->terminal = terminal;
3308 tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
3309 Wcm_clear (tty);
3311 #ifndef WINDOWSNT
3312 set_tty_hooks (terminal);
3315 int fd;
3316 FILE *file;
3318 #ifdef O_IGNORE_CTTY
3319 if (!ctty)
3320 /* Open the terminal device. Don't recognize it as our
3321 controlling terminal, and don't make it the controlling tty
3322 if we don't have one at the moment. */
3323 fd = emacs_open (name, O_RDWR | O_IGNORE_CTTY | O_NOCTTY, 0);
3324 else
3325 #else
3326 /* Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
3327 defined on Hurd. On other systems, we need to explicitly
3328 dissociate ourselves from the controlling tty when we want to
3329 open a frame on the same terminal. */
3330 fd = emacs_open (name, O_RDWR | O_NOCTTY, 0);
3331 #endif /* O_IGNORE_CTTY */
3333 if (fd < 0)
3334 maybe_fatal (must_succeed, buffer, terminal,
3335 "Could not open file: %s",
3336 "Could not open file: %s",
3337 name);
3338 if (!isatty (fd))
3340 close (fd);
3341 maybe_fatal (must_succeed, buffer, terminal,
3342 "Not a tty device: %s",
3343 "Not a tty device: %s",
3344 name);
3347 #ifndef O_IGNORE_CTTY
3348 if (!ctty)
3349 dissociate_if_controlling_tty (fd);
3350 #endif
3352 file = fdopen (fd, "w+");
3353 tty->name = xstrdup (name);
3354 terminal->name = xstrdup (name);
3355 tty->input = file;
3356 tty->output = file;
3359 tty->type = xstrdup (terminal_type);
3361 add_keyboard_wait_descriptor (fileno (tty->input));
3363 #endif
3365 encode_terminal_src_size = 0;
3366 encode_terminal_dst_size = 0;
3368 #ifdef HAVE_GPM
3369 terminal->mouse_position_hook = term_mouse_position;
3370 mouse_face_window = Qnil;
3371 #endif
3373 #ifdef WINDOWSNT
3374 initialize_w32_display (terminal);
3375 /* The following two are inaccessible from w32console.c. */
3376 terminal->delete_frame_hook = &delete_tty_output;
3377 terminal->delete_terminal_hook = &delete_tty;
3379 tty->name = xstrdup (name);
3380 terminal->name = xstrdup (name);
3381 tty->type = xstrdup (terminal_type);
3383 tty->output = stdout;
3384 tty->input = stdin;
3385 add_keyboard_wait_descriptor (0);
3387 Wcm_clear (tty);
3390 struct frame *f = XFRAME (selected_frame);
3392 FrameRows (tty) = FRAME_LINES (f);
3393 FrameCols (tty) = FRAME_COLS (f);
3394 tty->specified_window = FRAME_LINES (f);
3396 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
3397 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
3399 tty->delete_in_insert_mode = 1;
3401 UseTabs (tty) = 0;
3402 terminal->scroll_region_ok = 0;
3404 /* Seems to insert lines when it's not supposed to, messing up the
3405 display. In doing a trace, it didn't seem to be called much, so I
3406 don't think we're losing anything by turning it off. */
3407 terminal->line_ins_del_ok = 0;
3408 terminal->char_ins_del_ok = 1;
3410 baud_rate = 19200;
3412 tty->TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
3414 #else /* not WINDOWSNT */
3416 Wcm_clear (tty);
3418 buffer = (char *) xmalloc (buffer_size);
3420 /* On some systems, tgetent tries to access the controlling
3421 terminal. */
3422 sigblock (sigmask (SIGTTOU));
3423 status = tgetent (buffer, terminal_type);
3424 sigunblock (sigmask (SIGTTOU));
3426 if (status < 0)
3428 #ifdef TERMINFO
3429 maybe_fatal (must_succeed, buffer, terminal,
3430 "Cannot open terminfo database file",
3431 "Cannot open terminfo database file");
3432 #else
3433 maybe_fatal (must_succeed, buffer, terminal,
3434 "Cannot open termcap database file",
3435 "Cannot open termcap database file");
3436 #endif
3438 if (status == 0)
3440 #ifdef TERMINFO
3441 maybe_fatal (must_succeed, buffer, terminal,
3442 "Terminal type %s is not defined",
3443 "Terminal type %s is not defined.\n\
3444 If that is not the actual type of terminal you have,\n\
3445 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3446 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3447 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3448 terminal_type);
3449 #else
3450 maybe_fatal (must_succeed, buffer, terminal,
3451 "Terminal type %s is not defined",
3452 "Terminal type %s is not defined.\n\
3453 If that is not the actual type of terminal you have,\n\
3454 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3455 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3456 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3457 terminal_type);
3458 #endif
3461 #ifndef TERMINFO
3462 if (strlen (buffer) >= buffer_size)
3463 abort ();
3464 buffer_size = strlen (buffer);
3465 #endif
3466 area = (char *) xmalloc (buffer_size);
3468 tty->TS_ins_line = tgetstr ("al", address);
3469 tty->TS_ins_multi_lines = tgetstr ("AL", address);
3470 tty->TS_bell = tgetstr ("bl", address);
3471 BackTab (tty) = tgetstr ("bt", address);
3472 tty->TS_clr_to_bottom = tgetstr ("cd", address);
3473 tty->TS_clr_line = tgetstr ("ce", address);
3474 tty->TS_clr_frame = tgetstr ("cl", address);
3475 ColPosition (tty) = NULL; /* tgetstr ("ch", address); */
3476 AbsPosition (tty) = tgetstr ("cm", address);
3477 CR (tty) = tgetstr ("cr", address);
3478 tty->TS_set_scroll_region = tgetstr ("cs", address);
3479 tty->TS_set_scroll_region_1 = tgetstr ("cS", address);
3480 RowPosition (tty) = tgetstr ("cv", address);
3481 tty->TS_del_char = tgetstr ("dc", address);
3482 tty->TS_del_multi_chars = tgetstr ("DC", address);
3483 tty->TS_del_line = tgetstr ("dl", address);
3484 tty->TS_del_multi_lines = tgetstr ("DL", address);
3485 tty->TS_delete_mode = tgetstr ("dm", address);
3486 tty->TS_end_delete_mode = tgetstr ("ed", address);
3487 tty->TS_end_insert_mode = tgetstr ("ei", address);
3488 Home (tty) = tgetstr ("ho", address);
3489 tty->TS_ins_char = tgetstr ("ic", address);
3490 tty->TS_ins_multi_chars = tgetstr ("IC", address);
3491 tty->TS_insert_mode = tgetstr ("im", address);
3492 tty->TS_pad_inserted_char = tgetstr ("ip", address);
3493 tty->TS_end_keypad_mode = tgetstr ("ke", address);
3494 tty->TS_keypad_mode = tgetstr ("ks", address);
3495 LastLine (tty) = tgetstr ("ll", address);
3496 Right (tty) = tgetstr ("nd", address);
3497 Down (tty) = tgetstr ("do", address);
3498 if (!Down (tty))
3499 Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do" */
3500 #ifdef VMS
3501 /* VMS puts a carriage return before each linefeed,
3502 so it is not safe to use linefeeds. */
3503 if (Down (tty) && Down (tty)[0] == '\n' && Down (tty)[1] == '\0')
3504 Down (tty) = 0;
3505 #endif /* VMS */
3506 if (tgetflag ("bs"))
3507 Left (tty) = "\b"; /* can't possibly be longer! */
3508 else /* (Actually, "bs" is obsolete...) */
3509 Left (tty) = tgetstr ("le", address);
3510 if (!Left (tty))
3511 Left (tty) = tgetstr ("bc", address); /* Obsolete name for "le" */
3512 tty->TS_pad_char = tgetstr ("pc", address);
3513 tty->TS_repeat = tgetstr ("rp", address);
3514 tty->TS_end_standout_mode = tgetstr ("se", address);
3515 tty->TS_fwd_scroll = tgetstr ("sf", address);
3516 tty->TS_standout_mode = tgetstr ("so", address);
3517 tty->TS_rev_scroll = tgetstr ("sr", address);
3518 tty->Wcm->cm_tab = tgetstr ("ta", address);
3519 tty->TS_end_termcap_modes = tgetstr ("te", address);
3520 tty->TS_termcap_modes = tgetstr ("ti", address);
3521 Up (tty) = tgetstr ("up", address);
3522 tty->TS_visible_bell = tgetstr ("vb", address);
3523 tty->TS_cursor_normal = tgetstr ("ve", address);
3524 tty->TS_cursor_visible = tgetstr ("vs", address);
3525 tty->TS_cursor_invisible = tgetstr ("vi", address);
3526 tty->TS_set_window = tgetstr ("wi", address);
3528 tty->TS_enter_underline_mode = tgetstr ("us", address);
3529 tty->TS_exit_underline_mode = tgetstr ("ue", address);
3530 tty->TS_enter_bold_mode = tgetstr ("md", address);
3531 tty->TS_enter_dim_mode = tgetstr ("mh", address);
3532 tty->TS_enter_blink_mode = tgetstr ("mb", address);
3533 tty->TS_enter_reverse_mode = tgetstr ("mr", address);
3534 tty->TS_enter_alt_charset_mode = tgetstr ("as", address);
3535 tty->TS_exit_alt_charset_mode = tgetstr ("ae", address);
3536 tty->TS_exit_attribute_mode = tgetstr ("me", address);
3538 MultiUp (tty) = tgetstr ("UP", address);
3539 MultiDown (tty) = tgetstr ("DO", address);
3540 MultiLeft (tty) = tgetstr ("LE", address);
3541 MultiRight (tty) = tgetstr ("RI", address);
3543 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
3544 color because we can't switch back to the default foreground and
3545 background. */
3546 tty->TS_orig_pair = tgetstr ("op", address);
3547 if (tty->TS_orig_pair)
3549 tty->TS_set_foreground = tgetstr ("AF", address);
3550 tty->TS_set_background = tgetstr ("AB", address);
3551 if (!tty->TS_set_foreground)
3553 /* SVr4. */
3554 tty->TS_set_foreground = tgetstr ("Sf", address);
3555 tty->TS_set_background = tgetstr ("Sb", address);
3558 tty->TN_max_colors = tgetnum ("Co");
3559 tty->TN_max_pairs = tgetnum ("pa");
3561 tty->TN_no_color_video = tgetnum ("NC");
3562 if (tty->TN_no_color_video == -1)
3563 tty->TN_no_color_video = 0;
3566 tty_default_color_capabilities (tty, 1);
3568 MagicWrap (tty) = tgetflag ("xn");
3569 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
3570 the former flag imply the latter. */
3571 AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
3572 terminal->memory_below_frame = tgetflag ("db");
3573 tty->TF_hazeltine = tgetflag ("hz");
3574 terminal->must_write_spaces = tgetflag ("in");
3575 tty->meta_key = tgetflag ("km") || tgetflag ("MT");
3576 tty->TF_insmode_motion = tgetflag ("mi");
3577 tty->TF_standout_motion = tgetflag ("ms");
3578 tty->TF_underscore = tgetflag ("ul");
3579 tty->TF_teleray = tgetflag ("xt");
3581 #endif /* !WINDOWSNT */
3582 #ifdef MULTI_KBOARD
3583 terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
3584 init_kboard (terminal->kboard);
3585 terminal->kboard->Vwindow_system = Qnil;
3586 terminal->kboard->next_kboard = all_kboards;
3587 all_kboards = terminal->kboard;
3588 terminal->kboard->reference_count++;
3589 /* Don't let the initial kboard remain current longer than necessary.
3590 That would cause problems if a file loaded on startup tries to
3591 prompt in the mini-buffer. */
3592 if (current_kboard == initial_kboard)
3593 current_kboard = terminal->kboard;
3594 #ifndef WINDOWSNT
3595 term_get_fkeys (address, terminal->kboard);
3596 #endif
3597 #endif
3599 #ifndef WINDOWSNT
3600 /* Get frame size from system, or else from termcap. */
3602 int height, width;
3603 get_tty_size (fileno (tty->input), &width, &height);
3604 FrameCols (tty) = width;
3605 FrameRows (tty) = height;
3608 if (FrameCols (tty) <= 0)
3609 FrameCols (tty) = tgetnum ("co");
3610 if (FrameRows (tty) <= 0)
3611 FrameRows (tty) = tgetnum ("li");
3613 if (FrameRows (tty) < 3 || FrameCols (tty) < 3)
3614 maybe_fatal (must_succeed, NULL, terminal,
3615 "Screen size %dx%d is too small"
3616 "Screen size %dx%d is too small",
3617 FrameCols (tty), FrameRows (tty));
3619 #if 0 /* This is not used anywhere. */
3620 tty->terminal->min_padding_speed = tgetnum ("pb");
3621 #endif
3623 TabWidth (tty) = tgetnum ("tw");
3625 #ifdef VMS
3626 /* These capabilities commonly use ^J.
3627 I don't know why, but sending them on VMS does not work;
3628 it causes following spaces to be lost, sometimes.
3629 For now, the simplest fix is to avoid using these capabilities ever. */
3630 if (Down (tty) && Down (tty)[0] == '\n')
3631 Down (tty) = 0;
3632 #endif /* VMS */
3634 if (!tty->TS_bell)
3635 tty->TS_bell = "\07";
3637 if (!tty->TS_fwd_scroll)
3638 tty->TS_fwd_scroll = Down (tty);
3640 PC = tty->TS_pad_char ? *tty->TS_pad_char : 0;
3642 if (TabWidth (tty) < 0)
3643 TabWidth (tty) = 8;
3645 /* Turned off since /etc/termcap seems to have :ta= for most terminals
3646 and newer termcap doc does not seem to say there is a default.
3647 if (!tty->Wcm->cm_tab)
3648 tty->Wcm->cm_tab = "\t";
3651 /* We don't support standout modes that use `magic cookies', so
3652 turn off any that do. */
3653 if (tty->TS_standout_mode && tgetnum ("sg") >= 0)
3655 tty->TS_standout_mode = 0;
3656 tty->TS_end_standout_mode = 0;
3658 if (tty->TS_enter_underline_mode && tgetnum ("ug") >= 0)
3660 tty->TS_enter_underline_mode = 0;
3661 tty->TS_exit_underline_mode = 0;
3664 /* If there's no standout mode, try to use underlining instead. */
3665 if (tty->TS_standout_mode == 0)
3667 tty->TS_standout_mode = tty->TS_enter_underline_mode;
3668 tty->TS_end_standout_mode = tty->TS_exit_underline_mode;
3671 /* If no `se' string, try using a `me' string instead.
3672 If that fails, we can't use standout mode at all. */
3673 if (tty->TS_end_standout_mode == 0)
3675 char *s = tgetstr ("me", address);
3676 if (s != 0)
3677 tty->TS_end_standout_mode = s;
3678 else
3679 tty->TS_standout_mode = 0;
3682 if (tty->TF_teleray)
3684 tty->Wcm->cm_tab = 0;
3685 /* We can't support standout mode, because it uses magic cookies. */
3686 tty->TS_standout_mode = 0;
3687 /* But that means we cannot rely on ^M to go to column zero! */
3688 CR (tty) = 0;
3689 /* LF can't be trusted either -- can alter hpos */
3690 /* if move at column 0 thru a line with TS_standout_mode */
3691 Down (tty) = 0;
3694 /* Special handling for certain terminal types known to need it */
3696 if (!strcmp (terminal_type, "supdup"))
3698 terminal->memory_below_frame = 1;
3699 tty->Wcm->cm_losewrap = 1;
3701 if (!strncmp (terminal_type, "c10", 3)
3702 || !strcmp (terminal_type, "perq"))
3704 /* Supply a makeshift :wi string.
3705 This string is not valid in general since it works only
3706 for windows starting at the upper left corner;
3707 but that is all Emacs uses.
3709 This string works only if the frame is using
3710 the top of the video memory, because addressing is memory-relative.
3711 So first check the :ti string to see if that is true.
3713 It would be simpler if the :wi string could go in the termcap
3714 entry, but it can't because it is not fully valid.
3715 If it were in the termcap entry, it would confuse other programs. */
3716 if (!tty->TS_set_window)
3718 p = tty->TS_termcap_modes;
3719 while (*p && strcmp (p, "\033v "))
3720 p++;
3721 if (*p)
3722 tty->TS_set_window = "\033v%C %C %C %C ";
3724 /* Termcap entry often fails to have :in: flag */
3725 terminal->must_write_spaces = 1;
3726 /* :ti string typically fails to have \E^G! in it */
3727 /* This limits scope of insert-char to one line. */
3728 strcpy (area, tty->TS_termcap_modes);
3729 strcat (area, "\033\007!");
3730 tty->TS_termcap_modes = area;
3731 area += strlen (area) + 1;
3732 p = AbsPosition (tty);
3733 /* Change all %+ parameters to %C, to handle
3734 values above 96 correctly for the C100. */
3735 while (*p)
3737 if (p[0] == '%' && p[1] == '+')
3738 p[1] = 'C';
3739 p++;
3743 tty->specified_window = FrameRows (tty);
3745 if (Wcm_init (tty) == -1) /* can't do cursor motion */
3747 maybe_fatal (must_succeed, NULL, terminal,
3748 "Terminal type \"%s\" is not powerful enough to run Emacs",
3749 #ifdef VMS
3750 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3751 It lacks the ability to position the cursor.\n\
3752 If that is not the actual type of terminal you have, use either the\n\
3753 DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
3754 or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
3755 #else /* not VMS */
3756 # ifdef TERMINFO
3757 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3758 It lacks the ability to position the cursor.\n\
3759 If that is not the actual type of terminal you have,\n\
3760 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3761 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3762 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3763 # else /* TERMCAP */
3764 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3765 It lacks the ability to position the cursor.\n\
3766 If that is not the actual type of terminal you have,\n\
3767 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3768 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3769 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3770 # endif /* TERMINFO */
3771 #endif /*VMS */
3772 terminal_type);
3775 if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
3776 maybe_fatal (must_succeed, NULL, terminal,
3777 "Could not determine the frame size",
3778 "Could not determine the frame size");
3780 tty->delete_in_insert_mode
3781 = tty->TS_delete_mode && tty->TS_insert_mode
3782 && !strcmp (tty->TS_delete_mode, tty->TS_insert_mode);
3784 tty->se_is_so = (tty->TS_standout_mode
3785 && tty->TS_end_standout_mode
3786 && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode));
3788 UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8;
3790 terminal->scroll_region_ok
3791 = (tty->Wcm->cm_abs
3792 && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
3794 terminal->line_ins_del_ok
3795 = (((tty->TS_ins_line || tty->TS_ins_multi_lines)
3796 && (tty->TS_del_line || tty->TS_del_multi_lines))
3797 || (terminal->scroll_region_ok
3798 && tty->TS_fwd_scroll && tty->TS_rev_scroll));
3800 terminal->char_ins_del_ok
3801 = ((tty->TS_ins_char || tty->TS_insert_mode
3802 || tty->TS_pad_inserted_char || tty->TS_ins_multi_chars)
3803 && (tty->TS_del_char || tty->TS_del_multi_chars));
3805 terminal->fast_clear_end_of_line = tty->TS_clr_line != 0;
3807 init_baud_rate (fileno (tty->input));
3809 #ifdef AIXHFT
3810 /* The HFT system on AIX doesn't optimize for scrolling, so it's
3811 really ugly at times. */
3812 terminal->line_ins_del_ok = 0;
3813 terminal->char_ins_del_ok = 0;
3814 #endif
3816 /* Don't do this. I think termcap may still need the buffer. */
3817 /* xfree (buffer); */
3819 #endif /* not WINDOWSNT */
3821 /* Init system terminal modes (RAW or CBREAK, etc.). */
3822 init_sys_modes (tty);
3824 return terminal;
3827 /* Auxiliary error-handling function for init_tty.
3828 Free BUFFER and delete TERMINAL, then call error or fatal
3829 with str1 or str2, respectively, according to MUST_SUCCEED. */
3831 static void
3832 maybe_fatal (must_succeed, buffer, terminal, str1, str2, arg1, arg2)
3833 int must_succeed;
3834 char *buffer;
3835 struct terminal *terminal;
3836 char *str1, *str2, *arg1, *arg2;
3838 if (buffer)
3839 xfree (buffer);
3841 if (terminal)
3842 delete_tty (terminal);
3844 if (must_succeed)
3845 fatal (str2, arg1, arg2);
3846 else
3847 error (str1, arg1, arg2);
3849 abort ();
3852 void
3853 fatal (const char *str, ...)
3855 va_list ap;
3856 va_start (ap, str);
3857 fprintf (stderr, "emacs: ");
3858 vfprintf (stderr, str, ap);
3859 va_end (ap);
3860 fflush (stderr);
3861 exit (1);
3866 /* Delete the given tty terminal, closing all frames on it. */
3868 static void
3869 delete_tty (struct terminal *terminal)
3871 struct tty_display_info *tty;
3872 Lisp_Object tail, frame;
3873 int last_terminal;
3875 /* Protect against recursive calls. Fdelete_frame in
3876 delete_terminal calls us back when it deletes our last frame. */
3877 if (!terminal->name)
3878 return;
3880 if (terminal->type != output_termcap)
3881 abort ();
3883 tty = terminal->display_info.tty;
3885 last_terminal = 1;
3886 FOR_EACH_FRAME (tail, frame)
3888 struct frame *f = XFRAME (frame);
3889 if (FRAME_LIVE_P (f) && (!FRAME_TERMCAP_P (f) || FRAME_TTY (f) != tty))
3891 last_terminal = 0;
3892 break;
3895 if (last_terminal)
3896 error ("Attempt to delete the sole terminal device with live frames");
3898 if (tty == tty_list)
3899 tty_list = tty->next;
3900 else
3902 struct tty_display_info *p;
3903 for (p = tty_list; p && p->next != tty; p = p->next)
3906 if (! p)
3907 /* This should not happen. */
3908 abort ();
3910 p->next = tty->next;
3911 tty->next = 0;
3914 /* reset_sys_modes needs a valid device, so this call needs to be
3915 before delete_terminal. */
3916 reset_sys_modes (tty);
3918 delete_terminal (terminal);
3920 if (tty->name)
3921 xfree (tty->name);
3923 if (tty->type)
3924 xfree (tty->type);
3926 if (tty->input)
3928 delete_keyboard_wait_descriptor (fileno (tty->input));
3929 if (tty->input != stdin)
3930 fclose (tty->input);
3932 if (tty->output && tty->output != stdout && tty->output != tty->input)
3933 fclose (tty->output);
3934 if (tty->termscript)
3935 fclose (tty->termscript);
3937 if (tty->old_tty)
3938 xfree (tty->old_tty);
3940 if (tty->Wcm)
3941 xfree (tty->Wcm);
3943 bzero (tty, sizeof (struct tty_display_info));
3944 xfree (tty);
3949 /* Mark the pointers in the tty_display_info objects.
3950 Called by the Fgarbage_collector. */
3952 void
3953 mark_ttys (void)
3955 struct tty_display_info *tty;
3957 for (tty = tty_list; tty; tty = tty->next)
3958 mark_object (tty->top_frame);
3963 void
3964 syms_of_term ()
3966 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
3967 doc: /* Non-nil means the system uses terminfo rather than termcap.
3968 This variable can be used by terminal emulator packages. */);
3969 #ifdef TERMINFO
3970 system_uses_terminfo = 1;
3971 #else
3972 system_uses_terminfo = 0;
3973 #endif
3975 DEFVAR_LISP ("suspend-tty-functions", &Vsuspend_tty_functions,
3976 doc: /* Functions to be run after suspending a tty.
3977 The functions are run with one argument, the terminal id to be suspended.
3978 See `suspend-tty'. */);
3979 Vsuspend_tty_functions = Qnil;
3982 DEFVAR_LISP ("resume-tty-functions", &Vresume_tty_functions,
3983 doc: /* Functions to be run after resuming a tty.
3984 The functions are run with one argument, the terminal id that was revived.
3985 See `resume-tty'. */);
3986 Vresume_tty_functions = Qnil;
3988 DEFVAR_BOOL ("visible-cursor", &visible_cursor,
3989 doc: /* Non-nil means to make the cursor very visible.
3990 This only has an effect when running in a text terminal.
3991 What means \"very visible\" is up to your terminal. It may make the cursor
3992 bigger, or it may make it blink, or it may do nothing at all. */);
3993 visible_cursor = 1;
3995 defsubr (&Stty_display_color_p);
3996 defsubr (&Stty_display_color_cells);
3997 defsubr (&Stty_no_underline);
3998 defsubr (&Stty_type);
3999 defsubr (&Scontrolling_tty_p);
4000 defsubr (&Ssuspend_tty);
4001 defsubr (&Sresume_tty);
4002 #ifdef HAVE_GPM
4003 defsubr (&Sgpm_mouse_start);
4004 defsubr (&Sgpm_mouse_stop);
4006 staticpro (&mouse_face_window);
4007 #endif /* HAVE_GPM */
4012 /* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193
4013 (do not change this comment) */