Merge from trunk
[emacs.git] / src / term.c
blobf090cdd27923ceb1bda02bf55771a577a99366b0
1 /* Terminal control module for terminals described by TERMCAP
2 Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1998, 2000, 2001,
3 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
4 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
21 /* New redisplay, TTY faces by Gerd Moellmann <gerd@gnu.org>. */
23 #include <config.h>
24 #include <stdio.h>
25 #include <ctype.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <sys/file.h>
30 #ifdef HAVE_UNISTD_H
31 #include <unistd.h>
32 #endif
34 #ifdef HAVE_SYS_IOCTL_H
35 #include <sys/ioctl.h>
36 #endif
38 #include <signal.h>
39 #include <stdarg.h>
40 #include <setjmp.h>
42 #include "lisp.h"
43 #include "termchar.h"
44 #include "termopts.h"
45 #include "buffer.h"
46 #include "character.h"
47 #include "charset.h"
48 #include "coding.h"
49 #include "composite.h"
50 #include "keyboard.h"
51 #include "frame.h"
52 #include "disptab.h"
53 #include "termhooks.h"
54 #include "dispextern.h"
55 #include "window.h"
56 #include "keymap.h"
57 #include "blockinput.h"
58 #include "syssignal.h"
59 #include "systty.h"
60 #include "intervals.h"
61 #ifdef MSDOS
62 #include "msdos.h"
63 static int been_here = -1;
64 #endif
66 /* For now, don't try to include termcap.h. On some systems,
67 configure finds a non-standard termcap.h that the main build
68 won't find. */
69 extern void tputs (const char *, int, int (*)(int));
70 extern int tgetent (char *, const char *);
71 extern int tgetflag (char *id);
72 extern int tgetnum (char *id);
74 #include "cm.h"
75 #ifdef HAVE_X_WINDOWS
76 #include "xterm.h"
77 #endif
79 #ifndef O_RDWR
80 #define O_RDWR 2
81 #endif
83 #ifndef O_NOCTTY
84 #define O_NOCTTY 0
85 #endif
87 /* The name of the default console device. */
88 #ifdef WINDOWSNT
89 #define DEV_TTY "CONOUT$"
90 #else
91 #define DEV_TTY "/dev/tty"
92 #endif
94 static void tty_set_scroll_region (struct frame *f, int start, int stop);
95 static void turn_on_face (struct frame *, int face_id);
96 static void turn_off_face (struct frame *, int face_id);
97 static void tty_show_cursor (struct tty_display_info *);
98 static void tty_hide_cursor (struct tty_display_info *);
99 static void tty_background_highlight (struct tty_display_info *tty);
100 static void clear_tty_hooks (struct terminal *terminal);
101 static void set_tty_hooks (struct terminal *terminal);
102 static void dissociate_if_controlling_tty (int fd);
103 static void delete_tty (struct terminal *);
104 static void maybe_fatal (int must_succeed, struct terminal *terminal,
105 const char *str1, const char *str2, ...) NO_RETURN;
106 static void vfatal (const char *str, va_list ap) NO_RETURN;
109 #define OUTPUT(tty, a) \
110 emacs_tputs ((tty), a, \
111 (int) (FRAME_LINES (XFRAME (selected_frame)) \
112 - curY (tty)), \
113 cmputc)
115 #define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
116 #define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
118 #define OUTPUT_IF(tty, a) \
119 do { \
120 if (a) \
121 emacs_tputs ((tty), a, \
122 (int) (FRAME_LINES (XFRAME (selected_frame)) \
123 - curY (tty) ), \
124 cmputc); \
125 } while (0)
127 #define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
129 /* If true, use "vs", otherwise use "ve" to make the cursor visible. */
131 static int visible_cursor;
133 /* Display space properties */
135 /* Functions to call after suspending a tty. */
136 Lisp_Object Vsuspend_tty_functions;
138 /* Functions to call after resuming a tty. */
139 Lisp_Object Vresume_tty_functions;
141 /* Chain of all tty device parameters. */
142 struct tty_display_info *tty_list;
144 /* Nonzero means no need to redraw the entire frame on resuming a
145 suspended Emacs. This is useful on terminals with multiple
146 pages, where one page is used for Emacs and another for all
147 else. */
148 int no_redraw_on_reenter;
150 /* Meaning of bits in no_color_video. Each bit set means that the
151 corresponding attribute cannot be combined with colors. */
153 enum no_color_bit
155 NC_STANDOUT = 1 << 0,
156 NC_UNDERLINE = 1 << 1,
157 NC_REVERSE = 1 << 2,
158 NC_BLINK = 1 << 3,
159 NC_DIM = 1 << 4,
160 NC_BOLD = 1 << 5,
161 NC_INVIS = 1 << 6,
162 NC_PROTECT = 1 << 7,
163 NC_ALT_CHARSET = 1 << 8
166 /* internal state */
168 /* The largest frame width in any call to calculate_costs. */
170 int max_frame_cols;
172 /* The largest frame height in any call to calculate_costs. */
174 int max_frame_lines;
176 /* Non-zero if we have dropped our controlling tty and therefore
177 should not open a frame on stdout. */
178 static int no_controlling_tty;
180 /* Provided for lisp packages. */
182 static int system_uses_terminfo;
184 char *tparam (char *, char *, int, int, ...);
186 extern char *tgetstr (char *, char **);
189 #ifdef HAVE_GPM
190 #include <sys/fcntl.h>
192 static void term_clear_mouse_face (void);
193 static void term_mouse_highlight (struct frame *f, int x, int y);
195 /* The device for which we have enabled gpm support (or NULL). */
196 struct tty_display_info *gpm_tty = NULL;
198 /* These variables describe the range of text currently shown in its
199 mouse-face, together with the window they apply to. As long as
200 the mouse stays within this range, we need not redraw anything on
201 its account. Rows and columns are glyph matrix positions in
202 MOUSE_FACE_WINDOW. */
203 static int mouse_face_beg_row, mouse_face_beg_col;
204 static int mouse_face_end_row, mouse_face_end_col;
205 static int mouse_face_past_end;
206 static Lisp_Object mouse_face_window;
207 static int mouse_face_face_id;
209 static int pos_x, pos_y;
210 static int last_mouse_x, last_mouse_y;
211 #endif /* HAVE_GPM */
213 /* Ring the bell on a tty. */
215 static void
216 tty_ring_bell (struct frame *f)
218 struct tty_display_info *tty = FRAME_TTY (f);
220 if (tty->output)
222 OUTPUT (tty, (tty->TS_visible_bell && visible_bell
223 ? tty->TS_visible_bell
224 : tty->TS_bell));
225 fflush (tty->output);
229 /* Set up termcap modes for Emacs. */
231 void
232 tty_set_terminal_modes (struct terminal *terminal)
234 struct tty_display_info *tty = terminal->display_info.tty;
236 if (tty->output)
238 if (tty->TS_termcap_modes)
239 OUTPUT (tty, tty->TS_termcap_modes);
240 else
242 /* Output enough newlines to scroll all the old screen contents
243 off the screen, so it won't be overwritten and lost. */
244 int i;
245 current_tty = tty;
246 for (i = 0; i < FRAME_LINES (XFRAME (selected_frame)); i++)
247 cmputc ('\n');
250 OUTPUT_IF (tty, tty->TS_termcap_modes);
251 OUTPUT_IF (tty, visible_cursor ? tty->TS_cursor_visible : tty->TS_cursor_normal);
252 OUTPUT_IF (tty, tty->TS_keypad_mode);
253 losecursor (tty);
254 fflush (tty->output);
258 /* Reset termcap modes before exiting Emacs. */
260 void
261 tty_reset_terminal_modes (struct terminal *terminal)
263 struct tty_display_info *tty = terminal->display_info.tty;
265 if (tty->output)
267 tty_turn_off_highlight (tty);
268 tty_turn_off_insert (tty);
269 OUTPUT_IF (tty, tty->TS_end_keypad_mode);
270 OUTPUT_IF (tty, tty->TS_cursor_normal);
271 OUTPUT_IF (tty, tty->TS_end_termcap_modes);
272 OUTPUT_IF (tty, tty->TS_orig_pair);
273 /* Output raw CR so kernel can track the cursor hpos. */
274 current_tty = tty;
275 cmputc ('\r');
276 fflush (tty->output);
280 /* Flag the end of a display update on a termcap terminal. */
282 static void
283 tty_update_end (struct frame *f)
285 struct tty_display_info *tty = FRAME_TTY (f);
287 if (!XWINDOW (selected_window)->cursor_off_p)
288 tty_show_cursor (tty);
289 tty_turn_off_insert (tty);
290 tty_background_highlight (tty);
293 /* The implementation of set_terminal_window for termcap frames. */
295 static void
296 tty_set_terminal_window (struct frame *f, int size)
298 struct tty_display_info *tty = FRAME_TTY (f);
300 tty->specified_window = size ? size : FRAME_LINES (f);
301 if (FRAME_SCROLL_REGION_OK (f))
302 tty_set_scroll_region (f, 0, tty->specified_window);
305 static void
306 tty_set_scroll_region (struct frame *f, int start, int stop)
308 char *buf;
309 struct tty_display_info *tty = FRAME_TTY (f);
311 if (tty->TS_set_scroll_region)
312 buf = tparam (tty->TS_set_scroll_region, 0, 0, start, stop - 1);
313 else if (tty->TS_set_scroll_region_1)
314 buf = tparam (tty->TS_set_scroll_region_1, 0, 0,
315 FRAME_LINES (f), start,
316 FRAME_LINES (f) - stop,
317 FRAME_LINES (f));
318 else
319 buf = tparam (tty->TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (f));
321 OUTPUT (tty, buf);
322 xfree (buf);
323 losecursor (tty);
327 static void
328 tty_turn_on_insert (struct tty_display_info *tty)
330 if (!tty->insert_mode)
331 OUTPUT (tty, tty->TS_insert_mode);
332 tty->insert_mode = 1;
335 void
336 tty_turn_off_insert (struct tty_display_info *tty)
338 if (tty->insert_mode)
339 OUTPUT (tty, tty->TS_end_insert_mode);
340 tty->insert_mode = 0;
343 /* Handle highlighting. */
345 void
346 tty_turn_off_highlight (struct tty_display_info *tty)
348 if (tty->standout_mode)
349 OUTPUT_IF (tty, tty->TS_end_standout_mode);
350 tty->standout_mode = 0;
353 static void
354 tty_turn_on_highlight (struct tty_display_info *tty)
356 if (!tty->standout_mode)
357 OUTPUT_IF (tty, tty->TS_standout_mode);
358 tty->standout_mode = 1;
361 static void
362 tty_toggle_highlight (struct tty_display_info *tty)
364 if (tty->standout_mode)
365 tty_turn_off_highlight (tty);
366 else
367 tty_turn_on_highlight (tty);
371 /* Make cursor invisible. */
373 static void
374 tty_hide_cursor (struct tty_display_info *tty)
376 if (tty->cursor_hidden == 0)
378 tty->cursor_hidden = 1;
379 OUTPUT_IF (tty, tty->TS_cursor_invisible);
384 /* Ensure that cursor is visible. */
386 static void
387 tty_show_cursor (struct tty_display_info *tty)
389 if (tty->cursor_hidden)
391 tty->cursor_hidden = 0;
392 OUTPUT_IF (tty, tty->TS_cursor_normal);
393 if (visible_cursor)
394 OUTPUT_IF (tty, tty->TS_cursor_visible);
399 /* Set standout mode to the state it should be in for
400 empty space inside windows. What this is,
401 depends on the user option inverse-video. */
403 static void
404 tty_background_highlight (struct tty_display_info *tty)
406 if (inverse_video)
407 tty_turn_on_highlight (tty);
408 else
409 tty_turn_off_highlight (tty);
412 /* Set standout mode to the mode specified for the text to be output. */
414 static void
415 tty_highlight_if_desired (struct tty_display_info *tty)
417 if (inverse_video)
418 tty_turn_on_highlight (tty);
419 else
420 tty_turn_off_highlight (tty);
424 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
425 frame-relative coordinates. */
427 static void
428 tty_cursor_to (struct frame *f, int vpos, int hpos)
430 struct tty_display_info *tty = FRAME_TTY (f);
432 /* Detect the case where we are called from reset_sys_modes
433 and the costs have never been calculated. Do nothing. */
434 if (! tty->costs_set)
435 return;
437 if (curY (tty) == vpos
438 && curX (tty) == hpos)
439 return;
440 if (!tty->TF_standout_motion)
441 tty_background_highlight (tty);
442 if (!tty->TF_insmode_motion)
443 tty_turn_off_insert (tty);
444 cmgoto (tty, vpos, hpos);
447 /* Similar but don't take any account of the wasted characters. */
449 static void
450 tty_raw_cursor_to (struct frame *f, int row, int col)
452 struct tty_display_info *tty = FRAME_TTY (f);
454 if (curY (tty) == row
455 && curX (tty) == col)
456 return;
457 if (!tty->TF_standout_motion)
458 tty_background_highlight (tty);
459 if (!tty->TF_insmode_motion)
460 tty_turn_off_insert (tty);
461 cmgoto (tty, row, col);
464 /* Erase operations */
466 /* Clear from cursor to end of frame on a termcap device. */
468 static void
469 tty_clear_to_end (struct frame *f)
471 register int i;
472 struct tty_display_info *tty = FRAME_TTY (f);
474 if (tty->TS_clr_to_bottom)
476 tty_background_highlight (tty);
477 OUTPUT (tty, tty->TS_clr_to_bottom);
479 else
481 for (i = curY (tty); i < FRAME_LINES (f); i++)
483 cursor_to (f, i, 0);
484 clear_end_of_line (f, FRAME_COLS (f));
489 /* Clear an entire termcap frame. */
491 static void
492 tty_clear_frame (struct frame *f)
494 struct tty_display_info *tty = FRAME_TTY (f);
496 if (tty->TS_clr_frame)
498 tty_background_highlight (tty);
499 OUTPUT (tty, tty->TS_clr_frame);
500 cmat (tty, 0, 0);
502 else
504 cursor_to (f, 0, 0);
505 clear_to_end (f);
509 /* An implementation of clear_end_of_line for termcap frames.
511 Note that the cursor may be moved, on terminals lacking a `ce' string. */
513 static void
514 tty_clear_end_of_line (struct frame *f, int first_unused_hpos)
516 register int i;
517 struct tty_display_info *tty = FRAME_TTY (f);
519 /* Detect the case where we are called from reset_sys_modes
520 and the costs have never been calculated. Do nothing. */
521 if (! tty->costs_set)
522 return;
524 if (curX (tty) >= first_unused_hpos)
525 return;
526 tty_background_highlight (tty);
527 if (tty->TS_clr_line)
529 OUTPUT1 (tty, tty->TS_clr_line);
531 else
532 { /* have to do it the hard way */
533 tty_turn_off_insert (tty);
535 /* Do not write in last row last col with Auto-wrap on. */
536 if (AutoWrap (tty)
537 && curY (tty) == FrameRows (tty) - 1
538 && first_unused_hpos == FrameCols (tty))
539 first_unused_hpos--;
541 for (i = curX (tty); i < first_unused_hpos; i++)
543 if (tty->termscript)
544 fputc (' ', tty->termscript);
545 fputc (' ', tty->output);
547 cmplus (tty, first_unused_hpos - curX (tty));
551 /* Buffers to store the source and result of code conversion for terminal. */
552 static unsigned char *encode_terminal_src;
553 static unsigned char *encode_terminal_dst;
554 /* Allocated sizes of the above buffers. */
555 static int encode_terminal_src_size;
556 static int encode_terminal_dst_size;
558 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes.
559 Set CODING->produced to the byte-length of the resulting byte
560 sequence, and return a pointer to that byte sequence. */
562 unsigned char *
563 encode_terminal_code (struct glyph *src, int src_len, struct coding_system *coding)
565 struct glyph *src_end = src + src_len;
566 unsigned char *buf;
567 int nchars, nbytes, required;
568 register int tlen = GLYPH_TABLE_LENGTH;
569 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
570 Lisp_Object charset_list;
572 /* Allocate sufficient size of buffer to store all characters in
573 multibyte-form. But, it may be enlarged on demand if
574 Vglyph_table contains a string or a composite glyph is
575 encountered. */
576 required = MAX_MULTIBYTE_LENGTH * src_len;
577 if (encode_terminal_src_size < required)
579 if (encode_terminal_src)
580 encode_terminal_src = xrealloc (encode_terminal_src, required);
581 else
582 encode_terminal_src = xmalloc (required);
583 encode_terminal_src_size = required;
586 charset_list = coding_charset_list (coding);
588 buf = encode_terminal_src;
589 nchars = 0;
590 while (src < src_end)
592 if (src->type == COMPOSITE_GLYPH)
594 struct composition *cmp;
595 Lisp_Object gstring;
596 int i;
598 nbytes = buf - encode_terminal_src;
599 if (src->u.cmp.automatic)
601 gstring = composition_gstring_from_id (src->u.cmp.id);
602 required = src->u.cmp.to + 1 - src->u.cmp.from;
604 else
606 cmp = composition_table[src->u.cmp.id];
607 required = MAX_MULTIBYTE_LENGTH * cmp->glyph_len;
610 if (encode_terminal_src_size < nbytes + required)
612 encode_terminal_src_size = nbytes + required;
613 encode_terminal_src = xrealloc (encode_terminal_src,
614 encode_terminal_src_size);
615 buf = encode_terminal_src + nbytes;
618 if (src->u.cmp.automatic)
619 for (i = src->u.cmp.from; i <= src->u.cmp.to; i++)
621 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
622 int c = LGLYPH_CHAR (g);
624 if (! char_charset (c, charset_list, NULL))
625 c = '?';
626 buf += CHAR_STRING (c, buf);
627 nchars++;
629 else
630 for (i = 0; i < cmp->glyph_len; i++)
632 int c = COMPOSITION_GLYPH (cmp, i);
634 if (c == '\t')
635 continue;
636 if (char_charset (c, charset_list, NULL))
638 if (CHAR_WIDTH (c) == 0
639 && i > 0 && COMPOSITION_GLYPH (cmp, i - 1) == '\t')
640 /* Should be left-padded */
642 buf += CHAR_STRING (' ', buf);
643 nchars++;
646 else
647 c = '?';
648 buf += CHAR_STRING (c, buf);
649 nchars++;
652 /* We must skip glyphs to be padded for a wide character. */
653 else if (! CHAR_GLYPH_PADDING_P (*src))
655 GLYPH g;
656 int c;
657 Lisp_Object string;
659 string = Qnil;
660 SET_GLYPH_FROM_CHAR_GLYPH (g, src[0]);
662 if (GLYPH_INVALID_P (g) || GLYPH_SIMPLE_P (tbase, tlen, g))
664 /* This glyph doesn't have an entry in Vglyph_table. */
665 c = src->u.ch;
667 else
669 /* This glyph has an entry in Vglyph_table,
670 so process any alias before testing for simpleness. */
671 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
673 if (GLYPH_SIMPLE_P (tbase, tlen, g))
674 /* We set the multi-byte form of a character in G
675 (that should be an ASCII character) at WORKBUF. */
676 c = GLYPH_CHAR (g);
677 else
678 /* We have a string in Vglyph_table. */
679 string = tbase[GLYPH_CHAR (g)];
682 if (NILP (string))
684 nbytes = buf - encode_terminal_src;
685 if (encode_terminal_src_size < nbytes + MAX_MULTIBYTE_LENGTH)
687 encode_terminal_src_size = nbytes + MAX_MULTIBYTE_LENGTH;
688 encode_terminal_src = xrealloc (encode_terminal_src,
689 encode_terminal_src_size);
690 buf = encode_terminal_src + nbytes;
692 if (CHAR_BYTE8_P (c)
693 || char_charset (c, charset_list, NULL))
695 /* Store the multibyte form of C at BUF. */
696 buf += CHAR_STRING (c, buf);
697 nchars++;
699 else
701 /* C is not encodable. */
702 *buf++ = '?';
703 nchars++;
704 while (src + 1 < src_end && CHAR_GLYPH_PADDING_P (src[1]))
706 *buf++ = '?';
707 nchars++;
708 src++;
712 else
714 unsigned char *p = SDATA (string);
716 if (! STRING_MULTIBYTE (string))
717 string = string_to_multibyte (string);
718 nbytes = buf - encode_terminal_src;
719 if (encode_terminal_src_size < nbytes + SBYTES (string))
721 encode_terminal_src_size = nbytes + SBYTES (string);
722 encode_terminal_src = xrealloc (encode_terminal_src,
723 encode_terminal_src_size);
724 buf = encode_terminal_src + nbytes;
726 memcpy (buf, SDATA (string), SBYTES (string));
727 buf += SBYTES (string);
728 nchars += SCHARS (string);
731 src++;
734 if (nchars == 0)
736 coding->produced = 0;
737 return NULL;
740 nbytes = buf - encode_terminal_src;
741 coding->source = encode_terminal_src;
742 if (encode_terminal_dst_size == 0)
744 encode_terminal_dst_size = encode_terminal_src_size;
745 if (encode_terminal_dst)
746 encode_terminal_dst = xrealloc (encode_terminal_dst,
747 encode_terminal_dst_size);
748 else
749 encode_terminal_dst = xmalloc (encode_terminal_dst_size);
751 coding->destination = encode_terminal_dst;
752 coding->dst_bytes = encode_terminal_dst_size;
753 encode_coding_object (coding, Qnil, 0, 0, nchars, nbytes, Qnil);
754 /* coding->destination may have been reallocated. */
755 encode_terminal_dst = coding->destination;
756 encode_terminal_dst_size = coding->dst_bytes;
758 return (encode_terminal_dst);
763 /* An implementation of write_glyphs for termcap frames. */
765 static void
766 tty_write_glyphs (struct frame *f, struct glyph *string, int len)
768 unsigned char *conversion_buffer;
769 struct coding_system *coding;
771 struct tty_display_info *tty = FRAME_TTY (f);
773 tty_turn_off_insert (tty);
774 tty_hide_cursor (tty);
776 /* Don't dare write in last column of bottom line, if Auto-Wrap,
777 since that would scroll the whole frame on some terminals. */
779 if (AutoWrap (tty)
780 && curY (tty) + 1 == FRAME_LINES (f)
781 && (curX (tty) + len) == FRAME_COLS (f))
782 len --;
783 if (len <= 0)
784 return;
786 cmplus (tty, len);
788 /* If terminal_coding does any conversion, use it, otherwise use
789 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
790 because it always return 1 if the member src_multibyte is 1. */
791 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
792 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
793 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
794 the tail. */
795 coding->mode &= ~CODING_MODE_LAST_BLOCK;
797 while (len > 0)
799 /* Identify a run of glyphs with the same face. */
800 int face_id = string->face_id;
801 int n;
803 for (n = 1; n < len; ++n)
804 if (string[n].face_id != face_id)
805 break;
807 /* Turn appearance modes of the face of the run on. */
808 tty_highlight_if_desired (tty);
809 turn_on_face (f, face_id);
811 if (n == len)
812 /* This is the last run. */
813 coding->mode |= CODING_MODE_LAST_BLOCK;
814 conversion_buffer = encode_terminal_code (string, n, coding);
815 if (coding->produced > 0)
817 BLOCK_INPUT;
818 fwrite (conversion_buffer, 1, coding->produced, tty->output);
819 if (ferror (tty->output))
820 clearerr (tty->output);
821 if (tty->termscript)
822 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
823 UNBLOCK_INPUT;
825 len -= n;
826 string += n;
828 /* Turn appearance modes off. */
829 turn_off_face (f, face_id);
830 tty_turn_off_highlight (tty);
833 cmcheckmagic (tty);
836 #ifdef HAVE_GPM /* Only used by GPM code. */
838 static void
839 tty_write_glyphs_with_face (register struct frame *f, register struct glyph *string,
840 register int len, register int face_id)
842 unsigned char *conversion_buffer;
843 struct coding_system *coding;
845 struct tty_display_info *tty = FRAME_TTY (f);
847 tty_turn_off_insert (tty);
848 tty_hide_cursor (tty);
850 /* Don't dare write in last column of bottom line, if Auto-Wrap,
851 since that would scroll the whole frame on some terminals. */
853 if (AutoWrap (tty)
854 && curY (tty) + 1 == FRAME_LINES (f)
855 && (curX (tty) + len) == FRAME_COLS (f))
856 len --;
857 if (len <= 0)
858 return;
860 cmplus (tty, len);
862 /* If terminal_coding does any conversion, use it, otherwise use
863 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
864 because it always return 1 if the member src_multibyte is 1. */
865 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
866 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
867 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
868 the tail. */
869 coding->mode &= ~CODING_MODE_LAST_BLOCK;
871 /* Turn appearance modes of the face. */
872 tty_highlight_if_desired (tty);
873 turn_on_face (f, face_id);
875 coding->mode |= CODING_MODE_LAST_BLOCK;
876 conversion_buffer = encode_terminal_code (string, len, coding);
877 if (coding->produced > 0)
879 BLOCK_INPUT;
880 fwrite (conversion_buffer, 1, coding->produced, tty->output);
881 if (ferror (tty->output))
882 clearerr (tty->output);
883 if (tty->termscript)
884 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
885 UNBLOCK_INPUT;
888 /* Turn appearance modes off. */
889 turn_off_face (f, face_id);
890 tty_turn_off_highlight (tty);
892 cmcheckmagic (tty);
894 #endif
896 /* An implementation of insert_glyphs for termcap frames. */
898 static void
899 tty_insert_glyphs (struct frame *f, struct glyph *start, int len)
901 char *buf;
902 struct glyph *glyph = NULL;
903 unsigned char *conversion_buffer;
904 unsigned char space[1];
905 struct coding_system *coding;
907 struct tty_display_info *tty = FRAME_TTY (f);
909 if (tty->TS_ins_multi_chars)
911 buf = tparam (tty->TS_ins_multi_chars, 0, 0, len);
912 OUTPUT1 (tty, buf);
913 xfree (buf);
914 if (start)
915 write_glyphs (f, start, len);
916 return;
919 tty_turn_on_insert (tty);
920 cmplus (tty, len);
922 if (! start)
923 space[0] = SPACEGLYPH;
925 /* If terminal_coding does any conversion, use it, otherwise use
926 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
927 because it always return 1 if the member src_multibyte is 1. */
928 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
929 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
930 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
931 the tail. */
932 coding->mode &= ~CODING_MODE_LAST_BLOCK;
934 while (len-- > 0)
936 OUTPUT1_IF (tty, tty->TS_ins_char);
937 if (!start)
939 conversion_buffer = space;
940 coding->produced = 1;
942 else
944 tty_highlight_if_desired (tty);
945 turn_on_face (f, start->face_id);
946 glyph = start;
947 ++start;
948 /* We must open sufficient space for a character which
949 occupies more than one column. */
950 while (len && CHAR_GLYPH_PADDING_P (*start))
952 OUTPUT1_IF (tty, tty->TS_ins_char);
953 start++, len--;
956 if (len <= 0)
957 /* This is the last glyph. */
958 coding->mode |= CODING_MODE_LAST_BLOCK;
960 conversion_buffer = encode_terminal_code (glyph, 1, coding);
963 if (coding->produced > 0)
965 BLOCK_INPUT;
966 fwrite (conversion_buffer, 1, coding->produced, tty->output);
967 if (ferror (tty->output))
968 clearerr (tty->output);
969 if (tty->termscript)
970 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
971 UNBLOCK_INPUT;
974 OUTPUT1_IF (tty, tty->TS_pad_inserted_char);
975 if (start)
977 turn_off_face (f, glyph->face_id);
978 tty_turn_off_highlight (tty);
982 cmcheckmagic (tty);
985 /* An implementation of delete_glyphs for termcap frames. */
987 static void
988 tty_delete_glyphs (struct frame *f, int n)
990 char *buf;
991 register int i;
993 struct tty_display_info *tty = FRAME_TTY (f);
995 if (tty->delete_in_insert_mode)
997 tty_turn_on_insert (tty);
999 else
1001 tty_turn_off_insert (tty);
1002 OUTPUT_IF (tty, tty->TS_delete_mode);
1005 if (tty->TS_del_multi_chars)
1007 buf = tparam (tty->TS_del_multi_chars, 0, 0, n);
1008 OUTPUT1 (tty, buf);
1009 xfree (buf);
1011 else
1012 for (i = 0; i < n; i++)
1013 OUTPUT1 (tty, tty->TS_del_char);
1014 if (!tty->delete_in_insert_mode)
1015 OUTPUT_IF (tty, tty->TS_end_delete_mode);
1018 /* An implementation of ins_del_lines for termcap frames. */
1020 static void
1021 tty_ins_del_lines (struct frame *f, int vpos, int n)
1023 struct tty_display_info *tty = FRAME_TTY (f);
1024 char *multi = n > 0 ? tty->TS_ins_multi_lines : tty->TS_del_multi_lines;
1025 char *single = n > 0 ? tty->TS_ins_line : tty->TS_del_line;
1026 char *scroll = n > 0 ? tty->TS_rev_scroll : tty->TS_fwd_scroll;
1028 register int i = n > 0 ? n : -n;
1029 register char *buf;
1031 /* If the lines below the insertion are being pushed
1032 into the end of the window, this is the same as clearing;
1033 and we know the lines are already clear, since the matching
1034 deletion has already been done. So can ignore this. */
1035 /* If the lines below the deletion are blank lines coming
1036 out of the end of the window, don't bother,
1037 as there will be a matching inslines later that will flush them. */
1038 if (FRAME_SCROLL_REGION_OK (f)
1039 && vpos + i >= tty->specified_window)
1040 return;
1041 if (!FRAME_MEMORY_BELOW_FRAME (f)
1042 && vpos + i >= FRAME_LINES (f))
1043 return;
1045 if (multi)
1047 raw_cursor_to (f, vpos, 0);
1048 tty_background_highlight (tty);
1049 buf = tparam (multi, 0, 0, i);
1050 OUTPUT (tty, buf);
1051 xfree (buf);
1053 else if (single)
1055 raw_cursor_to (f, vpos, 0);
1056 tty_background_highlight (tty);
1057 while (--i >= 0)
1058 OUTPUT (tty, single);
1059 if (tty->TF_teleray)
1060 curX (tty) = 0;
1062 else
1064 tty_set_scroll_region (f, vpos, tty->specified_window);
1065 if (n < 0)
1066 raw_cursor_to (f, tty->specified_window - 1, 0);
1067 else
1068 raw_cursor_to (f, vpos, 0);
1069 tty_background_highlight (tty);
1070 while (--i >= 0)
1071 OUTPUTL (tty, scroll, tty->specified_window - vpos);
1072 tty_set_scroll_region (f, 0, tty->specified_window);
1075 if (!FRAME_SCROLL_REGION_OK (f)
1076 && FRAME_MEMORY_BELOW_FRAME (f)
1077 && n < 0)
1079 cursor_to (f, FRAME_LINES (f) + n, 0);
1080 clear_to_end (f);
1084 /* Compute cost of sending "str", in characters,
1085 not counting any line-dependent padding. */
1088 string_cost (const char *str)
1090 cost = 0;
1091 if (str)
1092 tputs (str, 0, evalcost);
1093 return cost;
1096 /* Compute cost of sending "str", in characters,
1097 counting any line-dependent padding at one line. */
1099 static int
1100 string_cost_one_line (const char *str)
1102 cost = 0;
1103 if (str)
1104 tputs (str, 1, evalcost);
1105 return cost;
1108 /* Compute per line amount of line-dependent padding,
1109 in tenths of characters. */
1112 per_line_cost (const char *str)
1114 cost = 0;
1115 if (str)
1116 tputs (str, 0, evalcost);
1117 cost = - cost;
1118 if (str)
1119 tputs (str, 10, evalcost);
1120 return cost;
1123 /* char_ins_del_cost[n] is cost of inserting N characters.
1124 char_ins_del_cost[-n] is cost of deleting N characters.
1125 The length of this vector is based on max_frame_cols. */
1127 int *char_ins_del_vector;
1129 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
1131 /* ARGSUSED */
1132 static void
1133 calculate_ins_del_char_costs (struct frame *f)
1135 struct tty_display_info *tty = FRAME_TTY (f);
1136 int ins_startup_cost, del_startup_cost;
1137 int ins_cost_per_char, del_cost_per_char;
1138 register int i;
1139 register int *p;
1141 if (tty->TS_ins_multi_chars)
1143 ins_cost_per_char = 0;
1144 ins_startup_cost = string_cost_one_line (tty->TS_ins_multi_chars);
1146 else if (tty->TS_ins_char || tty->TS_pad_inserted_char
1147 || (tty->TS_insert_mode && tty->TS_end_insert_mode))
1149 ins_startup_cost = (30 * (string_cost (tty->TS_insert_mode)
1150 + string_cost (tty->TS_end_insert_mode))) / 100;
1151 ins_cost_per_char = (string_cost_one_line (tty->TS_ins_char)
1152 + string_cost_one_line (tty->TS_pad_inserted_char));
1154 else
1156 ins_startup_cost = 9999;
1157 ins_cost_per_char = 0;
1160 if (tty->TS_del_multi_chars)
1162 del_cost_per_char = 0;
1163 del_startup_cost = string_cost_one_line (tty->TS_del_multi_chars);
1165 else if (tty->TS_del_char)
1167 del_startup_cost = (string_cost (tty->TS_delete_mode)
1168 + string_cost (tty->TS_end_delete_mode));
1169 if (tty->delete_in_insert_mode)
1170 del_startup_cost /= 2;
1171 del_cost_per_char = string_cost_one_line (tty->TS_del_char);
1173 else
1175 del_startup_cost = 9999;
1176 del_cost_per_char = 0;
1179 /* Delete costs are at negative offsets */
1180 p = &char_ins_del_cost (f)[0];
1181 for (i = FRAME_COLS (f); --i >= 0;)
1182 *--p = (del_startup_cost += del_cost_per_char);
1184 /* Doing nothing is free */
1185 p = &char_ins_del_cost (f)[0];
1186 *p++ = 0;
1188 /* Insert costs are at positive offsets */
1189 for (i = FRAME_COLS (f); --i >= 0;)
1190 *p++ = (ins_startup_cost += ins_cost_per_char);
1193 void
1194 calculate_costs (struct frame *frame)
1196 FRAME_COST_BAUD_RATE (frame) = baud_rate;
1198 if (FRAME_TERMCAP_P (frame))
1200 struct tty_display_info *tty = FRAME_TTY (frame);
1201 register char *f = (tty->TS_set_scroll_region
1202 ? tty->TS_set_scroll_region
1203 : tty->TS_set_scroll_region_1);
1205 FRAME_SCROLL_REGION_COST (frame) = string_cost (f);
1207 tty->costs_set = 1;
1209 /* These variables are only used for terminal stuff. They are
1210 allocated once for the terminal frame of X-windows emacs, but not
1211 used afterwards.
1213 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1214 X turns off char_ins_del_ok. */
1216 max_frame_lines = max (max_frame_lines, FRAME_LINES (frame));
1217 max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
1219 if (char_ins_del_vector != 0)
1220 char_ins_del_vector
1221 = (int *) xrealloc (char_ins_del_vector,
1222 (sizeof (int)
1223 + 2 * max_frame_cols * sizeof (int)));
1224 else
1225 char_ins_del_vector
1226 = (int *) xmalloc (sizeof (int)
1227 + 2 * max_frame_cols * sizeof (int));
1229 memset (char_ins_del_vector, 0,
1230 (sizeof (int) + 2 * max_frame_cols * sizeof (int)));
1233 if (f && (!tty->TS_ins_line && !tty->TS_del_line))
1234 do_line_insertion_deletion_costs (frame,
1235 tty->TS_rev_scroll, tty->TS_ins_multi_lines,
1236 tty->TS_fwd_scroll, tty->TS_del_multi_lines,
1237 f, f, 1);
1238 else
1239 do_line_insertion_deletion_costs (frame,
1240 tty->TS_ins_line, tty->TS_ins_multi_lines,
1241 tty->TS_del_line, tty->TS_del_multi_lines,
1242 0, 0, 1);
1244 calculate_ins_del_char_costs (frame);
1246 /* Don't use TS_repeat if its padding is worse than sending the chars */
1247 if (tty->TS_repeat && per_line_cost (tty->TS_repeat) * baud_rate < 9000)
1248 tty->RPov = string_cost (tty->TS_repeat);
1249 else
1250 tty->RPov = FRAME_COLS (frame) * 2;
1252 cmcostinit (FRAME_TTY (frame)); /* set up cursor motion costs */
1256 struct fkey_table {
1257 char *cap, *name;
1260 /* Termcap capability names that correspond directly to X keysyms.
1261 Some of these (marked "terminfo") aren't supplied by old-style
1262 (Berkeley) termcap entries. They're listed in X keysym order;
1263 except we put the keypad keys first, so that if they clash with
1264 other keys (as on the IBM PC keyboard) they get overridden.
1267 static const struct fkey_table keys[] =
1269 {"kh", "home"}, /* termcap */
1270 {"kl", "left"}, /* termcap */
1271 {"ku", "up"}, /* termcap */
1272 {"kr", "right"}, /* termcap */
1273 {"kd", "down"}, /* termcap */
1274 {"%8", "prior"}, /* terminfo */
1275 {"%5", "next"}, /* terminfo */
1276 {"@7", "end"}, /* terminfo */
1277 {"@1", "begin"}, /* terminfo */
1278 {"*6", "select"}, /* terminfo */
1279 {"%9", "print"}, /* terminfo */
1280 {"@4", "execute"}, /* terminfo --- actually the `command' key */
1282 * "insert" --- see below
1284 {"&8", "undo"}, /* terminfo */
1285 {"%0", "redo"}, /* terminfo */
1286 {"%7", "menu"}, /* terminfo --- actually the `options' key */
1287 {"@0", "find"}, /* terminfo */
1288 {"@2", "cancel"}, /* terminfo */
1289 {"%1", "help"}, /* terminfo */
1291 * "break" goes here, but can't be reliably intercepted with termcap
1293 {"&4", "reset"}, /* terminfo --- actually `restart' */
1295 * "system" and "user" --- no termcaps
1297 {"kE", "clearline"}, /* terminfo */
1298 {"kA", "insertline"}, /* terminfo */
1299 {"kL", "deleteline"}, /* terminfo */
1300 {"kI", "insertchar"}, /* terminfo */
1301 {"kD", "deletechar"}, /* terminfo */
1302 {"kB", "backtab"}, /* terminfo */
1304 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1306 {"@8", "kp-enter"}, /* terminfo */
1308 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1309 * "kp-multiply", "kp-add", "kp-separator",
1310 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1311 * --- no termcaps for any of these.
1313 {"K4", "kp-1"}, /* terminfo */
1315 * "kp-2" --- no termcap
1317 {"K5", "kp-3"}, /* terminfo */
1319 * "kp-4" --- no termcap
1321 {"K2", "kp-5"}, /* terminfo */
1323 * "kp-6" --- no termcap
1325 {"K1", "kp-7"}, /* terminfo */
1327 * "kp-8" --- no termcap
1329 {"K3", "kp-9"}, /* terminfo */
1331 * "kp-equal" --- no termcap
1333 {"k1", "f1"},
1334 {"k2", "f2"},
1335 {"k3", "f3"},
1336 {"k4", "f4"},
1337 {"k5", "f5"},
1338 {"k6", "f6"},
1339 {"k7", "f7"},
1340 {"k8", "f8"},
1341 {"k9", "f9"},
1343 {"&0", "S-cancel"}, /*shifted cancel key*/
1344 {"&9", "S-begin"}, /*shifted begin key*/
1345 {"*0", "S-find"}, /*shifted find key*/
1346 {"*1", "S-execute"}, /*shifted execute? actually shifted command key*/
1347 {"*4", "S-delete"}, /*shifted delete-character key*/
1348 {"*7", "S-end"}, /*shifted end key*/
1349 {"*8", "S-clearline"}, /*shifted clear-to end-of-line key*/
1350 {"#1", "S-help"}, /*shifted help key*/
1351 {"#2", "S-home"}, /*shifted home key*/
1352 {"#3", "S-insert"}, /*shifted insert-character key*/
1353 {"#4", "S-left"}, /*shifted left-arrow key*/
1354 {"%d", "S-menu"}, /*shifted menu? actually shifted options key*/
1355 {"%c", "S-next"}, /*shifted next key*/
1356 {"%e", "S-prior"}, /*shifted previous key*/
1357 {"%f", "S-print"}, /*shifted print key*/
1358 {"%g", "S-redo"}, /*shifted redo key*/
1359 {"%i", "S-right"}, /*shifted right-arrow key*/
1360 {"!3", "S-undo"} /*shifted undo key*/
1363 #ifndef DOS_NT
1364 static char **term_get_fkeys_address;
1365 static KBOARD *term_get_fkeys_kboard;
1366 static Lisp_Object term_get_fkeys_1 (void);
1368 /* Find the escape codes sent by the function keys for Vinput_decode_map.
1369 This function scans the termcap function key sequence entries, and
1370 adds entries to Vinput_decode_map for each function key it finds. */
1372 static void
1373 term_get_fkeys (char **address, KBOARD *kboard)
1375 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1376 errors during the call. The only errors should be from Fdefine_key
1377 when given a key sequence containing an invalid prefix key. If the
1378 termcap defines function keys which use a prefix that is already bound
1379 to a command by the default bindings, we should silently ignore that
1380 function key specification, rather than giving the user an error and
1381 refusing to run at all on such a terminal. */
1383 term_get_fkeys_address = address;
1384 term_get_fkeys_kboard = kboard;
1385 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1388 static Lisp_Object
1389 term_get_fkeys_1 (void)
1391 int i;
1393 char **address = term_get_fkeys_address;
1394 KBOARD *kboard = term_get_fkeys_kboard;
1396 /* This can happen if CANNOT_DUMP or with strange options. */
1397 if (!KEYMAPP (kboard->Vinput_decode_map))
1398 kboard->Vinput_decode_map = Fmake_sparse_keymap (Qnil);
1400 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1402 char *sequence = tgetstr (keys[i].cap, address);
1403 if (sequence)
1404 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence),
1405 Fmake_vector (make_number (1),
1406 intern (keys[i].name)));
1409 /* The uses of the "k0" capability are inconsistent; sometimes it
1410 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1411 We will attempt to politely accommodate both systems by testing for
1412 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1415 char *k_semi = tgetstr ("k;", address);
1416 char *k0 = tgetstr ("k0", address);
1417 char *k0_name = "f10";
1419 if (k_semi)
1421 if (k0)
1422 /* Define f0 first, so that f10 takes precedence in case the
1423 key sequences happens to be the same. */
1424 Fdefine_key (kboard->Vinput_decode_map, build_string (k0),
1425 Fmake_vector (make_number (1), intern ("f0")));
1426 Fdefine_key (kboard->Vinput_decode_map, build_string (k_semi),
1427 Fmake_vector (make_number (1), intern ("f10")));
1429 else if (k0)
1430 Fdefine_key (kboard->Vinput_decode_map, build_string (k0),
1431 Fmake_vector (make_number (1), intern (k0_name)));
1434 /* Set up cookies for numbered function keys above f10. */
1436 char fcap[3], fkey[4];
1438 fcap[0] = 'F'; fcap[2] = '\0';
1439 for (i = 11; i < 64; i++)
1441 if (i <= 19)
1442 fcap[1] = '1' + i - 11;
1443 else if (i <= 45)
1444 fcap[1] = 'A' + i - 20;
1445 else
1446 fcap[1] = 'a' + i - 46;
1449 char *sequence = tgetstr (fcap, address);
1450 if (sequence)
1452 sprintf (fkey, "f%d", i);
1453 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence),
1454 Fmake_vector (make_number (1),
1455 intern (fkey)));
1462 * Various mappings to try and get a better fit.
1465 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1466 if (!tgetstr (cap1, address)) \
1468 char *sequence = tgetstr (cap2, address); \
1469 if (sequence) \
1470 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence), \
1471 Fmake_vector (make_number (1), \
1472 intern (sym))); \
1475 /* if there's no key_next keycap, map key_npage to `next' keysym */
1476 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1477 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1478 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1479 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1480 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1481 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1482 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1484 /* IBM has their own non-standard dialect of terminfo.
1485 If the standard name isn't found, try the IBM name. */
1486 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1487 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1488 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1489 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1490 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1491 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1492 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1493 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1494 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1495 #undef CONDITIONAL_REASSIGN
1498 return Qnil;
1500 #endif /* not DOS_NT */
1503 /***********************************************************************
1504 Character Display Information
1505 ***********************************************************************/
1506 static void append_glyph (struct it *);
1507 static void produce_stretch_glyph (struct it *);
1508 static void append_composite_glyph (struct it *);
1509 static void produce_composite_glyph (struct it *);
1511 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1512 terminal frames if IT->glyph_row != NULL. IT->char_to_display is
1513 the character for which to produce glyphs; IT->face_id contains the
1514 character's face. Padding glyphs are appended if IT->c has a
1515 IT->pixel_width > 1. */
1517 static void
1518 append_glyph (struct it *it)
1520 struct glyph *glyph, *end;
1521 int i;
1523 xassert (it->glyph_row);
1524 glyph = (it->glyph_row->glyphs[it->area]
1525 + it->glyph_row->used[it->area]);
1526 end = it->glyph_row->glyphs[1 + it->area];
1528 /* If the glyph row is reversed, we need to prepend the glyph rather
1529 than append it. */
1530 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1532 struct glyph *g;
1533 int move_by = it->pixel_width;
1535 /* Make room for the new glyphs. */
1536 if (move_by > end - glyph) /* don't overstep end of this area */
1537 move_by = end - glyph;
1538 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1539 g[move_by] = *g;
1540 glyph = it->glyph_row->glyphs[it->area];
1541 end = glyph + move_by;
1544 /* BIDI Note: we put the glyphs of a "multi-pixel" character left to
1545 right, even in the REVERSED_P case, since (a) all of its u.ch are
1546 identical, and (b) the PADDING_P flag needs to be set for the
1547 leftmost one, because we write to the terminal left-to-right. */
1548 for (i = 0;
1549 i < it->pixel_width && glyph < end;
1550 ++i)
1552 glyph->type = CHAR_GLYPH;
1553 glyph->pixel_width = 1;
1554 glyph->u.ch = it->char_to_display;
1555 glyph->face_id = it->face_id;
1556 glyph->padding_p = i > 0;
1557 glyph->charpos = CHARPOS (it->position);
1558 glyph->object = it->object;
1559 if (it->bidi_p)
1561 glyph->resolved_level = it->bidi_it.resolved_level;
1562 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1563 abort ();
1564 glyph->bidi_type = it->bidi_it.type;
1566 else
1568 glyph->resolved_level = 0;
1569 glyph->bidi_type = UNKNOWN_BT;
1572 ++it->glyph_row->used[it->area];
1573 ++glyph;
1577 /* Produce glyphs for the display element described by IT. *IT
1578 specifies what we want to produce a glyph for (character, image, ...),
1579 and where in the glyph matrix we currently are (glyph row and hpos).
1580 produce_glyphs fills in output fields of *IT with information such as the
1581 pixel width and height of a character, and maybe output actual glyphs at
1582 the same time if IT->glyph_row is non-null. For an overview, see
1583 the explanation in dispextern.h, before the definition of the
1584 display_element_type enumeration.
1586 produce_glyphs also stores the result of glyph width, ascent
1587 etc. computations in *IT.
1589 IT->glyph_row may be null, in which case produce_glyphs does not
1590 actually fill in the glyphs. This is used in the move_* functions
1591 in xdisp.c for text width and height computations.
1593 Callers usually don't call produce_glyphs directly;
1594 instead they use the macro PRODUCE_GLYPHS. */
1596 void
1597 produce_glyphs (struct it *it)
1599 /* If a hook is installed, let it do the work. */
1601 /* Nothing but characters are supported on terminal frames. */
1602 xassert (it->what == IT_CHARACTER
1603 || it->what == IT_COMPOSITION
1604 || it->what == IT_STRETCH);
1606 if (it->what == IT_STRETCH)
1608 produce_stretch_glyph (it);
1609 goto done;
1612 if (it->what == IT_COMPOSITION)
1614 produce_composite_glyph (it);
1615 goto done;
1618 if (it->char_to_display >= 040 && it->char_to_display < 0177)
1620 it->pixel_width = it->nglyphs = 1;
1621 if (it->glyph_row)
1622 append_glyph (it);
1624 else if (it->char_to_display == '\n')
1625 it->pixel_width = it->nglyphs = 0;
1626 else if (it->char_to_display == '\t')
1628 int absolute_x = (it->current_x
1629 + it->continuation_lines_width);
1630 int next_tab_x
1631 = (((1 + absolute_x + it->tab_width - 1)
1632 / it->tab_width)
1633 * it->tab_width);
1634 int nspaces;
1636 /* If part of the TAB has been displayed on the previous line
1637 which is continued now, continuation_lines_width will have
1638 been incremented already by the part that fitted on the
1639 continued line. So, we will get the right number of spaces
1640 here. */
1641 nspaces = next_tab_x - absolute_x;
1643 if (it->glyph_row)
1645 int n = nspaces;
1647 it->char_to_display = ' ';
1648 it->pixel_width = it->len = 1;
1650 while (n--)
1651 append_glyph (it);
1654 it->pixel_width = nspaces;
1655 it->nglyphs = nspaces;
1657 else if (CHAR_BYTE8_P (it->char_to_display))
1659 /* Coming here means that we must send the raw 8-bit byte as is
1660 to the terminal. Although there's no way to know how many
1661 columns it occupies on a screen, it is a good assumption that
1662 a single byte code has 1-column width. */
1663 it->pixel_width = it->nglyphs = 1;
1664 if (it->glyph_row)
1665 append_glyph (it);
1667 else
1669 it->pixel_width = CHAR_WIDTH (it->char_to_display);
1670 it->nglyphs = it->pixel_width;
1672 if (it->glyph_row)
1673 append_glyph (it);
1676 done:
1677 /* Advance current_x by the pixel width as a convenience for
1678 the caller. */
1679 if (it->area == TEXT_AREA)
1680 it->current_x += it->pixel_width;
1681 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1682 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
1686 /* Produce a stretch glyph for iterator IT. IT->object is the value
1687 of the glyph property displayed. The value must be a list
1688 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1689 being recognized:
1691 1. `:width WIDTH' specifies that the space should be WIDTH *
1692 canonical char width wide. WIDTH may be an integer or floating
1693 point number.
1695 2. `:align-to HPOS' specifies that the space should be wide enough
1696 to reach HPOS, a value in canonical character units. */
1698 static void
1699 produce_stretch_glyph (struct it *it)
1701 /* (space :width WIDTH ...) */
1702 Lisp_Object prop, plist;
1703 int width = 0, align_to = -1;
1704 int zero_width_ok_p = 0;
1705 double tem;
1707 /* List should start with `space'. */
1708 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1709 plist = XCDR (it->object);
1711 /* Compute the width of the stretch. */
1712 if ((prop = Fplist_get (plist, QCwidth), !NILP (prop))
1713 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, 0))
1715 /* Absolute width `:width WIDTH' specified and valid. */
1716 zero_width_ok_p = 1;
1717 width = (int)(tem + 0.5);
1719 else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
1720 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, &align_to))
1722 if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
1723 align_to = (align_to < 0
1725 : align_to - window_box_left_offset (it->w, TEXT_AREA));
1726 else if (align_to < 0)
1727 align_to = window_box_left_offset (it->w, TEXT_AREA);
1728 width = max (0, (int)(tem + 0.5) + align_to - it->current_x);
1729 zero_width_ok_p = 1;
1731 else
1732 /* Nothing specified -> width defaults to canonical char width. */
1733 width = FRAME_COLUMN_WIDTH (it->f);
1735 if (width <= 0 && (width < 0 || !zero_width_ok_p))
1736 width = 1;
1738 if (width > 0 && it->line_wrap != TRUNCATE
1739 && it->current_x + width > it->last_visible_x)
1740 width = it->last_visible_x - it->current_x - 1;
1742 if (width > 0 && it->glyph_row)
1744 Lisp_Object o_object = it->object;
1745 Lisp_Object object = it->stack[it->sp - 1].string;
1746 int n = width;
1748 if (!STRINGP (object))
1749 object = it->w->buffer;
1750 it->object = object;
1751 it->char_to_display = ' ';
1752 it->pixel_width = it->len = 1;
1753 while (n--)
1754 append_glyph (it);
1755 it->object = o_object;
1757 it->pixel_width = width;
1758 it->nglyphs = width;
1762 /* Append glyphs to IT's glyph_row for the composition IT->cmp_id.
1763 Called from produce_composite_glyph for terminal frames if
1764 IT->glyph_row != NULL. IT->face_id contains the character's
1765 face. */
1767 static void
1768 append_composite_glyph (struct it *it)
1770 struct glyph *glyph;
1772 xassert (it->glyph_row);
1773 glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
1774 if (glyph < it->glyph_row->glyphs[1 + it->area])
1776 /* If the glyph row is reversed, we need to prepend the glyph
1777 rather than append it. */
1778 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1780 struct glyph *g;
1782 /* Make room for the new glyph. */
1783 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1784 g[1] = *g;
1785 glyph = it->glyph_row->glyphs[it->area];
1787 glyph->type = COMPOSITE_GLYPH;
1788 glyph->pixel_width = it->pixel_width;
1789 glyph->u.cmp.id = it->cmp_it.id;
1790 if (it->cmp_it.ch < 0)
1792 glyph->u.cmp.automatic = 0;
1793 glyph->u.cmp.id = it->cmp_it.id;
1795 else
1797 glyph->u.cmp.automatic = 1;
1798 glyph->u.cmp.id = it->cmp_it.id;
1799 glyph->u.cmp.from = it->cmp_it.from;
1800 glyph->u.cmp.to = it->cmp_it.to - 1;
1803 glyph->face_id = it->face_id;
1804 glyph->padding_p = 0;
1805 glyph->charpos = CHARPOS (it->position);
1806 glyph->object = it->object;
1807 if (it->bidi_p)
1809 glyph->resolved_level = it->bidi_it.resolved_level;
1810 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1811 abort ();
1812 glyph->bidi_type = it->bidi_it.type;
1814 else
1816 glyph->resolved_level = 0;
1817 glyph->bidi_type = UNKNOWN_BT;
1820 ++it->glyph_row->used[it->area];
1821 ++glyph;
1826 /* Produce a composite glyph for iterator IT. IT->cmp_id is the ID of
1827 the composition. We simply produces components of the composition
1828 assuming that the terminal has a capability to layout/render it
1829 correctly. */
1831 static void
1832 produce_composite_glyph (struct it *it)
1834 if (it->cmp_it.ch < 0)
1836 struct composition *cmp = composition_table[it->cmp_it.id];
1838 it->pixel_width = cmp->width;
1840 else
1842 Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id);
1844 it->pixel_width = composition_gstring_width (gstring, it->cmp_it.from,
1845 it->cmp_it.to, NULL);
1847 it->nglyphs = 1;
1848 if (it->glyph_row)
1849 append_composite_glyph (it);
1853 /* Get information about special display element WHAT in an
1854 environment described by IT. WHAT is one of IT_TRUNCATION or
1855 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1856 non-null glyph_row member. This function ensures that fields like
1857 face_id, c, len of IT are left untouched. */
1859 void
1860 produce_special_glyphs (struct it *it, enum display_element_type what)
1862 struct it temp_it;
1863 Lisp_Object gc;
1864 GLYPH glyph;
1866 temp_it = *it;
1867 temp_it.dp = NULL;
1868 temp_it.what = IT_CHARACTER;
1869 temp_it.len = 1;
1870 temp_it.object = make_number (0);
1871 memset (&temp_it.current, 0, sizeof temp_it.current);
1873 if (what == IT_CONTINUATION)
1875 /* Continuation glyph. For R2L lines, we mirror it by hand. */
1876 if (it->bidi_it.paragraph_dir == R2L)
1877 SET_GLYPH_FROM_CHAR (glyph, '/');
1878 else
1879 SET_GLYPH_FROM_CHAR (glyph, '\\');
1880 if (it->dp
1881 && (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc))
1882 && GLYPH_CODE_CHAR_VALID_P (gc))
1884 /* FIXME: Should we mirror GC for R2L lines? */
1885 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
1886 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
1889 else if (what == IT_TRUNCATION)
1891 /* Truncation glyph. */
1892 SET_GLYPH_FROM_CHAR (glyph, '$');
1893 if (it->dp
1894 && (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc))
1895 && GLYPH_CODE_CHAR_VALID_P (gc))
1897 /* FIXME: Should we mirror GC for R2L lines? */
1898 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
1899 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
1902 else
1903 abort ();
1905 temp_it.c = temp_it.char_to_display = GLYPH_CHAR (glyph);
1906 temp_it.face_id = GLYPH_FACE (glyph);
1907 temp_it.len = CHAR_BYTES (temp_it.c);
1909 produce_glyphs (&temp_it);
1910 it->pixel_width = temp_it.pixel_width;
1911 it->nglyphs = temp_it.pixel_width;
1916 /***********************************************************************
1917 Faces
1918 ***********************************************************************/
1920 /* Value is non-zero if attribute ATTR may be used. ATTR should be
1921 one of the enumerators from enum no_color_bit, or a bit set built
1922 from them. Some display attributes may not be used together with
1923 color; the termcap capability `NC' specifies which ones. */
1925 #define MAY_USE_WITH_COLORS_P(tty, ATTR) \
1926 (tty->TN_max_colors > 0 \
1927 ? (tty->TN_no_color_video & (ATTR)) == 0 \
1928 : 1)
1930 /* Turn appearances of face FACE_ID on tty frame F on.
1931 FACE_ID is a realized face ID number, in the face cache. */
1933 static void
1934 turn_on_face (struct frame *f, int face_id)
1936 struct face *face = FACE_FROM_ID (f, face_id);
1937 long fg = face->foreground;
1938 long bg = face->background;
1939 struct tty_display_info *tty = FRAME_TTY (f);
1941 /* Do this first because TS_end_standout_mode may be the same
1942 as TS_exit_attribute_mode, which turns all appearances off. */
1943 if (MAY_USE_WITH_COLORS_P (tty, NC_REVERSE))
1945 if (tty->TN_max_colors > 0)
1947 if (fg >= 0 && bg >= 0)
1949 /* If the terminal supports colors, we can set them
1950 below without using reverse video. The face's fg
1951 and bg colors are set as they should appear on
1952 the screen, i.e. they take the inverse-video'ness
1953 of the face already into account. */
1955 else if (inverse_video)
1957 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1958 || bg == FACE_TTY_DEFAULT_BG_COLOR)
1959 tty_toggle_highlight (tty);
1961 else
1963 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1964 || bg == FACE_TTY_DEFAULT_FG_COLOR)
1965 tty_toggle_highlight (tty);
1968 else
1970 /* If we can't display colors, use reverse video
1971 if the face specifies that. */
1972 if (inverse_video)
1974 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1975 || bg == FACE_TTY_DEFAULT_BG_COLOR)
1976 tty_toggle_highlight (tty);
1978 else
1980 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1981 || bg == FACE_TTY_DEFAULT_FG_COLOR)
1982 tty_toggle_highlight (tty);
1987 if (face->tty_bold_p && MAY_USE_WITH_COLORS_P (tty, NC_BOLD))
1988 OUTPUT1_IF (tty, tty->TS_enter_bold_mode);
1990 if (face->tty_dim_p && MAY_USE_WITH_COLORS_P (tty, NC_DIM))
1991 OUTPUT1_IF (tty, tty->TS_enter_dim_mode);
1993 /* Alternate charset and blinking not yet used. */
1994 if (face->tty_alt_charset_p
1995 && MAY_USE_WITH_COLORS_P (tty, NC_ALT_CHARSET))
1996 OUTPUT1_IF (tty, tty->TS_enter_alt_charset_mode);
1998 if (face->tty_blinking_p
1999 && MAY_USE_WITH_COLORS_P (tty, NC_BLINK))
2000 OUTPUT1_IF (tty, tty->TS_enter_blink_mode);
2002 if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (tty, NC_UNDERLINE))
2003 OUTPUT1_IF (tty, tty->TS_enter_underline_mode);
2005 if (tty->TN_max_colors > 0)
2007 char *ts, *p;
2009 ts = tty->standout_mode ? tty->TS_set_background : tty->TS_set_foreground;
2010 if (fg >= 0 && ts)
2012 p = tparam (ts, NULL, 0, (int) fg);
2013 OUTPUT (tty, p);
2014 xfree (p);
2017 ts = tty->standout_mode ? tty->TS_set_foreground : tty->TS_set_background;
2018 if (bg >= 0 && ts)
2020 p = tparam (ts, NULL, 0, (int) bg);
2021 OUTPUT (tty, p);
2022 xfree (p);
2028 /* Turn off appearances of face FACE_ID on tty frame F. */
2030 static void
2031 turn_off_face (struct frame *f, int face_id)
2033 struct face *face = FACE_FROM_ID (f, face_id);
2034 struct tty_display_info *tty = FRAME_TTY (f);
2036 xassert (face != NULL);
2038 if (tty->TS_exit_attribute_mode)
2040 /* Capability "me" will turn off appearance modes double-bright,
2041 half-bright, reverse-video, standout, underline. It may or
2042 may not turn off alt-char-mode. */
2043 if (face->tty_bold_p
2044 || face->tty_dim_p
2045 || face->tty_reverse_p
2046 || face->tty_alt_charset_p
2047 || face->tty_blinking_p
2048 || face->tty_underline_p)
2050 OUTPUT1_IF (tty, tty->TS_exit_attribute_mode);
2051 if (strcmp (tty->TS_exit_attribute_mode, tty->TS_end_standout_mode) == 0)
2052 tty->standout_mode = 0;
2055 if (face->tty_alt_charset_p)
2056 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
2058 else
2060 /* If we don't have "me" we can only have those appearances
2061 that have exit sequences defined. */
2062 if (face->tty_alt_charset_p)
2063 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
2065 if (face->tty_underline_p)
2066 OUTPUT_IF (tty, tty->TS_exit_underline_mode);
2069 /* Switch back to default colors. */
2070 if (tty->TN_max_colors > 0
2071 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
2072 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
2073 || (face->background != FACE_TTY_DEFAULT_COLOR
2074 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
2075 OUTPUT1_IF (tty, tty->TS_orig_pair);
2079 /* Return non-zero if the terminal on frame F supports all of the
2080 capabilities in CAPS simultaneously, with foreground and background
2081 colors FG and BG. */
2084 tty_capable_p (struct tty_display_info *tty, unsigned int caps,
2085 unsigned long fg, unsigned long bg)
2087 #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
2088 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
2089 return 0;
2091 TTY_CAPABLE_P_TRY (tty, TTY_CAP_INVERSE, tty->TS_standout_mode, NC_REVERSE);
2092 TTY_CAPABLE_P_TRY (tty, TTY_CAP_UNDERLINE, tty->TS_enter_underline_mode, NC_UNDERLINE);
2093 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BOLD, tty->TS_enter_bold_mode, NC_BOLD);
2094 TTY_CAPABLE_P_TRY (tty, TTY_CAP_DIM, tty->TS_enter_dim_mode, NC_DIM);
2095 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BLINK, tty->TS_enter_blink_mode, NC_BLINK);
2096 TTY_CAPABLE_P_TRY (tty, TTY_CAP_ALT_CHARSET, tty->TS_enter_alt_charset_mode, NC_ALT_CHARSET);
2098 /* We can do it! */
2099 return 1;
2102 /* Return non-zero if the terminal is capable to display colors. */
2104 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
2105 0, 1, 0,
2106 doc: /* Return non-nil if the tty device TERMINAL can display colors.
2108 TERMINAL can be a terminal object, a frame, or nil (meaning the
2109 selected frame's terminal). This function always returns nil if
2110 TERMINAL does not refer to a text-only terminal. */)
2111 (Lisp_Object terminal)
2113 struct terminal *t = get_tty_terminal (terminal, 0);
2114 if (!t)
2115 return Qnil;
2116 else
2117 return t->display_info.tty->TN_max_colors > 0 ? Qt : Qnil;
2120 /* Return the number of supported colors. */
2121 DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
2122 Stty_display_color_cells, 0, 1, 0,
2123 doc: /* Return the number of colors supported by the tty device TERMINAL.
2125 TERMINAL can be a terminal object, a frame, or nil (meaning the
2126 selected frame's terminal). This function always returns 0 if
2127 TERMINAL does not refer to a text-only terminal. */)
2128 (Lisp_Object terminal)
2130 struct terminal *t = get_tty_terminal (terminal, 0);
2131 if (!t)
2132 return make_number (0);
2133 else
2134 return make_number (t->display_info.tty->TN_max_colors);
2137 #ifndef DOS_NT
2139 /* Declare here rather than in the function, as in the rest of Emacs,
2140 to work around an HPUX compiler bug (?). See
2141 http://lists.gnu.org/archive/html/emacs-devel/2007-08/msg00410.html */
2142 static int default_max_colors;
2143 static int default_max_pairs;
2144 static int default_no_color_video;
2145 static char *default_orig_pair;
2146 static char *default_set_foreground;
2147 static char *default_set_background;
2149 /* Save or restore the default color-related capabilities of this
2150 terminal. */
2151 static void
2152 tty_default_color_capabilities (struct tty_display_info *tty, int save)
2155 if (save)
2157 xfree (default_orig_pair);
2158 default_orig_pair = tty->TS_orig_pair ? xstrdup (tty->TS_orig_pair) : NULL;
2160 xfree (default_set_foreground);
2161 default_set_foreground = tty->TS_set_foreground ? xstrdup (tty->TS_set_foreground)
2162 : NULL;
2164 xfree (default_set_background);
2165 default_set_background = tty->TS_set_background ? xstrdup (tty->TS_set_background)
2166 : NULL;
2168 default_max_colors = tty->TN_max_colors;
2169 default_max_pairs = tty->TN_max_pairs;
2170 default_no_color_video = tty->TN_no_color_video;
2172 else
2174 tty->TS_orig_pair = default_orig_pair;
2175 tty->TS_set_foreground = default_set_foreground;
2176 tty->TS_set_background = default_set_background;
2177 tty->TN_max_colors = default_max_colors;
2178 tty->TN_max_pairs = default_max_pairs;
2179 tty->TN_no_color_video = default_no_color_video;
2183 /* Setup one of the standard tty color schemes according to MODE.
2184 MODE's value is generally the number of colors which we want to
2185 support; zero means set up for the default capabilities, the ones
2186 we saw at init_tty time; -1 means turn off color support. */
2187 static void
2188 tty_setup_colors (struct tty_display_info *tty, int mode)
2190 /* Canonicalize all negative values of MODE. */
2191 if (mode < -1)
2192 mode = -1;
2194 switch (mode)
2196 case -1: /* no colors at all */
2197 tty->TN_max_colors = 0;
2198 tty->TN_max_pairs = 0;
2199 tty->TN_no_color_video = 0;
2200 tty->TS_set_foreground = tty->TS_set_background = tty->TS_orig_pair = NULL;
2201 break;
2202 case 0: /* default colors, if any */
2203 default:
2204 tty_default_color_capabilities (tty, 0);
2205 break;
2206 case 8: /* 8 standard ANSI colors */
2207 tty->TS_orig_pair = "\033[0m";
2208 #ifdef TERMINFO
2209 tty->TS_set_foreground = "\033[3%p1%dm";
2210 tty->TS_set_background = "\033[4%p1%dm";
2211 #else
2212 tty->TS_set_foreground = "\033[3%dm";
2213 tty->TS_set_background = "\033[4%dm";
2214 #endif
2215 tty->TN_max_colors = 8;
2216 tty->TN_max_pairs = 64;
2217 tty->TN_no_color_video = 0;
2218 break;
2222 void
2223 set_tty_color_mode (struct tty_display_info *tty, struct frame *f)
2225 Lisp_Object tem, val;
2226 Lisp_Object color_mode;
2227 int mode;
2228 Lisp_Object tty_color_mode_alist
2229 = Fintern_soft (build_string ("tty-color-mode-alist"), Qnil);
2231 tem = assq_no_quit (Qtty_color_mode, f->param_alist);
2232 val = CONSP (tem) ? XCDR (tem) : Qnil;
2234 if (INTEGERP (val))
2235 color_mode = val;
2236 else if (SYMBOLP (tty_color_mode_alist))
2238 tem = Fassq (val, Fsymbol_value (tty_color_mode_alist));
2239 color_mode = CONSP (tem) ? XCDR (tem) : Qnil;
2241 else
2242 color_mode = Qnil;
2244 mode = INTEGERP (color_mode) ? XINT (color_mode) : 0;
2246 if (mode != tty->previous_color_mode)
2248 Lisp_Object funsym = intern ("tty-set-up-initial-frame-faces");
2249 tty->previous_color_mode = mode;
2250 tty_setup_colors (tty , mode);
2251 /* This recomputes all the faces given the new color definitions. */
2252 safe_call (1, &funsym);
2256 #endif /* !DOS_NT */
2260 /* Return the tty display object specified by TERMINAL. */
2262 struct terminal *
2263 get_tty_terminal (Lisp_Object terminal, int throw)
2265 struct terminal *t = get_terminal (terminal, throw);
2267 if (t && t->type != output_termcap && t->type != output_msdos_raw)
2269 if (throw)
2270 error ("Device %d is not a termcap terminal device", t->id);
2271 else
2272 return NULL;
2275 return t;
2278 /* Return an active termcap device that uses the tty device with the
2279 given name.
2281 This function ignores suspended devices.
2283 Returns NULL if the named terminal device is not opened. */
2285 struct terminal *
2286 get_named_tty (const char *name)
2288 struct terminal *t;
2290 if (!name)
2291 abort ();
2293 for (t = terminal_list; t; t = t->next_terminal)
2295 if ((t->type == output_termcap || t->type == output_msdos_raw)
2296 && !strcmp (t->display_info.tty->name, name)
2297 && TERMINAL_ACTIVE_P (t))
2298 return t;
2301 return 0;
2305 DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0,
2306 doc: /* Return the type of the tty device that TERMINAL uses.
2307 Returns nil if TERMINAL is not on a tty device.
2309 TERMINAL can be a terminal object, a frame, or nil (meaning the
2310 selected frame's terminal). */)
2311 (Lisp_Object terminal)
2313 struct terminal *t = get_terminal (terminal, 1);
2315 if (t->type != output_termcap && t->type != output_msdos_raw)
2316 return Qnil;
2318 if (t->display_info.tty->type)
2319 return build_string (t->display_info.tty->type);
2320 else
2321 return Qnil;
2324 DEFUN ("controlling-tty-p", Fcontrolling_tty_p, Scontrolling_tty_p, 0, 1, 0,
2325 doc: /* Return non-nil if TERMINAL is the controlling tty of the Emacs process.
2327 TERMINAL can be a terminal object, a frame, or nil (meaning the
2328 selected frame's terminal). This function always returns nil if
2329 TERMINAL is not on a tty device. */)
2330 (Lisp_Object terminal)
2332 struct terminal *t = get_terminal (terminal, 1);
2334 if ((t->type != output_termcap && t->type != output_msdos_raw)
2335 || strcmp (t->display_info.tty->name, DEV_TTY) != 0)
2336 return Qnil;
2337 else
2338 return Qt;
2341 DEFUN ("tty-no-underline", Ftty_no_underline, Stty_no_underline, 0, 1, 0,
2342 doc: /* Declare that the tty used by TERMINAL does not handle underlining.
2343 This is used to override the terminfo data, for certain terminals that
2344 do not really do underlining, but say that they do. This function has
2345 no effect if used on a non-tty terminal.
2347 TERMINAL can be a terminal object, a frame or nil (meaning the
2348 selected frame's terminal). This function always returns nil if
2349 TERMINAL does not refer to a text-only terminal. */)
2350 (Lisp_Object terminal)
2352 struct terminal *t = get_terminal (terminal, 1);
2354 if (t->type == output_termcap)
2355 t->display_info.tty->TS_enter_underline_mode = 0;
2356 return Qnil;
2361 DEFUN ("suspend-tty", Fsuspend_tty, Ssuspend_tty, 0, 1, 0,
2362 doc: /* Suspend the terminal device TTY.
2364 The device is restored to its default state, and Emacs ceases all
2365 access to the tty device. Frames that use the device are not deleted,
2366 but input is not read from them and if they change, their display is
2367 not updated.
2369 TTY may be a terminal object, a frame, or nil for the terminal device
2370 of the currently selected frame.
2372 This function runs `suspend-tty-functions' after suspending the
2373 device. The functions are run with one arg, the id of the suspended
2374 terminal device.
2376 `suspend-tty' does nothing if it is called on a device that is already
2377 suspended.
2379 A suspended tty may be resumed by calling `resume-tty' on it. */)
2380 (Lisp_Object tty)
2382 struct terminal *t = get_tty_terminal (tty, 1);
2383 FILE *f;
2385 if (!t)
2386 error ("Unknown tty device");
2388 f = t->display_info.tty->input;
2390 if (f)
2392 /* First run `suspend-tty-functions' and then clean up the tty
2393 state because `suspend-tty-functions' might need to change
2394 the tty state. */
2395 if (!NILP (Vrun_hooks))
2397 Lisp_Object args[2];
2398 args[0] = intern ("suspend-tty-functions");
2399 XSETTERMINAL (args[1], t);
2400 Frun_hook_with_args (2, args);
2403 reset_sys_modes (t->display_info.tty);
2404 delete_keyboard_wait_descriptor (fileno (f));
2406 #ifndef MSDOS
2407 fclose (f);
2408 if (f != t->display_info.tty->output)
2409 fclose (t->display_info.tty->output);
2410 #endif
2412 t->display_info.tty->input = 0;
2413 t->display_info.tty->output = 0;
2415 if (FRAMEP (t->display_info.tty->top_frame))
2416 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0);
2420 /* Clear display hooks to prevent further output. */
2421 clear_tty_hooks (t);
2423 return Qnil;
2426 DEFUN ("resume-tty", Fresume_tty, Sresume_tty, 0, 1, 0,
2427 doc: /* Resume the previously suspended terminal device TTY.
2428 The terminal is opened and reinitialized. Frames that are on the
2429 suspended terminal are revived.
2431 It is an error to resume a terminal while another terminal is active
2432 on the same device.
2434 This function runs `resume-tty-functions' after resuming the terminal.
2435 The functions are run with one arg, the id of the resumed terminal
2436 device.
2438 `resume-tty' does nothing if it is called on a device that is not
2439 suspended.
2441 TTY may be a terminal object, a frame, or nil (meaning the selected
2442 frame's terminal). */)
2443 (Lisp_Object tty)
2445 struct terminal *t = get_tty_terminal (tty, 1);
2446 int fd;
2448 if (!t)
2449 error ("Unknown tty device");
2451 if (!t->display_info.tty->input)
2453 if (get_named_tty (t->display_info.tty->name))
2454 error ("Cannot resume display while another display is active on the same device");
2456 #ifdef MSDOS
2457 t->display_info.tty->output = stdout;
2458 t->display_info.tty->input = stdin;
2459 #else /* !MSDOS */
2460 fd = emacs_open (t->display_info.tty->name, O_RDWR | O_NOCTTY, 0);
2462 if (fd == -1)
2463 error ("Can not reopen tty device %s: %s", t->display_info.tty->name, strerror (errno));
2465 if (strcmp (t->display_info.tty->name, DEV_TTY))
2466 dissociate_if_controlling_tty (fd);
2468 t->display_info.tty->output = fdopen (fd, "w+");
2469 t->display_info.tty->input = t->display_info.tty->output;
2470 #endif
2472 add_keyboard_wait_descriptor (fd);
2474 if (FRAMEP (t->display_info.tty->top_frame))
2476 struct frame *f = XFRAME (t->display_info.tty->top_frame);
2477 int width, height;
2478 int old_height = FRAME_COLS (f);
2479 int old_width = FRAME_LINES (f);
2481 /* Check if terminal/window size has changed while the frame
2482 was suspended. */
2483 get_tty_size (fileno (t->display_info.tty->input), &width, &height);
2484 if (width != old_width || height != old_height)
2485 change_frame_size (f, height, width, 0, 0, 0);
2486 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
2489 init_sys_modes (t->display_info.tty);
2491 /* Run `resume-tty-functions'. */
2492 if (!NILP (Vrun_hooks))
2494 Lisp_Object args[2];
2495 args[0] = intern ("resume-tty-functions");
2496 XSETTERMINAL (args[1], t);
2497 Frun_hook_with_args (2, args);
2501 set_tty_hooks (t);
2503 return Qnil;
2507 /***********************************************************************
2508 Mouse
2509 ***********************************************************************/
2511 #ifdef HAVE_GPM
2512 void
2513 term_mouse_moveto (int x, int y)
2515 /* TODO: how to set mouse position?
2516 const char *name;
2517 int fd;
2518 name = (const char *) ttyname (0);
2519 fd = open (name, O_WRONLY);
2520 SOME_FUNCTION (x, y, fd);
2521 close (fd);
2522 last_mouse_x = x;
2523 last_mouse_y = y; */
2526 static void
2527 term_show_mouse_face (enum draw_glyphs_face draw)
2529 struct window *w = XWINDOW (mouse_face_window);
2530 int save_x, save_y;
2531 int i;
2533 struct frame *f = XFRAME (w->frame);
2534 struct tty_display_info *tty = FRAME_TTY (f);
2536 if (/* If window is in the process of being destroyed, don't bother
2537 to do anything. */
2538 w->current_matrix != NULL
2539 /* Recognize when we are called to operate on rows that don't exist
2540 anymore. This can happen when a window is split. */
2541 && mouse_face_end_row < w->current_matrix->nrows)
2543 /* write_glyphs writes at cursor position, so we need to
2544 temporarily move cursor coordinates to the beginning of
2545 the highlight region. */
2547 /* Save current cursor co-ordinates */
2548 save_y = curY (tty);
2549 save_x = curX (tty);
2551 /* Note that mouse_face_beg_row etc. are window relative. */
2552 for (i = mouse_face_beg_row; i <= mouse_face_end_row; i++)
2554 int start_hpos, end_hpos, nglyphs;
2555 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
2557 /* Don't do anything if row doesn't have valid contents. */
2558 if (!row->enabled_p)
2559 continue;
2561 /* For all but the first row, the highlight starts at column 0. */
2562 if (i == mouse_face_beg_row)
2563 start_hpos = mouse_face_beg_col;
2564 else
2565 start_hpos = 0;
2567 if (i == mouse_face_end_row)
2568 end_hpos = mouse_face_end_col;
2569 else
2571 end_hpos = row->used[TEXT_AREA];
2572 if (draw == DRAW_NORMAL_TEXT)
2573 row->fill_line_p = 1; /* Clear to end of line */
2576 if (end_hpos <= start_hpos)
2577 continue;
2578 /* Record that some glyphs of this row are displayed in
2579 mouse-face. */
2580 row->mouse_face_p = draw > 0;
2582 nglyphs = end_hpos - start_hpos;
2584 if (end_hpos >= row->used[TEXT_AREA])
2585 nglyphs = row->used[TEXT_AREA] - start_hpos;
2587 pos_y = row->y + WINDOW_TOP_EDGE_Y (w);
2588 pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos
2589 + WINDOW_LEFT_EDGE_X (w);
2591 cursor_to (f, pos_y, pos_x);
2593 if (draw == DRAW_MOUSE_FACE)
2595 tty_write_glyphs_with_face (f, row->glyphs[TEXT_AREA] + start_hpos,
2596 nglyphs, mouse_face_face_id);
2598 else /* draw == DRAW_NORMAL_TEXT */
2599 write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
2601 cursor_to (f, save_y, save_x);
2605 static void
2606 term_clear_mouse_face (void)
2608 if (!NILP (mouse_face_window))
2609 term_show_mouse_face (DRAW_NORMAL_TEXT);
2611 mouse_face_beg_row = mouse_face_beg_col = -1;
2612 mouse_face_end_row = mouse_face_end_col = -1;
2613 mouse_face_window = Qnil;
2616 /* Find the glyph matrix position of buffer position POS in window W.
2617 *HPOS and *VPOS are set to the positions found. W's current glyphs
2618 must be up to date. If POS is above window start return (0, 0).
2619 If POS is after end of W, return end of last line in W.
2620 - taken from msdos.c */
2621 static int
2622 fast_find_position (struct window *w, int pos, int *hpos, int *vpos)
2624 int i, lastcol, line_start_position, maybe_next_line_p = 0;
2625 int yb = window_text_bottom_y (w);
2626 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0), *best_row = row;
2628 while (row->y < yb)
2630 if (row->used[TEXT_AREA])
2631 line_start_position = row->glyphs[TEXT_AREA]->charpos;
2632 else
2633 line_start_position = 0;
2635 if (line_start_position > pos)
2636 break;
2637 /* If the position sought is the end of the buffer,
2638 don't include the blank lines at the bottom of the window. */
2639 else if (line_start_position == pos
2640 && pos == BUF_ZV (XBUFFER (w->buffer)))
2642 maybe_next_line_p = 1;
2643 break;
2645 else if (line_start_position > 0)
2646 best_row = row;
2648 /* Don't overstep the last matrix row, lest we get into the
2649 never-never land... */
2650 if (row->y + 1 >= yb)
2651 break;
2653 ++row;
2656 /* Find the right column within BEST_ROW. */
2657 lastcol = 0;
2658 row = best_row;
2659 for (i = 0; i < row->used[TEXT_AREA]; i++)
2661 struct glyph *glyph = row->glyphs[TEXT_AREA] + i;
2662 int charpos;
2664 charpos = glyph->charpos;
2665 if (charpos == pos)
2667 *hpos = i;
2668 *vpos = row->y;
2669 return 1;
2671 else if (charpos > pos)
2672 break;
2673 else if (charpos > 0)
2674 lastcol = i;
2677 /* If we're looking for the end of the buffer,
2678 and we didn't find it in the line we scanned,
2679 use the start of the following line. */
2680 if (maybe_next_line_p)
2682 ++row;
2683 lastcol = 0;
2686 *vpos = row->y;
2687 *hpos = lastcol + 1;
2688 return 0;
2691 static void
2692 term_mouse_highlight (struct frame *f, int x, int y)
2694 enum window_part part;
2695 Lisp_Object window;
2696 struct window *w;
2697 struct buffer *b;
2699 if (NILP (Vmouse_highlight)
2700 || !f->glyphs_initialized_p)
2701 return;
2703 /* Which window is that in? */
2704 window = window_from_coordinates (f, x, y, &part, &x, &y, 0);
2706 /* Not on a window -> return. */
2707 if (!WINDOWP (window))
2708 return;
2710 if (!EQ (window, mouse_face_window))
2711 term_clear_mouse_face ();
2713 w = XWINDOW (window);
2715 /* Are we in a window whose display is up to date?
2716 And verify the buffer's text has not changed. */
2717 b = XBUFFER (w->buffer);
2718 if (part == ON_TEXT
2719 && EQ (w->window_end_valid, w->buffer)
2720 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
2721 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
2723 int pos, i, nrows = w->current_matrix->nrows;
2724 struct glyph_row *row;
2725 struct glyph *glyph;
2727 /* Find the glyph under X/Y. */
2728 glyph = NULL;
2729 if (y >= 0 && y < nrows)
2731 row = MATRIX_ROW (w->current_matrix, y);
2732 /* Give up if some row before the one we are looking for is
2733 not enabled. */
2734 for (i = 0; i <= y; i++)
2735 if (!MATRIX_ROW (w->current_matrix, i)->enabled_p)
2736 break;
2737 if (i > y /* all rows upto and including the one at Y are enabled */
2738 && row->displays_text_p
2739 && x < window_box_width (w, TEXT_AREA))
2741 glyph = row->glyphs[TEXT_AREA];
2742 if (x >= row->used[TEXT_AREA])
2743 glyph = NULL;
2744 else
2746 glyph += x;
2747 if (!BUFFERP (glyph->object))
2748 glyph = NULL;
2753 /* Clear mouse face if X/Y not over text. */
2754 if (glyph == NULL)
2756 term_clear_mouse_face ();
2757 return;
2760 if (!BUFFERP (glyph->object))
2761 abort ();
2762 pos = glyph->charpos;
2764 /* Check for mouse-face. */
2766 Lisp_Object mouse_face, overlay, position, *overlay_vec;
2767 int noverlays, obegv, ozv;
2768 struct buffer *obuf;
2770 /* If we get an out-of-range value, return now; avoid an error. */
2771 if (pos > BUF_Z (b))
2772 return;
2774 /* Make the window's buffer temporarily current for
2775 overlays_at and compute_char_face. */
2776 obuf = current_buffer;
2777 current_buffer = b;
2778 obegv = BEGV;
2779 ozv = ZV;
2780 BEGV = BEG;
2781 ZV = Z;
2783 /* Is this char mouse-active? */
2784 XSETINT (position, pos);
2786 /* Put all the overlays we want in a vector in overlay_vec. */
2787 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL, 0);
2788 /* Sort overlays into increasing priority order. */
2789 noverlays = sort_overlays (overlay_vec, noverlays, w);
2791 /* Check mouse-face highlighting. */
2792 if (!(EQ (window, mouse_face_window)
2793 && y >= mouse_face_beg_row
2794 && y <= mouse_face_end_row
2795 && (y > mouse_face_beg_row
2796 || x >= mouse_face_beg_col)
2797 && (y < mouse_face_end_row
2798 || x < mouse_face_end_col
2799 || mouse_face_past_end)))
2801 /* Clear the display of the old active region, if any. */
2802 term_clear_mouse_face ();
2804 /* Find the highest priority overlay that has a mouse-face
2805 property. */
2806 overlay = Qnil;
2807 for (i = noverlays - 1; i >= 0; --i)
2809 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
2810 if (!NILP (mouse_face))
2812 overlay = overlay_vec[i];
2813 break;
2817 /* If no overlay applies, get a text property. */
2818 if (NILP (overlay))
2819 mouse_face = Fget_text_property (position, Qmouse_face,
2820 w->buffer);
2822 /* Handle the overlay case. */
2823 if (!NILP (overlay))
2825 /* Find the range of text around this char that
2826 should be active. */
2827 Lisp_Object before, after;
2828 EMACS_INT ignore;
2831 before = Foverlay_start (overlay);
2832 after = Foverlay_end (overlay);
2833 /* Record this as the current active region. */
2834 fast_find_position (w, XFASTINT (before),
2835 &mouse_face_beg_col,
2836 &mouse_face_beg_row);
2838 mouse_face_past_end
2839 = !fast_find_position (w, XFASTINT (after),
2840 &mouse_face_end_col,
2841 &mouse_face_end_row);
2842 mouse_face_window = window;
2844 mouse_face_face_id
2845 = face_at_buffer_position (w, pos, 0, 0,
2846 &ignore, pos + 1, 1, -1);
2848 /* Display it as active. */
2849 term_show_mouse_face (DRAW_MOUSE_FACE);
2851 /* Handle the text property case. */
2852 else if (!NILP (mouse_face))
2854 /* Find the range of text around this char that
2855 should be active. */
2856 Lisp_Object before, after, beginning, end;
2857 EMACS_INT ignore;
2859 beginning = Fmarker_position (w->start);
2860 XSETINT (end, (BUF_Z (b) - XFASTINT (w->window_end_pos)));
2861 before
2862 = Fprevious_single_property_change (make_number (pos + 1),
2863 Qmouse_face,
2864 w->buffer, beginning);
2865 after
2866 = Fnext_single_property_change (position, Qmouse_face,
2867 w->buffer, end);
2869 /* Record this as the current active region. */
2870 fast_find_position (w, XFASTINT (before),
2871 &mouse_face_beg_col,
2872 &mouse_face_beg_row);
2873 mouse_face_past_end
2874 = !fast_find_position (w, XFASTINT (after),
2875 &mouse_face_end_col,
2876 &mouse_face_end_row);
2877 mouse_face_window = window;
2879 mouse_face_face_id
2880 = face_at_buffer_position (w, pos, 0, 0,
2881 &ignore, pos + 1, 1, -1);
2883 /* Display it as active. */
2884 term_show_mouse_face (DRAW_MOUSE_FACE);
2888 /* Look for a `help-echo' property. */
2890 Lisp_Object help;
2892 /* Check overlays first. */
2893 help = Qnil;
2894 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
2896 overlay = overlay_vec[i];
2897 help = Foverlay_get (overlay, Qhelp_echo);
2900 if (!NILP (help))
2902 help_echo_string = help;
2903 help_echo_window = window;
2904 help_echo_object = overlay;
2905 help_echo_pos = pos;
2907 /* Try text properties. */
2908 else if (NILP (help)
2909 && ((STRINGP (glyph->object)
2910 && glyph->charpos >= 0
2911 && glyph->charpos < SCHARS (glyph->object))
2912 || (BUFFERP (glyph->object)
2913 && glyph->charpos >= BEGV
2914 && glyph->charpos < ZV)))
2916 help = Fget_text_property (make_number (glyph->charpos),
2917 Qhelp_echo, glyph->object);
2918 if (!NILP (help))
2920 help_echo_string = help;
2921 help_echo_window = window;
2922 help_echo_object = glyph->object;
2923 help_echo_pos = glyph->charpos;
2928 BEGV = obegv;
2929 ZV = ozv;
2930 current_buffer = obuf;
2935 static int
2936 term_mouse_movement (FRAME_PTR frame, Gpm_Event *event)
2938 /* Has the mouse moved off the glyph it was on at the last sighting? */
2939 if (event->x != last_mouse_x || event->y != last_mouse_y)
2941 frame->mouse_moved = 1;
2942 term_mouse_highlight (frame, event->x, event->y);
2943 /* Remember which glyph we're now on. */
2944 last_mouse_x = event->x;
2945 last_mouse_y = event->y;
2946 return 1;
2948 return 0;
2951 /* Return the current position of the mouse.
2953 Set *f to the frame the mouse is in, or zero if the mouse is in no
2954 Emacs frame. If it is set to zero, all the other arguments are
2955 garbage.
2957 Set *bar_window to Qnil, and *x and *y to the column and
2958 row of the character cell the mouse is over.
2960 Set *time to the time the mouse was at the returned position.
2962 This clears mouse_moved until the next motion
2963 event arrives. */
2964 static void
2965 term_mouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
2966 enum scroll_bar_part *part, Lisp_Object *x,
2967 Lisp_Object *y, unsigned long *time)
2969 struct timeval now;
2971 *fp = SELECTED_FRAME ();
2972 (*fp)->mouse_moved = 0;
2974 *bar_window = Qnil;
2975 *part = 0;
2977 XSETINT (*x, last_mouse_x);
2978 XSETINT (*y, last_mouse_y);
2979 gettimeofday(&now, 0);
2980 *time = (now.tv_sec * 1000) + (now.tv_usec / 1000);
2983 /* Prepare a mouse-event in *RESULT for placement in the input queue.
2985 If the event is a button press, then note that we have grabbed
2986 the mouse. */
2988 static Lisp_Object
2989 term_mouse_click (struct input_event *result, Gpm_Event *event,
2990 struct frame *f)
2992 struct timeval now;
2993 int i, j;
2995 result->kind = GPM_CLICK_EVENT;
2996 for (i = 0, j = GPM_B_LEFT; i < 3; i++, j >>= 1 )
2998 if (event->buttons & j) {
2999 result->code = i; /* button number */
3000 break;
3003 gettimeofday(&now, 0);
3004 result->timestamp = (now.tv_sec * 1000) + (now.tv_usec / 1000);
3006 if (event->type & GPM_UP)
3007 result->modifiers = up_modifier;
3008 else if (event->type & GPM_DOWN)
3009 result->modifiers = down_modifier;
3010 else
3011 result->modifiers = 0;
3013 if (event->type & GPM_SINGLE)
3014 result->modifiers |= click_modifier;
3016 if (event->type & GPM_DOUBLE)
3017 result->modifiers |= double_modifier;
3019 if (event->type & GPM_TRIPLE)
3020 result->modifiers |= triple_modifier;
3022 if (event->type & GPM_DRAG)
3023 result->modifiers |= drag_modifier;
3025 if (!(event->type & (GPM_MOVE | GPM_DRAG))) {
3027 /* 1 << KG_SHIFT */
3028 if (event->modifiers & (1 << 0))
3029 result->modifiers |= shift_modifier;
3031 /* 1 << KG_CTRL */
3032 if (event->modifiers & (1 << 2))
3033 result->modifiers |= ctrl_modifier;
3035 /* 1 << KG_ALT || KG_ALTGR */
3036 if (event->modifiers & (1 << 3)
3037 || event->modifiers & (1 << 1))
3038 result->modifiers |= meta_modifier;
3041 XSETINT (result->x, event->x);
3042 XSETINT (result->y, event->y);
3043 XSETFRAME (result->frame_or_window, f);
3044 result->arg = Qnil;
3045 return Qnil;
3049 handle_one_term_event (struct tty_display_info *tty, Gpm_Event *event, struct input_event* hold_quit)
3051 struct frame *f = XFRAME (tty->top_frame);
3052 struct input_event ie;
3053 int do_help = 0;
3054 int count = 0;
3056 EVENT_INIT (ie);
3057 ie.kind = NO_EVENT;
3058 ie.arg = Qnil;
3060 if (event->type & (GPM_MOVE | GPM_DRAG)) {
3061 previous_help_echo_string = help_echo_string;
3062 help_echo_string = Qnil;
3064 Gpm_DrawPointer (event->x, event->y, fileno (tty->output));
3066 if (!term_mouse_movement (f, event))
3067 help_echo_string = previous_help_echo_string;
3069 /* If the contents of the global variable help_echo_string
3070 has changed, generate a HELP_EVENT. */
3071 if (!NILP (help_echo_string)
3072 || !NILP (previous_help_echo_string))
3073 do_help = 1;
3075 goto done;
3077 else {
3078 f->mouse_moved = 0;
3079 term_mouse_click (&ie, event, f);
3082 done:
3083 if (ie.kind != NO_EVENT)
3085 kbd_buffer_store_event_hold (&ie, hold_quit);
3086 count++;
3089 if (do_help
3090 && !(hold_quit && hold_quit->kind != NO_EVENT))
3092 Lisp_Object frame;
3094 if (f)
3095 XSETFRAME (frame, f);
3096 else
3097 frame = Qnil;
3099 gen_help_event (help_echo_string, frame, help_echo_window,
3100 help_echo_object, help_echo_pos);
3101 count++;
3104 return count;
3107 DEFUN ("gpm-mouse-start", Fgpm_mouse_start, Sgpm_mouse_start,
3108 0, 0, 0,
3109 doc: /* Open a connection to Gpm.
3110 Gpm-mouse can only be activated for one tty at a time. */)
3111 (void)
3113 struct frame *f = SELECTED_FRAME ();
3114 struct tty_display_info *tty
3115 = ((f)->output_method == output_termcap
3116 ? (f)->terminal->display_info.tty : NULL);
3117 Gpm_Connect connection;
3119 if (!tty)
3120 error ("Gpm-mouse only works in the GNU/Linux console");
3121 if (gpm_tty == tty)
3122 return Qnil; /* Already activated, nothing to do. */
3123 if (gpm_tty)
3124 error ("Gpm-mouse can only be activated for one tty at a time");
3126 connection.eventMask = ~0;
3127 connection.defaultMask = ~GPM_HARD;
3128 connection.maxMod = ~0;
3129 connection.minMod = 0;
3130 gpm_zerobased = 1;
3132 if (Gpm_Open (&connection, 0) < 0)
3133 error ("Gpm-mouse failed to connect to the gpm daemon");
3134 else
3136 gpm_tty = tty;
3137 /* `init_sys_modes' arranges for mouse movements sent through gpm_fd
3138 to generate SIGIOs. Apparently we need to call reset_sys_modes
3139 before calling init_sys_modes. */
3140 reset_sys_modes (tty);
3141 init_sys_modes (tty);
3142 add_gpm_wait_descriptor (gpm_fd);
3143 return Qnil;
3147 void
3148 close_gpm (int fd)
3150 if (fd >= 0)
3151 delete_gpm_wait_descriptor (fd);
3152 while (Gpm_Close()); /* close all the stack */
3153 gpm_tty = NULL;
3156 DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop, Sgpm_mouse_stop,
3157 0, 0, 0,
3158 doc: /* Close a connection to Gpm. */)
3159 (void)
3161 struct frame *f = SELECTED_FRAME ();
3162 struct tty_display_info *tty
3163 = ((f)->output_method == output_termcap
3164 ? (f)->terminal->display_info.tty : NULL);
3166 if (!tty || gpm_tty != tty)
3167 return Qnil; /* Not activated on this terminal, nothing to do. */
3169 close_gpm (gpm_fd);
3170 return Qnil;
3172 #endif /* HAVE_GPM */
3175 #ifndef MSDOS
3176 /***********************************************************************
3177 Initialization
3178 ***********************************************************************/
3180 /* Initialize the tty-dependent part of frame F. The frame must
3181 already have its device initialized. */
3183 void
3184 create_tty_output (struct frame *f)
3186 struct tty_output *t;
3188 if (! FRAME_TERMCAP_P (f))
3189 abort ();
3191 t = xmalloc (sizeof (struct tty_output));
3192 memset (t, 0, sizeof (struct tty_output));
3194 t->display_info = FRAME_TERMINAL (f)->display_info.tty;
3196 f->output_data.tty = t;
3199 /* Delete frame F's face cache, and its tty-dependent part. */
3201 static void
3202 tty_free_frame_resources (struct frame *f)
3204 if (! FRAME_TERMCAP_P (f))
3205 abort ();
3207 if (FRAME_FACE_CACHE (f))
3208 free_frame_faces (f);
3210 xfree (f->output_data.tty);
3213 #else /* MSDOS */
3215 /* Delete frame F's face cache. */
3217 static void
3218 tty_free_frame_resources (struct frame *f)
3220 if (! FRAME_TERMCAP_P (f) && ! FRAME_MSDOS_P (f))
3221 abort ();
3223 if (FRAME_FACE_CACHE (f))
3224 free_frame_faces (f);
3226 #endif /* MSDOS */
3228 /* Reset the hooks in TERMINAL. */
3230 static void
3231 clear_tty_hooks (struct terminal *terminal)
3233 terminal->rif = 0;
3234 terminal->cursor_to_hook = 0;
3235 terminal->raw_cursor_to_hook = 0;
3236 terminal->clear_to_end_hook = 0;
3237 terminal->clear_frame_hook = 0;
3238 terminal->clear_end_of_line_hook = 0;
3239 terminal->ins_del_lines_hook = 0;
3240 terminal->insert_glyphs_hook = 0;
3241 terminal->write_glyphs_hook = 0;
3242 terminal->delete_glyphs_hook = 0;
3243 terminal->ring_bell_hook = 0;
3244 terminal->reset_terminal_modes_hook = 0;
3245 terminal->set_terminal_modes_hook = 0;
3246 terminal->update_begin_hook = 0;
3247 terminal->update_end_hook = 0;
3248 terminal->set_terminal_window_hook = 0;
3249 terminal->mouse_position_hook = 0;
3250 terminal->frame_rehighlight_hook = 0;
3251 terminal->frame_raise_lower_hook = 0;
3252 terminal->fullscreen_hook = 0;
3253 terminal->set_vertical_scroll_bar_hook = 0;
3254 terminal->condemn_scroll_bars_hook = 0;
3255 terminal->redeem_scroll_bar_hook = 0;
3256 terminal->judge_scroll_bars_hook = 0;
3257 terminal->read_socket_hook = 0;
3258 terminal->frame_up_to_date_hook = 0;
3260 /* Leave these two set, or suspended frames are not deleted
3261 correctly. */
3262 terminal->delete_frame_hook = &tty_free_frame_resources;
3263 terminal->delete_terminal_hook = &delete_tty;
3266 /* Initialize hooks in TERMINAL with the values needed for a tty. */
3268 static void
3269 set_tty_hooks (struct terminal *terminal)
3271 terminal->rif = 0; /* ttys don't support window-based redisplay. */
3273 terminal->cursor_to_hook = &tty_cursor_to;
3274 terminal->raw_cursor_to_hook = &tty_raw_cursor_to;
3276 terminal->clear_to_end_hook = &tty_clear_to_end;
3277 terminal->clear_frame_hook = &tty_clear_frame;
3278 terminal->clear_end_of_line_hook = &tty_clear_end_of_line;
3280 terminal->ins_del_lines_hook = &tty_ins_del_lines;
3282 terminal->insert_glyphs_hook = &tty_insert_glyphs;
3283 terminal->write_glyphs_hook = &tty_write_glyphs;
3284 terminal->delete_glyphs_hook = &tty_delete_glyphs;
3286 terminal->ring_bell_hook = &tty_ring_bell;
3288 terminal->reset_terminal_modes_hook = &tty_reset_terminal_modes;
3289 terminal->set_terminal_modes_hook = &tty_set_terminal_modes;
3290 terminal->update_begin_hook = 0; /* Not needed. */
3291 terminal->update_end_hook = &tty_update_end;
3292 terminal->set_terminal_window_hook = &tty_set_terminal_window;
3294 terminal->mouse_position_hook = 0; /* Not needed. */
3295 terminal->frame_rehighlight_hook = 0; /* Not needed. */
3296 terminal->frame_raise_lower_hook = 0; /* Not needed. */
3298 terminal->set_vertical_scroll_bar_hook = 0; /* Not needed. */
3299 terminal->condemn_scroll_bars_hook = 0; /* Not needed. */
3300 terminal->redeem_scroll_bar_hook = 0; /* Not needed. */
3301 terminal->judge_scroll_bars_hook = 0; /* Not needed. */
3303 terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */
3304 terminal->frame_up_to_date_hook = 0; /* Not needed. */
3306 terminal->delete_frame_hook = &tty_free_frame_resources;
3307 terminal->delete_terminal_hook = &delete_tty;
3310 /* Drop the controlling terminal if fd is the same device. */
3311 static void
3312 dissociate_if_controlling_tty (int fd)
3314 #ifndef DOS_NT
3315 int pgid;
3316 EMACS_GET_TTY_PGRP (fd, &pgid); /* If tcgetpgrp succeeds, fd is the ctty. */
3317 if (pgid != -1)
3319 #if defined (USG5)
3320 setpgrp ();
3321 no_controlling_tty = 1;
3322 #elif defined (CYGWIN)
3323 setsid ();
3324 no_controlling_tty = 1;
3325 #else
3326 #ifdef TIOCNOTTY /* Try BSD ioctls. */
3327 sigblock (sigmask (SIGTTOU));
3328 fd = emacs_open (DEV_TTY, O_RDWR, 0);
3329 if (fd != -1 && ioctl (fd, TIOCNOTTY, 0) != -1)
3331 no_controlling_tty = 1;
3333 if (fd != -1)
3334 emacs_close (fd);
3335 sigunblock (sigmask (SIGTTOU));
3336 #else
3337 /* Unknown system. */
3338 croak ();
3339 #endif /* ! TIOCNOTTY */
3340 #endif /* ! USG */
3342 #endif /* !DOS_NT */
3345 /* Create a termcap display on the tty device with the given name and
3346 type.
3348 If NAME is NULL, then use the controlling tty, i.e., "/dev/tty".
3349 Otherwise NAME should be a path to the tty device file,
3350 e.g. "/dev/pts/7".
3352 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
3354 If MUST_SUCCEED is true, then all errors are fatal. */
3356 struct terminal *
3357 init_tty (const char *name, const char *terminal_type, int must_succeed)
3359 char *area = NULL;
3360 char **address = &area;
3361 int buffer_size = 4096;
3362 register char *p = NULL;
3363 int status;
3364 struct tty_display_info *tty = NULL;
3365 struct terminal *terminal = NULL;
3366 int ctty = 0; /* 1 if asked to open controlling tty. */
3368 if (!terminal_type)
3369 maybe_fatal (must_succeed, 0,
3370 "Unknown terminal type",
3371 "Unknown terminal type");
3373 if (name == NULL)
3374 name = DEV_TTY;
3375 if (!strcmp (name, DEV_TTY))
3376 ctty = 1;
3378 /* If we already have a terminal on the given device, use that. If
3379 all such terminals are suspended, create a new one instead. */
3380 /* XXX Perhaps this should be made explicit by having init_tty
3381 always create a new terminal and separating terminal and frame
3382 creation on Lisp level. */
3383 terminal = get_named_tty (name);
3384 if (terminal)
3385 return terminal;
3387 terminal = create_terminal ();
3388 #ifdef MSDOS
3389 if (been_here > 0)
3390 maybe_fatal (1, 0, "Attempt to create another terminal %s", "",
3391 name, "");
3392 been_here = 1;
3393 tty = &the_only_display_info;
3394 #else
3395 tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info));
3396 #endif
3397 memset (tty, 0, sizeof (struct tty_display_info));
3398 tty->next = tty_list;
3399 tty_list = tty;
3401 terminal->type = output_termcap;
3402 terminal->display_info.tty = tty;
3403 tty->terminal = terminal;
3405 tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
3406 Wcm_clear (tty);
3408 #ifndef DOS_NT
3409 set_tty_hooks (terminal);
3412 int fd;
3413 FILE *file;
3415 #ifdef O_IGNORE_CTTY
3416 if (!ctty)
3417 /* Open the terminal device. Don't recognize it as our
3418 controlling terminal, and don't make it the controlling tty
3419 if we don't have one at the moment. */
3420 fd = emacs_open (name, O_RDWR | O_IGNORE_CTTY | O_NOCTTY, 0);
3421 else
3422 #else
3423 /* Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
3424 defined on Hurd. On other systems, we need to explicitly
3425 dissociate ourselves from the controlling tty when we want to
3426 open a frame on the same terminal. */
3427 fd = emacs_open (name, O_RDWR | O_NOCTTY, 0);
3428 #endif /* O_IGNORE_CTTY */
3430 tty->name = xstrdup (name);
3431 terminal->name = xstrdup (name);
3433 if (fd < 0)
3434 maybe_fatal (must_succeed, terminal,
3435 "Could not open file: %s",
3436 "Could not open file: %s",
3437 name);
3438 if (!isatty (fd))
3440 close (fd);
3441 maybe_fatal (must_succeed, terminal,
3442 "Not a tty device: %s",
3443 "Not a tty device: %s",
3444 name);
3447 #ifndef O_IGNORE_CTTY
3448 if (!ctty)
3449 dissociate_if_controlling_tty (fd);
3450 #endif
3452 file = fdopen (fd, "w+");
3453 tty->input = file;
3454 tty->output = file;
3457 tty->type = xstrdup (terminal_type);
3459 add_keyboard_wait_descriptor (fileno (tty->input));
3461 #endif /* !DOS_NT */
3463 encode_terminal_src_size = 0;
3464 encode_terminal_dst_size = 0;
3466 #ifdef HAVE_GPM
3467 terminal->mouse_position_hook = term_mouse_position;
3468 mouse_face_window = Qnil;
3469 #endif
3471 #ifdef DOS_NT
3472 #ifdef WINDOWSNT
3473 initialize_w32_display (terminal);
3474 #else /* MSDOS */
3475 if (strcmp (terminal_type, "internal") == 0)
3476 terminal->type = output_msdos_raw;
3477 initialize_msdos_display (terminal);
3478 #endif /* MSDOS */
3479 tty->output = stdout;
3480 tty->input = stdin;
3481 /* The following two are inaccessible from w32console.c. */
3482 terminal->delete_frame_hook = &tty_free_frame_resources;
3483 terminal->delete_terminal_hook = &delete_tty;
3485 tty->name = xstrdup (name);
3486 terminal->name = xstrdup (name);
3487 tty->type = xstrdup (terminal_type);
3489 add_keyboard_wait_descriptor (0);
3491 Wcm_clear (tty);
3493 #ifdef WINDOWSNT
3495 struct frame *f = XFRAME (selected_frame);
3497 FrameRows (tty) = FRAME_LINES (f);
3498 FrameCols (tty) = FRAME_COLS (f);
3499 tty->specified_window = FRAME_LINES (f);
3501 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
3502 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
3504 #else /* MSDOS */
3506 int height, width;
3507 get_tty_size (fileno (tty->input), &width, &height);
3508 FrameCols (tty) = width;
3509 FrameRows (tty) = height;
3511 #endif /* MSDOS */
3512 tty->delete_in_insert_mode = 1;
3514 UseTabs (tty) = 0;
3515 terminal->scroll_region_ok = 0;
3517 /* Seems to insert lines when it's not supposed to, messing up the
3518 display. In doing a trace, it didn't seem to be called much, so I
3519 don't think we're losing anything by turning it off. */
3520 terminal->line_ins_del_ok = 0;
3521 #ifdef WINDOWSNT
3522 terminal->char_ins_del_ok = 1;
3523 baud_rate = 19200;
3524 #else /* MSDOS */
3525 terminal->char_ins_del_ok = 0;
3526 init_baud_rate (fileno (tty->input));
3527 #endif /* MSDOS */
3529 tty->TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
3531 #else /* not DOS_NT */
3533 Wcm_clear (tty);
3535 tty->termcap_term_buffer = (char *) xmalloc (buffer_size);
3537 /* On some systems, tgetent tries to access the controlling
3538 terminal. */
3539 sigblock (sigmask (SIGTTOU));
3540 status = tgetent (tty->termcap_term_buffer, terminal_type);
3541 sigunblock (sigmask (SIGTTOU));
3543 if (status < 0)
3545 #ifdef TERMINFO
3546 maybe_fatal (must_succeed, terminal,
3547 "Cannot open terminfo database file",
3548 "Cannot open terminfo database file");
3549 #else
3550 maybe_fatal (must_succeed, terminal,
3551 "Cannot open termcap database file",
3552 "Cannot open termcap database file");
3553 #endif
3555 if (status == 0)
3557 maybe_fatal (must_succeed, terminal,
3558 "Terminal type %s is not defined",
3559 "Terminal type %s is not defined.\n\
3560 If that is not the actual type of terminal you have,\n\
3561 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3562 `setenv TERM ...') to specify the correct type. It may be necessary\n"
3563 #ifdef TERMINFO
3564 "to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3565 #else
3566 "to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3567 #endif
3568 terminal_type);
3571 #ifndef TERMINFO
3572 if (strlen (tty->termcap_term_buffer) >= buffer_size)
3573 abort ();
3574 buffer_size = strlen (tty->termcap_term_buffer);
3575 #endif
3576 tty->termcap_strings_buffer = area = (char *) xmalloc (buffer_size);
3577 tty->TS_ins_line = tgetstr ("al", address);
3578 tty->TS_ins_multi_lines = tgetstr ("AL", address);
3579 tty->TS_bell = tgetstr ("bl", address);
3580 BackTab (tty) = tgetstr ("bt", address);
3581 tty->TS_clr_to_bottom = tgetstr ("cd", address);
3582 tty->TS_clr_line = tgetstr ("ce", address);
3583 tty->TS_clr_frame = tgetstr ("cl", address);
3584 ColPosition (tty) = NULL; /* tgetstr ("ch", address); */
3585 AbsPosition (tty) = tgetstr ("cm", address);
3586 CR (tty) = tgetstr ("cr", address);
3587 tty->TS_set_scroll_region = tgetstr ("cs", address);
3588 tty->TS_set_scroll_region_1 = tgetstr ("cS", address);
3589 RowPosition (tty) = tgetstr ("cv", address);
3590 tty->TS_del_char = tgetstr ("dc", address);
3591 tty->TS_del_multi_chars = tgetstr ("DC", address);
3592 tty->TS_del_line = tgetstr ("dl", address);
3593 tty->TS_del_multi_lines = tgetstr ("DL", address);
3594 tty->TS_delete_mode = tgetstr ("dm", address);
3595 tty->TS_end_delete_mode = tgetstr ("ed", address);
3596 tty->TS_end_insert_mode = tgetstr ("ei", address);
3597 Home (tty) = tgetstr ("ho", address);
3598 tty->TS_ins_char = tgetstr ("ic", address);
3599 tty->TS_ins_multi_chars = tgetstr ("IC", address);
3600 tty->TS_insert_mode = tgetstr ("im", address);
3601 tty->TS_pad_inserted_char = tgetstr ("ip", address);
3602 tty->TS_end_keypad_mode = tgetstr ("ke", address);
3603 tty->TS_keypad_mode = tgetstr ("ks", address);
3604 LastLine (tty) = tgetstr ("ll", address);
3605 Right (tty) = tgetstr ("nd", address);
3606 Down (tty) = tgetstr ("do", address);
3607 if (!Down (tty))
3608 Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do" */
3609 if (tgetflag ("bs"))
3610 Left (tty) = "\b"; /* can't possibly be longer! */
3611 else /* (Actually, "bs" is obsolete...) */
3612 Left (tty) = tgetstr ("le", address);
3613 if (!Left (tty))
3614 Left (tty) = tgetstr ("bc", address); /* Obsolete name for "le" */
3615 tty->TS_pad_char = tgetstr ("pc", address);
3616 tty->TS_repeat = tgetstr ("rp", address);
3617 tty->TS_end_standout_mode = tgetstr ("se", address);
3618 tty->TS_fwd_scroll = tgetstr ("sf", address);
3619 tty->TS_standout_mode = tgetstr ("so", address);
3620 tty->TS_rev_scroll = tgetstr ("sr", address);
3621 tty->Wcm->cm_tab = tgetstr ("ta", address);
3622 tty->TS_end_termcap_modes = tgetstr ("te", address);
3623 tty->TS_termcap_modes = tgetstr ("ti", address);
3624 Up (tty) = tgetstr ("up", address);
3625 tty->TS_visible_bell = tgetstr ("vb", address);
3626 tty->TS_cursor_normal = tgetstr ("ve", address);
3627 tty->TS_cursor_visible = tgetstr ("vs", address);
3628 tty->TS_cursor_invisible = tgetstr ("vi", address);
3629 tty->TS_set_window = tgetstr ("wi", address);
3631 tty->TS_enter_underline_mode = tgetstr ("us", address);
3632 tty->TS_exit_underline_mode = tgetstr ("ue", address);
3633 tty->TS_enter_bold_mode = tgetstr ("md", address);
3634 tty->TS_enter_dim_mode = tgetstr ("mh", address);
3635 tty->TS_enter_blink_mode = tgetstr ("mb", address);
3636 tty->TS_enter_reverse_mode = tgetstr ("mr", address);
3637 tty->TS_enter_alt_charset_mode = tgetstr ("as", address);
3638 tty->TS_exit_alt_charset_mode = tgetstr ("ae", address);
3639 tty->TS_exit_attribute_mode = tgetstr ("me", address);
3641 MultiUp (tty) = tgetstr ("UP", address);
3642 MultiDown (tty) = tgetstr ("DO", address);
3643 MultiLeft (tty) = tgetstr ("LE", address);
3644 MultiRight (tty) = tgetstr ("RI", address);
3646 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
3647 color because we can't switch back to the default foreground and
3648 background. */
3649 tty->TS_orig_pair = tgetstr ("op", address);
3650 if (tty->TS_orig_pair)
3652 tty->TS_set_foreground = tgetstr ("AF", address);
3653 tty->TS_set_background = tgetstr ("AB", address);
3654 if (!tty->TS_set_foreground)
3656 /* SVr4. */
3657 tty->TS_set_foreground = tgetstr ("Sf", address);
3658 tty->TS_set_background = tgetstr ("Sb", address);
3661 tty->TN_max_colors = tgetnum ("Co");
3662 tty->TN_max_pairs = tgetnum ("pa");
3664 tty->TN_no_color_video = tgetnum ("NC");
3665 if (tty->TN_no_color_video == -1)
3666 tty->TN_no_color_video = 0;
3669 tty_default_color_capabilities (tty, 1);
3671 MagicWrap (tty) = tgetflag ("xn");
3672 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
3673 the former flag imply the latter. */
3674 AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
3675 terminal->memory_below_frame = tgetflag ("db");
3676 tty->TF_hazeltine = tgetflag ("hz");
3677 terminal->must_write_spaces = tgetflag ("in");
3678 tty->meta_key = tgetflag ("km") || tgetflag ("MT");
3679 tty->TF_insmode_motion = tgetflag ("mi");
3680 tty->TF_standout_motion = tgetflag ("ms");
3681 tty->TF_underscore = tgetflag ("ul");
3682 tty->TF_teleray = tgetflag ("xt");
3684 #endif /* !DOS_NT */
3685 terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
3686 init_kboard (terminal->kboard);
3687 terminal->kboard->Vwindow_system = Qnil;
3688 terminal->kboard->next_kboard = all_kboards;
3689 all_kboards = terminal->kboard;
3690 terminal->kboard->reference_count++;
3691 /* Don't let the initial kboard remain current longer than necessary.
3692 That would cause problems if a file loaded on startup tries to
3693 prompt in the mini-buffer. */
3694 if (current_kboard == initial_kboard)
3695 current_kboard = terminal->kboard;
3696 #ifndef DOS_NT
3697 term_get_fkeys (address, terminal->kboard);
3699 /* Get frame size from system, or else from termcap. */
3701 int height, width;
3702 get_tty_size (fileno (tty->input), &width, &height);
3703 FrameCols (tty) = width;
3704 FrameRows (tty) = height;
3707 if (FrameCols (tty) <= 0)
3708 FrameCols (tty) = tgetnum ("co");
3709 if (FrameRows (tty) <= 0)
3710 FrameRows (tty) = tgetnum ("li");
3712 if (FrameRows (tty) < 3 || FrameCols (tty) < 3)
3713 maybe_fatal (must_succeed, terminal,
3714 "Screen size %dx%d is too small",
3715 "Screen size %dx%d is too small",
3716 FrameCols (tty), FrameRows (tty));
3718 TabWidth (tty) = tgetnum ("tw");
3720 if (!tty->TS_bell)
3721 tty->TS_bell = "\07";
3723 if (!tty->TS_fwd_scroll)
3724 tty->TS_fwd_scroll = Down (tty);
3726 PC = tty->TS_pad_char ? *tty->TS_pad_char : 0;
3728 if (TabWidth (tty) < 0)
3729 TabWidth (tty) = 8;
3731 /* Turned off since /etc/termcap seems to have :ta= for most terminals
3732 and newer termcap doc does not seem to say there is a default.
3733 if (!tty->Wcm->cm_tab)
3734 tty->Wcm->cm_tab = "\t";
3737 /* We don't support standout modes that use `magic cookies', so
3738 turn off any that do. */
3739 if (tty->TS_standout_mode && tgetnum ("sg") >= 0)
3741 tty->TS_standout_mode = 0;
3742 tty->TS_end_standout_mode = 0;
3744 if (tty->TS_enter_underline_mode && tgetnum ("ug") >= 0)
3746 tty->TS_enter_underline_mode = 0;
3747 tty->TS_exit_underline_mode = 0;
3750 /* If there's no standout mode, try to use underlining instead. */
3751 if (tty->TS_standout_mode == 0)
3753 tty->TS_standout_mode = tty->TS_enter_underline_mode;
3754 tty->TS_end_standout_mode = tty->TS_exit_underline_mode;
3757 /* If no `se' string, try using a `me' string instead.
3758 If that fails, we can't use standout mode at all. */
3759 if (tty->TS_end_standout_mode == 0)
3761 char *s = tgetstr ("me", address);
3762 if (s != 0)
3763 tty->TS_end_standout_mode = s;
3764 else
3765 tty->TS_standout_mode = 0;
3768 if (tty->TF_teleray)
3770 tty->Wcm->cm_tab = 0;
3771 /* We can't support standout mode, because it uses magic cookies. */
3772 tty->TS_standout_mode = 0;
3773 /* But that means we cannot rely on ^M to go to column zero! */
3774 CR (tty) = 0;
3775 /* LF can't be trusted either -- can alter hpos */
3776 /* if move at column 0 thru a line with TS_standout_mode */
3777 Down (tty) = 0;
3780 /* Special handling for certain terminal types known to need it */
3782 if (!strcmp (terminal_type, "supdup"))
3784 terminal->memory_below_frame = 1;
3785 tty->Wcm->cm_losewrap = 1;
3787 if (!strncmp (terminal_type, "c10", 3)
3788 || !strcmp (terminal_type, "perq"))
3790 /* Supply a makeshift :wi string.
3791 This string is not valid in general since it works only
3792 for windows starting at the upper left corner;
3793 but that is all Emacs uses.
3795 This string works only if the frame is using
3796 the top of the video memory, because addressing is memory-relative.
3797 So first check the :ti string to see if that is true.
3799 It would be simpler if the :wi string could go in the termcap
3800 entry, but it can't because it is not fully valid.
3801 If it were in the termcap entry, it would confuse other programs. */
3802 if (!tty->TS_set_window)
3804 p = tty->TS_termcap_modes;
3805 while (*p && strcmp (p, "\033v "))
3806 p++;
3807 if (*p)
3808 tty->TS_set_window = "\033v%C %C %C %C ";
3810 /* Termcap entry often fails to have :in: flag */
3811 terminal->must_write_spaces = 1;
3812 /* :ti string typically fails to have \E^G! in it */
3813 /* This limits scope of insert-char to one line. */
3814 strcpy (area, tty->TS_termcap_modes);
3815 strcat (area, "\033\007!");
3816 tty->TS_termcap_modes = area;
3817 area += strlen (area) + 1;
3818 p = AbsPosition (tty);
3819 /* Change all %+ parameters to %C, to handle
3820 values above 96 correctly for the C100. */
3821 while (*p)
3823 if (p[0] == '%' && p[1] == '+')
3824 p[1] = 'C';
3825 p++;
3829 tty->specified_window = FrameRows (tty);
3831 if (Wcm_init (tty) == -1) /* can't do cursor motion */
3833 maybe_fatal (must_succeed, terminal,
3834 "Terminal type \"%s\" is not powerful enough to run Emacs",
3835 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3836 It lacks the ability to position the cursor.\n\
3837 If that is not the actual type of terminal you have,\n\
3838 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3839 `setenv TERM ...') to specify the correct type. It may be necessary\n"
3840 # ifdef TERMINFO
3841 "to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3842 # else /* TERMCAP */
3843 "to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3844 # endif /* TERMINFO */
3845 terminal_type);
3848 if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
3849 maybe_fatal (must_succeed, terminal,
3850 "Could not determine the frame size",
3851 "Could not determine the frame size");
3853 tty->delete_in_insert_mode
3854 = tty->TS_delete_mode && tty->TS_insert_mode
3855 && !strcmp (tty->TS_delete_mode, tty->TS_insert_mode);
3857 tty->se_is_so = (tty->TS_standout_mode
3858 && tty->TS_end_standout_mode
3859 && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode));
3861 UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8;
3863 terminal->scroll_region_ok
3864 = (tty->Wcm->cm_abs
3865 && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
3867 terminal->line_ins_del_ok
3868 = (((tty->TS_ins_line || tty->TS_ins_multi_lines)
3869 && (tty->TS_del_line || tty->TS_del_multi_lines))
3870 || (terminal->scroll_region_ok
3871 && tty->TS_fwd_scroll && tty->TS_rev_scroll));
3873 terminal->char_ins_del_ok
3874 = ((tty->TS_ins_char || tty->TS_insert_mode
3875 || tty->TS_pad_inserted_char || tty->TS_ins_multi_chars)
3876 && (tty->TS_del_char || tty->TS_del_multi_chars));
3878 terminal->fast_clear_end_of_line = tty->TS_clr_line != 0;
3880 init_baud_rate (fileno (tty->input));
3882 #endif /* not DOS_NT */
3884 /* Init system terminal modes (RAW or CBREAK, etc.). */
3885 init_sys_modes (tty);
3887 return terminal;
3891 static void
3892 vfatal (const char *str, va_list ap)
3894 fprintf (stderr, "emacs: ");
3895 vfprintf (stderr, str, ap);
3896 if (!(strlen (str) > 0 && str[strlen (str) - 1] == '\n'))
3897 fprintf (stderr, "\n");
3898 va_end (ap);
3899 fflush (stderr);
3900 exit (1);
3904 /* Auxiliary error-handling function for init_tty.
3905 Delete TERMINAL, then call error or fatal with str1 or str2,
3906 respectively, according to MUST_SUCCEED. */
3908 static void
3909 maybe_fatal (int must_succeed, struct terminal *terminal,
3910 const char *str1, const char *str2, ...)
3912 va_list ap;
3913 va_start (ap, str2);
3914 if (terminal)
3915 delete_tty (terminal);
3917 if (must_succeed)
3918 vfatal (str2, ap);
3919 else
3920 verror (str1, ap);
3922 va_end (ap);
3923 abort ();
3926 void
3927 fatal (const char *str, ...)
3929 va_list ap;
3930 va_start (ap, str);
3931 vfatal (str, ap);
3932 va_end (ap);
3937 /* Delete the given tty terminal, closing all frames on it. */
3939 static void
3940 delete_tty (struct terminal *terminal)
3942 struct tty_display_info *tty;
3944 /* Protect against recursive calls. delete_frame in
3945 delete_terminal calls us back when it deletes our last frame. */
3946 if (!terminal->name)
3947 return;
3949 if (terminal->type != output_termcap)
3950 abort ();
3952 tty = terminal->display_info.tty;
3954 if (tty == tty_list)
3955 tty_list = tty->next;
3956 else
3958 struct tty_display_info *p;
3959 for (p = tty_list; p && p->next != tty; p = p->next)
3962 if (! p)
3963 /* This should not happen. */
3964 abort ();
3966 p->next = tty->next;
3967 tty->next = 0;
3970 /* reset_sys_modes needs a valid device, so this call needs to be
3971 before delete_terminal. */
3972 reset_sys_modes (tty);
3974 delete_terminal (terminal);
3976 xfree (tty->name);
3977 xfree (tty->type);
3979 if (tty->input)
3981 delete_keyboard_wait_descriptor (fileno (tty->input));
3982 if (tty->input != stdin)
3983 fclose (tty->input);
3985 if (tty->output && tty->output != stdout && tty->output != tty->input)
3986 fclose (tty->output);
3987 if (tty->termscript)
3988 fclose (tty->termscript);
3990 xfree (tty->old_tty);
3991 xfree (tty->Wcm);
3992 xfree (tty->termcap_strings_buffer);
3993 xfree (tty->termcap_term_buffer);
3995 memset (tty, 0, sizeof (struct tty_display_info));
3996 xfree (tty);
4001 /* Mark the pointers in the tty_display_info objects.
4002 Called by the Fgarbage_collector. */
4004 void
4005 mark_ttys (void)
4007 struct tty_display_info *tty;
4009 for (tty = tty_list; tty; tty = tty->next)
4010 mark_object (tty->top_frame);
4015 void
4016 syms_of_term (void)
4018 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
4019 doc: /* Non-nil means the system uses terminfo rather than termcap.
4020 This variable can be used by terminal emulator packages. */);
4021 #ifdef TERMINFO
4022 system_uses_terminfo = 1;
4023 #else
4024 system_uses_terminfo = 0;
4025 #endif
4027 DEFVAR_LISP ("suspend-tty-functions", &Vsuspend_tty_functions,
4028 doc: /* Functions to be run after suspending a tty.
4029 The functions are run with one argument, the terminal object to be suspended.
4030 See `suspend-tty'. */);
4031 Vsuspend_tty_functions = Qnil;
4034 DEFVAR_LISP ("resume-tty-functions", &Vresume_tty_functions,
4035 doc: /* Functions to be run after resuming a tty.
4036 The functions are run with one argument, the terminal object that was revived.
4037 See `resume-tty'. */);
4038 Vresume_tty_functions = Qnil;
4040 DEFVAR_BOOL ("visible-cursor", &visible_cursor,
4041 doc: /* Non-nil means to make the cursor very visible.
4042 This only has an effect when running in a text terminal.
4043 What means \"very visible\" is up to your terminal. It may make the cursor
4044 bigger, or it may make it blink, or it may do nothing at all. */);
4045 visible_cursor = 1;
4047 defsubr (&Stty_display_color_p);
4048 defsubr (&Stty_display_color_cells);
4049 defsubr (&Stty_no_underline);
4050 defsubr (&Stty_type);
4051 defsubr (&Scontrolling_tty_p);
4052 defsubr (&Ssuspend_tty);
4053 defsubr (&Sresume_tty);
4054 #ifdef HAVE_GPM
4055 defsubr (&Sgpm_mouse_start);
4056 defsubr (&Sgpm_mouse_stop);
4058 staticpro (&mouse_face_window);
4059 #endif /* HAVE_GPM */
4061 #ifndef DOS_NT
4062 default_orig_pair = NULL;
4063 default_set_foreground = NULL;
4064 default_set_background = NULL;
4065 #endif /* !DOS_NT */
4067 encode_terminal_src = NULL;
4068 encode_terminal_dst = NULL;
4073 /* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193
4074 (do not change this comment) */