* NEWS: Mention --enable-checking is now supported on Windows.
[emacs.git] / src / term.c
blob3233db84cf7471e9dda24298fa8af62dad31b8ab
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 #if HAVE_TERMIOS_H
35 #include <termios.h> /* For TIOCNOTTY. */
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 extern Lisp_Object Qspace, QCalign_to, QCwidth;
137 /* Functions to call after suspending a tty. */
138 Lisp_Object Vsuspend_tty_functions;
140 /* Functions to call after resuming a tty. */
141 Lisp_Object Vresume_tty_functions;
143 /* Chain of all tty device parameters. */
144 struct tty_display_info *tty_list;
146 /* Nonzero means no need to redraw the entire frame on resuming a
147 suspended Emacs. This is useful on terminals with multiple
148 pages, where one page is used for Emacs and another for all
149 else. */
150 int no_redraw_on_reenter;
152 /* Meaning of bits in no_color_video. Each bit set means that the
153 corresponding attribute cannot be combined with colors. */
155 enum no_color_bit
157 NC_STANDOUT = 1 << 0,
158 NC_UNDERLINE = 1 << 1,
159 NC_REVERSE = 1 << 2,
160 NC_BLINK = 1 << 3,
161 NC_DIM = 1 << 4,
162 NC_BOLD = 1 << 5,
163 NC_INVIS = 1 << 6,
164 NC_PROTECT = 1 << 7,
165 NC_ALT_CHARSET = 1 << 8
168 /* internal state */
170 /* The largest frame width in any call to calculate_costs. */
172 int max_frame_cols;
174 /* The largest frame height in any call to calculate_costs. */
176 int max_frame_lines;
178 /* Non-zero if we have dropped our controlling tty and therefore
179 should not open a frame on stdout. */
180 static int no_controlling_tty;
182 /* Provided for lisp packages. */
184 static int system_uses_terminfo;
186 char *tparam ();
188 extern char *tgetstr (char *, char **);
191 #ifdef HAVE_GPM
192 #include <sys/fcntl.h>
194 static void term_clear_mouse_face (void);
195 static void term_mouse_highlight (struct frame *f, int x, int y);
197 /* The device for which we have enabled gpm support (or NULL). */
198 struct tty_display_info *gpm_tty = NULL;
200 /* These variables describe the range of text currently shown in its
201 mouse-face, together with the window they apply to. As long as
202 the mouse stays within this range, we need not redraw anything on
203 its account. Rows and columns are glyph matrix positions in
204 MOUSE_FACE_WINDOW. */
205 static int mouse_face_beg_row, mouse_face_beg_col;
206 static int mouse_face_end_row, mouse_face_end_col;
207 static int mouse_face_past_end;
208 static Lisp_Object mouse_face_window;
209 static int mouse_face_face_id;
211 static int pos_x, pos_y;
212 static int last_mouse_x, last_mouse_y;
213 #endif /* HAVE_GPM */
215 /* Ring the bell on a tty. */
217 static void
218 tty_ring_bell (struct frame *f)
220 struct tty_display_info *tty = FRAME_TTY (f);
222 if (tty->output)
224 OUTPUT (tty, (tty->TS_visible_bell && visible_bell
225 ? tty->TS_visible_bell
226 : tty->TS_bell));
227 fflush (tty->output);
231 /* Set up termcap modes for Emacs. */
233 void
234 tty_set_terminal_modes (struct terminal *terminal)
236 struct tty_display_info *tty = terminal->display_info.tty;
238 if (tty->output)
240 if (tty->TS_termcap_modes)
241 OUTPUT (tty, tty->TS_termcap_modes);
242 else
244 /* Output enough newlines to scroll all the old screen contents
245 off the screen, so it won't be overwritten and lost. */
246 int i;
247 current_tty = tty;
248 for (i = 0; i < FRAME_LINES (XFRAME (selected_frame)); i++)
249 cmputc ('\n');
252 OUTPUT_IF (tty, tty->TS_termcap_modes);
253 OUTPUT_IF (tty, visible_cursor ? tty->TS_cursor_visible : tty->TS_cursor_normal);
254 OUTPUT_IF (tty, tty->TS_keypad_mode);
255 losecursor (tty);
256 fflush (tty->output);
260 /* Reset termcap modes before exiting Emacs. */
262 void
263 tty_reset_terminal_modes (struct terminal *terminal)
265 struct tty_display_info *tty = terminal->display_info.tty;
267 if (tty->output)
269 tty_turn_off_highlight (tty);
270 tty_turn_off_insert (tty);
271 OUTPUT_IF (tty, tty->TS_end_keypad_mode);
272 OUTPUT_IF (tty, tty->TS_cursor_normal);
273 OUTPUT_IF (tty, tty->TS_end_termcap_modes);
274 OUTPUT_IF (tty, tty->TS_orig_pair);
275 /* Output raw CR so kernel can track the cursor hpos. */
276 current_tty = tty;
277 cmputc ('\r');
278 fflush (tty->output);
282 /* Flag the end of a display update on a termcap terminal. */
284 static void
285 tty_update_end (struct frame *f)
287 struct tty_display_info *tty = FRAME_TTY (f);
289 if (!XWINDOW (selected_window)->cursor_off_p)
290 tty_show_cursor (tty);
291 tty_turn_off_insert (tty);
292 tty_background_highlight (tty);
295 /* The implementation of set_terminal_window for termcap frames. */
297 static void
298 tty_set_terminal_window (struct frame *f, int size)
300 struct tty_display_info *tty = FRAME_TTY (f);
302 tty->specified_window = size ? size : FRAME_LINES (f);
303 if (FRAME_SCROLL_REGION_OK (f))
304 tty_set_scroll_region (f, 0, tty->specified_window);
307 static void
308 tty_set_scroll_region (struct frame *f, int start, int stop)
310 char *buf;
311 struct tty_display_info *tty = FRAME_TTY (f);
313 if (tty->TS_set_scroll_region)
314 buf = tparam (tty->TS_set_scroll_region, 0, 0, start, stop - 1);
315 else if (tty->TS_set_scroll_region_1)
316 buf = tparam (tty->TS_set_scroll_region_1, 0, 0,
317 FRAME_LINES (f), start,
318 FRAME_LINES (f) - stop,
319 FRAME_LINES (f));
320 else
321 buf = tparam (tty->TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (f));
323 OUTPUT (tty, buf);
324 xfree (buf);
325 losecursor (tty);
329 static void
330 tty_turn_on_insert (struct tty_display_info *tty)
332 if (!tty->insert_mode)
333 OUTPUT (tty, tty->TS_insert_mode);
334 tty->insert_mode = 1;
337 void
338 tty_turn_off_insert (struct tty_display_info *tty)
340 if (tty->insert_mode)
341 OUTPUT (tty, tty->TS_end_insert_mode);
342 tty->insert_mode = 0;
345 /* Handle highlighting. */
347 void
348 tty_turn_off_highlight (struct tty_display_info *tty)
350 if (tty->standout_mode)
351 OUTPUT_IF (tty, tty->TS_end_standout_mode);
352 tty->standout_mode = 0;
355 static void
356 tty_turn_on_highlight (struct tty_display_info *tty)
358 if (!tty->standout_mode)
359 OUTPUT_IF (tty, tty->TS_standout_mode);
360 tty->standout_mode = 1;
363 static void
364 tty_toggle_highlight (struct tty_display_info *tty)
366 if (tty->standout_mode)
367 tty_turn_off_highlight (tty);
368 else
369 tty_turn_on_highlight (tty);
373 /* Make cursor invisible. */
375 static void
376 tty_hide_cursor (struct tty_display_info *tty)
378 if (tty->cursor_hidden == 0)
380 tty->cursor_hidden = 1;
381 OUTPUT_IF (tty, tty->TS_cursor_invisible);
386 /* Ensure that cursor is visible. */
388 static void
389 tty_show_cursor (struct tty_display_info *tty)
391 if (tty->cursor_hidden)
393 tty->cursor_hidden = 0;
394 OUTPUT_IF (tty, tty->TS_cursor_normal);
395 if (visible_cursor)
396 OUTPUT_IF (tty, tty->TS_cursor_visible);
401 /* Set standout mode to the state it should be in for
402 empty space inside windows. What this is,
403 depends on the user option inverse-video. */
405 static void
406 tty_background_highlight (struct tty_display_info *tty)
408 if (inverse_video)
409 tty_turn_on_highlight (tty);
410 else
411 tty_turn_off_highlight (tty);
414 /* Set standout mode to the mode specified for the text to be output. */
416 static void
417 tty_highlight_if_desired (struct tty_display_info *tty)
419 if (inverse_video)
420 tty_turn_on_highlight (tty);
421 else
422 tty_turn_off_highlight (tty);
426 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
427 frame-relative coordinates. */
429 static void
430 tty_cursor_to (struct frame *f, int vpos, int hpos)
432 struct tty_display_info *tty = FRAME_TTY (f);
434 /* Detect the case where we are called from reset_sys_modes
435 and the costs have never been calculated. Do nothing. */
436 if (! tty->costs_set)
437 return;
439 if (curY (tty) == vpos
440 && curX (tty) == hpos)
441 return;
442 if (!tty->TF_standout_motion)
443 tty_background_highlight (tty);
444 if (!tty->TF_insmode_motion)
445 tty_turn_off_insert (tty);
446 cmgoto (tty, vpos, hpos);
449 /* Similar but don't take any account of the wasted characters. */
451 static void
452 tty_raw_cursor_to (struct frame *f, int row, int col)
454 struct tty_display_info *tty = FRAME_TTY (f);
456 if (curY (tty) == row
457 && curX (tty) == col)
458 return;
459 if (!tty->TF_standout_motion)
460 tty_background_highlight (tty);
461 if (!tty->TF_insmode_motion)
462 tty_turn_off_insert (tty);
463 cmgoto (tty, row, col);
466 /* Erase operations */
468 /* Clear from cursor to end of frame on a termcap device. */
470 static void
471 tty_clear_to_end (struct frame *f)
473 register int i;
474 struct tty_display_info *tty = FRAME_TTY (f);
476 if (tty->TS_clr_to_bottom)
478 tty_background_highlight (tty);
479 OUTPUT (tty, tty->TS_clr_to_bottom);
481 else
483 for (i = curY (tty); i < FRAME_LINES (f); i++)
485 cursor_to (f, i, 0);
486 clear_end_of_line (f, FRAME_COLS (f));
491 /* Clear an entire termcap frame. */
493 static void
494 tty_clear_frame (struct frame *f)
496 struct tty_display_info *tty = FRAME_TTY (f);
498 if (tty->TS_clr_frame)
500 tty_background_highlight (tty);
501 OUTPUT (tty, tty->TS_clr_frame);
502 cmat (tty, 0, 0);
504 else
506 cursor_to (f, 0, 0);
507 clear_to_end (f);
511 /* An implementation of clear_end_of_line for termcap frames.
513 Note that the cursor may be moved, on terminals lacking a `ce' string. */
515 static void
516 tty_clear_end_of_line (struct frame *f, int first_unused_hpos)
518 register int i;
519 struct tty_display_info *tty = FRAME_TTY (f);
521 /* Detect the case where we are called from reset_sys_modes
522 and the costs have never been calculated. Do nothing. */
523 if (! tty->costs_set)
524 return;
526 if (curX (tty) >= first_unused_hpos)
527 return;
528 tty_background_highlight (tty);
529 if (tty->TS_clr_line)
531 OUTPUT1 (tty, tty->TS_clr_line);
533 else
534 { /* have to do it the hard way */
535 tty_turn_off_insert (tty);
537 /* Do not write in last row last col with Auto-wrap on. */
538 if (AutoWrap (tty)
539 && curY (tty) == FrameRows (tty) - 1
540 && first_unused_hpos == FrameCols (tty))
541 first_unused_hpos--;
543 for (i = curX (tty); i < first_unused_hpos; i++)
545 if (tty->termscript)
546 fputc (' ', tty->termscript);
547 fputc (' ', tty->output);
549 cmplus (tty, first_unused_hpos - curX (tty));
553 /* Buffers to store the source and result of code conversion for terminal. */
554 static unsigned char *encode_terminal_src;
555 static unsigned char *encode_terminal_dst;
556 /* Allocated sizes of the above buffers. */
557 static int encode_terminal_src_size;
558 static int encode_terminal_dst_size;
560 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes.
561 Set CODING->produced to the byte-length of the resulting byte
562 sequence, and return a pointer to that byte sequence. */
564 unsigned char *
565 encode_terminal_code (struct glyph *src, int src_len, struct coding_system *coding)
567 struct glyph *src_end = src + src_len;
568 unsigned char *buf;
569 int nchars, nbytes, required;
570 register int tlen = GLYPH_TABLE_LENGTH;
571 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
572 Lisp_Object charset_list;
574 /* Allocate sufficient size of buffer to store all characters in
575 multibyte-form. But, it may be enlarged on demand if
576 Vglyph_table contains a string or a composite glyph is
577 encountered. */
578 required = MAX_MULTIBYTE_LENGTH * src_len;
579 if (encode_terminal_src_size < required)
581 if (encode_terminal_src)
582 encode_terminal_src = xrealloc (encode_terminal_src, required);
583 else
584 encode_terminal_src = xmalloc (required);
585 encode_terminal_src_size = required;
588 charset_list = coding_charset_list (coding);
590 buf = encode_terminal_src;
591 nchars = 0;
592 while (src < src_end)
594 if (src->type == COMPOSITE_GLYPH)
596 struct composition *cmp;
597 Lisp_Object gstring;
598 int i;
600 nbytes = buf - encode_terminal_src;
601 if (src->u.cmp.automatic)
603 gstring = composition_gstring_from_id (src->u.cmp.id);
604 required = src->u.cmp.to + 1 - src->u.cmp.from;
606 else
608 cmp = composition_table[src->u.cmp.id];
609 required = MAX_MULTIBYTE_LENGTH * cmp->glyph_len;
612 if (encode_terminal_src_size < nbytes + required)
614 encode_terminal_src_size = nbytes + required;
615 encode_terminal_src = xrealloc (encode_terminal_src,
616 encode_terminal_src_size);
617 buf = encode_terminal_src + nbytes;
620 if (src->u.cmp.automatic)
621 for (i = src->u.cmp.from; i <= src->u.cmp.to; i++)
623 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
624 int c = LGLYPH_CHAR (g);
626 if (! char_charset (c, charset_list, NULL))
627 c = '?';
628 buf += CHAR_STRING (c, buf);
629 nchars++;
631 else
632 for (i = 0; i < cmp->glyph_len; i++)
634 int c = COMPOSITION_GLYPH (cmp, i);
636 if (c == '\t')
637 continue;
638 if (char_charset (c, charset_list, NULL))
640 if (CHAR_WIDTH (c) == 0
641 && i > 0 && COMPOSITION_GLYPH (cmp, i - 1) == '\t')
642 /* Should be left-padded */
644 buf += CHAR_STRING (' ', buf);
645 nchars++;
648 else
649 c = '?';
650 buf += CHAR_STRING (c, buf);
651 nchars++;
654 /* We must skip glyphs to be padded for a wide character. */
655 else if (! CHAR_GLYPH_PADDING_P (*src))
657 GLYPH g;
658 int c;
659 Lisp_Object string;
661 string = Qnil;
662 SET_GLYPH_FROM_CHAR_GLYPH (g, src[0]);
664 if (GLYPH_INVALID_P (g) || GLYPH_SIMPLE_P (tbase, tlen, g))
666 /* This glyph doesn't have an entry in Vglyph_table. */
667 c = src->u.ch;
669 else
671 /* This glyph has an entry in Vglyph_table,
672 so process any alias before testing for simpleness. */
673 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
675 if (GLYPH_SIMPLE_P (tbase, tlen, g))
676 /* We set the multi-byte form of a character in G
677 (that should be an ASCII character) at WORKBUF. */
678 c = GLYPH_CHAR (g);
679 else
680 /* We have a string in Vglyph_table. */
681 string = tbase[GLYPH_CHAR (g)];
684 if (NILP (string))
686 nbytes = buf - encode_terminal_src;
687 if (encode_terminal_src_size < nbytes + MAX_MULTIBYTE_LENGTH)
689 encode_terminal_src_size = nbytes + MAX_MULTIBYTE_LENGTH;
690 encode_terminal_src = xrealloc (encode_terminal_src,
691 encode_terminal_src_size);
692 buf = encode_terminal_src + nbytes;
694 if (char_charset (c, charset_list, NULL))
696 /* Store the multibyte form of C at BUF. */
697 buf += CHAR_STRING (c, buf);
698 nchars++;
700 else
702 /* C is not encodable. */
703 *buf++ = '?';
704 nchars++;
705 while (src + 1 < src_end && CHAR_GLYPH_PADDING_P (src[1]))
707 *buf++ = '?';
708 nchars++;
709 src++;
713 else
715 unsigned char *p = SDATA (string), *pend = p + SBYTES (string);
717 if (! STRING_MULTIBYTE (string))
718 string = string_to_multibyte (string);
719 nbytes = buf - encode_terminal_src;
720 if (encode_terminal_src_size < nbytes + SBYTES (string))
722 encode_terminal_src_size = nbytes + SBYTES (string);
723 encode_terminal_src = xrealloc (encode_terminal_src,
724 encode_terminal_src_size);
725 buf = encode_terminal_src + nbytes;
727 memcpy (buf, SDATA (string), SBYTES (string));
728 buf += SBYTES (string);
729 nchars += SCHARS (string);
732 src++;
735 if (nchars == 0)
737 coding->produced = 0;
738 return NULL;
741 nbytes = buf - encode_terminal_src;
742 coding->source = encode_terminal_src;
743 if (encode_terminal_dst_size == 0)
745 encode_terminal_dst_size = encode_terminal_src_size;
746 if (encode_terminal_dst)
747 encode_terminal_dst = xrealloc (encode_terminal_dst,
748 encode_terminal_dst_size);
749 else
750 encode_terminal_dst = xmalloc (encode_terminal_dst_size);
752 coding->destination = encode_terminal_dst;
753 coding->dst_bytes = encode_terminal_dst_size;
754 encode_coding_object (coding, Qnil, 0, 0, nchars, nbytes, Qnil);
755 /* coding->destination may have been reallocated. */
756 encode_terminal_dst = coding->destination;
757 encode_terminal_dst_size = coding->dst_bytes;
759 return (encode_terminal_dst);
764 /* An implementation of write_glyphs for termcap frames. */
766 static void
767 tty_write_glyphs (struct frame *f, struct glyph *string, int len)
769 unsigned char *conversion_buffer;
770 struct coding_system *coding;
772 struct tty_display_info *tty = FRAME_TTY (f);
774 tty_turn_off_insert (tty);
775 tty_hide_cursor (tty);
777 /* Don't dare write in last column of bottom line, if Auto-Wrap,
778 since that would scroll the whole frame on some terminals. */
780 if (AutoWrap (tty)
781 && curY (tty) + 1 == FRAME_LINES (f)
782 && (curX (tty) + len) == FRAME_COLS (f))
783 len --;
784 if (len <= 0)
785 return;
787 cmplus (tty, len);
789 /* If terminal_coding does any conversion, use it, otherwise use
790 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
791 because it always return 1 if the member src_multibyte is 1. */
792 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
793 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
794 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
795 the tail. */
796 coding->mode &= ~CODING_MODE_LAST_BLOCK;
798 while (len > 0)
800 /* Identify a run of glyphs with the same face. */
801 int face_id = string->face_id;
802 int n;
804 for (n = 1; n < len; ++n)
805 if (string[n].face_id != face_id)
806 break;
808 /* Turn appearance modes of the face of the run on. */
809 tty_highlight_if_desired (tty);
810 turn_on_face (f, face_id);
812 if (n == len)
813 /* This is the last run. */
814 coding->mode |= CODING_MODE_LAST_BLOCK;
815 conversion_buffer = encode_terminal_code (string, n, coding);
816 if (coding->produced > 0)
818 BLOCK_INPUT;
819 fwrite (conversion_buffer, 1, coding->produced, tty->output);
820 if (ferror (tty->output))
821 clearerr (tty->output);
822 if (tty->termscript)
823 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
824 UNBLOCK_INPUT;
826 len -= n;
827 string += n;
829 /* Turn appearance modes off. */
830 turn_off_face (f, face_id);
831 tty_turn_off_highlight (tty);
834 cmcheckmagic (tty);
837 #ifdef HAVE_GPM /* Only used by GPM code. */
839 static void
840 tty_write_glyphs_with_face (register struct frame *f, register struct glyph *string,
841 register int len, register int face_id)
843 unsigned char *conversion_buffer;
844 struct coding_system *coding;
846 struct tty_display_info *tty = FRAME_TTY (f);
848 tty_turn_off_insert (tty);
849 tty_hide_cursor (tty);
851 /* Don't dare write in last column of bottom line, if Auto-Wrap,
852 since that would scroll the whole frame on some terminals. */
854 if (AutoWrap (tty)
855 && curY (tty) + 1 == FRAME_LINES (f)
856 && (curX (tty) + len) == FRAME_COLS (f))
857 len --;
858 if (len <= 0)
859 return;
861 cmplus (tty, len);
863 /* If terminal_coding does any conversion, use it, otherwise use
864 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
865 because it always return 1 if the member src_multibyte is 1. */
866 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
867 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
868 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
869 the tail. */
870 coding->mode &= ~CODING_MODE_LAST_BLOCK;
872 /* Turn appearance modes of the face. */
873 tty_highlight_if_desired (tty);
874 turn_on_face (f, face_id);
876 coding->mode |= CODING_MODE_LAST_BLOCK;
877 conversion_buffer = encode_terminal_code (string, len, coding);
878 if (coding->produced > 0)
880 BLOCK_INPUT;
881 fwrite (conversion_buffer, 1, coding->produced, tty->output);
882 if (ferror (tty->output))
883 clearerr (tty->output);
884 if (tty->termscript)
885 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
886 UNBLOCK_INPUT;
889 /* Turn appearance modes off. */
890 turn_off_face (f, face_id);
891 tty_turn_off_highlight (tty);
893 cmcheckmagic (tty);
895 #endif
897 /* An implementation of insert_glyphs for termcap frames. */
899 static void
900 tty_insert_glyphs (struct frame *f, struct glyph *start, int len)
902 char *buf;
903 struct glyph *glyph = NULL;
904 unsigned char *conversion_buffer;
905 unsigned char space[1];
906 struct coding_system *coding;
908 struct tty_display_info *tty = FRAME_TTY (f);
910 if (tty->TS_ins_multi_chars)
912 buf = tparam (tty->TS_ins_multi_chars, 0, 0, len);
913 OUTPUT1 (tty, buf);
914 xfree (buf);
915 if (start)
916 write_glyphs (f, start, len);
917 return;
920 tty_turn_on_insert (tty);
921 cmplus (tty, len);
923 if (! start)
924 space[0] = SPACEGLYPH;
926 /* If terminal_coding does any conversion, use it, otherwise use
927 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
928 because it always return 1 if the member src_multibyte is 1. */
929 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
930 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
931 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
932 the tail. */
933 coding->mode &= ~CODING_MODE_LAST_BLOCK;
935 while (len-- > 0)
937 OUTPUT1_IF (tty, tty->TS_ins_char);
938 if (!start)
940 conversion_buffer = space;
941 coding->produced = 1;
943 else
945 tty_highlight_if_desired (tty);
946 turn_on_face (f, start->face_id);
947 glyph = start;
948 ++start;
949 /* We must open sufficient space for a character which
950 occupies more than one column. */
951 while (len && CHAR_GLYPH_PADDING_P (*start))
953 OUTPUT1_IF (tty, tty->TS_ins_char);
954 start++, len--;
957 if (len <= 0)
958 /* This is the last glyph. */
959 coding->mode |= CODING_MODE_LAST_BLOCK;
961 conversion_buffer = encode_terminal_code (glyph, 1, coding);
964 if (coding->produced > 0)
966 BLOCK_INPUT;
967 fwrite (conversion_buffer, 1, coding->produced, tty->output);
968 if (ferror (tty->output))
969 clearerr (tty->output);
970 if (tty->termscript)
971 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
972 UNBLOCK_INPUT;
975 OUTPUT1_IF (tty, tty->TS_pad_inserted_char);
976 if (start)
978 turn_off_face (f, glyph->face_id);
979 tty_turn_off_highlight (tty);
983 cmcheckmagic (tty);
986 /* An implementation of delete_glyphs for termcap frames. */
988 static void
989 tty_delete_glyphs (struct frame *f, int n)
991 char *buf;
992 register int i;
994 struct tty_display_info *tty = FRAME_TTY (f);
996 if (tty->delete_in_insert_mode)
998 tty_turn_on_insert (tty);
1000 else
1002 tty_turn_off_insert (tty);
1003 OUTPUT_IF (tty, tty->TS_delete_mode);
1006 if (tty->TS_del_multi_chars)
1008 buf = tparam (tty->TS_del_multi_chars, 0, 0, n);
1009 OUTPUT1 (tty, buf);
1010 xfree (buf);
1012 else
1013 for (i = 0; i < n; i++)
1014 OUTPUT1 (tty, tty->TS_del_char);
1015 if (!tty->delete_in_insert_mode)
1016 OUTPUT_IF (tty, tty->TS_end_delete_mode);
1019 /* An implementation of ins_del_lines for termcap frames. */
1021 static void
1022 tty_ins_del_lines (struct frame *f, int vpos, int n)
1024 struct tty_display_info *tty = FRAME_TTY (f);
1025 char *multi = n > 0 ? tty->TS_ins_multi_lines : tty->TS_del_multi_lines;
1026 char *single = n > 0 ? tty->TS_ins_line : tty->TS_del_line;
1027 char *scroll = n > 0 ? tty->TS_rev_scroll : tty->TS_fwd_scroll;
1029 register int i = n > 0 ? n : -n;
1030 register char *buf;
1032 /* If the lines below the insertion are being pushed
1033 into the end of the window, this is the same as clearing;
1034 and we know the lines are already clear, since the matching
1035 deletion has already been done. So can ignore this. */
1036 /* If the lines below the deletion are blank lines coming
1037 out of the end of the window, don't bother,
1038 as there will be a matching inslines later that will flush them. */
1039 if (FRAME_SCROLL_REGION_OK (f)
1040 && vpos + i >= tty->specified_window)
1041 return;
1042 if (!FRAME_MEMORY_BELOW_FRAME (f)
1043 && vpos + i >= FRAME_LINES (f))
1044 return;
1046 if (multi)
1048 raw_cursor_to (f, vpos, 0);
1049 tty_background_highlight (tty);
1050 buf = tparam (multi, 0, 0, i);
1051 OUTPUT (tty, buf);
1052 xfree (buf);
1054 else if (single)
1056 raw_cursor_to (f, vpos, 0);
1057 tty_background_highlight (tty);
1058 while (--i >= 0)
1059 OUTPUT (tty, single);
1060 if (tty->TF_teleray)
1061 curX (tty) = 0;
1063 else
1065 tty_set_scroll_region (f, vpos, tty->specified_window);
1066 if (n < 0)
1067 raw_cursor_to (f, tty->specified_window - 1, 0);
1068 else
1069 raw_cursor_to (f, vpos, 0);
1070 tty_background_highlight (tty);
1071 while (--i >= 0)
1072 OUTPUTL (tty, scroll, tty->specified_window - vpos);
1073 tty_set_scroll_region (f, 0, tty->specified_window);
1076 if (!FRAME_SCROLL_REGION_OK (f)
1077 && FRAME_MEMORY_BELOW_FRAME (f)
1078 && n < 0)
1080 cursor_to (f, FRAME_LINES (f) + n, 0);
1081 clear_to_end (f);
1085 /* Compute cost of sending "str", in characters,
1086 not counting any line-dependent padding. */
1089 string_cost (char *str)
1091 cost = 0;
1092 if (str)
1093 tputs (str, 0, evalcost);
1094 return cost;
1097 /* Compute cost of sending "str", in characters,
1098 counting any line-dependent padding at one line. */
1100 static int
1101 string_cost_one_line (char *str)
1103 cost = 0;
1104 if (str)
1105 tputs (str, 1, evalcost);
1106 return cost;
1109 /* Compute per line amount of line-dependent padding,
1110 in tenths of characters. */
1113 per_line_cost (char *str)
1115 cost = 0;
1116 if (str)
1117 tputs (str, 0, evalcost);
1118 cost = - cost;
1119 if (str)
1120 tputs (str, 10, evalcost);
1121 return cost;
1124 #ifndef old
1125 /* char_ins_del_cost[n] is cost of inserting N characters.
1126 char_ins_del_cost[-n] is cost of deleting N characters.
1127 The length of this vector is based on max_frame_cols. */
1129 int *char_ins_del_vector;
1131 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
1132 #endif
1134 /* ARGSUSED */
1135 static void
1136 calculate_ins_del_char_costs (struct frame *f)
1138 struct tty_display_info *tty = FRAME_TTY (f);
1139 int ins_startup_cost, del_startup_cost;
1140 int ins_cost_per_char, del_cost_per_char;
1141 register int i;
1142 register int *p;
1144 if (tty->TS_ins_multi_chars)
1146 ins_cost_per_char = 0;
1147 ins_startup_cost = string_cost_one_line (tty->TS_ins_multi_chars);
1149 else if (tty->TS_ins_char || tty->TS_pad_inserted_char
1150 || (tty->TS_insert_mode && tty->TS_end_insert_mode))
1152 ins_startup_cost = (30 * (string_cost (tty->TS_insert_mode)
1153 + string_cost (tty->TS_end_insert_mode))) / 100;
1154 ins_cost_per_char = (string_cost_one_line (tty->TS_ins_char)
1155 + string_cost_one_line (tty->TS_pad_inserted_char));
1157 else
1159 ins_startup_cost = 9999;
1160 ins_cost_per_char = 0;
1163 if (tty->TS_del_multi_chars)
1165 del_cost_per_char = 0;
1166 del_startup_cost = string_cost_one_line (tty->TS_del_multi_chars);
1168 else if (tty->TS_del_char)
1170 del_startup_cost = (string_cost (tty->TS_delete_mode)
1171 + string_cost (tty->TS_end_delete_mode));
1172 if (tty->delete_in_insert_mode)
1173 del_startup_cost /= 2;
1174 del_cost_per_char = string_cost_one_line (tty->TS_del_char);
1176 else
1178 del_startup_cost = 9999;
1179 del_cost_per_char = 0;
1182 /* Delete costs are at negative offsets */
1183 p = &char_ins_del_cost (f)[0];
1184 for (i = FRAME_COLS (f); --i >= 0;)
1185 *--p = (del_startup_cost += del_cost_per_char);
1187 /* Doing nothing is free */
1188 p = &char_ins_del_cost (f)[0];
1189 *p++ = 0;
1191 /* Insert costs are at positive offsets */
1192 for (i = FRAME_COLS (f); --i >= 0;)
1193 *p++ = (ins_startup_cost += ins_cost_per_char);
1196 void
1197 calculate_costs (struct frame *frame)
1199 FRAME_COST_BAUD_RATE (frame) = baud_rate;
1201 if (FRAME_TERMCAP_P (frame))
1203 struct tty_display_info *tty = FRAME_TTY (frame);
1204 register char *f = (tty->TS_set_scroll_region
1205 ? tty->TS_set_scroll_region
1206 : tty->TS_set_scroll_region_1);
1208 FRAME_SCROLL_REGION_COST (frame) = string_cost (f);
1210 tty->costs_set = 1;
1212 /* These variables are only used for terminal stuff. They are
1213 allocated once for the terminal frame of X-windows emacs, but not
1214 used afterwards.
1216 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1217 X turns off char_ins_del_ok. */
1219 max_frame_lines = max (max_frame_lines, FRAME_LINES (frame));
1220 max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
1222 if (char_ins_del_vector != 0)
1223 char_ins_del_vector
1224 = (int *) xrealloc (char_ins_del_vector,
1225 (sizeof (int)
1226 + 2 * max_frame_cols * sizeof (int)));
1227 else
1228 char_ins_del_vector
1229 = (int *) xmalloc (sizeof (int)
1230 + 2 * max_frame_cols * sizeof (int));
1232 memset (char_ins_del_vector, 0,
1233 (sizeof (int) + 2 * max_frame_cols * sizeof (int)));
1236 if (f && (!tty->TS_ins_line && !tty->TS_del_line))
1237 do_line_insertion_deletion_costs (frame,
1238 tty->TS_rev_scroll, tty->TS_ins_multi_lines,
1239 tty->TS_fwd_scroll, tty->TS_del_multi_lines,
1240 f, f, 1);
1241 else
1242 do_line_insertion_deletion_costs (frame,
1243 tty->TS_ins_line, tty->TS_ins_multi_lines,
1244 tty->TS_del_line, tty->TS_del_multi_lines,
1245 0, 0, 1);
1247 calculate_ins_del_char_costs (frame);
1249 /* Don't use TS_repeat if its padding is worse than sending the chars */
1250 if (tty->TS_repeat && per_line_cost (tty->TS_repeat) * baud_rate < 9000)
1251 tty->RPov = string_cost (tty->TS_repeat);
1252 else
1253 tty->RPov = FRAME_COLS (frame) * 2;
1255 cmcostinit (FRAME_TTY (frame)); /* set up cursor motion costs */
1259 struct fkey_table {
1260 char *cap, *name;
1263 /* Termcap capability names that correspond directly to X keysyms.
1264 Some of these (marked "terminfo") aren't supplied by old-style
1265 (Berkeley) termcap entries. They're listed in X keysym order;
1266 except we put the keypad keys first, so that if they clash with
1267 other keys (as on the IBM PC keyboard) they get overridden.
1270 static struct fkey_table keys[] =
1272 {"kh", "home"}, /* termcap */
1273 {"kl", "left"}, /* termcap */
1274 {"ku", "up"}, /* termcap */
1275 {"kr", "right"}, /* termcap */
1276 {"kd", "down"}, /* termcap */
1277 {"%8", "prior"}, /* terminfo */
1278 {"%5", "next"}, /* terminfo */
1279 {"@7", "end"}, /* terminfo */
1280 {"@1", "begin"}, /* terminfo */
1281 {"*6", "select"}, /* terminfo */
1282 {"%9", "print"}, /* terminfo */
1283 {"@4", "execute"}, /* terminfo --- actually the `command' key */
1285 * "insert" --- see below
1287 {"&8", "undo"}, /* terminfo */
1288 {"%0", "redo"}, /* terminfo */
1289 {"%7", "menu"}, /* terminfo --- actually the `options' key */
1290 {"@0", "find"}, /* terminfo */
1291 {"@2", "cancel"}, /* terminfo */
1292 {"%1", "help"}, /* terminfo */
1294 * "break" goes here, but can't be reliably intercepted with termcap
1296 {"&4", "reset"}, /* terminfo --- actually `restart' */
1298 * "system" and "user" --- no termcaps
1300 {"kE", "clearline"}, /* terminfo */
1301 {"kA", "insertline"}, /* terminfo */
1302 {"kL", "deleteline"}, /* terminfo */
1303 {"kI", "insertchar"}, /* terminfo */
1304 {"kD", "deletechar"}, /* terminfo */
1305 {"kB", "backtab"}, /* terminfo */
1307 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1309 {"@8", "kp-enter"}, /* terminfo */
1311 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1312 * "kp-multiply", "kp-add", "kp-separator",
1313 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1314 * --- no termcaps for any of these.
1316 {"K4", "kp-1"}, /* terminfo */
1318 * "kp-2" --- no termcap
1320 {"K5", "kp-3"}, /* terminfo */
1322 * "kp-4" --- no termcap
1324 {"K2", "kp-5"}, /* terminfo */
1326 * "kp-6" --- no termcap
1328 {"K1", "kp-7"}, /* terminfo */
1330 * "kp-8" --- no termcap
1332 {"K3", "kp-9"}, /* terminfo */
1334 * "kp-equal" --- no termcap
1336 {"k1", "f1"},
1337 {"k2", "f2"},
1338 {"k3", "f3"},
1339 {"k4", "f4"},
1340 {"k5", "f5"},
1341 {"k6", "f6"},
1342 {"k7", "f7"},
1343 {"k8", "f8"},
1344 {"k9", "f9"},
1346 {"&0", "S-cancel"}, /*shifted cancel key*/
1347 {"&9", "S-begin"}, /*shifted begin key*/
1348 {"*0", "S-find"}, /*shifted find key*/
1349 {"*1", "S-execute"}, /*shifted execute? actually shifted command key*/
1350 {"*4", "S-delete"}, /*shifted delete-character key*/
1351 {"*7", "S-end"}, /*shifted end key*/
1352 {"*8", "S-clearline"}, /*shifted clear-to end-of-line key*/
1353 {"#1", "S-help"}, /*shifted help key*/
1354 {"#2", "S-home"}, /*shifted home key*/
1355 {"#3", "S-insert"}, /*shifted insert-character key*/
1356 {"#4", "S-left"}, /*shifted left-arrow key*/
1357 {"%d", "S-menu"}, /*shifted menu? actually shifted options key*/
1358 {"%c", "S-next"}, /*shifted next key*/
1359 {"%e", "S-prior"}, /*shifted previous key*/
1360 {"%f", "S-print"}, /*shifted print key*/
1361 {"%g", "S-redo"}, /*shifted redo key*/
1362 {"%i", "S-right"}, /*shifted right-arrow key*/
1363 {"!3", "S-undo"} /*shifted undo key*/
1366 static char **term_get_fkeys_address;
1367 static KBOARD *term_get_fkeys_kboard;
1368 static Lisp_Object term_get_fkeys_1 (void);
1370 /* Find the escape codes sent by the function keys for Vinput_decode_map.
1371 This function scans the termcap function key sequence entries, and
1372 adds entries to Vinput_decode_map for each function key it finds. */
1374 static void
1375 term_get_fkeys (char **address, KBOARD *kboard)
1377 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1378 errors during the call. The only errors should be from Fdefine_key
1379 when given a key sequence containing an invalid prefix key. If the
1380 termcap defines function keys which use a prefix that is already bound
1381 to a command by the default bindings, we should silently ignore that
1382 function key specification, rather than giving the user an error and
1383 refusing to run at all on such a terminal. */
1385 extern Lisp_Object Fidentity (Lisp_Object);
1386 term_get_fkeys_address = address;
1387 term_get_fkeys_kboard = kboard;
1388 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1391 static Lisp_Object
1392 term_get_fkeys_1 (void)
1394 int i;
1396 char **address = term_get_fkeys_address;
1397 KBOARD *kboard = term_get_fkeys_kboard;
1399 /* This can happen if CANNOT_DUMP or with strange options. */
1400 if (!KEYMAPP (kboard->Vinput_decode_map))
1401 kboard->Vinput_decode_map = Fmake_sparse_keymap (Qnil);
1403 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1405 char *sequence = tgetstr (keys[i].cap, address);
1406 if (sequence)
1407 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence),
1408 Fmake_vector (make_number (1),
1409 intern (keys[i].name)));
1412 /* The uses of the "k0" capability are inconsistent; sometimes it
1413 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1414 We will attempt to politely accommodate both systems by testing for
1415 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1418 char *k_semi = tgetstr ("k;", address);
1419 char *k0 = tgetstr ("k0", address);
1420 char *k0_name = "f10";
1422 if (k_semi)
1424 if (k0)
1425 /* Define f0 first, so that f10 takes precedence in case the
1426 key sequences happens to be the same. */
1427 Fdefine_key (kboard->Vinput_decode_map, build_string (k0),
1428 Fmake_vector (make_number (1), intern ("f0")));
1429 Fdefine_key (kboard->Vinput_decode_map, build_string (k_semi),
1430 Fmake_vector (make_number (1), intern ("f10")));
1432 else if (k0)
1433 Fdefine_key (kboard->Vinput_decode_map, build_string (k0),
1434 Fmake_vector (make_number (1), intern (k0_name)));
1437 /* Set up cookies for numbered function keys above f10. */
1439 char fcap[3], fkey[4];
1441 fcap[0] = 'F'; fcap[2] = '\0';
1442 for (i = 11; i < 64; i++)
1444 if (i <= 19)
1445 fcap[1] = '1' + i - 11;
1446 else if (i <= 45)
1447 fcap[1] = 'A' + i - 20;
1448 else
1449 fcap[1] = 'a' + i - 46;
1452 char *sequence = tgetstr (fcap, address);
1453 if (sequence)
1455 sprintf (fkey, "f%d", i);
1456 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence),
1457 Fmake_vector (make_number (1),
1458 intern (fkey)));
1465 * Various mappings to try and get a better fit.
1468 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1469 if (!tgetstr (cap1, address)) \
1471 char *sequence = tgetstr (cap2, address); \
1472 if (sequence) \
1473 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence), \
1474 Fmake_vector (make_number (1), \
1475 intern (sym))); \
1478 /* if there's no key_next keycap, map key_npage to `next' keysym */
1479 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1480 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1481 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1482 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1483 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1484 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1485 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1487 /* IBM has their own non-standard dialect of terminfo.
1488 If the standard name isn't found, try the IBM name. */
1489 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1490 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1491 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1492 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1493 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1494 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1495 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1496 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1497 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1498 #undef CONDITIONAL_REASSIGN
1501 return Qnil;
1505 /***********************************************************************
1506 Character Display Information
1507 ***********************************************************************/
1509 /* Avoid name clash with functions defined in xterm.c */
1510 #ifdef static
1511 #define append_glyph append_glyph_term
1512 #define produce_stretch_glyph produce_stretch_glyph_term
1513 #define append_composite_glyph append_composite_glyph_term
1514 #define produce_composite_glyph produce_composite_glyph_term
1515 #endif
1517 static void append_glyph (struct it *);
1518 static void produce_stretch_glyph (struct it *);
1519 static void append_composite_glyph (struct it *);
1520 static void produce_composite_glyph (struct it *);
1522 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1523 terminal frames if IT->glyph_row != NULL. IT->char_to_display is
1524 the character for which to produce glyphs; IT->face_id contains the
1525 character's face. Padding glyphs are appended if IT->c has a
1526 IT->pixel_width > 1. */
1528 static void
1529 append_glyph (struct it *it)
1531 struct glyph *glyph, *end;
1532 int i;
1534 xassert (it->glyph_row);
1535 glyph = (it->glyph_row->glyphs[it->area]
1536 + it->glyph_row->used[it->area]);
1537 end = it->glyph_row->glyphs[1 + it->area];
1539 /* If the glyph row is reversed, we need to prepend the glyph rather
1540 than append it. */
1541 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1543 struct glyph *g;
1544 int move_by = it->pixel_width;
1546 /* Make room for the new glyphs. */
1547 if (move_by > end - glyph) /* don't overstep end of this area */
1548 move_by = end - glyph;
1549 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1550 g[move_by] = *g;
1551 glyph = it->glyph_row->glyphs[it->area];
1552 end = glyph + move_by;
1555 /* BIDI Note: we put the glyphs of a "multi-pixel" character left to
1556 right, even in the REVERSED_P case, since (a) all of its u.ch are
1557 identical, and (b) the PADDING_P flag needs to be set for the
1558 leftmost one, because we write to the terminal left-to-right. */
1559 for (i = 0;
1560 i < it->pixel_width && glyph < end;
1561 ++i)
1563 glyph->type = CHAR_GLYPH;
1564 glyph->pixel_width = 1;
1565 glyph->u.ch = it->char_to_display;
1566 glyph->face_id = it->face_id;
1567 glyph->padding_p = i > 0;
1568 glyph->charpos = CHARPOS (it->position);
1569 glyph->object = it->object;
1570 if (it->bidi_p)
1572 glyph->resolved_level = it->bidi_it.resolved_level;
1573 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1574 abort ();
1575 glyph->bidi_type = it->bidi_it.type;
1577 else
1579 glyph->resolved_level = 0;
1580 glyph->bidi_type = UNKNOWN_BT;
1583 ++it->glyph_row->used[it->area];
1584 ++glyph;
1588 /* Produce glyphs for the display element described by IT. *IT
1589 specifies what we want to produce a glyph for (character, image, ...),
1590 and where in the glyph matrix we currently are (glyph row and hpos).
1591 produce_glyphs fills in output fields of *IT with information such as the
1592 pixel width and height of a character, and maybe output actual glyphs at
1593 the same time if IT->glyph_row is non-null. For an overview, see
1594 the explanation in dispextern.h, before the definition of the
1595 display_element_type enumeration.
1597 produce_glyphs also stores the result of glyph width, ascent
1598 etc. computations in *IT.
1600 IT->glyph_row may be null, in which case produce_glyphs does not
1601 actually fill in the glyphs. This is used in the move_* functions
1602 in xdisp.c for text width and height computations.
1604 Callers usually don't call produce_glyphs directly;
1605 instead they use the macro PRODUCE_GLYPHS. */
1607 void
1608 produce_glyphs (struct it *it)
1610 /* If a hook is installed, let it do the work. */
1612 /* Nothing but characters are supported on terminal frames. */
1613 xassert (it->what == IT_CHARACTER
1614 || it->what == IT_COMPOSITION
1615 || it->what == IT_STRETCH);
1617 if (it->what == IT_STRETCH)
1619 produce_stretch_glyph (it);
1620 goto done;
1623 if (it->what == IT_COMPOSITION)
1625 produce_composite_glyph (it);
1626 goto done;
1629 /* Maybe translate single-byte characters to multibyte. */
1630 it->char_to_display = it->c;
1632 if (it->c >= 040 && it->c < 0177)
1634 it->pixel_width = it->nglyphs = 1;
1635 if (it->glyph_row)
1636 append_glyph (it);
1638 else if (it->c == '\n')
1639 it->pixel_width = it->nglyphs = 0;
1640 else if (it->c == '\t')
1642 int absolute_x = (it->current_x
1643 + it->continuation_lines_width);
1644 int next_tab_x
1645 = (((1 + absolute_x + it->tab_width - 1)
1646 / it->tab_width)
1647 * it->tab_width);
1648 int nspaces;
1650 /* If part of the TAB has been displayed on the previous line
1651 which is continued now, continuation_lines_width will have
1652 been incremented already by the part that fitted on the
1653 continued line. So, we will get the right number of spaces
1654 here. */
1655 nspaces = next_tab_x - absolute_x;
1657 if (it->glyph_row)
1659 int n = nspaces;
1661 it->char_to_display = ' ';
1662 it->pixel_width = it->len = 1;
1664 while (n--)
1665 append_glyph (it);
1668 it->pixel_width = nspaces;
1669 it->nglyphs = nspaces;
1671 else if (CHAR_BYTE8_P (it->c))
1673 if (unibyte_display_via_language_environment
1674 && (it->c >= 0240))
1676 it->char_to_display = BYTE8_TO_CHAR (it->c);
1677 it->pixel_width = CHAR_WIDTH (it->char_to_display);
1678 it->nglyphs = it->pixel_width;
1679 if (it->glyph_row)
1680 append_glyph (it);
1682 else
1684 /* Coming here means that it->c is from display table, thus
1685 we must send the raw 8-bit byte as is to the terminal.
1686 Although there's no way to know how many columns it
1687 occupies on a screen, it is a good assumption that a
1688 single byte code has 1-column width. */
1689 it->pixel_width = it->nglyphs = 1;
1690 if (it->glyph_row)
1691 append_glyph (it);
1694 else
1696 it->pixel_width = CHAR_WIDTH (it->c);
1697 it->nglyphs = it->pixel_width;
1699 if (it->glyph_row)
1700 append_glyph (it);
1703 done:
1704 /* Advance current_x by the pixel width as a convenience for
1705 the caller. */
1706 if (it->area == TEXT_AREA)
1707 it->current_x += it->pixel_width;
1708 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1709 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
1713 /* Produce a stretch glyph for iterator IT. IT->object is the value
1714 of the glyph property displayed. The value must be a list
1715 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1716 being recognized:
1718 1. `:width WIDTH' specifies that the space should be WIDTH *
1719 canonical char width wide. WIDTH may be an integer or floating
1720 point number.
1722 2. `:align-to HPOS' specifies that the space should be wide enough
1723 to reach HPOS, a value in canonical character units. */
1725 static void
1726 produce_stretch_glyph (struct it *it)
1728 /* (space :width WIDTH ...) */
1729 Lisp_Object prop, plist;
1730 int width = 0, align_to = -1;
1731 int zero_width_ok_p = 0;
1732 double tem;
1734 /* List should start with `space'. */
1735 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1736 plist = XCDR (it->object);
1738 /* Compute the width of the stretch. */
1739 if ((prop = Fplist_get (plist, QCwidth), !NILP (prop))
1740 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, 0))
1742 /* Absolute width `:width WIDTH' specified and valid. */
1743 zero_width_ok_p = 1;
1744 width = (int)(tem + 0.5);
1746 else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
1747 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, &align_to))
1749 if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
1750 align_to = (align_to < 0
1752 : align_to - window_box_left_offset (it->w, TEXT_AREA));
1753 else if (align_to < 0)
1754 align_to = window_box_left_offset (it->w, TEXT_AREA);
1755 width = max (0, (int)(tem + 0.5) + align_to - it->current_x);
1756 zero_width_ok_p = 1;
1758 else
1759 /* Nothing specified -> width defaults to canonical char width. */
1760 width = FRAME_COLUMN_WIDTH (it->f);
1762 if (width <= 0 && (width < 0 || !zero_width_ok_p))
1763 width = 1;
1765 if (width > 0 && it->line_wrap != TRUNCATE
1766 && it->current_x + width > it->last_visible_x)
1767 width = it->last_visible_x - it->current_x - 1;
1769 if (width > 0 && it->glyph_row)
1771 Lisp_Object o_object = it->object;
1772 Lisp_Object object = it->stack[it->sp - 1].string;
1773 int n = width;
1775 if (!STRINGP (object))
1776 object = it->w->buffer;
1777 it->object = object;
1778 it->char_to_display = ' ';
1779 it->pixel_width = it->len = 1;
1780 while (n--)
1781 append_glyph (it);
1782 it->object = o_object;
1784 it->pixel_width = width;
1785 it->nglyphs = width;
1789 /* Append glyphs to IT's glyph_row for the composition IT->cmp_id.
1790 Called from produce_composite_glyph for terminal frames if
1791 IT->glyph_row != NULL. IT->face_id contains the character's
1792 face. */
1794 static void
1795 append_composite_glyph (struct it *it)
1797 struct glyph *glyph;
1799 xassert (it->glyph_row);
1800 glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
1801 if (glyph < it->glyph_row->glyphs[1 + it->area])
1803 /* If the glyph row is reversed, we need to prepend the glyph
1804 rather than append it. */
1805 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1807 struct glyph *g;
1809 /* Make room for the new glyph. */
1810 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1811 g[1] = *g;
1812 glyph = it->glyph_row->glyphs[it->area];
1814 glyph->type = COMPOSITE_GLYPH;
1815 glyph->pixel_width = it->pixel_width;
1816 glyph->u.cmp.id = it->cmp_it.id;
1817 if (it->cmp_it.ch < 0)
1819 glyph->u.cmp.automatic = 0;
1820 glyph->u.cmp.id = it->cmp_it.id;
1822 else
1824 glyph->u.cmp.automatic = 1;
1825 glyph->u.cmp.id = it->cmp_it.id;
1826 glyph->u.cmp.from = it->cmp_it.from;
1827 glyph->u.cmp.to = it->cmp_it.to - 1;
1830 glyph->face_id = it->face_id;
1831 glyph->padding_p = 0;
1832 glyph->charpos = CHARPOS (it->position);
1833 glyph->object = it->object;
1834 if (it->bidi_p)
1836 glyph->resolved_level = it->bidi_it.resolved_level;
1837 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1838 abort ();
1839 glyph->bidi_type = it->bidi_it.type;
1841 else
1843 glyph->resolved_level = 0;
1844 glyph->bidi_type = UNKNOWN_BT;
1847 ++it->glyph_row->used[it->area];
1848 ++glyph;
1853 /* Produce a composite glyph for iterator IT. IT->cmp_id is the ID of
1854 the composition. We simply produces components of the composition
1855 assuming that the terminal has a capability to layout/render it
1856 correctly. */
1858 static void
1859 produce_composite_glyph (struct it *it)
1861 int c;
1863 if (it->cmp_it.ch < 0)
1865 struct composition *cmp = composition_table[it->cmp_it.id];
1867 it->pixel_width = cmp->width;
1869 else
1871 Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id);
1873 it->pixel_width = composition_gstring_width (gstring, it->cmp_it.from,
1874 it->cmp_it.to, NULL);
1876 it->nglyphs = 1;
1877 if (it->glyph_row)
1878 append_composite_glyph (it);
1882 /* Get information about special display element WHAT in an
1883 environment described by IT. WHAT is one of IT_TRUNCATION or
1884 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1885 non-null glyph_row member. This function ensures that fields like
1886 face_id, c, len of IT are left untouched. */
1888 void
1889 produce_special_glyphs (struct it *it, enum display_element_type what)
1891 struct it temp_it;
1892 Lisp_Object gc;
1893 GLYPH glyph;
1895 temp_it = *it;
1896 temp_it.dp = NULL;
1897 temp_it.what = IT_CHARACTER;
1898 temp_it.len = 1;
1899 temp_it.object = make_number (0);
1900 memset (&temp_it.current, 0, sizeof temp_it.current);
1902 if (what == IT_CONTINUATION)
1904 /* Continuation glyph. For R2L lines, we mirror it by hand. */
1905 if (it->bidi_it.paragraph_dir == R2L)
1906 SET_GLYPH_FROM_CHAR (glyph, '/');
1907 else
1908 SET_GLYPH_FROM_CHAR (glyph, '\\');
1909 if (it->dp
1910 && (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc))
1911 && GLYPH_CODE_CHAR_VALID_P (gc))
1913 /* FIXME: Should we mirror GC for R2L lines? */
1914 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
1915 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
1918 else if (what == IT_TRUNCATION)
1920 /* Truncation glyph. */
1921 SET_GLYPH_FROM_CHAR (glyph, '$');
1922 if (it->dp
1923 && (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc))
1924 && GLYPH_CODE_CHAR_VALID_P (gc))
1926 /* FIXME: Should we mirror GC for R2L lines? */
1927 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
1928 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
1931 else
1932 abort ();
1934 temp_it.c = GLYPH_CHAR (glyph);
1935 temp_it.face_id = GLYPH_FACE (glyph);
1936 temp_it.len = CHAR_BYTES (temp_it.c);
1938 produce_glyphs (&temp_it);
1939 it->pixel_width = temp_it.pixel_width;
1940 it->nglyphs = temp_it.pixel_width;
1945 /***********************************************************************
1946 Faces
1947 ***********************************************************************/
1949 /* Value is non-zero if attribute ATTR may be used. ATTR should be
1950 one of the enumerators from enum no_color_bit, or a bit set built
1951 from them. Some display attributes may not be used together with
1952 color; the termcap capability `NC' specifies which ones. */
1954 #define MAY_USE_WITH_COLORS_P(tty, ATTR) \
1955 (tty->TN_max_colors > 0 \
1956 ? (tty->TN_no_color_video & (ATTR)) == 0 \
1957 : 1)
1959 /* Turn appearances of face FACE_ID on tty frame F on.
1960 FACE_ID is a realized face ID number, in the face cache. */
1962 static void
1963 turn_on_face (struct frame *f, int face_id)
1965 struct face *face = FACE_FROM_ID (f, face_id);
1966 long fg = face->foreground;
1967 long bg = face->background;
1968 struct tty_display_info *tty = FRAME_TTY (f);
1970 /* Do this first because TS_end_standout_mode may be the same
1971 as TS_exit_attribute_mode, which turns all appearances off. */
1972 if (MAY_USE_WITH_COLORS_P (tty, NC_REVERSE))
1974 if (tty->TN_max_colors > 0)
1976 if (fg >= 0 && bg >= 0)
1978 /* If the terminal supports colors, we can set them
1979 below without using reverse video. The face's fg
1980 and bg colors are set as they should appear on
1981 the screen, i.e. they take the inverse-video'ness
1982 of the face already into account. */
1984 else if (inverse_video)
1986 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1987 || bg == FACE_TTY_DEFAULT_BG_COLOR)
1988 tty_toggle_highlight (tty);
1990 else
1992 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1993 || bg == FACE_TTY_DEFAULT_FG_COLOR)
1994 tty_toggle_highlight (tty);
1997 else
1999 /* If we can't display colors, use reverse video
2000 if the face specifies that. */
2001 if (inverse_video)
2003 if (fg == FACE_TTY_DEFAULT_FG_COLOR
2004 || bg == FACE_TTY_DEFAULT_BG_COLOR)
2005 tty_toggle_highlight (tty);
2007 else
2009 if (fg == FACE_TTY_DEFAULT_BG_COLOR
2010 || bg == FACE_TTY_DEFAULT_FG_COLOR)
2011 tty_toggle_highlight (tty);
2016 if (face->tty_bold_p && MAY_USE_WITH_COLORS_P (tty, NC_BOLD))
2017 OUTPUT1_IF (tty, tty->TS_enter_bold_mode);
2019 if (face->tty_dim_p && MAY_USE_WITH_COLORS_P (tty, NC_DIM))
2020 OUTPUT1_IF (tty, tty->TS_enter_dim_mode);
2022 /* Alternate charset and blinking not yet used. */
2023 if (face->tty_alt_charset_p
2024 && MAY_USE_WITH_COLORS_P (tty, NC_ALT_CHARSET))
2025 OUTPUT1_IF (tty, tty->TS_enter_alt_charset_mode);
2027 if (face->tty_blinking_p
2028 && MAY_USE_WITH_COLORS_P (tty, NC_BLINK))
2029 OUTPUT1_IF (tty, tty->TS_enter_blink_mode);
2031 if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (tty, NC_UNDERLINE))
2032 OUTPUT1_IF (tty, tty->TS_enter_underline_mode);
2034 if (tty->TN_max_colors > 0)
2036 char *ts, *p;
2038 ts = tty->standout_mode ? tty->TS_set_background : tty->TS_set_foreground;
2039 if (fg >= 0 && ts)
2041 p = tparam (ts, NULL, 0, (int) fg);
2042 OUTPUT (tty, p);
2043 xfree (p);
2046 ts = tty->standout_mode ? tty->TS_set_foreground : tty->TS_set_background;
2047 if (bg >= 0 && ts)
2049 p = tparam (ts, NULL, 0, (int) bg);
2050 OUTPUT (tty, p);
2051 xfree (p);
2057 /* Turn off appearances of face FACE_ID on tty frame F. */
2059 static void
2060 turn_off_face (struct frame *f, int face_id)
2062 struct face *face = FACE_FROM_ID (f, face_id);
2063 struct tty_display_info *tty = FRAME_TTY (f);
2065 xassert (face != NULL);
2067 if (tty->TS_exit_attribute_mode)
2069 /* Capability "me" will turn off appearance modes double-bright,
2070 half-bright, reverse-video, standout, underline. It may or
2071 may not turn off alt-char-mode. */
2072 if (face->tty_bold_p
2073 || face->tty_dim_p
2074 || face->tty_reverse_p
2075 || face->tty_alt_charset_p
2076 || face->tty_blinking_p
2077 || face->tty_underline_p)
2079 OUTPUT1_IF (tty, tty->TS_exit_attribute_mode);
2080 if (strcmp (tty->TS_exit_attribute_mode, tty->TS_end_standout_mode) == 0)
2081 tty->standout_mode = 0;
2084 if (face->tty_alt_charset_p)
2085 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
2087 else
2089 /* If we don't have "me" we can only have those appearances
2090 that have exit sequences defined. */
2091 if (face->tty_alt_charset_p)
2092 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
2094 if (face->tty_underline_p)
2095 OUTPUT_IF (tty, tty->TS_exit_underline_mode);
2098 /* Switch back to default colors. */
2099 if (tty->TN_max_colors > 0
2100 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
2101 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
2102 || (face->background != FACE_TTY_DEFAULT_COLOR
2103 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
2104 OUTPUT1_IF (tty, tty->TS_orig_pair);
2108 /* Return non-zero if the terminal on frame F supports all of the
2109 capabilities in CAPS simultaneously, with foreground and background
2110 colors FG and BG. */
2113 tty_capable_p (struct tty_display_info *tty, unsigned int caps,
2114 unsigned long fg, unsigned long bg)
2116 #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
2117 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
2118 return 0;
2120 TTY_CAPABLE_P_TRY (tty, TTY_CAP_INVERSE, tty->TS_standout_mode, NC_REVERSE);
2121 TTY_CAPABLE_P_TRY (tty, TTY_CAP_UNDERLINE, tty->TS_enter_underline_mode, NC_UNDERLINE);
2122 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BOLD, tty->TS_enter_bold_mode, NC_BOLD);
2123 TTY_CAPABLE_P_TRY (tty, TTY_CAP_DIM, tty->TS_enter_dim_mode, NC_DIM);
2124 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BLINK, tty->TS_enter_blink_mode, NC_BLINK);
2125 TTY_CAPABLE_P_TRY (tty, TTY_CAP_ALT_CHARSET, tty->TS_enter_alt_charset_mode, NC_ALT_CHARSET);
2127 /* We can do it! */
2128 return 1;
2131 /* Return non-zero if the terminal is capable to display colors. */
2133 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
2134 0, 1, 0,
2135 doc: /* Return non-nil if the tty device TERMINAL can display colors.
2137 TERMINAL can be a terminal object, a frame, or nil (meaning the
2138 selected frame's terminal). This function always returns nil if
2139 TERMINAL does not refer to a text-only terminal. */)
2140 (Lisp_Object terminal)
2142 struct terminal *t = get_tty_terminal (terminal, 0);
2143 if (!t)
2144 return Qnil;
2145 else
2146 return t->display_info.tty->TN_max_colors > 0 ? Qt : Qnil;
2149 /* Return the number of supported colors. */
2150 DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
2151 Stty_display_color_cells, 0, 1, 0,
2152 doc: /* Return the number of colors supported by the tty device TERMINAL.
2154 TERMINAL can be a terminal object, a frame, or nil (meaning the
2155 selected frame's terminal). This function always returns 0 if
2156 TERMINAL does not refer to a text-only terminal. */)
2157 (Lisp_Object terminal)
2159 struct terminal *t = get_tty_terminal (terminal, 0);
2160 if (!t)
2161 return make_number (0);
2162 else
2163 return make_number (t->display_info.tty->TN_max_colors);
2166 #ifndef DOS_NT
2168 /* Declare here rather than in the function, as in the rest of Emacs,
2169 to work around an HPUX compiler bug (?). See
2170 http://lists.gnu.org/archive/html/emacs-devel/2007-08/msg00410.html */
2171 static int default_max_colors;
2172 static int default_max_pairs;
2173 static int default_no_color_video;
2174 static char *default_orig_pair;
2175 static char *default_set_foreground;
2176 static char *default_set_background;
2178 /* Save or restore the default color-related capabilities of this
2179 terminal. */
2180 static void
2181 tty_default_color_capabilities (struct tty_display_info *tty, int save)
2184 if (save)
2186 xfree (default_orig_pair);
2187 default_orig_pair = tty->TS_orig_pair ? xstrdup (tty->TS_orig_pair) : NULL;
2189 xfree (default_set_foreground);
2190 default_set_foreground = tty->TS_set_foreground ? xstrdup (tty->TS_set_foreground)
2191 : NULL;
2193 xfree (default_set_background);
2194 default_set_background = tty->TS_set_background ? xstrdup (tty->TS_set_background)
2195 : NULL;
2197 default_max_colors = tty->TN_max_colors;
2198 default_max_pairs = tty->TN_max_pairs;
2199 default_no_color_video = tty->TN_no_color_video;
2201 else
2203 tty->TS_orig_pair = default_orig_pair;
2204 tty->TS_set_foreground = default_set_foreground;
2205 tty->TS_set_background = default_set_background;
2206 tty->TN_max_colors = default_max_colors;
2207 tty->TN_max_pairs = default_max_pairs;
2208 tty->TN_no_color_video = default_no_color_video;
2212 /* Setup one of the standard tty color schemes according to MODE.
2213 MODE's value is generally the number of colors which we want to
2214 support; zero means set up for the default capabilities, the ones
2215 we saw at init_tty time; -1 means turn off color support. */
2216 static void
2217 tty_setup_colors (struct tty_display_info *tty, int mode)
2219 /* Canonicalize all negative values of MODE. */
2220 if (mode < -1)
2221 mode = -1;
2223 switch (mode)
2225 case -1: /* no colors at all */
2226 tty->TN_max_colors = 0;
2227 tty->TN_max_pairs = 0;
2228 tty->TN_no_color_video = 0;
2229 tty->TS_set_foreground = tty->TS_set_background = tty->TS_orig_pair = NULL;
2230 break;
2231 case 0: /* default colors, if any */
2232 default:
2233 tty_default_color_capabilities (tty, 0);
2234 break;
2235 case 8: /* 8 standard ANSI colors */
2236 tty->TS_orig_pair = "\033[0m";
2237 #ifdef TERMINFO
2238 tty->TS_set_foreground = "\033[3%p1%dm";
2239 tty->TS_set_background = "\033[4%p1%dm";
2240 #else
2241 tty->TS_set_foreground = "\033[3%dm";
2242 tty->TS_set_background = "\033[4%dm";
2243 #endif
2244 tty->TN_max_colors = 8;
2245 tty->TN_max_pairs = 64;
2246 tty->TN_no_color_video = 0;
2247 break;
2251 void
2252 set_tty_color_mode (struct tty_display_info *tty, struct frame *f)
2254 Lisp_Object tem, val;
2255 Lisp_Object color_mode;
2256 int mode;
2257 extern Lisp_Object Qtty_color_mode;
2258 Lisp_Object tty_color_mode_alist
2259 = Fintern_soft (build_string ("tty-color-mode-alist"), Qnil);
2261 tem = assq_no_quit (Qtty_color_mode, f->param_alist);
2262 val = CONSP (tem) ? XCDR (tem) : Qnil;
2264 if (INTEGERP (val))
2265 color_mode = val;
2266 else if (SYMBOLP (tty_color_mode_alist))
2268 tem = Fassq (val, Fsymbol_value (tty_color_mode_alist));
2269 color_mode = CONSP (tem) ? XCDR (tem) : Qnil;
2271 else
2272 color_mode = Qnil;
2274 mode = INTEGERP (color_mode) ? XINT (color_mode) : 0;
2276 if (mode != tty->previous_color_mode)
2278 Lisp_Object funsym = intern ("tty-set-up-initial-frame-faces");
2279 tty->previous_color_mode = mode;
2280 tty_setup_colors (tty , mode);
2281 /* This recomputes all the faces given the new color definitions. */
2282 safe_call (1, &funsym);
2286 #endif /* !DOS_NT */
2290 /* Return the tty display object specified by TERMINAL. */
2292 struct terminal *
2293 get_tty_terminal (Lisp_Object terminal, int throw)
2295 struct terminal *t = get_terminal (terminal, throw);
2297 if (t && t->type != output_termcap && t->type != output_msdos_raw)
2299 if (throw)
2300 error ("Device %d is not a termcap terminal device", t->id);
2301 else
2302 return NULL;
2305 return t;
2308 /* Return an active termcap device that uses the tty device with the
2309 given name.
2311 This function ignores suspended devices.
2313 Returns NULL if the named terminal device is not opened. */
2315 struct terminal *
2316 get_named_tty (char *name)
2318 struct terminal *t;
2320 if (!name)
2321 abort ();
2323 for (t = terminal_list; t; t = t->next_terminal)
2325 if ((t->type == output_termcap || t->type == output_msdos_raw)
2326 && !strcmp (t->display_info.tty->name, name)
2327 && TERMINAL_ACTIVE_P (t))
2328 return t;
2331 return 0;
2335 DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0,
2336 doc: /* Return the type of the tty device that TERMINAL uses.
2337 Returns nil if TERMINAL is not on a tty device.
2339 TERMINAL can be a terminal object, a frame, or nil (meaning the
2340 selected frame's terminal). */)
2341 (Lisp_Object terminal)
2343 struct terminal *t = get_terminal (terminal, 1);
2345 if (t->type != output_termcap && t->type != output_msdos_raw)
2346 return Qnil;
2348 if (t->display_info.tty->type)
2349 return build_string (t->display_info.tty->type);
2350 else
2351 return Qnil;
2354 DEFUN ("controlling-tty-p", Fcontrolling_tty_p, Scontrolling_tty_p, 0, 1, 0,
2355 doc: /* Return non-nil if TERMINAL is the controlling tty of the Emacs process.
2357 TERMINAL can be a terminal object, a frame, or nil (meaning the
2358 selected frame's terminal). This function always returns nil if
2359 TERMINAL is not on a tty device. */)
2360 (Lisp_Object terminal)
2362 struct terminal *t = get_terminal (terminal, 1);
2364 if ((t->type != output_termcap && t->type != output_msdos_raw)
2365 || strcmp (t->display_info.tty->name, DEV_TTY) != 0)
2366 return Qnil;
2367 else
2368 return Qt;
2371 DEFUN ("tty-no-underline", Ftty_no_underline, Stty_no_underline, 0, 1, 0,
2372 doc: /* Declare that the tty used by TERMINAL does not handle underlining.
2373 This is used to override the terminfo data, for certain terminals that
2374 do not really do underlining, but say that they do. This function has
2375 no effect if used on a non-tty terminal.
2377 TERMINAL can be a terminal object, a frame or nil (meaning the
2378 selected frame's terminal). This function always returns nil if
2379 TERMINAL does not refer to a text-only terminal. */)
2380 (Lisp_Object terminal)
2382 struct terminal *t = get_terminal (terminal, 1);
2384 if (t->type == output_termcap)
2385 t->display_info.tty->TS_enter_underline_mode = 0;
2386 return Qnil;
2391 DEFUN ("suspend-tty", Fsuspend_tty, Ssuspend_tty, 0, 1, 0,
2392 doc: /* Suspend the terminal device TTY.
2394 The device is restored to its default state, and Emacs ceases all
2395 access to the tty device. Frames that use the device are not deleted,
2396 but input is not read from them and if they change, their display is
2397 not updated.
2399 TTY may be a terminal object, a frame, or nil for the terminal device
2400 of the currently selected frame.
2402 This function runs `suspend-tty-functions' after suspending the
2403 device. The functions are run with one arg, the id of the suspended
2404 terminal device.
2406 `suspend-tty' does nothing if it is called on a device that is already
2407 suspended.
2409 A suspended tty may be resumed by calling `resume-tty' on it. */)
2410 (Lisp_Object tty)
2412 struct terminal *t = get_tty_terminal (tty, 1);
2413 FILE *f;
2415 if (!t)
2416 error ("Unknown tty device");
2418 f = t->display_info.tty->input;
2420 if (f)
2422 /* First run `suspend-tty-functions' and then clean up the tty
2423 state because `suspend-tty-functions' might need to change
2424 the tty state. */
2425 if (!NILP (Vrun_hooks))
2427 Lisp_Object args[2];
2428 args[0] = intern ("suspend-tty-functions");
2429 XSETTERMINAL (args[1], t);
2430 Frun_hook_with_args (2, args);
2433 reset_sys_modes (t->display_info.tty);
2434 delete_keyboard_wait_descriptor (fileno (f));
2436 #ifndef MSDOS
2437 fclose (f);
2438 if (f != t->display_info.tty->output)
2439 fclose (t->display_info.tty->output);
2440 #endif
2442 t->display_info.tty->input = 0;
2443 t->display_info.tty->output = 0;
2445 if (FRAMEP (t->display_info.tty->top_frame))
2446 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0);
2450 /* Clear display hooks to prevent further output. */
2451 clear_tty_hooks (t);
2453 return Qnil;
2456 DEFUN ("resume-tty", Fresume_tty, Sresume_tty, 0, 1, 0,
2457 doc: /* Resume the previously suspended terminal device TTY.
2458 The terminal is opened and reinitialized. Frames that are on the
2459 suspended terminal are revived.
2461 It is an error to resume a terminal while another terminal is active
2462 on the same device.
2464 This function runs `resume-tty-functions' after resuming the terminal.
2465 The functions are run with one arg, the id of the resumed terminal
2466 device.
2468 `resume-tty' does nothing if it is called on a device that is not
2469 suspended.
2471 TTY may be a terminal object, a frame, or nil (meaning the selected
2472 frame's terminal). */)
2473 (Lisp_Object tty)
2475 struct terminal *t = get_tty_terminal (tty, 1);
2476 int fd;
2478 if (!t)
2479 error ("Unknown tty device");
2481 if (!t->display_info.tty->input)
2483 if (get_named_tty (t->display_info.tty->name))
2484 error ("Cannot resume display while another display is active on the same device");
2486 #ifdef MSDOS
2487 t->display_info.tty->output = stdout;
2488 t->display_info.tty->input = stdin;
2489 #else /* !MSDOS */
2490 fd = emacs_open (t->display_info.tty->name, O_RDWR | O_NOCTTY, 0);
2492 if (fd == -1)
2493 error ("Can not reopen tty device %s: %s", t->display_info.tty->name, strerror (errno));
2495 if (strcmp (t->display_info.tty->name, DEV_TTY))
2496 dissociate_if_controlling_tty (fd);
2498 t->display_info.tty->output = fdopen (fd, "w+");
2499 t->display_info.tty->input = t->display_info.tty->output;
2500 #endif
2502 add_keyboard_wait_descriptor (fd);
2504 if (FRAMEP (t->display_info.tty->top_frame))
2506 struct frame *f = XFRAME (t->display_info.tty->top_frame);
2507 int width, height;
2508 int old_height = FRAME_COLS (f);
2509 int old_width = FRAME_LINES (f);
2511 /* Check if terminal/window size has changed while the frame
2512 was suspended. */
2513 get_tty_size (fileno (t->display_info.tty->input), &width, &height);
2514 if (width != old_width || height != old_height)
2515 change_frame_size (f, height, width, 0, 0, 0);
2516 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
2519 init_sys_modes (t->display_info.tty);
2521 /* Run `resume-tty-functions'. */
2522 if (!NILP (Vrun_hooks))
2524 Lisp_Object args[2];
2525 args[0] = intern ("resume-tty-functions");
2526 XSETTERMINAL (args[1], t);
2527 Frun_hook_with_args (2, args);
2531 set_tty_hooks (t);
2533 return Qnil;
2537 /***********************************************************************
2538 Mouse
2539 ***********************************************************************/
2541 #ifdef HAVE_GPM
2542 void
2543 term_mouse_moveto (int x, int y)
2545 /* TODO: how to set mouse position?
2546 const char *name;
2547 int fd;
2548 name = (const char *) ttyname (0);
2549 fd = open (name, O_WRONLY);
2550 SOME_FUNCTION (x, y, fd);
2551 close (fd);
2552 last_mouse_x = x;
2553 last_mouse_y = y; */
2556 static void
2557 term_show_mouse_face (enum draw_glyphs_face draw)
2559 struct window *w = XWINDOW (mouse_face_window);
2560 int save_x, save_y;
2561 int i;
2563 struct frame *f = XFRAME (w->frame);
2564 struct tty_display_info *tty = FRAME_TTY (f);
2566 if (/* If window is in the process of being destroyed, don't bother
2567 to do anything. */
2568 w->current_matrix != NULL
2569 /* Recognize when we are called to operate on rows that don't exist
2570 anymore. This can happen when a window is split. */
2571 && mouse_face_end_row < w->current_matrix->nrows)
2573 /* write_glyphs writes at cursor position, so we need to
2574 temporarily move cursor coordinates to the beginning of
2575 the highlight region. */
2577 /* Save current cursor co-ordinates */
2578 save_y = curY (tty);
2579 save_x = curX (tty);
2581 /* Note that mouse_face_beg_row etc. are window relative. */
2582 for (i = mouse_face_beg_row; i <= mouse_face_end_row; i++)
2584 int start_hpos, end_hpos, nglyphs;
2585 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
2587 /* Don't do anything if row doesn't have valid contents. */
2588 if (!row->enabled_p)
2589 continue;
2591 /* For all but the first row, the highlight starts at column 0. */
2592 if (i == mouse_face_beg_row)
2593 start_hpos = mouse_face_beg_col;
2594 else
2595 start_hpos = 0;
2597 if (i == mouse_face_end_row)
2598 end_hpos = mouse_face_end_col;
2599 else
2601 end_hpos = row->used[TEXT_AREA];
2602 if (draw == DRAW_NORMAL_TEXT)
2603 row->fill_line_p = 1; /* Clear to end of line */
2606 if (end_hpos <= start_hpos)
2607 continue;
2608 /* Record that some glyphs of this row are displayed in
2609 mouse-face. */
2610 row->mouse_face_p = draw > 0;
2612 nglyphs = end_hpos - start_hpos;
2614 if (end_hpos >= row->used[TEXT_AREA])
2615 nglyphs = row->used[TEXT_AREA] - start_hpos;
2617 pos_y = row->y + WINDOW_TOP_EDGE_Y (w);
2618 pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos
2619 + WINDOW_LEFT_EDGE_X (w);
2621 cursor_to (f, pos_y, pos_x);
2623 if (draw == DRAW_MOUSE_FACE)
2625 tty_write_glyphs_with_face (f, row->glyphs[TEXT_AREA] + start_hpos,
2626 nglyphs, mouse_face_face_id);
2628 else /* draw == DRAW_NORMAL_TEXT */
2629 write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
2631 cursor_to (f, save_y, save_x);
2635 static void
2636 term_clear_mouse_face (void)
2638 if (!NILP (mouse_face_window))
2639 term_show_mouse_face (DRAW_NORMAL_TEXT);
2641 mouse_face_beg_row = mouse_face_beg_col = -1;
2642 mouse_face_end_row = mouse_face_end_col = -1;
2643 mouse_face_window = Qnil;
2646 /* Find the glyph matrix position of buffer position POS in window W.
2647 *HPOS and *VPOS are set to the positions found. W's current glyphs
2648 must be up to date. If POS is above window start return (0, 0).
2649 If POS is after end of W, return end of last line in W.
2650 - taken from msdos.c */
2651 static int
2652 fast_find_position (struct window *w, int pos, int *hpos, int *vpos)
2654 int i, lastcol, line_start_position, maybe_next_line_p = 0;
2655 int yb = window_text_bottom_y (w);
2656 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0), *best_row = row;
2658 while (row->y < yb)
2660 if (row->used[TEXT_AREA])
2661 line_start_position = row->glyphs[TEXT_AREA]->charpos;
2662 else
2663 line_start_position = 0;
2665 if (line_start_position > pos)
2666 break;
2667 /* If the position sought is the end of the buffer,
2668 don't include the blank lines at the bottom of the window. */
2669 else if (line_start_position == pos
2670 && pos == BUF_ZV (XBUFFER (w->buffer)))
2672 maybe_next_line_p = 1;
2673 break;
2675 else if (line_start_position > 0)
2676 best_row = row;
2678 /* Don't overstep the last matrix row, lest we get into the
2679 never-never land... */
2680 if (row->y + 1 >= yb)
2681 break;
2683 ++row;
2686 /* Find the right column within BEST_ROW. */
2687 lastcol = 0;
2688 row = best_row;
2689 for (i = 0; i < row->used[TEXT_AREA]; i++)
2691 struct glyph *glyph = row->glyphs[TEXT_AREA] + i;
2692 int charpos;
2694 charpos = glyph->charpos;
2695 if (charpos == pos)
2697 *hpos = i;
2698 *vpos = row->y;
2699 return 1;
2701 else if (charpos > pos)
2702 break;
2703 else if (charpos > 0)
2704 lastcol = i;
2707 /* If we're looking for the end of the buffer,
2708 and we didn't find it in the line we scanned,
2709 use the start of the following line. */
2710 if (maybe_next_line_p)
2712 ++row;
2713 lastcol = 0;
2716 *vpos = row->y;
2717 *hpos = lastcol + 1;
2718 return 0;
2721 static void
2722 term_mouse_highlight (struct frame *f, int x, int y)
2724 enum window_part part;
2725 Lisp_Object window;
2726 struct window *w;
2727 struct buffer *b;
2729 if (NILP (Vmouse_highlight)
2730 || !f->glyphs_initialized_p)
2731 return;
2733 /* Which window is that in? */
2734 window = window_from_coordinates (f, x, y, &part, &x, &y, 0);
2736 /* Not on a window -> return. */
2737 if (!WINDOWP (window))
2738 return;
2740 if (!EQ (window, mouse_face_window))
2741 term_clear_mouse_face ();
2743 w = XWINDOW (window);
2745 /* Are we in a window whose display is up to date?
2746 And verify the buffer's text has not changed. */
2747 b = XBUFFER (w->buffer);
2748 if (part == ON_TEXT
2749 && EQ (w->window_end_valid, w->buffer)
2750 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
2751 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
2753 int pos, i, nrows = w->current_matrix->nrows;
2754 struct glyph_row *row;
2755 struct glyph *glyph;
2757 /* Find the glyph under X/Y. */
2758 glyph = NULL;
2759 if (y >= 0 && y < nrows)
2761 row = MATRIX_ROW (w->current_matrix, y);
2762 /* Give up if some row before the one we are looking for is
2763 not enabled. */
2764 for (i = 0; i <= y; i++)
2765 if (!MATRIX_ROW (w->current_matrix, i)->enabled_p)
2766 break;
2767 if (i > y /* all rows upto and including the one at Y are enabled */
2768 && row->displays_text_p
2769 && x < window_box_width (w, TEXT_AREA))
2771 glyph = row->glyphs[TEXT_AREA];
2772 if (x >= row->used[TEXT_AREA])
2773 glyph = NULL;
2774 else
2776 glyph += x;
2777 if (!BUFFERP (glyph->object))
2778 glyph = NULL;
2783 /* Clear mouse face if X/Y not over text. */
2784 if (glyph == NULL)
2786 term_clear_mouse_face ();
2787 return;
2790 if (!BUFFERP (glyph->object))
2791 abort ();
2792 pos = glyph->charpos;
2794 /* Check for mouse-face. */
2796 extern Lisp_Object Qmouse_face;
2797 Lisp_Object mouse_face, overlay, position, *overlay_vec;
2798 int noverlays, obegv, ozv;
2799 struct buffer *obuf;
2801 /* If we get an out-of-range value, return now; avoid an error. */
2802 if (pos > BUF_Z (b))
2803 return;
2805 /* Make the window's buffer temporarily current for
2806 overlays_at and compute_char_face. */
2807 obuf = current_buffer;
2808 current_buffer = b;
2809 obegv = BEGV;
2810 ozv = ZV;
2811 BEGV = BEG;
2812 ZV = Z;
2814 /* Is this char mouse-active? */
2815 XSETINT (position, pos);
2817 /* Put all the overlays we want in a vector in overlay_vec. */
2818 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL, 0);
2819 /* Sort overlays into increasing priority order. */
2820 noverlays = sort_overlays (overlay_vec, noverlays, w);
2822 /* Check mouse-face highlighting. */
2823 if (!(EQ (window, mouse_face_window)
2824 && y >= mouse_face_beg_row
2825 && y <= mouse_face_end_row
2826 && (y > mouse_face_beg_row
2827 || x >= mouse_face_beg_col)
2828 && (y < mouse_face_end_row
2829 || x < mouse_face_end_col
2830 || mouse_face_past_end)))
2832 /* Clear the display of the old active region, if any. */
2833 term_clear_mouse_face ();
2835 /* Find the highest priority overlay that has a mouse-face
2836 property. */
2837 overlay = Qnil;
2838 for (i = noverlays - 1; i >= 0; --i)
2840 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
2841 if (!NILP (mouse_face))
2843 overlay = overlay_vec[i];
2844 break;
2848 /* If no overlay applies, get a text property. */
2849 if (NILP (overlay))
2850 mouse_face = Fget_text_property (position, Qmouse_face,
2851 w->buffer);
2853 /* Handle the overlay case. */
2854 if (!NILP (overlay))
2856 /* Find the range of text around this char that
2857 should be active. */
2858 Lisp_Object before, after;
2859 EMACS_INT ignore;
2862 before = Foverlay_start (overlay);
2863 after = Foverlay_end (overlay);
2864 /* Record this as the current active region. */
2865 fast_find_position (w, XFASTINT (before),
2866 &mouse_face_beg_col,
2867 &mouse_face_beg_row);
2869 mouse_face_past_end
2870 = !fast_find_position (w, XFASTINT (after),
2871 &mouse_face_end_col,
2872 &mouse_face_end_row);
2873 mouse_face_window = window;
2875 mouse_face_face_id
2876 = face_at_buffer_position (w, pos, 0, 0,
2877 &ignore, pos + 1, 1, -1);
2879 /* Display it as active. */
2880 term_show_mouse_face (DRAW_MOUSE_FACE);
2882 /* Handle the text property case. */
2883 else if (!NILP (mouse_face))
2885 /* Find the range of text around this char that
2886 should be active. */
2887 Lisp_Object before, after, beginning, end;
2888 EMACS_INT ignore;
2890 beginning = Fmarker_position (w->start);
2891 XSETINT (end, (BUF_Z (b) - XFASTINT (w->window_end_pos)));
2892 before
2893 = Fprevious_single_property_change (make_number (pos + 1),
2894 Qmouse_face,
2895 w->buffer, beginning);
2896 after
2897 = Fnext_single_property_change (position, Qmouse_face,
2898 w->buffer, end);
2900 /* Record this as the current active region. */
2901 fast_find_position (w, XFASTINT (before),
2902 &mouse_face_beg_col,
2903 &mouse_face_beg_row);
2904 mouse_face_past_end
2905 = !fast_find_position (w, XFASTINT (after),
2906 &mouse_face_end_col,
2907 &mouse_face_end_row);
2908 mouse_face_window = window;
2910 mouse_face_face_id
2911 = face_at_buffer_position (w, pos, 0, 0,
2912 &ignore, pos + 1, 1, -1);
2914 /* Display it as active. */
2915 term_show_mouse_face (DRAW_MOUSE_FACE);
2919 /* Look for a `help-echo' property. */
2921 Lisp_Object help;
2922 extern Lisp_Object Qhelp_echo;
2924 /* Check overlays first. */
2925 help = Qnil;
2926 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
2928 overlay = overlay_vec[i];
2929 help = Foverlay_get (overlay, Qhelp_echo);
2932 if (!NILP (help))
2934 help_echo_string = help;
2935 help_echo_window = window;
2936 help_echo_object = overlay;
2937 help_echo_pos = pos;
2939 /* Try text properties. */
2940 else if (NILP (help)
2941 && ((STRINGP (glyph->object)
2942 && glyph->charpos >= 0
2943 && glyph->charpos < SCHARS (glyph->object))
2944 || (BUFFERP (glyph->object)
2945 && glyph->charpos >= BEGV
2946 && glyph->charpos < ZV)))
2948 help = Fget_text_property (make_number (glyph->charpos),
2949 Qhelp_echo, glyph->object);
2950 if (!NILP (help))
2952 help_echo_string = help;
2953 help_echo_window = window;
2954 help_echo_object = glyph->object;
2955 help_echo_pos = glyph->charpos;
2960 BEGV = obegv;
2961 ZV = ozv;
2962 current_buffer = obuf;
2967 static int
2968 term_mouse_movement (FRAME_PTR frame, Gpm_Event *event)
2970 /* Has the mouse moved off the glyph it was on at the last sighting? */
2971 if (event->x != last_mouse_x || event->y != last_mouse_y)
2973 frame->mouse_moved = 1;
2974 term_mouse_highlight (frame, event->x, event->y);
2975 /* Remember which glyph we're now on. */
2976 last_mouse_x = event->x;
2977 last_mouse_y = event->y;
2978 return 1;
2980 return 0;
2983 /* Return the current position of the mouse.
2985 Set *f to the frame the mouse is in, or zero if the mouse is in no
2986 Emacs frame. If it is set to zero, all the other arguments are
2987 garbage.
2989 Set *bar_window to Qnil, and *x and *y to the column and
2990 row of the character cell the mouse is over.
2992 Set *time to the time the mouse was at the returned position.
2994 This clears mouse_moved until the next motion
2995 event arrives. */
2996 static void
2997 term_mouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
2998 enum scroll_bar_part *part, Lisp_Object *x,
2999 Lisp_Object *y, unsigned long *time)
3001 struct timeval now;
3003 *fp = SELECTED_FRAME ();
3004 (*fp)->mouse_moved = 0;
3006 *bar_window = Qnil;
3007 *part = 0;
3009 XSETINT (*x, last_mouse_x);
3010 XSETINT (*y, last_mouse_y);
3011 gettimeofday(&now, 0);
3012 *time = (now.tv_sec * 1000) + (now.tv_usec / 1000);
3015 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3017 If the event is a button press, then note that we have grabbed
3018 the mouse. */
3020 static Lisp_Object
3021 term_mouse_click (struct input_event *result, Gpm_Event *event,
3022 struct frame *f)
3024 struct timeval now;
3025 int i, j;
3027 result->kind = GPM_CLICK_EVENT;
3028 for (i = 0, j = GPM_B_LEFT; i < 3; i++, j >>= 1 )
3030 if (event->buttons & j) {
3031 result->code = i; /* button number */
3032 break;
3035 gettimeofday(&now, 0);
3036 result->timestamp = (now.tv_sec * 1000) + (now.tv_usec / 1000);
3038 if (event->type & GPM_UP)
3039 result->modifiers = up_modifier;
3040 else if (event->type & GPM_DOWN)
3041 result->modifiers = down_modifier;
3042 else
3043 result->modifiers = 0;
3045 if (event->type & GPM_SINGLE)
3046 result->modifiers |= click_modifier;
3048 if (event->type & GPM_DOUBLE)
3049 result->modifiers |= double_modifier;
3051 if (event->type & GPM_TRIPLE)
3052 result->modifiers |= triple_modifier;
3054 if (event->type & GPM_DRAG)
3055 result->modifiers |= drag_modifier;
3057 if (!(event->type & (GPM_MOVE | GPM_DRAG))) {
3059 /* 1 << KG_SHIFT */
3060 if (event->modifiers & (1 << 0))
3061 result->modifiers |= shift_modifier;
3063 /* 1 << KG_CTRL */
3064 if (event->modifiers & (1 << 2))
3065 result->modifiers |= ctrl_modifier;
3067 /* 1 << KG_ALT || KG_ALTGR */
3068 if (event->modifiers & (1 << 3)
3069 || event->modifiers & (1 << 1))
3070 result->modifiers |= meta_modifier;
3073 XSETINT (result->x, event->x);
3074 XSETINT (result->y, event->y);
3075 XSETFRAME (result->frame_or_window, f);
3076 result->arg = Qnil;
3077 return Qnil;
3081 handle_one_term_event (struct tty_display_info *tty, Gpm_Event *event, struct input_event* hold_quit)
3083 struct frame *f = XFRAME (tty->top_frame);
3084 struct input_event ie;
3085 int do_help = 0;
3086 int count = 0;
3088 EVENT_INIT (ie);
3089 ie.kind = NO_EVENT;
3090 ie.arg = Qnil;
3092 if (event->type & (GPM_MOVE | GPM_DRAG)) {
3093 previous_help_echo_string = help_echo_string;
3094 help_echo_string = Qnil;
3096 Gpm_DrawPointer (event->x, event->y, fileno (tty->output));
3098 if (!term_mouse_movement (f, event))
3099 help_echo_string = previous_help_echo_string;
3101 /* If the contents of the global variable help_echo_string
3102 has changed, generate a HELP_EVENT. */
3103 if (!NILP (help_echo_string)
3104 || !NILP (previous_help_echo_string))
3105 do_help = 1;
3107 goto done;
3109 else {
3110 f->mouse_moved = 0;
3111 term_mouse_click (&ie, event, f);
3114 done:
3115 if (ie.kind != NO_EVENT)
3117 kbd_buffer_store_event_hold (&ie, hold_quit);
3118 count++;
3121 if (do_help
3122 && !(hold_quit && hold_quit->kind != NO_EVENT))
3124 Lisp_Object frame;
3126 if (f)
3127 XSETFRAME (frame, f);
3128 else
3129 frame = Qnil;
3131 gen_help_event (help_echo_string, frame, help_echo_window,
3132 help_echo_object, help_echo_pos);
3133 count++;
3136 return count;
3139 DEFUN ("gpm-mouse-start", Fgpm_mouse_start, Sgpm_mouse_start,
3140 0, 0, 0,
3141 doc: /* Open a connection to Gpm.
3142 Gpm-mouse can only be activated for one tty at a time. */)
3143 (void)
3145 struct frame *f = SELECTED_FRAME ();
3146 struct tty_display_info *tty
3147 = ((f)->output_method == output_termcap
3148 ? (f)->terminal->display_info.tty : NULL);
3149 Gpm_Connect connection;
3151 if (!tty)
3152 error ("Gpm-mouse only works in the GNU/Linux console");
3153 if (gpm_tty == tty)
3154 return Qnil; /* Already activated, nothing to do. */
3155 if (gpm_tty)
3156 error ("Gpm-mouse can only be activated for one tty at a time");
3158 connection.eventMask = ~0;
3159 connection.defaultMask = ~GPM_HARD;
3160 connection.maxMod = ~0;
3161 connection.minMod = 0;
3162 gpm_zerobased = 1;
3164 if (Gpm_Open (&connection, 0) < 0)
3165 error ("Gpm-mouse failed to connect to the gpm daemon");
3166 else
3168 gpm_tty = tty;
3169 /* `init_sys_modes' arranges for mouse movements sent through gpm_fd
3170 to generate SIGIOs. Apparently we need to call reset_sys_modes
3171 before calling init_sys_modes. */
3172 reset_sys_modes (tty);
3173 init_sys_modes (tty);
3174 add_gpm_wait_descriptor (gpm_fd);
3175 return Qnil;
3179 void
3180 close_gpm (int fd)
3182 if (fd >= 0)
3183 delete_gpm_wait_descriptor (fd);
3184 while (Gpm_Close()); /* close all the stack */
3185 gpm_tty = NULL;
3188 DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop, Sgpm_mouse_stop,
3189 0, 0, 0,
3190 doc: /* Close a connection to Gpm. */)
3191 (void)
3193 struct frame *f = SELECTED_FRAME ();
3194 struct tty_display_info *tty
3195 = ((f)->output_method == output_termcap
3196 ? (f)->terminal->display_info.tty : NULL);
3198 if (!tty || gpm_tty != tty)
3199 return Qnil; /* Not activated on this terminal, nothing to do. */
3201 close_gpm (gpm_fd);
3202 return Qnil;
3204 #endif /* HAVE_GPM */
3207 #ifndef MSDOS
3208 /***********************************************************************
3209 Initialization
3210 ***********************************************************************/
3212 /* Initialize the tty-dependent part of frame F. The frame must
3213 already have its device initialized. */
3215 void
3216 create_tty_output (struct frame *f)
3218 struct tty_output *t;
3220 if (! FRAME_TERMCAP_P (f))
3221 abort ();
3223 t = xmalloc (sizeof (struct tty_output));
3224 memset (t, 0, sizeof (struct tty_output));
3226 t->display_info = FRAME_TERMINAL (f)->display_info.tty;
3228 f->output_data.tty = t;
3231 /* Delete frame F's face cache, and its tty-dependent part. */
3233 static void
3234 tty_free_frame_resources (struct frame *f)
3236 if (! FRAME_TERMCAP_P (f))
3237 abort ();
3239 if (FRAME_FACE_CACHE (f))
3240 free_frame_faces (f);
3242 xfree (f->output_data.tty);
3245 #else /* MSDOS */
3247 /* Delete frame F's face cache. */
3249 static void
3250 tty_free_frame_resources (struct frame *f)
3252 if (! FRAME_TERMCAP_P (f) && ! FRAME_MSDOS_P (f))
3253 abort ();
3255 if (FRAME_FACE_CACHE (f))
3256 free_frame_faces (f);
3258 #endif /* MSDOS */
3260 /* Reset the hooks in TERMINAL. */
3262 static void
3263 clear_tty_hooks (struct terminal *terminal)
3265 terminal->rif = 0;
3266 terminal->cursor_to_hook = 0;
3267 terminal->raw_cursor_to_hook = 0;
3268 terminal->clear_to_end_hook = 0;
3269 terminal->clear_frame_hook = 0;
3270 terminal->clear_end_of_line_hook = 0;
3271 terminal->ins_del_lines_hook = 0;
3272 terminal->insert_glyphs_hook = 0;
3273 terminal->write_glyphs_hook = 0;
3274 terminal->delete_glyphs_hook = 0;
3275 terminal->ring_bell_hook = 0;
3276 terminal->reset_terminal_modes_hook = 0;
3277 terminal->set_terminal_modes_hook = 0;
3278 terminal->update_begin_hook = 0;
3279 terminal->update_end_hook = 0;
3280 terminal->set_terminal_window_hook = 0;
3281 terminal->mouse_position_hook = 0;
3282 terminal->frame_rehighlight_hook = 0;
3283 terminal->frame_raise_lower_hook = 0;
3284 terminal->fullscreen_hook = 0;
3285 terminal->set_vertical_scroll_bar_hook = 0;
3286 terminal->condemn_scroll_bars_hook = 0;
3287 terminal->redeem_scroll_bar_hook = 0;
3288 terminal->judge_scroll_bars_hook = 0;
3289 terminal->read_socket_hook = 0;
3290 terminal->frame_up_to_date_hook = 0;
3292 /* Leave these two set, or suspended frames are not deleted
3293 correctly. */
3294 terminal->delete_frame_hook = &tty_free_frame_resources;
3295 terminal->delete_terminal_hook = &delete_tty;
3298 /* Initialize hooks in TERMINAL with the values needed for a tty. */
3300 static void
3301 set_tty_hooks (struct terminal *terminal)
3303 terminal->rif = 0; /* ttys don't support window-based redisplay. */
3305 terminal->cursor_to_hook = &tty_cursor_to;
3306 terminal->raw_cursor_to_hook = &tty_raw_cursor_to;
3308 terminal->clear_to_end_hook = &tty_clear_to_end;
3309 terminal->clear_frame_hook = &tty_clear_frame;
3310 terminal->clear_end_of_line_hook = &tty_clear_end_of_line;
3312 terminal->ins_del_lines_hook = &tty_ins_del_lines;
3314 terminal->insert_glyphs_hook = &tty_insert_glyphs;
3315 terminal->write_glyphs_hook = &tty_write_glyphs;
3316 terminal->delete_glyphs_hook = &tty_delete_glyphs;
3318 terminal->ring_bell_hook = &tty_ring_bell;
3320 terminal->reset_terminal_modes_hook = &tty_reset_terminal_modes;
3321 terminal->set_terminal_modes_hook = &tty_set_terminal_modes;
3322 terminal->update_begin_hook = 0; /* Not needed. */
3323 terminal->update_end_hook = &tty_update_end;
3324 terminal->set_terminal_window_hook = &tty_set_terminal_window;
3326 terminal->mouse_position_hook = 0; /* Not needed. */
3327 terminal->frame_rehighlight_hook = 0; /* Not needed. */
3328 terminal->frame_raise_lower_hook = 0; /* Not needed. */
3330 terminal->set_vertical_scroll_bar_hook = 0; /* Not needed. */
3331 terminal->condemn_scroll_bars_hook = 0; /* Not needed. */
3332 terminal->redeem_scroll_bar_hook = 0; /* Not needed. */
3333 terminal->judge_scroll_bars_hook = 0; /* Not needed. */
3335 terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */
3336 terminal->frame_up_to_date_hook = 0; /* Not needed. */
3338 terminal->delete_frame_hook = &tty_free_frame_resources;
3339 terminal->delete_terminal_hook = &delete_tty;
3342 /* Drop the controlling terminal if fd is the same device. */
3343 static void
3344 dissociate_if_controlling_tty (int fd)
3346 #ifndef DOS_NT
3347 int pgid;
3348 EMACS_GET_TTY_PGRP (fd, &pgid); /* If tcgetpgrp succeeds, fd is the ctty. */
3349 if (pgid != -1)
3351 #if defined (USG)
3352 setpgrp ();
3353 no_controlling_tty = 1;
3354 #elif defined (CYGWIN)
3355 setsid ();
3356 no_controlling_tty = 1;
3357 #else
3358 #ifdef TIOCNOTTY /* Try BSD ioctls. */
3359 sigblock (sigmask (SIGTTOU));
3360 fd = emacs_open (DEV_TTY, O_RDWR, 0);
3361 if (fd != -1 && ioctl (fd, TIOCNOTTY, 0) != -1)
3363 no_controlling_tty = 1;
3365 if (fd != -1)
3366 emacs_close (fd);
3367 sigunblock (sigmask (SIGTTOU));
3368 #else
3369 /* Unknown system. */
3370 croak ();
3371 #endif /* ! TIOCNOTTY */
3372 #endif /* ! USG */
3374 #endif /* !DOS_NT */
3377 /* Create a termcap display on the tty device with the given name and
3378 type.
3380 If NAME is NULL, then use the controlling tty, i.e., "/dev/tty".
3381 Otherwise NAME should be a path to the tty device file,
3382 e.g. "/dev/pts/7".
3384 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
3386 If MUST_SUCCEED is true, then all errors are fatal. */
3388 struct terminal *
3389 init_tty (char *name, char *terminal_type, int must_succeed)
3391 char *area = NULL;
3392 char **address = &area;
3393 int buffer_size = 4096;
3394 register char *p = NULL;
3395 int status;
3396 struct tty_display_info *tty = NULL;
3397 struct terminal *terminal = NULL;
3398 int ctty = 0; /* 1 if asked to open controlling tty. */
3400 if (!terminal_type)
3401 maybe_fatal (must_succeed, 0,
3402 "Unknown terminal type",
3403 "Unknown terminal type");
3405 if (name == NULL)
3406 name = DEV_TTY;
3407 if (!strcmp (name, DEV_TTY))
3408 ctty = 1;
3410 /* If we already have a terminal on the given device, use that. If
3411 all such terminals are suspended, create a new one instead. */
3412 /* XXX Perhaps this should be made explicit by having init_tty
3413 always create a new terminal and separating terminal and frame
3414 creation on Lisp level. */
3415 terminal = get_named_tty (name);
3416 if (terminal)
3417 return terminal;
3419 terminal = create_terminal ();
3420 #ifdef MSDOS
3421 if (been_here > 0)
3422 maybe_fatal (1, 0, "Attempt to create another terminal %s", "",
3423 name, "");
3424 been_here = 1;
3425 tty = &the_only_display_info;
3426 #else
3427 tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info));
3428 #endif
3429 memset (tty, 0, sizeof (struct tty_display_info));
3430 tty->next = tty_list;
3431 tty_list = tty;
3433 terminal->type = output_termcap;
3434 terminal->display_info.tty = tty;
3435 tty->terminal = terminal;
3437 tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
3438 Wcm_clear (tty);
3440 #ifndef DOS_NT
3441 set_tty_hooks (terminal);
3444 int fd;
3445 FILE *file;
3447 #ifdef O_IGNORE_CTTY
3448 if (!ctty)
3449 /* Open the terminal device. Don't recognize it as our
3450 controlling terminal, and don't make it the controlling tty
3451 if we don't have one at the moment. */
3452 fd = emacs_open (name, O_RDWR | O_IGNORE_CTTY | O_NOCTTY, 0);
3453 else
3454 #else
3455 /* Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
3456 defined on Hurd. On other systems, we need to explicitly
3457 dissociate ourselves from the controlling tty when we want to
3458 open a frame on the same terminal. */
3459 fd = emacs_open (name, O_RDWR | O_NOCTTY, 0);
3460 #endif /* O_IGNORE_CTTY */
3462 tty->name = xstrdup (name);
3463 terminal->name = xstrdup (name);
3465 if (fd < 0)
3466 maybe_fatal (must_succeed, terminal,
3467 "Could not open file: %s",
3468 "Could not open file: %s",
3469 name);
3470 if (!isatty (fd))
3472 close (fd);
3473 maybe_fatal (must_succeed, terminal,
3474 "Not a tty device: %s",
3475 "Not a tty device: %s",
3476 name);
3479 #ifndef O_IGNORE_CTTY
3480 if (!ctty)
3481 dissociate_if_controlling_tty (fd);
3482 #endif
3484 file = fdopen (fd, "w+");
3485 tty->input = file;
3486 tty->output = file;
3489 tty->type = xstrdup (terminal_type);
3491 add_keyboard_wait_descriptor (fileno (tty->input));
3493 #endif /* !DOS_NT */
3495 encode_terminal_src_size = 0;
3496 encode_terminal_dst_size = 0;
3498 #ifdef HAVE_GPM
3499 terminal->mouse_position_hook = term_mouse_position;
3500 mouse_face_window = Qnil;
3501 #endif
3503 #ifdef DOS_NT
3504 #ifdef WINDOWSNT
3505 initialize_w32_display (terminal);
3506 #else /* MSDOS */
3507 if (strcmp (terminal_type, "internal") == 0)
3508 terminal->type = output_msdos_raw;
3509 initialize_msdos_display (terminal);
3510 #endif /* MSDOS */
3511 tty->output = stdout;
3512 tty->input = stdin;
3513 /* The following two are inaccessible from w32console.c. */
3514 terminal->delete_frame_hook = &tty_free_frame_resources;
3515 terminal->delete_terminal_hook = &delete_tty;
3517 tty->name = xstrdup (name);
3518 terminal->name = xstrdup (name);
3519 tty->type = xstrdup (terminal_type);
3521 add_keyboard_wait_descriptor (0);
3523 Wcm_clear (tty);
3525 #ifdef WINDOWSNT
3527 struct frame *f = XFRAME (selected_frame);
3529 FrameRows (tty) = FRAME_LINES (f);
3530 FrameCols (tty) = FRAME_COLS (f);
3531 tty->specified_window = FRAME_LINES (f);
3533 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
3534 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
3536 #else /* MSDOS */
3538 int height, width;
3539 get_tty_size (fileno (tty->input), &width, &height);
3540 FrameCols (tty) = width;
3541 FrameRows (tty) = height;
3543 #endif /* MSDOS */
3544 tty->delete_in_insert_mode = 1;
3546 UseTabs (tty) = 0;
3547 terminal->scroll_region_ok = 0;
3549 /* Seems to insert lines when it's not supposed to, messing up the
3550 display. In doing a trace, it didn't seem to be called much, so I
3551 don't think we're losing anything by turning it off. */
3552 terminal->line_ins_del_ok = 0;
3553 #ifdef WINDOWSNT
3554 terminal->char_ins_del_ok = 1;
3555 baud_rate = 19200;
3556 #else /* MSDOS */
3557 terminal->char_ins_del_ok = 0;
3558 init_baud_rate (fileno (tty->input));
3559 #endif /* MSDOS */
3561 tty->TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
3563 #else /* not DOS_NT */
3565 Wcm_clear (tty);
3567 tty->termcap_term_buffer = (char *) xmalloc (buffer_size);
3569 /* On some systems, tgetent tries to access the controlling
3570 terminal. */
3571 sigblock (sigmask (SIGTTOU));
3572 status = tgetent (tty->termcap_term_buffer, terminal_type);
3573 sigunblock (sigmask (SIGTTOU));
3575 if (status < 0)
3577 #ifdef TERMINFO
3578 maybe_fatal (must_succeed, terminal,
3579 "Cannot open terminfo database file",
3580 "Cannot open terminfo database file");
3581 #else
3582 maybe_fatal (must_succeed, terminal,
3583 "Cannot open termcap database file",
3584 "Cannot open termcap database file");
3585 #endif
3587 if (status == 0)
3589 maybe_fatal (must_succeed, terminal,
3590 "Terminal type %s is not defined",
3591 "Terminal type %s is not defined.\n\
3592 If that is not the actual type of terminal you have,\n\
3593 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3594 `setenv TERM ...') to specify the correct type. It may be necessary\n"
3595 #ifdef TERMINFO
3596 "to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3597 #else
3598 "to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3599 #endif
3600 terminal_type);
3603 #ifndef TERMINFO
3604 if (strlen (tty->termcap_term_buffer) >= buffer_size)
3605 abort ();
3606 buffer_size = strlen (tty->termcap_term_buffer);
3607 #endif
3608 tty->termcap_strings_buffer = area = (char *) xmalloc (buffer_size);
3609 tty->TS_ins_line = tgetstr ("al", address);
3610 tty->TS_ins_multi_lines = tgetstr ("AL", address);
3611 tty->TS_bell = tgetstr ("bl", address);
3612 BackTab (tty) = tgetstr ("bt", address);
3613 tty->TS_clr_to_bottom = tgetstr ("cd", address);
3614 tty->TS_clr_line = tgetstr ("ce", address);
3615 tty->TS_clr_frame = tgetstr ("cl", address);
3616 ColPosition (tty) = NULL; /* tgetstr ("ch", address); */
3617 AbsPosition (tty) = tgetstr ("cm", address);
3618 CR (tty) = tgetstr ("cr", address);
3619 tty->TS_set_scroll_region = tgetstr ("cs", address);
3620 tty->TS_set_scroll_region_1 = tgetstr ("cS", address);
3621 RowPosition (tty) = tgetstr ("cv", address);
3622 tty->TS_del_char = tgetstr ("dc", address);
3623 tty->TS_del_multi_chars = tgetstr ("DC", address);
3624 tty->TS_del_line = tgetstr ("dl", address);
3625 tty->TS_del_multi_lines = tgetstr ("DL", address);
3626 tty->TS_delete_mode = tgetstr ("dm", address);
3627 tty->TS_end_delete_mode = tgetstr ("ed", address);
3628 tty->TS_end_insert_mode = tgetstr ("ei", address);
3629 Home (tty) = tgetstr ("ho", address);
3630 tty->TS_ins_char = tgetstr ("ic", address);
3631 tty->TS_ins_multi_chars = tgetstr ("IC", address);
3632 tty->TS_insert_mode = tgetstr ("im", address);
3633 tty->TS_pad_inserted_char = tgetstr ("ip", address);
3634 tty->TS_end_keypad_mode = tgetstr ("ke", address);
3635 tty->TS_keypad_mode = tgetstr ("ks", address);
3636 LastLine (tty) = tgetstr ("ll", address);
3637 Right (tty) = tgetstr ("nd", address);
3638 Down (tty) = tgetstr ("do", address);
3639 if (!Down (tty))
3640 Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do" */
3641 if (tgetflag ("bs"))
3642 Left (tty) = "\b"; /* can't possibly be longer! */
3643 else /* (Actually, "bs" is obsolete...) */
3644 Left (tty) = tgetstr ("le", address);
3645 if (!Left (tty))
3646 Left (tty) = tgetstr ("bc", address); /* Obsolete name for "le" */
3647 tty->TS_pad_char = tgetstr ("pc", address);
3648 tty->TS_repeat = tgetstr ("rp", address);
3649 tty->TS_end_standout_mode = tgetstr ("se", address);
3650 tty->TS_fwd_scroll = tgetstr ("sf", address);
3651 tty->TS_standout_mode = tgetstr ("so", address);
3652 tty->TS_rev_scroll = tgetstr ("sr", address);
3653 tty->Wcm->cm_tab = tgetstr ("ta", address);
3654 tty->TS_end_termcap_modes = tgetstr ("te", address);
3655 tty->TS_termcap_modes = tgetstr ("ti", address);
3656 Up (tty) = tgetstr ("up", address);
3657 tty->TS_visible_bell = tgetstr ("vb", address);
3658 tty->TS_cursor_normal = tgetstr ("ve", address);
3659 tty->TS_cursor_visible = tgetstr ("vs", address);
3660 tty->TS_cursor_invisible = tgetstr ("vi", address);
3661 tty->TS_set_window = tgetstr ("wi", address);
3663 tty->TS_enter_underline_mode = tgetstr ("us", address);
3664 tty->TS_exit_underline_mode = tgetstr ("ue", address);
3665 tty->TS_enter_bold_mode = tgetstr ("md", address);
3666 tty->TS_enter_dim_mode = tgetstr ("mh", address);
3667 tty->TS_enter_blink_mode = tgetstr ("mb", address);
3668 tty->TS_enter_reverse_mode = tgetstr ("mr", address);
3669 tty->TS_enter_alt_charset_mode = tgetstr ("as", address);
3670 tty->TS_exit_alt_charset_mode = tgetstr ("ae", address);
3671 tty->TS_exit_attribute_mode = tgetstr ("me", address);
3673 MultiUp (tty) = tgetstr ("UP", address);
3674 MultiDown (tty) = tgetstr ("DO", address);
3675 MultiLeft (tty) = tgetstr ("LE", address);
3676 MultiRight (tty) = tgetstr ("RI", address);
3678 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
3679 color because we can't switch back to the default foreground and
3680 background. */
3681 tty->TS_orig_pair = tgetstr ("op", address);
3682 if (tty->TS_orig_pair)
3684 tty->TS_set_foreground = tgetstr ("AF", address);
3685 tty->TS_set_background = tgetstr ("AB", address);
3686 if (!tty->TS_set_foreground)
3688 /* SVr4. */
3689 tty->TS_set_foreground = tgetstr ("Sf", address);
3690 tty->TS_set_background = tgetstr ("Sb", address);
3693 tty->TN_max_colors = tgetnum ("Co");
3694 tty->TN_max_pairs = tgetnum ("pa");
3696 tty->TN_no_color_video = tgetnum ("NC");
3697 if (tty->TN_no_color_video == -1)
3698 tty->TN_no_color_video = 0;
3701 tty_default_color_capabilities (tty, 1);
3703 MagicWrap (tty) = tgetflag ("xn");
3704 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
3705 the former flag imply the latter. */
3706 AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
3707 terminal->memory_below_frame = tgetflag ("db");
3708 tty->TF_hazeltine = tgetflag ("hz");
3709 terminal->must_write_spaces = tgetflag ("in");
3710 tty->meta_key = tgetflag ("km") || tgetflag ("MT");
3711 tty->TF_insmode_motion = tgetflag ("mi");
3712 tty->TF_standout_motion = tgetflag ("ms");
3713 tty->TF_underscore = tgetflag ("ul");
3714 tty->TF_teleray = tgetflag ("xt");
3716 #endif /* !DOS_NT */
3717 terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
3718 init_kboard (terminal->kboard);
3719 terminal->kboard->Vwindow_system = Qnil;
3720 terminal->kboard->next_kboard = all_kboards;
3721 all_kboards = terminal->kboard;
3722 terminal->kboard->reference_count++;
3723 /* Don't let the initial kboard remain current longer than necessary.
3724 That would cause problems if a file loaded on startup tries to
3725 prompt in the mini-buffer. */
3726 if (current_kboard == initial_kboard)
3727 current_kboard = terminal->kboard;
3728 #ifndef DOS_NT
3729 term_get_fkeys (address, terminal->kboard);
3731 /* Get frame size from system, or else from termcap. */
3733 int height, width;
3734 get_tty_size (fileno (tty->input), &width, &height);
3735 FrameCols (tty) = width;
3736 FrameRows (tty) = height;
3739 if (FrameCols (tty) <= 0)
3740 FrameCols (tty) = tgetnum ("co");
3741 if (FrameRows (tty) <= 0)
3742 FrameRows (tty) = tgetnum ("li");
3744 if (FrameRows (tty) < 3 || FrameCols (tty) < 3)
3745 maybe_fatal (must_succeed, terminal,
3746 "Screen size %dx%d is too small",
3747 "Screen size %dx%d is too small",
3748 FrameCols (tty), FrameRows (tty));
3750 TabWidth (tty) = tgetnum ("tw");
3752 if (!tty->TS_bell)
3753 tty->TS_bell = "\07";
3755 if (!tty->TS_fwd_scroll)
3756 tty->TS_fwd_scroll = Down (tty);
3758 PC = tty->TS_pad_char ? *tty->TS_pad_char : 0;
3760 if (TabWidth (tty) < 0)
3761 TabWidth (tty) = 8;
3763 /* Turned off since /etc/termcap seems to have :ta= for most terminals
3764 and newer termcap doc does not seem to say there is a default.
3765 if (!tty->Wcm->cm_tab)
3766 tty->Wcm->cm_tab = "\t";
3769 /* We don't support standout modes that use `magic cookies', so
3770 turn off any that do. */
3771 if (tty->TS_standout_mode && tgetnum ("sg") >= 0)
3773 tty->TS_standout_mode = 0;
3774 tty->TS_end_standout_mode = 0;
3776 if (tty->TS_enter_underline_mode && tgetnum ("ug") >= 0)
3778 tty->TS_enter_underline_mode = 0;
3779 tty->TS_exit_underline_mode = 0;
3782 /* If there's no standout mode, try to use underlining instead. */
3783 if (tty->TS_standout_mode == 0)
3785 tty->TS_standout_mode = tty->TS_enter_underline_mode;
3786 tty->TS_end_standout_mode = tty->TS_exit_underline_mode;
3789 /* If no `se' string, try using a `me' string instead.
3790 If that fails, we can't use standout mode at all. */
3791 if (tty->TS_end_standout_mode == 0)
3793 char *s = tgetstr ("me", address);
3794 if (s != 0)
3795 tty->TS_end_standout_mode = s;
3796 else
3797 tty->TS_standout_mode = 0;
3800 if (tty->TF_teleray)
3802 tty->Wcm->cm_tab = 0;
3803 /* We can't support standout mode, because it uses magic cookies. */
3804 tty->TS_standout_mode = 0;
3805 /* But that means we cannot rely on ^M to go to column zero! */
3806 CR (tty) = 0;
3807 /* LF can't be trusted either -- can alter hpos */
3808 /* if move at column 0 thru a line with TS_standout_mode */
3809 Down (tty) = 0;
3812 /* Special handling for certain terminal types known to need it */
3814 if (!strcmp (terminal_type, "supdup"))
3816 terminal->memory_below_frame = 1;
3817 tty->Wcm->cm_losewrap = 1;
3819 if (!strncmp (terminal_type, "c10", 3)
3820 || !strcmp (terminal_type, "perq"))
3822 /* Supply a makeshift :wi string.
3823 This string is not valid in general since it works only
3824 for windows starting at the upper left corner;
3825 but that is all Emacs uses.
3827 This string works only if the frame is using
3828 the top of the video memory, because addressing is memory-relative.
3829 So first check the :ti string to see if that is true.
3831 It would be simpler if the :wi string could go in the termcap
3832 entry, but it can't because it is not fully valid.
3833 If it were in the termcap entry, it would confuse other programs. */
3834 if (!tty->TS_set_window)
3836 p = tty->TS_termcap_modes;
3837 while (*p && strcmp (p, "\033v "))
3838 p++;
3839 if (*p)
3840 tty->TS_set_window = "\033v%C %C %C %C ";
3842 /* Termcap entry often fails to have :in: flag */
3843 terminal->must_write_spaces = 1;
3844 /* :ti string typically fails to have \E^G! in it */
3845 /* This limits scope of insert-char to one line. */
3846 strcpy (area, tty->TS_termcap_modes);
3847 strcat (area, "\033\007!");
3848 tty->TS_termcap_modes = area;
3849 area += strlen (area) + 1;
3850 p = AbsPosition (tty);
3851 /* Change all %+ parameters to %C, to handle
3852 values above 96 correctly for the C100. */
3853 while (*p)
3855 if (p[0] == '%' && p[1] == '+')
3856 p[1] = 'C';
3857 p++;
3861 tty->specified_window = FrameRows (tty);
3863 if (Wcm_init (tty) == -1) /* can't do cursor motion */
3865 maybe_fatal (must_succeed, terminal,
3866 "Terminal type \"%s\" is not powerful enough to run Emacs",
3867 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3868 It lacks the ability to position the cursor.\n\
3869 If that is not the actual type of terminal you have,\n\
3870 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3871 `setenv TERM ...') to specify the correct type. It may be necessary\n"
3872 # ifdef TERMINFO
3873 "to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3874 # else /* TERMCAP */
3875 "to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3876 # endif /* TERMINFO */
3877 terminal_type);
3880 if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
3881 maybe_fatal (must_succeed, terminal,
3882 "Could not determine the frame size",
3883 "Could not determine the frame size");
3885 tty->delete_in_insert_mode
3886 = tty->TS_delete_mode && tty->TS_insert_mode
3887 && !strcmp (tty->TS_delete_mode, tty->TS_insert_mode);
3889 tty->se_is_so = (tty->TS_standout_mode
3890 && tty->TS_end_standout_mode
3891 && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode));
3893 UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8;
3895 terminal->scroll_region_ok
3896 = (tty->Wcm->cm_abs
3897 && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
3899 terminal->line_ins_del_ok
3900 = (((tty->TS_ins_line || tty->TS_ins_multi_lines)
3901 && (tty->TS_del_line || tty->TS_del_multi_lines))
3902 || (terminal->scroll_region_ok
3903 && tty->TS_fwd_scroll && tty->TS_rev_scroll));
3905 terminal->char_ins_del_ok
3906 = ((tty->TS_ins_char || tty->TS_insert_mode
3907 || tty->TS_pad_inserted_char || tty->TS_ins_multi_chars)
3908 && (tty->TS_del_char || tty->TS_del_multi_chars));
3910 terminal->fast_clear_end_of_line = tty->TS_clr_line != 0;
3912 init_baud_rate (fileno (tty->input));
3914 #endif /* not DOS_NT */
3916 /* Init system terminal modes (RAW or CBREAK, etc.). */
3917 init_sys_modes (tty);
3919 return terminal;
3923 static void
3924 vfatal (const char *str, va_list ap)
3926 fprintf (stderr, "emacs: ");
3927 vfprintf (stderr, str, ap);
3928 if (!(strlen (str) > 0 && str[strlen (str) - 1] == '\n'))
3929 fprintf (stderr, "\n");
3930 va_end (ap);
3931 fflush (stderr);
3932 exit (1);
3936 /* Auxiliary error-handling function for init_tty.
3937 Delete TERMINAL, then call error or fatal with str1 or str2,
3938 respectively, according to MUST_SUCCEED. */
3940 static void
3941 maybe_fatal (int must_succeed, struct terminal *terminal,
3942 const char *str1, const char *str2, ...)
3944 va_list ap;
3945 va_start (ap, str2);
3946 if (terminal)
3947 delete_tty (terminal);
3949 if (must_succeed)
3950 vfatal (str2, ap);
3951 else
3952 verror (str1, ap);
3954 va_end (ap);
3955 abort ();
3958 void
3959 fatal (const char *str, ...)
3961 va_list ap;
3962 va_start (ap, str);
3963 vfatal (str, ap);
3964 va_end (ap);
3969 /* Delete the given tty terminal, closing all frames on it. */
3971 static void
3972 delete_tty (struct terminal *terminal)
3974 struct tty_display_info *tty;
3976 /* Protect against recursive calls. delete_frame in
3977 delete_terminal calls us back when it deletes our last frame. */
3978 if (!terminal->name)
3979 return;
3981 if (terminal->type != output_termcap)
3982 abort ();
3984 tty = terminal->display_info.tty;
3986 if (tty == tty_list)
3987 tty_list = tty->next;
3988 else
3990 struct tty_display_info *p;
3991 for (p = tty_list; p && p->next != tty; p = p->next)
3994 if (! p)
3995 /* This should not happen. */
3996 abort ();
3998 p->next = tty->next;
3999 tty->next = 0;
4002 /* reset_sys_modes needs a valid device, so this call needs to be
4003 before delete_terminal. */
4004 reset_sys_modes (tty);
4006 delete_terminal (terminal);
4008 xfree (tty->name);
4009 xfree (tty->type);
4011 if (tty->input)
4013 delete_keyboard_wait_descriptor (fileno (tty->input));
4014 if (tty->input != stdin)
4015 fclose (tty->input);
4017 if (tty->output && tty->output != stdout && tty->output != tty->input)
4018 fclose (tty->output);
4019 if (tty->termscript)
4020 fclose (tty->termscript);
4022 xfree (tty->old_tty);
4023 xfree (tty->Wcm);
4024 xfree (tty->termcap_strings_buffer);
4025 xfree (tty->termcap_term_buffer);
4027 memset (tty, 0, sizeof (struct tty_display_info));
4028 xfree (tty);
4033 /* Mark the pointers in the tty_display_info objects.
4034 Called by the Fgarbage_collector. */
4036 void
4037 mark_ttys (void)
4039 struct tty_display_info *tty;
4041 for (tty = tty_list; tty; tty = tty->next)
4042 mark_object (tty->top_frame);
4047 void
4048 syms_of_term (void)
4050 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
4051 doc: /* Non-nil means the system uses terminfo rather than termcap.
4052 This variable can be used by terminal emulator packages. */);
4053 #ifdef TERMINFO
4054 system_uses_terminfo = 1;
4055 #else
4056 system_uses_terminfo = 0;
4057 #endif
4059 DEFVAR_LISP ("suspend-tty-functions", &Vsuspend_tty_functions,
4060 doc: /* Functions to be run after suspending a tty.
4061 The functions are run with one argument, the terminal object to be suspended.
4062 See `suspend-tty'. */);
4063 Vsuspend_tty_functions = Qnil;
4066 DEFVAR_LISP ("resume-tty-functions", &Vresume_tty_functions,
4067 doc: /* Functions to be run after resuming a tty.
4068 The functions are run with one argument, the terminal object that was revived.
4069 See `resume-tty'. */);
4070 Vresume_tty_functions = Qnil;
4072 DEFVAR_BOOL ("visible-cursor", &visible_cursor,
4073 doc: /* Non-nil means to make the cursor very visible.
4074 This only has an effect when running in a text terminal.
4075 What means \"very visible\" is up to your terminal. It may make the cursor
4076 bigger, or it may make it blink, or it may do nothing at all. */);
4077 visible_cursor = 1;
4079 defsubr (&Stty_display_color_p);
4080 defsubr (&Stty_display_color_cells);
4081 defsubr (&Stty_no_underline);
4082 defsubr (&Stty_type);
4083 defsubr (&Scontrolling_tty_p);
4084 defsubr (&Ssuspend_tty);
4085 defsubr (&Sresume_tty);
4086 #ifdef HAVE_GPM
4087 defsubr (&Sgpm_mouse_start);
4088 defsubr (&Sgpm_mouse_stop);
4090 staticpro (&mouse_face_window);
4091 #endif /* HAVE_GPM */
4093 #ifndef DOS_NT
4094 default_orig_pair = NULL;
4095 default_set_foreground = NULL;
4096 default_set_background = NULL;
4097 #endif /* !DOS_NT */
4099 encode_terminal_src = NULL;
4100 encode_terminal_dst = NULL;
4105 /* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193
4106 (do not change this comment) */