Remove nodes visited during Isearch from the Info history.
[emacs.git] / src / term.c
blobfad6e3c80d7419a2ba20146935a9f449cd1e5c31
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 P_ ((const char *, int, int (*)(int)));
70 extern int tgetent P_ ((char *, const char *));
71 extern int tgetflag P_ ((char *id));
72 extern int tgetnum P_ ((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 P_ ((struct frame *f, int start, int stop));
95 static void turn_on_face P_ ((struct frame *, int face_id));
96 static void turn_off_face P_ ((struct frame *, int face_id));
97 static void tty_show_cursor P_ ((struct tty_display_info *));
98 static void tty_hide_cursor P_ ((struct tty_display_info *));
99 static void tty_background_highlight P_ ((struct tty_display_info *tty));
100 static void clear_tty_hooks P_ ((struct terminal *terminal));
101 static void set_tty_hooks P_ ((struct terminal *terminal));
102 static void dissociate_if_controlling_tty P_ ((int fd));
103 static void delete_tty P_ ((struct terminal *));
105 #define OUTPUT(tty, a) \
106 emacs_tputs ((tty), a, \
107 (int) (FRAME_LINES (XFRAME (selected_frame)) \
108 - curY (tty)), \
109 cmputc)
111 #define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
112 #define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
114 #define OUTPUT_IF(tty, a) \
115 do { \
116 if (a) \
117 emacs_tputs ((tty), a, \
118 (int) (FRAME_LINES (XFRAME (selected_frame)) \
119 - curY (tty) ), \
120 cmputc); \
121 } while (0)
123 #define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
125 /* If true, use "vs", otherwise use "ve" to make the cursor visible. */
127 static int visible_cursor;
129 /* Display space properties */
131 extern Lisp_Object Qspace, QCalign_to, QCwidth;
133 /* Functions to call after suspending a tty. */
134 Lisp_Object Vsuspend_tty_functions;
136 /* Functions to call after resuming a tty. */
137 Lisp_Object Vresume_tty_functions;
139 /* Chain of all tty device parameters. */
140 struct tty_display_info *tty_list;
142 /* Nonzero means no need to redraw the entire frame on resuming a
143 suspended Emacs. This is useful on terminals with multiple
144 pages, where one page is used for Emacs and another for all
145 else. */
146 int no_redraw_on_reenter;
148 /* Meaning of bits in no_color_video. Each bit set means that the
149 corresponding attribute cannot be combined with colors. */
151 enum no_color_bit
153 NC_STANDOUT = 1 << 0,
154 NC_UNDERLINE = 1 << 1,
155 NC_REVERSE = 1 << 2,
156 NC_BLINK = 1 << 3,
157 NC_DIM = 1 << 4,
158 NC_BOLD = 1 << 5,
159 NC_INVIS = 1 << 6,
160 NC_PROTECT = 1 << 7,
161 NC_ALT_CHARSET = 1 << 8
164 /* internal state */
166 /* The largest frame width in any call to calculate_costs. */
168 int max_frame_cols;
170 /* The largest frame height in any call to calculate_costs. */
172 int max_frame_lines;
174 /* Non-zero if we have dropped our controlling tty and therefore
175 should not open a frame on stdout. */
176 static int no_controlling_tty;
178 /* Provided for lisp packages. */
180 static int system_uses_terminfo;
182 char *tparam ();
184 extern char *tgetstr ();
187 #ifdef HAVE_GPM
188 #include <sys/fcntl.h>
190 static void term_clear_mouse_face ();
191 static void term_mouse_highlight (struct frame *f, int x, int y);
193 /* The device for which we have enabled gpm support (or NULL). */
194 struct tty_display_info *gpm_tty = NULL;
196 /* These variables describe the range of text currently shown in its
197 mouse-face, together with the window they apply to. As long as
198 the mouse stays within this range, we need not redraw anything on
199 its account. Rows and columns are glyph matrix positions in
200 MOUSE_FACE_WINDOW. */
201 static int mouse_face_beg_row, mouse_face_beg_col;
202 static int mouse_face_end_row, mouse_face_end_col;
203 static int mouse_face_past_end;
204 static Lisp_Object mouse_face_window;
205 static int mouse_face_face_id;
207 static int pos_x, pos_y;
208 static int last_mouse_x, last_mouse_y;
209 #endif /* HAVE_GPM */
211 /* Ring the bell on a tty. */
213 static void
214 tty_ring_bell (struct frame *f)
216 struct tty_display_info *tty = FRAME_TTY (f);
218 if (tty->output)
220 OUTPUT (tty, (tty->TS_visible_bell && visible_bell
221 ? tty->TS_visible_bell
222 : tty->TS_bell));
223 fflush (tty->output);
227 /* Set up termcap modes for Emacs. */
229 void
230 tty_set_terminal_modes (struct terminal *terminal)
232 struct tty_display_info *tty = terminal->display_info.tty;
234 if (tty->output)
236 if (tty->TS_termcap_modes)
237 OUTPUT (tty, tty->TS_termcap_modes);
238 else
240 /* Output enough newlines to scroll all the old screen contents
241 off the screen, so it won't be overwritten and lost. */
242 int i;
243 current_tty = tty;
244 for (i = 0; i < FRAME_LINES (XFRAME (selected_frame)); i++)
245 cmputc ('\n');
248 OUTPUT_IF (tty, tty->TS_termcap_modes);
249 OUTPUT_IF (tty, visible_cursor ? tty->TS_cursor_visible : tty->TS_cursor_normal);
250 OUTPUT_IF (tty, tty->TS_keypad_mode);
251 losecursor (tty);
252 fflush (tty->output);
256 /* Reset termcap modes before exiting Emacs. */
258 void
259 tty_reset_terminal_modes (struct terminal *terminal)
261 struct tty_display_info *tty = terminal->display_info.tty;
263 if (tty->output)
265 tty_turn_off_highlight (tty);
266 tty_turn_off_insert (tty);
267 OUTPUT_IF (tty, tty->TS_end_keypad_mode);
268 OUTPUT_IF (tty, tty->TS_cursor_normal);
269 OUTPUT_IF (tty, tty->TS_end_termcap_modes);
270 OUTPUT_IF (tty, tty->TS_orig_pair);
271 /* Output raw CR so kernel can track the cursor hpos. */
272 current_tty = tty;
273 cmputc ('\r');
274 fflush (tty->output);
278 /* Flag the end of a display update on a termcap terminal. */
280 static void
281 tty_update_end (struct frame *f)
283 struct tty_display_info *tty = FRAME_TTY (f);
285 if (!XWINDOW (selected_window)->cursor_off_p)
286 tty_show_cursor (tty);
287 tty_turn_off_insert (tty);
288 tty_background_highlight (tty);
291 /* The implementation of set_terminal_window for termcap frames. */
293 static void
294 tty_set_terminal_window (struct frame *f, int size)
296 struct tty_display_info *tty = FRAME_TTY (f);
298 tty->specified_window = size ? size : FRAME_LINES (f);
299 if (FRAME_SCROLL_REGION_OK (f))
300 tty_set_scroll_region (f, 0, tty->specified_window);
303 static void
304 tty_set_scroll_region (struct frame *f, int start, int stop)
306 char *buf;
307 struct tty_display_info *tty = FRAME_TTY (f);
309 if (tty->TS_set_scroll_region)
310 buf = tparam (tty->TS_set_scroll_region, 0, 0, start, stop - 1);
311 else if (tty->TS_set_scroll_region_1)
312 buf = tparam (tty->TS_set_scroll_region_1, 0, 0,
313 FRAME_LINES (f), start,
314 FRAME_LINES (f) - stop,
315 FRAME_LINES (f));
316 else
317 buf = tparam (tty->TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (f));
319 OUTPUT (tty, buf);
320 xfree (buf);
321 losecursor (tty);
325 static void
326 tty_turn_on_insert (struct tty_display_info *tty)
328 if (!tty->insert_mode)
329 OUTPUT (tty, tty->TS_insert_mode);
330 tty->insert_mode = 1;
333 void
334 tty_turn_off_insert (struct tty_display_info *tty)
336 if (tty->insert_mode)
337 OUTPUT (tty, tty->TS_end_insert_mode);
338 tty->insert_mode = 0;
341 /* Handle highlighting. */
343 void
344 tty_turn_off_highlight (struct tty_display_info *tty)
346 if (tty->standout_mode)
347 OUTPUT_IF (tty, tty->TS_end_standout_mode);
348 tty->standout_mode = 0;
351 static void
352 tty_turn_on_highlight (struct tty_display_info *tty)
354 if (!tty->standout_mode)
355 OUTPUT_IF (tty, tty->TS_standout_mode);
356 tty->standout_mode = 1;
359 static void
360 tty_toggle_highlight (struct tty_display_info *tty)
362 if (tty->standout_mode)
363 tty_turn_off_highlight (tty);
364 else
365 tty_turn_on_highlight (tty);
369 /* Make cursor invisible. */
371 static void
372 tty_hide_cursor (struct tty_display_info *tty)
374 if (tty->cursor_hidden == 0)
376 tty->cursor_hidden = 1;
377 OUTPUT_IF (tty, tty->TS_cursor_invisible);
382 /* Ensure that cursor is visible. */
384 static void
385 tty_show_cursor (struct tty_display_info *tty)
387 if (tty->cursor_hidden)
389 tty->cursor_hidden = 0;
390 OUTPUT_IF (tty, tty->TS_cursor_normal);
391 if (visible_cursor)
392 OUTPUT_IF (tty, tty->TS_cursor_visible);
397 /* Set standout mode to the state it should be in for
398 empty space inside windows. What this is,
399 depends on the user option inverse-video. */
401 static void
402 tty_background_highlight (struct tty_display_info *tty)
404 if (inverse_video)
405 tty_turn_on_highlight (tty);
406 else
407 tty_turn_off_highlight (tty);
410 /* Set standout mode to the mode specified for the text to be output. */
412 static void
413 tty_highlight_if_desired (struct tty_display_info *tty)
415 if (inverse_video)
416 tty_turn_on_highlight (tty);
417 else
418 tty_turn_off_highlight (tty);
422 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
423 frame-relative coordinates. */
425 static void
426 tty_cursor_to (struct frame *f, int vpos, int hpos)
428 struct tty_display_info *tty = FRAME_TTY (f);
430 /* Detect the case where we are called from reset_sys_modes
431 and the costs have never been calculated. Do nothing. */
432 if (! tty->costs_set)
433 return;
435 if (curY (tty) == vpos
436 && curX (tty) == hpos)
437 return;
438 if (!tty->TF_standout_motion)
439 tty_background_highlight (tty);
440 if (!tty->TF_insmode_motion)
441 tty_turn_off_insert (tty);
442 cmgoto (tty, vpos, hpos);
445 /* Similar but don't take any account of the wasted characters. */
447 static void
448 tty_raw_cursor_to (struct frame *f, int row, int col)
450 struct tty_display_info *tty = FRAME_TTY (f);
452 if (curY (tty) == row
453 && curX (tty) == col)
454 return;
455 if (!tty->TF_standout_motion)
456 tty_background_highlight (tty);
457 if (!tty->TF_insmode_motion)
458 tty_turn_off_insert (tty);
459 cmgoto (tty, row, col);
462 /* Erase operations */
464 /* Clear from cursor to end of frame on a termcap device. */
466 static void
467 tty_clear_to_end (struct frame *f)
469 register int i;
470 struct tty_display_info *tty = FRAME_TTY (f);
472 if (tty->TS_clr_to_bottom)
474 tty_background_highlight (tty);
475 OUTPUT (tty, tty->TS_clr_to_bottom);
477 else
479 for (i = curY (tty); i < FRAME_LINES (f); i++)
481 cursor_to (f, i, 0);
482 clear_end_of_line (f, FRAME_COLS (f));
487 /* Clear an entire termcap frame. */
489 static void
490 tty_clear_frame (struct frame *f)
492 struct tty_display_info *tty = FRAME_TTY (f);
494 if (tty->TS_clr_frame)
496 tty_background_highlight (tty);
497 OUTPUT (tty, tty->TS_clr_frame);
498 cmat (tty, 0, 0);
500 else
502 cursor_to (f, 0, 0);
503 clear_to_end (f);
507 /* An implementation of clear_end_of_line for termcap frames.
509 Note that the cursor may be moved, on terminals lacking a `ce' string. */
511 static void
512 tty_clear_end_of_line (struct frame *f, int first_unused_hpos)
514 register int i;
515 struct tty_display_info *tty = FRAME_TTY (f);
517 /* Detect the case where we are called from reset_sys_modes
518 and the costs have never been calculated. Do nothing. */
519 if (! tty->costs_set)
520 return;
522 if (curX (tty) >= first_unused_hpos)
523 return;
524 tty_background_highlight (tty);
525 if (tty->TS_clr_line)
527 OUTPUT1 (tty, tty->TS_clr_line);
529 else
530 { /* have to do it the hard way */
531 tty_turn_off_insert (tty);
533 /* Do not write in last row last col with Auto-wrap on. */
534 if (AutoWrap (tty)
535 && curY (tty) == FrameRows (tty) - 1
536 && first_unused_hpos == FrameCols (tty))
537 first_unused_hpos--;
539 for (i = curX (tty); i < first_unused_hpos; i++)
541 if (tty->termscript)
542 fputc (' ', tty->termscript);
543 fputc (' ', tty->output);
545 cmplus (tty, first_unused_hpos - curX (tty));
549 /* Buffers to store the source and result of code conversion for terminal. */
550 static unsigned char *encode_terminal_src;
551 static unsigned char *encode_terminal_dst;
552 /* Allocated sizes of the above buffers. */
553 static int encode_terminal_src_size;
554 static int encode_terminal_dst_size;
556 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes.
557 Set CODING->produced to the byte-length of the resulting byte
558 sequence, and return a pointer to that byte sequence. */
560 unsigned char *
561 encode_terminal_code (src, src_len, coding)
562 struct glyph *src;
563 int src_len;
564 struct coding_system *coding;
566 struct glyph *src_end = src + src_len;
567 unsigned char *buf;
568 int nchars, nbytes, required;
569 register int tlen = GLYPH_TABLE_LENGTH;
570 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
571 Lisp_Object charset_list;
573 /* Allocate sufficient size of buffer to store all characters in
574 multibyte-form. But, it may be enlarged on demand if
575 Vglyph_table contains a string or a composite glyph is
576 encountered. */
577 required = MAX_MULTIBYTE_LENGTH * src_len;
578 if (encode_terminal_src_size < required)
580 if (encode_terminal_src)
581 encode_terminal_src = xrealloc (encode_terminal_src, required);
582 else
583 encode_terminal_src = xmalloc (required);
584 encode_terminal_src_size = required;
587 charset_list = coding_charset_list (coding);
589 buf = encode_terminal_src;
590 nchars = 0;
591 while (src < src_end)
593 if (src->type == COMPOSITE_GLYPH)
595 struct composition *cmp;
596 Lisp_Object gstring;
597 int i;
599 nbytes = buf - encode_terminal_src;
600 if (src->u.cmp.automatic)
602 gstring = composition_gstring_from_id (src->u.cmp.id);
603 required = src->u.cmp.to + 1 - src->u.cmp.from;
605 else
607 cmp = composition_table[src->u.cmp.id];
608 required = MAX_MULTIBYTE_LENGTH * cmp->glyph_len;
611 if (encode_terminal_src_size < nbytes + required)
613 encode_terminal_src_size = nbytes + required;
614 encode_terminal_src = xrealloc (encode_terminal_src,
615 encode_terminal_src_size);
616 buf = encode_terminal_src + nbytes;
619 if (src->u.cmp.automatic)
620 for (i = src->u.cmp.from; i <= src->u.cmp.to; i++)
622 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
623 int c = LGLYPH_CHAR (g);
625 if (! char_charset (c, charset_list, NULL))
626 c = '?';
627 buf += CHAR_STRING (c, buf);
628 nchars++;
630 else
631 for (i = 0; i < cmp->glyph_len; i++)
633 int c = COMPOSITION_GLYPH (cmp, i);
635 if (c == '\t')
636 continue;
637 if (char_charset (c, charset_list, NULL))
639 if (CHAR_WIDTH (c) == 0
640 && i > 0 && COMPOSITION_GLYPH (cmp, i - 1) == '\t')
641 /* Should be left-padded */
643 buf += CHAR_STRING (' ', buf);
644 nchars++;
647 else
648 c = '?';
649 buf += CHAR_STRING (c, buf);
650 nchars++;
653 /* We must skip glyphs to be padded for a wide character. */
654 else if (! CHAR_GLYPH_PADDING_P (*src))
656 GLYPH g;
657 int c;
658 Lisp_Object string;
660 string = Qnil;
661 SET_GLYPH_FROM_CHAR_GLYPH (g, src[0]);
663 if (GLYPH_INVALID_P (g) || GLYPH_SIMPLE_P (tbase, tlen, g))
665 /* This glyph doesn't have an entry in Vglyph_table. */
666 c = src->u.ch;
668 else
670 /* This glyph has an entry in Vglyph_table,
671 so process any alias before testing for simpleness. */
672 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
674 if (GLYPH_SIMPLE_P (tbase, tlen, g))
675 /* We set the multi-byte form of a character in G
676 (that should be an ASCII character) at WORKBUF. */
677 c = GLYPH_CHAR (g);
678 else
679 /* We have a string in Vglyph_table. */
680 string = tbase[GLYPH_CHAR (g)];
683 if (NILP (string))
685 nbytes = buf - encode_terminal_src;
686 if (encode_terminal_src_size < nbytes + MAX_MULTIBYTE_LENGTH)
688 encode_terminal_src_size = nbytes + MAX_MULTIBYTE_LENGTH;
689 encode_terminal_src = xrealloc (encode_terminal_src,
690 encode_terminal_src_size);
691 buf = encode_terminal_src + nbytes;
693 if (char_charset (c, charset_list, NULL))
695 /* Store the multibyte form of C at BUF. */
696 buf += CHAR_STRING (c, buf);
697 nchars++;
699 else
701 /* C is not encodable. */
702 *buf++ = '?';
703 nchars++;
704 while (src + 1 < src_end && CHAR_GLYPH_PADDING_P (src[1]))
706 *buf++ = '?';
707 nchars++;
708 src++;
712 else
714 unsigned char *p = SDATA (string), *pend = p + SBYTES (string);
716 if (! STRING_MULTIBYTE (string))
717 string = string_to_multibyte (string);
718 nbytes = buf - encode_terminal_src;
719 if (encode_terminal_src_size < nbytes + SBYTES (string))
721 encode_terminal_src_size = nbytes + SBYTES (string);
722 encode_terminal_src = xrealloc (encode_terminal_src,
723 encode_terminal_src_size);
724 buf = encode_terminal_src + nbytes;
726 bcopy (SDATA (string), buf, SBYTES (string));
727 buf += SBYTES (string);
728 nchars += SCHARS (string);
731 src++;
734 if (nchars == 0)
736 coding->produced = 0;
737 return NULL;
740 nbytes = buf - encode_terminal_src;
741 coding->source = encode_terminal_src;
742 if (encode_terminal_dst_size == 0)
744 encode_terminal_dst_size = encode_terminal_src_size;
745 if (encode_terminal_dst)
746 encode_terminal_dst = xrealloc (encode_terminal_dst,
747 encode_terminal_dst_size);
748 else
749 encode_terminal_dst = xmalloc (encode_terminal_dst_size);
751 coding->destination = encode_terminal_dst;
752 coding->dst_bytes = encode_terminal_dst_size;
753 encode_coding_object (coding, Qnil, 0, 0, nchars, nbytes, Qnil);
754 /* coding->destination may have been reallocated. */
755 encode_terminal_dst = coding->destination;
756 encode_terminal_dst_size = coding->dst_bytes;
758 return (encode_terminal_dst);
763 /* An implementation of write_glyphs for termcap frames. */
765 static void
766 tty_write_glyphs (struct frame *f, struct glyph *string, int len)
768 unsigned char *conversion_buffer;
769 struct coding_system *coding;
771 struct tty_display_info *tty = FRAME_TTY (f);
773 tty_turn_off_insert (tty);
774 tty_hide_cursor (tty);
776 /* Don't dare write in last column of bottom line, if Auto-Wrap,
777 since that would scroll the whole frame on some terminals. */
779 if (AutoWrap (tty)
780 && curY (tty) + 1 == FRAME_LINES (f)
781 && (curX (tty) + len) == FRAME_COLS (f))
782 len --;
783 if (len <= 0)
784 return;
786 cmplus (tty, len);
788 /* If terminal_coding does any conversion, use it, otherwise use
789 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
790 because it always return 1 if the member src_multibyte is 1. */
791 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
792 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
793 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
794 the tail. */
795 coding->mode &= ~CODING_MODE_LAST_BLOCK;
797 while (len > 0)
799 /* Identify a run of glyphs with the same face. */
800 int face_id = string->face_id;
801 int n;
803 for (n = 1; n < len; ++n)
804 if (string[n].face_id != face_id)
805 break;
807 /* Turn appearance modes of the face of the run on. */
808 tty_highlight_if_desired (tty);
809 turn_on_face (f, face_id);
811 if (n == len)
812 /* This is the last run. */
813 coding->mode |= CODING_MODE_LAST_BLOCK;
814 conversion_buffer = encode_terminal_code (string, n, coding);
815 if (coding->produced > 0)
817 BLOCK_INPUT;
818 fwrite (conversion_buffer, 1, coding->produced, tty->output);
819 if (ferror (tty->output))
820 clearerr (tty->output);
821 if (tty->termscript)
822 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
823 UNBLOCK_INPUT;
825 len -= n;
826 string += n;
828 /* Turn appearance modes off. */
829 turn_off_face (f, face_id);
830 tty_turn_off_highlight (tty);
833 cmcheckmagic (tty);
836 #ifdef HAVE_GPM /* Only used by GPM code. */
838 static void
839 tty_write_glyphs_with_face (f, string, len, face_id)
840 register struct frame *f;
841 register struct glyph *string;
842 register int len, face_id;
844 unsigned char *conversion_buffer;
845 struct coding_system *coding;
847 struct tty_display_info *tty = FRAME_TTY (f);
849 tty_turn_off_insert (tty);
850 tty_hide_cursor (tty);
852 /* Don't dare write in last column of bottom line, if Auto-Wrap,
853 since that would scroll the whole frame on some terminals. */
855 if (AutoWrap (tty)
856 && curY (tty) + 1 == FRAME_LINES (f)
857 && (curX (tty) + len) == FRAME_COLS (f))
858 len --;
859 if (len <= 0)
860 return;
862 cmplus (tty, len);
864 /* If terminal_coding does any conversion, use it, otherwise use
865 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
866 because it always return 1 if the member src_multibyte is 1. */
867 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
868 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
869 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
870 the tail. */
871 coding->mode &= ~CODING_MODE_LAST_BLOCK;
873 /* Turn appearance modes of the face. */
874 tty_highlight_if_desired (tty);
875 turn_on_face (f, face_id);
877 coding->mode |= CODING_MODE_LAST_BLOCK;
878 conversion_buffer = encode_terminal_code (string, len, coding);
879 if (coding->produced > 0)
881 BLOCK_INPUT;
882 fwrite (conversion_buffer, 1, coding->produced, tty->output);
883 if (ferror (tty->output))
884 clearerr (tty->output);
885 if (tty->termscript)
886 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
887 UNBLOCK_INPUT;
890 /* Turn appearance modes off. */
891 turn_off_face (f, face_id);
892 tty_turn_off_highlight (tty);
894 cmcheckmagic (tty);
896 #endif
898 /* An implementation of insert_glyphs for termcap frames. */
900 static void
901 tty_insert_glyphs (struct frame *f, struct glyph *start, int len)
903 char *buf;
904 struct glyph *glyph = NULL;
905 unsigned char *conversion_buffer;
906 unsigned char space[1];
907 struct coding_system *coding;
909 struct tty_display_info *tty = FRAME_TTY (f);
911 if (tty->TS_ins_multi_chars)
913 buf = tparam (tty->TS_ins_multi_chars, 0, 0, len);
914 OUTPUT1 (tty, buf);
915 xfree (buf);
916 if (start)
917 write_glyphs (f, start, len);
918 return;
921 tty_turn_on_insert (tty);
922 cmplus (tty, len);
924 if (! start)
925 space[0] = SPACEGLYPH;
927 /* If terminal_coding does any conversion, use it, otherwise use
928 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
929 because it always return 1 if the member src_multibyte is 1. */
930 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
931 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
932 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
933 the tail. */
934 coding->mode &= ~CODING_MODE_LAST_BLOCK;
936 while (len-- > 0)
938 OUTPUT1_IF (tty, tty->TS_ins_char);
939 if (!start)
941 conversion_buffer = space;
942 coding->produced = 1;
944 else
946 tty_highlight_if_desired (tty);
947 turn_on_face (f, start->face_id);
948 glyph = start;
949 ++start;
950 /* We must open sufficient space for a character which
951 occupies more than one column. */
952 while (len && CHAR_GLYPH_PADDING_P (*start))
954 OUTPUT1_IF (tty, tty->TS_ins_char);
955 start++, len--;
958 if (len <= 0)
959 /* This is the last glyph. */
960 coding->mode |= CODING_MODE_LAST_BLOCK;
962 conversion_buffer = encode_terminal_code (glyph, 1, coding);
965 if (coding->produced > 0)
967 BLOCK_INPUT;
968 fwrite (conversion_buffer, 1, coding->produced, tty->output);
969 if (ferror (tty->output))
970 clearerr (tty->output);
971 if (tty->termscript)
972 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
973 UNBLOCK_INPUT;
976 OUTPUT1_IF (tty, tty->TS_pad_inserted_char);
977 if (start)
979 turn_off_face (f, glyph->face_id);
980 tty_turn_off_highlight (tty);
984 cmcheckmagic (tty);
987 /* An implementation of delete_glyphs for termcap frames. */
989 static void
990 tty_delete_glyphs (struct frame *f, int n)
992 char *buf;
993 register int i;
995 struct tty_display_info *tty = FRAME_TTY (f);
997 if (tty->delete_in_insert_mode)
999 tty_turn_on_insert (tty);
1001 else
1003 tty_turn_off_insert (tty);
1004 OUTPUT_IF (tty, tty->TS_delete_mode);
1007 if (tty->TS_del_multi_chars)
1009 buf = tparam (tty->TS_del_multi_chars, 0, 0, n);
1010 OUTPUT1 (tty, buf);
1011 xfree (buf);
1013 else
1014 for (i = 0; i < n; i++)
1015 OUTPUT1 (tty, tty->TS_del_char);
1016 if (!tty->delete_in_insert_mode)
1017 OUTPUT_IF (tty, tty->TS_end_delete_mode);
1020 /* An implementation of ins_del_lines for termcap frames. */
1022 static void
1023 tty_ins_del_lines (struct frame *f, int vpos, int n)
1025 struct tty_display_info *tty = FRAME_TTY (f);
1026 char *multi = n > 0 ? tty->TS_ins_multi_lines : tty->TS_del_multi_lines;
1027 char *single = n > 0 ? tty->TS_ins_line : tty->TS_del_line;
1028 char *scroll = n > 0 ? tty->TS_rev_scroll : tty->TS_fwd_scroll;
1030 register int i = n > 0 ? n : -n;
1031 register char *buf;
1033 /* If the lines below the insertion are being pushed
1034 into the end of the window, this is the same as clearing;
1035 and we know the lines are already clear, since the matching
1036 deletion has already been done. So can ignore this. */
1037 /* If the lines below the deletion are blank lines coming
1038 out of the end of the window, don't bother,
1039 as there will be a matching inslines later that will flush them. */
1040 if (FRAME_SCROLL_REGION_OK (f)
1041 && vpos + i >= tty->specified_window)
1042 return;
1043 if (!FRAME_MEMORY_BELOW_FRAME (f)
1044 && vpos + i >= FRAME_LINES (f))
1045 return;
1047 if (multi)
1049 raw_cursor_to (f, vpos, 0);
1050 tty_background_highlight (tty);
1051 buf = tparam (multi, 0, 0, i);
1052 OUTPUT (tty, buf);
1053 xfree (buf);
1055 else if (single)
1057 raw_cursor_to (f, vpos, 0);
1058 tty_background_highlight (tty);
1059 while (--i >= 0)
1060 OUTPUT (tty, single);
1061 if (tty->TF_teleray)
1062 curX (tty) = 0;
1064 else
1066 tty_set_scroll_region (f, vpos, tty->specified_window);
1067 if (n < 0)
1068 raw_cursor_to (f, tty->specified_window - 1, 0);
1069 else
1070 raw_cursor_to (f, vpos, 0);
1071 tty_background_highlight (tty);
1072 while (--i >= 0)
1073 OUTPUTL (tty, scroll, tty->specified_window - vpos);
1074 tty_set_scroll_region (f, 0, tty->specified_window);
1077 if (!FRAME_SCROLL_REGION_OK (f)
1078 && FRAME_MEMORY_BELOW_FRAME (f)
1079 && n < 0)
1081 cursor_to (f, FRAME_LINES (f) + n, 0);
1082 clear_to_end (f);
1086 /* Compute cost of sending "str", in characters,
1087 not counting any line-dependent padding. */
1090 string_cost (char *str)
1092 cost = 0;
1093 if (str)
1094 tputs (str, 0, evalcost);
1095 return cost;
1098 /* Compute cost of sending "str", in characters,
1099 counting any line-dependent padding at one line. */
1101 static int
1102 string_cost_one_line (char *str)
1104 cost = 0;
1105 if (str)
1106 tputs (str, 1, evalcost);
1107 return cost;
1110 /* Compute per line amount of line-dependent padding,
1111 in tenths of characters. */
1114 per_line_cost (char *str)
1116 cost = 0;
1117 if (str)
1118 tputs (str, 0, evalcost);
1119 cost = - cost;
1120 if (str)
1121 tputs (str, 10, evalcost);
1122 return cost;
1125 #ifndef old
1126 /* char_ins_del_cost[n] is cost of inserting N characters.
1127 char_ins_del_cost[-n] is cost of deleting N characters.
1128 The length of this vector is based on max_frame_cols. */
1130 int *char_ins_del_vector;
1132 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
1133 #endif
1135 /* ARGSUSED */
1136 static void
1137 calculate_ins_del_char_costs (struct frame *f)
1139 struct tty_display_info *tty = FRAME_TTY (f);
1140 int ins_startup_cost, del_startup_cost;
1141 int ins_cost_per_char, del_cost_per_char;
1142 register int i;
1143 register int *p;
1145 if (tty->TS_ins_multi_chars)
1147 ins_cost_per_char = 0;
1148 ins_startup_cost = string_cost_one_line (tty->TS_ins_multi_chars);
1150 else if (tty->TS_ins_char || tty->TS_pad_inserted_char
1151 || (tty->TS_insert_mode && tty->TS_end_insert_mode))
1153 ins_startup_cost = (30 * (string_cost (tty->TS_insert_mode)
1154 + string_cost (tty->TS_end_insert_mode))) / 100;
1155 ins_cost_per_char = (string_cost_one_line (tty->TS_ins_char)
1156 + string_cost_one_line (tty->TS_pad_inserted_char));
1158 else
1160 ins_startup_cost = 9999;
1161 ins_cost_per_char = 0;
1164 if (tty->TS_del_multi_chars)
1166 del_cost_per_char = 0;
1167 del_startup_cost = string_cost_one_line (tty->TS_del_multi_chars);
1169 else if (tty->TS_del_char)
1171 del_startup_cost = (string_cost (tty->TS_delete_mode)
1172 + string_cost (tty->TS_end_delete_mode));
1173 if (tty->delete_in_insert_mode)
1174 del_startup_cost /= 2;
1175 del_cost_per_char = string_cost_one_line (tty->TS_del_char);
1177 else
1179 del_startup_cost = 9999;
1180 del_cost_per_char = 0;
1183 /* Delete costs are at negative offsets */
1184 p = &char_ins_del_cost (f)[0];
1185 for (i = FRAME_COLS (f); --i >= 0;)
1186 *--p = (del_startup_cost += del_cost_per_char);
1188 /* Doing nothing is free */
1189 p = &char_ins_del_cost (f)[0];
1190 *p++ = 0;
1192 /* Insert costs are at positive offsets */
1193 for (i = FRAME_COLS (f); --i >= 0;)
1194 *p++ = (ins_startup_cost += ins_cost_per_char);
1197 void
1198 calculate_costs (struct frame *frame)
1200 FRAME_COST_BAUD_RATE (frame) = baud_rate;
1202 if (FRAME_TERMCAP_P (frame))
1204 struct tty_display_info *tty = FRAME_TTY (frame);
1205 register char *f = (tty->TS_set_scroll_region
1206 ? tty->TS_set_scroll_region
1207 : tty->TS_set_scroll_region_1);
1209 FRAME_SCROLL_REGION_COST (frame) = string_cost (f);
1211 tty->costs_set = 1;
1213 /* These variables are only used for terminal stuff. They are
1214 allocated once for the terminal frame of X-windows emacs, but not
1215 used afterwards.
1217 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1218 X turns off char_ins_del_ok. */
1220 max_frame_lines = max (max_frame_lines, FRAME_LINES (frame));
1221 max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
1223 if (char_ins_del_vector != 0)
1224 char_ins_del_vector
1225 = (int *) xrealloc (char_ins_del_vector,
1226 (sizeof (int)
1227 + 2 * max_frame_cols * sizeof (int)));
1228 else
1229 char_ins_del_vector
1230 = (int *) xmalloc (sizeof (int)
1231 + 2 * max_frame_cols * sizeof (int));
1233 bzero (char_ins_del_vector, (sizeof (int)
1234 + 2 * max_frame_cols * sizeof (int)));
1237 if (f && (!tty->TS_ins_line && !tty->TS_del_line))
1238 do_line_insertion_deletion_costs (frame,
1239 tty->TS_rev_scroll, tty->TS_ins_multi_lines,
1240 tty->TS_fwd_scroll, tty->TS_del_multi_lines,
1241 f, f, 1);
1242 else
1243 do_line_insertion_deletion_costs (frame,
1244 tty->TS_ins_line, tty->TS_ins_multi_lines,
1245 tty->TS_del_line, tty->TS_del_multi_lines,
1246 0, 0, 1);
1248 calculate_ins_del_char_costs (frame);
1250 /* Don't use TS_repeat if its padding is worse than sending the chars */
1251 if (tty->TS_repeat && per_line_cost (tty->TS_repeat) * baud_rate < 9000)
1252 tty->RPov = string_cost (tty->TS_repeat);
1253 else
1254 tty->RPov = FRAME_COLS (frame) * 2;
1256 cmcostinit (FRAME_TTY (frame)); /* set up cursor motion costs */
1260 struct fkey_table {
1261 char *cap, *name;
1264 /* Termcap capability names that correspond directly to X keysyms.
1265 Some of these (marked "terminfo") aren't supplied by old-style
1266 (Berkeley) termcap entries. They're listed in X keysym order;
1267 except we put the keypad keys first, so that if they clash with
1268 other keys (as on the IBM PC keyboard) they get overridden.
1271 static struct fkey_table keys[] =
1273 {"kh", "home"}, /* termcap */
1274 {"kl", "left"}, /* termcap */
1275 {"ku", "up"}, /* termcap */
1276 {"kr", "right"}, /* termcap */
1277 {"kd", "down"}, /* termcap */
1278 {"%8", "prior"}, /* terminfo */
1279 {"%5", "next"}, /* terminfo */
1280 {"@7", "end"}, /* terminfo */
1281 {"@1", "begin"}, /* terminfo */
1282 {"*6", "select"}, /* terminfo */
1283 {"%9", "print"}, /* terminfo */
1284 {"@4", "execute"}, /* terminfo --- actually the `command' key */
1286 * "insert" --- see below
1288 {"&8", "undo"}, /* terminfo */
1289 {"%0", "redo"}, /* terminfo */
1290 {"%7", "menu"}, /* terminfo --- actually the `options' key */
1291 {"@0", "find"}, /* terminfo */
1292 {"@2", "cancel"}, /* terminfo */
1293 {"%1", "help"}, /* terminfo */
1295 * "break" goes here, but can't be reliably intercepted with termcap
1297 {"&4", "reset"}, /* terminfo --- actually `restart' */
1299 * "system" and "user" --- no termcaps
1301 {"kE", "clearline"}, /* terminfo */
1302 {"kA", "insertline"}, /* terminfo */
1303 {"kL", "deleteline"}, /* terminfo */
1304 {"kI", "insertchar"}, /* terminfo */
1305 {"kD", "deletechar"}, /* terminfo */
1306 {"kB", "backtab"}, /* terminfo */
1308 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1310 {"@8", "kp-enter"}, /* terminfo */
1312 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1313 * "kp-multiply", "kp-add", "kp-separator",
1314 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1315 * --- no termcaps for any of these.
1317 {"K4", "kp-1"}, /* terminfo */
1319 * "kp-2" --- no termcap
1321 {"K5", "kp-3"}, /* terminfo */
1323 * "kp-4" --- no termcap
1325 {"K2", "kp-5"}, /* terminfo */
1327 * "kp-6" --- no termcap
1329 {"K1", "kp-7"}, /* terminfo */
1331 * "kp-8" --- no termcap
1333 {"K3", "kp-9"}, /* terminfo */
1335 * "kp-equal" --- no termcap
1337 {"k1", "f1"},
1338 {"k2", "f2"},
1339 {"k3", "f3"},
1340 {"k4", "f4"},
1341 {"k5", "f5"},
1342 {"k6", "f6"},
1343 {"k7", "f7"},
1344 {"k8", "f8"},
1345 {"k9", "f9"},
1347 {"&0", "S-cancel"}, /*shifted cancel key*/
1348 {"&9", "S-begin"}, /*shifted begin key*/
1349 {"*0", "S-find"}, /*shifted find key*/
1350 {"*1", "S-execute"}, /*shifted execute? actually shifted command key*/
1351 {"*4", "S-delete"}, /*shifted delete-character key*/
1352 {"*7", "S-end"}, /*shifted end key*/
1353 {"*8", "S-clearline"}, /*shifted clear-to end-of-line key*/
1354 {"#1", "S-help"}, /*shifted help key*/
1355 {"#2", "S-home"}, /*shifted home key*/
1356 {"#3", "S-insert"}, /*shifted insert-character key*/
1357 {"#4", "S-left"}, /*shifted left-arrow key*/
1358 {"%d", "S-menu"}, /*shifted menu? actually shifted options key*/
1359 {"%c", "S-next"}, /*shifted next key*/
1360 {"%e", "S-prior"}, /*shifted previous key*/
1361 {"%f", "S-print"}, /*shifted print key*/
1362 {"%g", "S-redo"}, /*shifted redo key*/
1363 {"%i", "S-right"}, /*shifted right-arrow key*/
1364 {"!3", "S-undo"} /*shifted undo key*/
1367 static char **term_get_fkeys_address;
1368 static KBOARD *term_get_fkeys_kboard;
1369 static Lisp_Object term_get_fkeys_1 ();
1371 /* Find the escape codes sent by the function keys for Vinput_decode_map.
1372 This function scans the termcap function key sequence entries, and
1373 adds entries to Vinput_decode_map for each function key it finds. */
1375 static void
1376 term_get_fkeys (address, kboard)
1377 char **address;
1378 KBOARD *kboard;
1380 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1381 errors during the call. The only errors should be from Fdefine_key
1382 when given a key sequence containing an invalid prefix key. If the
1383 termcap defines function keys which use a prefix that is already bound
1384 to a command by the default bindings, we should silently ignore that
1385 function key specification, rather than giving the user an error and
1386 refusing to run at all on such a terminal. */
1388 extern Lisp_Object Fidentity ();
1389 term_get_fkeys_address = address;
1390 term_get_fkeys_kboard = kboard;
1391 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1394 static Lisp_Object
1395 term_get_fkeys_1 ()
1397 int i;
1399 char **address = term_get_fkeys_address;
1400 KBOARD *kboard = term_get_fkeys_kboard;
1402 /* This can happen if CANNOT_DUMP or with strange options. */
1403 if (!KEYMAPP (kboard->Vinput_decode_map))
1404 kboard->Vinput_decode_map = Fmake_sparse_keymap (Qnil);
1406 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1408 char *sequence = tgetstr (keys[i].cap, address);
1409 if (sequence)
1410 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence),
1411 Fmake_vector (make_number (1),
1412 intern (keys[i].name)));
1415 /* The uses of the "k0" capability are inconsistent; sometimes it
1416 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1417 We will attempt to politely accommodate both systems by testing for
1418 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1421 char *k_semi = tgetstr ("k;", address);
1422 char *k0 = tgetstr ("k0", address);
1423 char *k0_name = "f10";
1425 if (k_semi)
1427 if (k0)
1428 /* Define f0 first, so that f10 takes precedence in case the
1429 key sequences happens to be the same. */
1430 Fdefine_key (kboard->Vinput_decode_map, build_string (k0),
1431 Fmake_vector (make_number (1), intern ("f0")));
1432 Fdefine_key (kboard->Vinput_decode_map, build_string (k_semi),
1433 Fmake_vector (make_number (1), intern ("f10")));
1435 else if (k0)
1436 Fdefine_key (kboard->Vinput_decode_map, build_string (k0),
1437 Fmake_vector (make_number (1), intern (k0_name)));
1440 /* Set up cookies for numbered function keys above f10. */
1442 char fcap[3], fkey[4];
1444 fcap[0] = 'F'; fcap[2] = '\0';
1445 for (i = 11; i < 64; i++)
1447 if (i <= 19)
1448 fcap[1] = '1' + i - 11;
1449 else if (i <= 45)
1450 fcap[1] = 'A' + i - 20;
1451 else
1452 fcap[1] = 'a' + i - 46;
1455 char *sequence = tgetstr (fcap, address);
1456 if (sequence)
1458 sprintf (fkey, "f%d", i);
1459 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence),
1460 Fmake_vector (make_number (1),
1461 intern (fkey)));
1468 * Various mappings to try and get a better fit.
1471 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1472 if (!tgetstr (cap1, address)) \
1474 char *sequence = tgetstr (cap2, address); \
1475 if (sequence) \
1476 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence), \
1477 Fmake_vector (make_number (1), \
1478 intern (sym))); \
1481 /* if there's no key_next keycap, map key_npage to `next' keysym */
1482 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1483 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1484 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1485 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1486 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1487 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1488 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1490 /* IBM has their own non-standard dialect of terminfo.
1491 If the standard name isn't found, try the IBM name. */
1492 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1493 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1494 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1495 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1496 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1497 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1498 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1499 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1500 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1501 #undef CONDITIONAL_REASSIGN
1504 return Qnil;
1508 /***********************************************************************
1509 Character Display Information
1510 ***********************************************************************/
1512 /* Avoid name clash with functions defined in xterm.c */
1513 #ifdef static
1514 #define append_glyph append_glyph_term
1515 #define produce_stretch_glyph produce_stretch_glyph_term
1516 #define append_composite_glyph append_composite_glyph_term
1517 #define produce_composite_glyph produce_composite_glyph_term
1518 #endif
1520 static void append_glyph P_ ((struct it *));
1521 static void produce_stretch_glyph P_ ((struct it *));
1522 static void append_composite_glyph P_ ((struct it *));
1523 static void produce_composite_glyph P_ ((struct it *));
1525 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1526 terminal frames if IT->glyph_row != NULL. IT->char_to_display is
1527 the character for which to produce glyphs; IT->face_id contains the
1528 character's face. Padding glyphs are appended if IT->c has a
1529 IT->pixel_width > 1. */
1531 static void
1532 append_glyph (it)
1533 struct it *it;
1535 struct glyph *glyph, *end;
1536 int i;
1538 xassert (it->glyph_row);
1539 glyph = (it->glyph_row->glyphs[it->area]
1540 + it->glyph_row->used[it->area]);
1541 end = it->glyph_row->glyphs[1 + it->area];
1543 /* If the glyph row is reversed, we need to prepend the glyph rather
1544 than append it. */
1545 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1547 struct glyph *g;
1548 int move_by = it->pixel_width;
1550 /* Make room for the new glyphs. */
1551 if (move_by > end - glyph) /* don't overstep end of this area */
1552 move_by = end - glyph;
1553 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1554 g[move_by] = *g;
1555 glyph = it->glyph_row->glyphs[it->area];
1556 end = glyph + move_by;
1559 /* BIDI Note: we put the glyphs of a "multi-pixel" character left to
1560 right, even in the REVERSED_P case, since (a) all of its u.ch are
1561 identical, and (b) the PADDING_P flag needs to be set for the
1562 leftmost one, because we write to the terminal left-to-right. */
1563 for (i = 0;
1564 i < it->pixel_width && glyph < end;
1565 ++i)
1567 glyph->type = CHAR_GLYPH;
1568 glyph->pixel_width = 1;
1569 glyph->u.ch = it->char_to_display;
1570 glyph->face_id = it->face_id;
1571 glyph->padding_p = i > 0;
1572 glyph->charpos = CHARPOS (it->position);
1573 glyph->object = it->object;
1574 if (it->bidi_p)
1576 glyph->resolved_level = it->bidi_it.resolved_level;
1577 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1578 abort ();
1579 glyph->bidi_type = it->bidi_it.type;
1581 else
1583 glyph->resolved_level = 0;
1584 glyph->bidi_type = UNKNOWN_BT;
1587 ++it->glyph_row->used[it->area];
1588 ++glyph;
1592 /* Produce glyphs for the display element described by IT. *IT
1593 specifies what we want to produce a glyph for (character, image, ...),
1594 and where in the glyph matrix we currently are (glyph row and hpos).
1595 produce_glyphs fills in output fields of *IT with information such as the
1596 pixel width and height of a character, and maybe output actual glyphs at
1597 the same time if IT->glyph_row is non-null. For an overview, see
1598 the explanation in dispextern.h, before the definition of the
1599 display_element_type enumeration.
1601 produce_glyphs also stores the result of glyph width, ascent
1602 etc. computations in *IT.
1604 IT->glyph_row may be null, in which case produce_glyphs does not
1605 actually fill in the glyphs. This is used in the move_* functions
1606 in xdisp.c for text width and height computations.
1608 Callers usually don't call produce_glyphs directly;
1609 instead they use the macro PRODUCE_GLYPHS. */
1611 void
1612 produce_glyphs (it)
1613 struct it *it;
1615 /* If a hook is installed, let it do the work. */
1617 /* Nothing but characters are supported on terminal frames. */
1618 xassert (it->what == IT_CHARACTER
1619 || it->what == IT_COMPOSITION
1620 || it->what == IT_STRETCH);
1622 if (it->what == IT_STRETCH)
1624 produce_stretch_glyph (it);
1625 goto done;
1628 if (it->what == IT_COMPOSITION)
1630 produce_composite_glyph (it);
1631 goto done;
1634 /* Maybe translate single-byte characters to multibyte. */
1635 it->char_to_display = it->c;
1637 if (it->c >= 040 && it->c < 0177)
1639 it->pixel_width = it->nglyphs = 1;
1640 if (it->glyph_row)
1641 append_glyph (it);
1643 else if (it->c == '\n')
1644 it->pixel_width = it->nglyphs = 0;
1645 else if (it->c == '\t')
1647 int absolute_x = (it->current_x
1648 + it->continuation_lines_width);
1649 int next_tab_x
1650 = (((1 + absolute_x + it->tab_width - 1)
1651 / it->tab_width)
1652 * it->tab_width);
1653 int nspaces;
1655 /* If part of the TAB has been displayed on the previous line
1656 which is continued now, continuation_lines_width will have
1657 been incremented already by the part that fitted on the
1658 continued line. So, we will get the right number of spaces
1659 here. */
1660 nspaces = next_tab_x - absolute_x;
1662 if (it->glyph_row)
1664 int n = nspaces;
1666 it->char_to_display = ' ';
1667 it->pixel_width = it->len = 1;
1669 while (n--)
1670 append_glyph (it);
1673 it->pixel_width = nspaces;
1674 it->nglyphs = nspaces;
1676 else if (CHAR_BYTE8_P (it->c))
1678 if (unibyte_display_via_language_environment
1679 && (it->c >= 0240))
1681 it->char_to_display = BYTE8_TO_CHAR (it->c);
1682 it->pixel_width = CHAR_WIDTH (it->char_to_display);
1683 it->nglyphs = it->pixel_width;
1684 if (it->glyph_row)
1685 append_glyph (it);
1687 else
1689 /* Coming here means that it->c is from display table, thus
1690 we must send the raw 8-bit byte as is to the terminal.
1691 Although there's no way to know how many columns it
1692 occupies on a screen, it is a good assumption that a
1693 single byte code has 1-column width. */
1694 it->pixel_width = it->nglyphs = 1;
1695 if (it->glyph_row)
1696 append_glyph (it);
1699 else
1701 it->pixel_width = CHAR_WIDTH (it->c);
1702 it->nglyphs = it->pixel_width;
1704 if (it->glyph_row)
1705 append_glyph (it);
1708 done:
1709 /* Advance current_x by the pixel width as a convenience for
1710 the caller. */
1711 if (it->area == TEXT_AREA)
1712 it->current_x += it->pixel_width;
1713 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1714 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
1718 /* Produce a stretch glyph for iterator IT. IT->object is the value
1719 of the glyph property displayed. The value must be a list
1720 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1721 being recognized:
1723 1. `:width WIDTH' specifies that the space should be WIDTH *
1724 canonical char width wide. WIDTH may be an integer or floating
1725 point number.
1727 2. `:align-to HPOS' specifies that the space should be wide enough
1728 to reach HPOS, a value in canonical character units. */
1730 static void
1731 produce_stretch_glyph (it)
1732 struct it *it;
1734 /* (space :width WIDTH ...) */
1735 Lisp_Object prop, plist;
1736 int width = 0, align_to = -1;
1737 int zero_width_ok_p = 0;
1738 double tem;
1740 /* List should start with `space'. */
1741 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1742 plist = XCDR (it->object);
1744 /* Compute the width of the stretch. */
1745 if ((prop = Fplist_get (plist, QCwidth), !NILP (prop))
1746 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, 0))
1748 /* Absolute width `:width WIDTH' specified and valid. */
1749 zero_width_ok_p = 1;
1750 width = (int)(tem + 0.5);
1752 else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
1753 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, &align_to))
1755 if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
1756 align_to = (align_to < 0
1758 : align_to - window_box_left_offset (it->w, TEXT_AREA));
1759 else if (align_to < 0)
1760 align_to = window_box_left_offset (it->w, TEXT_AREA);
1761 width = max (0, (int)(tem + 0.5) + align_to - it->current_x);
1762 zero_width_ok_p = 1;
1764 else
1765 /* Nothing specified -> width defaults to canonical char width. */
1766 width = FRAME_COLUMN_WIDTH (it->f);
1768 if (width <= 0 && (width < 0 || !zero_width_ok_p))
1769 width = 1;
1771 if (width > 0 && it->line_wrap != TRUNCATE
1772 && it->current_x + width > it->last_visible_x)
1773 width = it->last_visible_x - it->current_x - 1;
1775 if (width > 0 && it->glyph_row)
1777 Lisp_Object o_object = it->object;
1778 Lisp_Object object = it->stack[it->sp - 1].string;
1779 int n = width;
1781 if (!STRINGP (object))
1782 object = it->w->buffer;
1783 it->object = object;
1784 it->char_to_display = ' ';
1785 it->pixel_width = it->len = 1;
1786 while (n--)
1787 append_glyph (it);
1788 it->object = o_object;
1790 it->pixel_width = width;
1791 it->nglyphs = width;
1795 /* Append glyphs to IT's glyph_row for the composition IT->cmp_id.
1796 Called from produce_composite_glyph for terminal frames if
1797 IT->glyph_row != NULL. IT->face_id contains the character's
1798 face. */
1800 static void
1801 append_composite_glyph (it)
1802 struct it *it;
1804 struct glyph *glyph;
1806 xassert (it->glyph_row);
1807 glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
1808 if (glyph < it->glyph_row->glyphs[1 + it->area])
1810 /* If the glyph row is reversed, we need to prepend the glyph
1811 rather than append it. */
1812 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1814 struct glyph *g;
1816 /* Make room for the new glyph. */
1817 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1818 g[1] = *g;
1819 glyph = it->glyph_row->glyphs[it->area];
1821 glyph->type = COMPOSITE_GLYPH;
1822 glyph->pixel_width = it->pixel_width;
1823 glyph->u.cmp.id = it->cmp_it.id;
1824 if (it->cmp_it.ch < 0)
1826 glyph->u.cmp.automatic = 0;
1827 glyph->u.cmp.id = it->cmp_it.id;
1829 else
1831 glyph->u.cmp.automatic = 1;
1832 glyph->u.cmp.id = it->cmp_it.id;
1833 glyph->u.cmp.from = it->cmp_it.from;
1834 glyph->u.cmp.to = it->cmp_it.to - 1;
1837 glyph->face_id = it->face_id;
1838 glyph->padding_p = 0;
1839 glyph->charpos = CHARPOS (it->position);
1840 glyph->object = it->object;
1841 if (it->bidi_p)
1843 glyph->resolved_level = it->bidi_it.resolved_level;
1844 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1845 abort ();
1846 glyph->bidi_type = it->bidi_it.type;
1848 else
1850 glyph->resolved_level = 0;
1851 glyph->bidi_type = UNKNOWN_BT;
1854 ++it->glyph_row->used[it->area];
1855 ++glyph;
1860 /* Produce a composite glyph for iterator IT. IT->cmp_id is the ID of
1861 the composition. We simply produces components of the composition
1862 assuming that the terminal has a capability to layout/render it
1863 correctly. */
1865 static void
1866 produce_composite_glyph (it)
1867 struct it *it;
1869 int c;
1871 if (it->cmp_it.ch < 0)
1873 struct composition *cmp = composition_table[it->cmp_it.id];
1875 it->pixel_width = cmp->width;
1877 else
1879 Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id);
1881 it->pixel_width = composition_gstring_width (gstring, it->cmp_it.from,
1882 it->cmp_it.to, NULL);
1884 it->nglyphs = 1;
1885 if (it->glyph_row)
1886 append_composite_glyph (it);
1890 /* Get information about special display element WHAT in an
1891 environment described by IT. WHAT is one of IT_TRUNCATION or
1892 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1893 non-null glyph_row member. This function ensures that fields like
1894 face_id, c, len of IT are left untouched. */
1896 void
1897 produce_special_glyphs (it, what)
1898 struct it *it;
1899 enum display_element_type what;
1901 struct it temp_it;
1902 Lisp_Object gc;
1903 GLYPH glyph;
1905 temp_it = *it;
1906 temp_it.dp = NULL;
1907 temp_it.what = IT_CHARACTER;
1908 temp_it.len = 1;
1909 temp_it.object = make_number (0);
1910 bzero (&temp_it.current, sizeof temp_it.current);
1912 if (what == IT_CONTINUATION)
1914 /* Continuation glyph. For R2L lines, we mirror it by hand. */
1915 if (it->bidi_it.paragraph_dir == R2L)
1916 SET_GLYPH_FROM_CHAR (glyph, '/');
1917 else
1918 SET_GLYPH_FROM_CHAR (glyph, '\\');
1919 if (it->dp
1920 && (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc))
1921 && GLYPH_CODE_CHAR_VALID_P (gc))
1923 /* FIXME: Should we mirror GC for R2L lines? */
1924 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
1925 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
1928 else if (what == IT_TRUNCATION)
1930 /* Truncation glyph. */
1931 SET_GLYPH_FROM_CHAR (glyph, '$');
1932 if (it->dp
1933 && (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc))
1934 && GLYPH_CODE_CHAR_VALID_P (gc))
1936 /* FIXME: Should we mirror GC for R2L lines? */
1937 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
1938 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
1941 else
1942 abort ();
1944 temp_it.c = GLYPH_CHAR (glyph);
1945 temp_it.face_id = GLYPH_FACE (glyph);
1946 temp_it.len = CHAR_BYTES (temp_it.c);
1948 produce_glyphs (&temp_it);
1949 it->pixel_width = temp_it.pixel_width;
1950 it->nglyphs = temp_it.pixel_width;
1955 /***********************************************************************
1956 Faces
1957 ***********************************************************************/
1959 /* Value is non-zero if attribute ATTR may be used. ATTR should be
1960 one of the enumerators from enum no_color_bit, or a bit set built
1961 from them. Some display attributes may not be used together with
1962 color; the termcap capability `NC' specifies which ones. */
1964 #define MAY_USE_WITH_COLORS_P(tty, ATTR) \
1965 (tty->TN_max_colors > 0 \
1966 ? (tty->TN_no_color_video & (ATTR)) == 0 \
1967 : 1)
1969 /* Turn appearances of face FACE_ID on tty frame F on.
1970 FACE_ID is a realized face ID number, in the face cache. */
1972 static void
1973 turn_on_face (f, face_id)
1974 struct frame *f;
1975 int face_id;
1977 struct face *face = FACE_FROM_ID (f, face_id);
1978 long fg = face->foreground;
1979 long bg = face->background;
1980 struct tty_display_info *tty = FRAME_TTY (f);
1982 /* Do this first because TS_end_standout_mode may be the same
1983 as TS_exit_attribute_mode, which turns all appearances off. */
1984 if (MAY_USE_WITH_COLORS_P (tty, NC_REVERSE))
1986 if (tty->TN_max_colors > 0)
1988 if (fg >= 0 && bg >= 0)
1990 /* If the terminal supports colors, we can set them
1991 below without using reverse video. The face's fg
1992 and bg colors are set as they should appear on
1993 the screen, i.e. they take the inverse-video'ness
1994 of the face already into account. */
1996 else if (inverse_video)
1998 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1999 || bg == FACE_TTY_DEFAULT_BG_COLOR)
2000 tty_toggle_highlight (tty);
2002 else
2004 if (fg == FACE_TTY_DEFAULT_BG_COLOR
2005 || bg == FACE_TTY_DEFAULT_FG_COLOR)
2006 tty_toggle_highlight (tty);
2009 else
2011 /* If we can't display colors, use reverse video
2012 if the face specifies that. */
2013 if (inverse_video)
2015 if (fg == FACE_TTY_DEFAULT_FG_COLOR
2016 || bg == FACE_TTY_DEFAULT_BG_COLOR)
2017 tty_toggle_highlight (tty);
2019 else
2021 if (fg == FACE_TTY_DEFAULT_BG_COLOR
2022 || bg == FACE_TTY_DEFAULT_FG_COLOR)
2023 tty_toggle_highlight (tty);
2028 if (face->tty_bold_p && MAY_USE_WITH_COLORS_P (tty, NC_BOLD))
2029 OUTPUT1_IF (tty, tty->TS_enter_bold_mode);
2031 if (face->tty_dim_p && MAY_USE_WITH_COLORS_P (tty, NC_DIM))
2032 OUTPUT1_IF (tty, tty->TS_enter_dim_mode);
2034 /* Alternate charset and blinking not yet used. */
2035 if (face->tty_alt_charset_p
2036 && MAY_USE_WITH_COLORS_P (tty, NC_ALT_CHARSET))
2037 OUTPUT1_IF (tty, tty->TS_enter_alt_charset_mode);
2039 if (face->tty_blinking_p
2040 && MAY_USE_WITH_COLORS_P (tty, NC_BLINK))
2041 OUTPUT1_IF (tty, tty->TS_enter_blink_mode);
2043 if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (tty, NC_UNDERLINE))
2044 OUTPUT1_IF (tty, tty->TS_enter_underline_mode);
2046 if (tty->TN_max_colors > 0)
2048 char *ts, *p;
2050 ts = tty->standout_mode ? tty->TS_set_background : tty->TS_set_foreground;
2051 if (fg >= 0 && ts)
2053 p = tparam (ts, NULL, 0, (int) fg);
2054 OUTPUT (tty, p);
2055 xfree (p);
2058 ts = tty->standout_mode ? tty->TS_set_foreground : tty->TS_set_background;
2059 if (bg >= 0 && ts)
2061 p = tparam (ts, NULL, 0, (int) bg);
2062 OUTPUT (tty, p);
2063 xfree (p);
2069 /* Turn off appearances of face FACE_ID on tty frame F. */
2071 static void
2072 turn_off_face (f, face_id)
2073 struct frame *f;
2074 int face_id;
2076 struct face *face = FACE_FROM_ID (f, face_id);
2077 struct tty_display_info *tty = FRAME_TTY (f);
2079 xassert (face != NULL);
2081 if (tty->TS_exit_attribute_mode)
2083 /* Capability "me" will turn off appearance modes double-bright,
2084 half-bright, reverse-video, standout, underline. It may or
2085 may not turn off alt-char-mode. */
2086 if (face->tty_bold_p
2087 || face->tty_dim_p
2088 || face->tty_reverse_p
2089 || face->tty_alt_charset_p
2090 || face->tty_blinking_p
2091 || face->tty_underline_p)
2093 OUTPUT1_IF (tty, tty->TS_exit_attribute_mode);
2094 if (strcmp (tty->TS_exit_attribute_mode, tty->TS_end_standout_mode) == 0)
2095 tty->standout_mode = 0;
2098 if (face->tty_alt_charset_p)
2099 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
2101 else
2103 /* If we don't have "me" we can only have those appearances
2104 that have exit sequences defined. */
2105 if (face->tty_alt_charset_p)
2106 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
2108 if (face->tty_underline_p)
2109 OUTPUT_IF (tty, tty->TS_exit_underline_mode);
2112 /* Switch back to default colors. */
2113 if (tty->TN_max_colors > 0
2114 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
2115 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
2116 || (face->background != FACE_TTY_DEFAULT_COLOR
2117 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
2118 OUTPUT1_IF (tty, tty->TS_orig_pair);
2122 /* Return non-zero if the terminal on frame F supports all of the
2123 capabilities in CAPS simultaneously, with foreground and background
2124 colors FG and BG. */
2127 tty_capable_p (tty, caps, fg, bg)
2128 struct tty_display_info *tty;
2129 unsigned caps;
2130 unsigned long fg, bg;
2132 #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
2133 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
2134 return 0;
2136 TTY_CAPABLE_P_TRY (tty, TTY_CAP_INVERSE, tty->TS_standout_mode, NC_REVERSE);
2137 TTY_CAPABLE_P_TRY (tty, TTY_CAP_UNDERLINE, tty->TS_enter_underline_mode, NC_UNDERLINE);
2138 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BOLD, tty->TS_enter_bold_mode, NC_BOLD);
2139 TTY_CAPABLE_P_TRY (tty, TTY_CAP_DIM, tty->TS_enter_dim_mode, NC_DIM);
2140 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BLINK, tty->TS_enter_blink_mode, NC_BLINK);
2141 TTY_CAPABLE_P_TRY (tty, TTY_CAP_ALT_CHARSET, tty->TS_enter_alt_charset_mode, NC_ALT_CHARSET);
2143 /* We can do it! */
2144 return 1;
2147 /* Return non-zero if the terminal is capable to display colors. */
2149 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
2150 0, 1, 0,
2151 doc: /* Return non-nil if the tty device TERMINAL can display colors.
2153 TERMINAL can be a terminal object, a frame, or nil (meaning the
2154 selected frame's terminal). This function always returns nil if
2155 TERMINAL does not refer to a text-only terminal. */)
2156 (terminal)
2157 Lisp_Object terminal;
2159 struct terminal *t = get_tty_terminal (terminal, 0);
2160 if (!t)
2161 return Qnil;
2162 else
2163 return t->display_info.tty->TN_max_colors > 0 ? Qt : Qnil;
2166 /* Return the number of supported colors. */
2167 DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
2168 Stty_display_color_cells, 0, 1, 0,
2169 doc: /* Return the number of colors supported by the tty device TERMINAL.
2171 TERMINAL can be a terminal object, a frame, or nil (meaning the
2172 selected frame's terminal). This function always returns 0 if
2173 TERMINAL does not refer to a text-only terminal. */)
2174 (terminal)
2175 Lisp_Object terminal;
2177 struct terminal *t = get_tty_terminal (terminal, 0);
2178 if (!t)
2179 return make_number (0);
2180 else
2181 return make_number (t->display_info.tty->TN_max_colors);
2184 #ifndef DOS_NT
2186 /* Declare here rather than in the function, as in the rest of Emacs,
2187 to work around an HPUX compiler bug (?). See
2188 http://lists.gnu.org/archive/html/emacs-devel/2007-08/msg00410.html */
2189 static int default_max_colors;
2190 static int default_max_pairs;
2191 static int default_no_color_video;
2192 static char *default_orig_pair;
2193 static char *default_set_foreground;
2194 static char *default_set_background;
2196 /* Save or restore the default color-related capabilities of this
2197 terminal. */
2198 static void
2199 tty_default_color_capabilities (struct tty_display_info *tty, int save)
2202 if (save)
2204 xfree (default_orig_pair);
2205 default_orig_pair = tty->TS_orig_pair ? xstrdup (tty->TS_orig_pair) : NULL;
2207 xfree (default_set_foreground);
2208 default_set_foreground = tty->TS_set_foreground ? xstrdup (tty->TS_set_foreground)
2209 : NULL;
2211 xfree (default_set_background);
2212 default_set_background = tty->TS_set_background ? xstrdup (tty->TS_set_background)
2213 : NULL;
2215 default_max_colors = tty->TN_max_colors;
2216 default_max_pairs = tty->TN_max_pairs;
2217 default_no_color_video = tty->TN_no_color_video;
2219 else
2221 tty->TS_orig_pair = default_orig_pair;
2222 tty->TS_set_foreground = default_set_foreground;
2223 tty->TS_set_background = default_set_background;
2224 tty->TN_max_colors = default_max_colors;
2225 tty->TN_max_pairs = default_max_pairs;
2226 tty->TN_no_color_video = default_no_color_video;
2230 /* Setup one of the standard tty color schemes according to MODE.
2231 MODE's value is generally the number of colors which we want to
2232 support; zero means set up for the default capabilities, the ones
2233 we saw at init_tty time; -1 means turn off color support. */
2234 static void
2235 tty_setup_colors (struct tty_display_info *tty, int mode)
2237 /* Canonicalize all negative values of MODE. */
2238 if (mode < -1)
2239 mode = -1;
2241 switch (mode)
2243 case -1: /* no colors at all */
2244 tty->TN_max_colors = 0;
2245 tty->TN_max_pairs = 0;
2246 tty->TN_no_color_video = 0;
2247 tty->TS_set_foreground = tty->TS_set_background = tty->TS_orig_pair = NULL;
2248 break;
2249 case 0: /* default colors, if any */
2250 default:
2251 tty_default_color_capabilities (tty, 0);
2252 break;
2253 case 8: /* 8 standard ANSI colors */
2254 tty->TS_orig_pair = "\033[0m";
2255 #ifdef TERMINFO
2256 tty->TS_set_foreground = "\033[3%p1%dm";
2257 tty->TS_set_background = "\033[4%p1%dm";
2258 #else
2259 tty->TS_set_foreground = "\033[3%dm";
2260 tty->TS_set_background = "\033[4%dm";
2261 #endif
2262 tty->TN_max_colors = 8;
2263 tty->TN_max_pairs = 64;
2264 tty->TN_no_color_video = 0;
2265 break;
2269 void
2270 set_tty_color_mode (tty, f)
2271 struct tty_display_info *tty;
2272 struct frame *f;
2274 Lisp_Object tem, val;
2275 Lisp_Object color_mode;
2276 int mode;
2277 extern Lisp_Object Qtty_color_mode;
2278 Lisp_Object tty_color_mode_alist
2279 = Fintern_soft (build_string ("tty-color-mode-alist"), Qnil);
2281 tem = assq_no_quit (Qtty_color_mode, f->param_alist);
2282 val = CONSP (tem) ? XCDR (tem) : Qnil;
2284 if (INTEGERP (val))
2285 color_mode = val;
2286 else if (SYMBOLP (tty_color_mode_alist))
2288 tem = Fassq (val, Fsymbol_value (tty_color_mode_alist));
2289 color_mode = CONSP (tem) ? XCDR (tem) : Qnil;
2291 else
2292 color_mode = Qnil;
2294 mode = INTEGERP (color_mode) ? XINT (color_mode) : 0;
2296 if (mode != tty->previous_color_mode)
2298 Lisp_Object funsym = intern ("tty-set-up-initial-frame-faces");
2299 tty->previous_color_mode = mode;
2300 tty_setup_colors (tty , mode);
2301 /* This recomputes all the faces given the new color definitions. */
2302 safe_call (1, &funsym);
2306 #endif /* !DOS_NT */
2310 /* Return the tty display object specified by TERMINAL. */
2312 struct terminal *
2313 get_tty_terminal (Lisp_Object terminal, int throw)
2315 struct terminal *t = get_terminal (terminal, throw);
2317 if (t && t->type != output_termcap && t->type != output_msdos_raw)
2319 if (throw)
2320 error ("Device %d is not a termcap terminal device", t->id);
2321 else
2322 return NULL;
2325 return t;
2328 /* Return an active termcap device that uses the tty device with the
2329 given name.
2331 This function ignores suspended devices.
2333 Returns NULL if the named terminal device is not opened. */
2335 struct terminal *
2336 get_named_tty (name)
2337 char *name;
2339 struct terminal *t;
2341 if (!name)
2342 abort ();
2344 for (t = terminal_list; t; t = t->next_terminal)
2346 if ((t->type == output_termcap || t->type == output_msdos_raw)
2347 && !strcmp (t->display_info.tty->name, name)
2348 && TERMINAL_ACTIVE_P (t))
2349 return t;
2352 return 0;
2356 DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0,
2357 doc: /* Return the type of the tty device that TERMINAL uses.
2358 Returns nil if TERMINAL is not on a tty device.
2360 TERMINAL can be a terminal object, a frame, or nil (meaning the
2361 selected frame's terminal). */)
2362 (terminal)
2363 Lisp_Object terminal;
2365 struct terminal *t = get_terminal (terminal, 1);
2367 if (t->type != output_termcap && t->type != output_msdos_raw)
2368 return Qnil;
2370 if (t->display_info.tty->type)
2371 return build_string (t->display_info.tty->type);
2372 else
2373 return Qnil;
2376 DEFUN ("controlling-tty-p", Fcontrolling_tty_p, Scontrolling_tty_p, 0, 1, 0,
2377 doc: /* Return non-nil if TERMINAL is the controlling tty of the Emacs process.
2379 TERMINAL can be a terminal object, a frame, or nil (meaning the
2380 selected frame's terminal). This function always returns nil if
2381 TERMINAL is not on a tty device. */)
2382 (terminal)
2383 Lisp_Object terminal;
2385 struct terminal *t = get_terminal (terminal, 1);
2387 if ((t->type != output_termcap && t->type != output_msdos_raw)
2388 || strcmp (t->display_info.tty->name, DEV_TTY) != 0)
2389 return Qnil;
2390 else
2391 return Qt;
2394 DEFUN ("tty-no-underline", Ftty_no_underline, Stty_no_underline, 0, 1, 0,
2395 doc: /* Declare that the tty used by TERMINAL does not handle underlining.
2396 This is used to override the terminfo data, for certain terminals that
2397 do not really do underlining, but say that they do. This function has
2398 no effect if used on a non-tty terminal.
2400 TERMINAL can be a terminal object, a frame or nil (meaning the
2401 selected frame's terminal). This function always returns nil if
2402 TERMINAL does not refer to a text-only terminal. */)
2403 (terminal)
2404 Lisp_Object terminal;
2406 struct terminal *t = get_terminal (terminal, 1);
2408 if (t->type == output_termcap)
2409 t->display_info.tty->TS_enter_underline_mode = 0;
2410 return Qnil;
2415 DEFUN ("suspend-tty", Fsuspend_tty, Ssuspend_tty, 0, 1, 0,
2416 doc: /* Suspend the terminal device TTY.
2418 The device is restored to its default state, and Emacs ceases all
2419 access to the tty device. Frames that use the device are not deleted,
2420 but input is not read from them and if they change, their display is
2421 not updated.
2423 TTY may be a terminal object, a frame, or nil for the terminal device
2424 of the currently selected frame.
2426 This function runs `suspend-tty-functions' after suspending the
2427 device. The functions are run with one arg, the id of the suspended
2428 terminal device.
2430 `suspend-tty' does nothing if it is called on a device that is already
2431 suspended.
2433 A suspended tty may be resumed by calling `resume-tty' on it. */)
2434 (tty)
2435 Lisp_Object tty;
2437 struct terminal *t = get_tty_terminal (tty, 1);
2438 FILE *f;
2440 if (!t)
2441 error ("Unknown tty device");
2443 f = t->display_info.tty->input;
2445 if (f)
2447 /* First run `suspend-tty-functions' and then clean up the tty
2448 state because `suspend-tty-functions' might need to change
2449 the tty state. */
2450 if (!NILP (Vrun_hooks))
2452 Lisp_Object args[2];
2453 args[0] = intern ("suspend-tty-functions");
2454 XSETTERMINAL (args[1], t);
2455 Frun_hook_with_args (2, args);
2458 reset_sys_modes (t->display_info.tty);
2460 #ifdef subprocesses
2461 delete_keyboard_wait_descriptor (fileno (f));
2462 #endif
2464 #ifndef MSDOS
2465 fclose (f);
2466 if (f != t->display_info.tty->output)
2467 fclose (t->display_info.tty->output);
2468 #endif
2470 t->display_info.tty->input = 0;
2471 t->display_info.tty->output = 0;
2473 if (FRAMEP (t->display_info.tty->top_frame))
2474 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0);
2478 /* Clear display hooks to prevent further output. */
2479 clear_tty_hooks (t);
2481 return Qnil;
2484 DEFUN ("resume-tty", Fresume_tty, Sresume_tty, 0, 1, 0,
2485 doc: /* Resume the previously suspended terminal device TTY.
2486 The terminal is opened and reinitialized. Frames that are on the
2487 suspended terminal are revived.
2489 It is an error to resume a terminal while another terminal is active
2490 on the same device.
2492 This function runs `resume-tty-functions' after resuming the terminal.
2493 The functions are run with one arg, the id of the resumed terminal
2494 device.
2496 `resume-tty' does nothing if it is called on a device that is not
2497 suspended.
2499 TTY may be a terminal object, a frame, or nil (meaning the selected
2500 frame's terminal). */)
2501 (tty)
2502 Lisp_Object tty;
2504 struct terminal *t = get_tty_terminal (tty, 1);
2505 int fd;
2507 if (!t)
2508 error ("Unknown tty device");
2510 if (!t->display_info.tty->input)
2512 if (get_named_tty (t->display_info.tty->name))
2513 error ("Cannot resume display while another display is active on the same device");
2515 #ifdef MSDOS
2516 t->display_info.tty->output = stdout;
2517 t->display_info.tty->input = stdin;
2518 #else /* !MSDOS */
2519 fd = emacs_open (t->display_info.tty->name, O_RDWR | O_NOCTTY, 0);
2521 if (fd == -1)
2522 error ("Can not reopen tty device %s: %s", t->display_info.tty->name, strerror (errno));
2524 if (strcmp (t->display_info.tty->name, DEV_TTY))
2525 dissociate_if_controlling_tty (fd);
2527 t->display_info.tty->output = fdopen (fd, "w+");
2528 t->display_info.tty->input = t->display_info.tty->output;
2529 #endif
2531 #ifdef subprocesses
2532 add_keyboard_wait_descriptor (fd);
2533 #endif
2535 if (FRAMEP (t->display_info.tty->top_frame))
2537 struct frame *f = XFRAME (t->display_info.tty->top_frame);
2538 int width, height;
2539 int old_height = FRAME_COLS (f);
2540 int old_width = FRAME_LINES (f);
2542 /* Check if terminal/window size has changed while the frame
2543 was suspended. */
2544 get_tty_size (fileno (t->display_info.tty->input), &width, &height);
2545 if (width != old_width || height != old_height)
2546 change_frame_size (f, height, width, 0, 0, 0);
2547 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
2550 init_sys_modes (t->display_info.tty);
2552 /* Run `resume-tty-functions'. */
2553 if (!NILP (Vrun_hooks))
2555 Lisp_Object args[2];
2556 args[0] = intern ("resume-tty-functions");
2557 XSETTERMINAL (args[1], t);
2558 Frun_hook_with_args (2, args);
2562 set_tty_hooks (t);
2564 return Qnil;
2568 /***********************************************************************
2569 Mouse
2570 ***********************************************************************/
2572 #ifdef HAVE_GPM
2573 void
2574 term_mouse_moveto (int x, int y)
2576 /* TODO: how to set mouse position?
2577 const char *name;
2578 int fd;
2579 name = (const char *) ttyname (0);
2580 fd = open (name, O_WRONLY);
2581 SOME_FUNCTION (x, y, fd);
2582 close (fd);
2583 last_mouse_x = x;
2584 last_mouse_y = y; */
2587 static void
2588 term_show_mouse_face (enum draw_glyphs_face draw)
2590 struct window *w = XWINDOW (mouse_face_window);
2591 int save_x, save_y;
2592 int i;
2594 struct frame *f = XFRAME (w->frame);
2595 struct tty_display_info *tty = FRAME_TTY (f);
2597 if (/* If window is in the process of being destroyed, don't bother
2598 to do anything. */
2599 w->current_matrix != NULL
2600 /* Recognize when we are called to operate on rows that don't exist
2601 anymore. This can happen when a window is split. */
2602 && mouse_face_end_row < w->current_matrix->nrows)
2604 /* write_glyphs writes at cursor position, so we need to
2605 temporarily move cursor coordinates to the beginning of
2606 the highlight region. */
2608 /* Save current cursor co-ordinates */
2609 save_y = curY (tty);
2610 save_x = curX (tty);
2612 /* Note that mouse_face_beg_row etc. are window relative. */
2613 for (i = mouse_face_beg_row; i <= mouse_face_end_row; i++)
2615 int start_hpos, end_hpos, nglyphs;
2616 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
2618 /* Don't do anything if row doesn't have valid contents. */
2619 if (!row->enabled_p)
2620 continue;
2622 /* For all but the first row, the highlight starts at column 0. */
2623 if (i == mouse_face_beg_row)
2624 start_hpos = mouse_face_beg_col;
2625 else
2626 start_hpos = 0;
2628 if (i == mouse_face_end_row)
2629 end_hpos = mouse_face_end_col;
2630 else
2632 end_hpos = row->used[TEXT_AREA];
2633 if (draw == DRAW_NORMAL_TEXT)
2634 row->fill_line_p = 1; /* Clear to end of line */
2637 if (end_hpos <= start_hpos)
2638 continue;
2639 /* Record that some glyphs of this row are displayed in
2640 mouse-face. */
2641 row->mouse_face_p = draw > 0;
2643 nglyphs = end_hpos - start_hpos;
2645 if (end_hpos >= row->used[TEXT_AREA])
2646 nglyphs = row->used[TEXT_AREA] - start_hpos;
2648 pos_y = row->y + WINDOW_TOP_EDGE_Y (w);
2649 pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos
2650 + WINDOW_LEFT_EDGE_X (w);
2652 cursor_to (f, pos_y, pos_x);
2654 if (draw == DRAW_MOUSE_FACE)
2656 tty_write_glyphs_with_face (f, row->glyphs[TEXT_AREA] + start_hpos,
2657 nglyphs, mouse_face_face_id);
2659 else /* draw == DRAW_NORMAL_TEXT */
2660 write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
2662 cursor_to (f, save_y, save_x);
2666 static void
2667 term_clear_mouse_face ()
2669 if (!NILP (mouse_face_window))
2670 term_show_mouse_face (DRAW_NORMAL_TEXT);
2672 mouse_face_beg_row = mouse_face_beg_col = -1;
2673 mouse_face_end_row = mouse_face_end_col = -1;
2674 mouse_face_window = Qnil;
2677 /* Find the glyph matrix position of buffer position POS in window W.
2678 *HPOS and *VPOS are set to the positions found. W's current glyphs
2679 must be up to date. If POS is above window start return (0, 0).
2680 If POS is after end of W, return end of last line in W.
2681 - taken from msdos.c */
2682 static int
2683 fast_find_position (struct window *w, int pos, int *hpos, int *vpos)
2685 int i, lastcol, line_start_position, maybe_next_line_p = 0;
2686 int yb = window_text_bottom_y (w);
2687 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0), *best_row = row;
2689 while (row->y < yb)
2691 if (row->used[TEXT_AREA])
2692 line_start_position = row->glyphs[TEXT_AREA]->charpos;
2693 else
2694 line_start_position = 0;
2696 if (line_start_position > pos)
2697 break;
2698 /* If the position sought is the end of the buffer,
2699 don't include the blank lines at the bottom of the window. */
2700 else if (line_start_position == pos
2701 && pos == BUF_ZV (XBUFFER (w->buffer)))
2703 maybe_next_line_p = 1;
2704 break;
2706 else if (line_start_position > 0)
2707 best_row = row;
2709 /* Don't overstep the last matrix row, lest we get into the
2710 never-never land... */
2711 if (row->y + 1 >= yb)
2712 break;
2714 ++row;
2717 /* Find the right column within BEST_ROW. */
2718 lastcol = 0;
2719 row = best_row;
2720 for (i = 0; i < row->used[TEXT_AREA]; i++)
2722 struct glyph *glyph = row->glyphs[TEXT_AREA] + i;
2723 int charpos;
2725 charpos = glyph->charpos;
2726 if (charpos == pos)
2728 *hpos = i;
2729 *vpos = row->y;
2730 return 1;
2732 else if (charpos > pos)
2733 break;
2734 else if (charpos > 0)
2735 lastcol = i;
2738 /* If we're looking for the end of the buffer,
2739 and we didn't find it in the line we scanned,
2740 use the start of the following line. */
2741 if (maybe_next_line_p)
2743 ++row;
2744 lastcol = 0;
2747 *vpos = row->y;
2748 *hpos = lastcol + 1;
2749 return 0;
2752 static void
2753 term_mouse_highlight (struct frame *f, int x, int y)
2755 enum window_part part;
2756 Lisp_Object window;
2757 struct window *w;
2758 struct buffer *b;
2760 if (NILP (Vmouse_highlight)
2761 || !f->glyphs_initialized_p)
2762 return;
2764 /* Which window is that in? */
2765 window = window_from_coordinates (f, x, y, &part, &x, &y, 0);
2767 /* Not on a window -> return. */
2768 if (!WINDOWP (window))
2769 return;
2771 if (!EQ (window, mouse_face_window))
2772 term_clear_mouse_face ();
2774 w = XWINDOW (window);
2776 /* Are we in a window whose display is up to date?
2777 And verify the buffer's text has not changed. */
2778 b = XBUFFER (w->buffer);
2779 if (part == ON_TEXT
2780 && EQ (w->window_end_valid, w->buffer)
2781 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
2782 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
2784 int pos, i, nrows = w->current_matrix->nrows;
2785 struct glyph_row *row;
2786 struct glyph *glyph;
2788 /* Find the glyph under X/Y. */
2789 glyph = NULL;
2790 if (y >= 0 && y < nrows)
2792 row = MATRIX_ROW (w->current_matrix, y);
2793 /* Give up if some row before the one we are looking for is
2794 not enabled. */
2795 for (i = 0; i <= y; i++)
2796 if (!MATRIX_ROW (w->current_matrix, i)->enabled_p)
2797 break;
2798 if (i > y /* all rows upto and including the one at Y are enabled */
2799 && row->displays_text_p
2800 && x < window_box_width (w, TEXT_AREA))
2802 glyph = row->glyphs[TEXT_AREA];
2803 if (x >= row->used[TEXT_AREA])
2804 glyph = NULL;
2805 else
2807 glyph += x;
2808 if (!BUFFERP (glyph->object))
2809 glyph = NULL;
2814 /* Clear mouse face if X/Y not over text. */
2815 if (glyph == NULL)
2817 term_clear_mouse_face ();
2818 return;
2821 if (!BUFFERP (glyph->object))
2822 abort ();
2823 pos = glyph->charpos;
2825 /* Check for mouse-face. */
2827 extern Lisp_Object Qmouse_face;
2828 Lisp_Object mouse_face, overlay, position, *overlay_vec;
2829 int noverlays, obegv, ozv;
2830 struct buffer *obuf;
2832 /* If we get an out-of-range value, return now; avoid an error. */
2833 if (pos > BUF_Z (b))
2834 return;
2836 /* Make the window's buffer temporarily current for
2837 overlays_at and compute_char_face. */
2838 obuf = current_buffer;
2839 current_buffer = b;
2840 obegv = BEGV;
2841 ozv = ZV;
2842 BEGV = BEG;
2843 ZV = Z;
2845 /* Is this char mouse-active? */
2846 XSETINT (position, pos);
2848 /* Put all the overlays we want in a vector in overlay_vec. */
2849 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL, 0);
2850 /* Sort overlays into increasing priority order. */
2851 noverlays = sort_overlays (overlay_vec, noverlays, w);
2853 /* Check mouse-face highlighting. */
2854 if (!(EQ (window, mouse_face_window)
2855 && y >= mouse_face_beg_row
2856 && y <= mouse_face_end_row
2857 && (y > mouse_face_beg_row
2858 || x >= mouse_face_beg_col)
2859 && (y < mouse_face_end_row
2860 || x < mouse_face_end_col
2861 || mouse_face_past_end)))
2863 /* Clear the display of the old active region, if any. */
2864 term_clear_mouse_face ();
2866 /* Find the highest priority overlay that has a mouse-face
2867 property. */
2868 overlay = Qnil;
2869 for (i = noverlays - 1; i >= 0; --i)
2871 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
2872 if (!NILP (mouse_face))
2874 overlay = overlay_vec[i];
2875 break;
2879 /* If no overlay applies, get a text property. */
2880 if (NILP (overlay))
2881 mouse_face = Fget_text_property (position, Qmouse_face,
2882 w->buffer);
2884 /* Handle the overlay case. */
2885 if (!NILP (overlay))
2887 /* Find the range of text around this char that
2888 should be active. */
2889 Lisp_Object before, after;
2890 EMACS_INT ignore;
2893 before = Foverlay_start (overlay);
2894 after = Foverlay_end (overlay);
2895 /* Record this as the current active region. */
2896 fast_find_position (w, XFASTINT (before),
2897 &mouse_face_beg_col,
2898 &mouse_face_beg_row);
2900 mouse_face_past_end
2901 = !fast_find_position (w, XFASTINT (after),
2902 &mouse_face_end_col,
2903 &mouse_face_end_row);
2904 mouse_face_window = window;
2906 mouse_face_face_id
2907 = face_at_buffer_position (w, pos, 0, 0,
2908 &ignore, pos + 1, 1, -1);
2910 /* Display it as active. */
2911 term_show_mouse_face (DRAW_MOUSE_FACE);
2913 /* Handle the text property case. */
2914 else if (!NILP (mouse_face))
2916 /* Find the range of text around this char that
2917 should be active. */
2918 Lisp_Object before, after, beginning, end;
2919 EMACS_INT ignore;
2921 beginning = Fmarker_position (w->start);
2922 XSETINT (end, (BUF_Z (b) - XFASTINT (w->window_end_pos)));
2923 before
2924 = Fprevious_single_property_change (make_number (pos + 1),
2925 Qmouse_face,
2926 w->buffer, beginning);
2927 after
2928 = Fnext_single_property_change (position, Qmouse_face,
2929 w->buffer, end);
2931 /* Record this as the current active region. */
2932 fast_find_position (w, XFASTINT (before),
2933 &mouse_face_beg_col,
2934 &mouse_face_beg_row);
2935 mouse_face_past_end
2936 = !fast_find_position (w, XFASTINT (after),
2937 &mouse_face_end_col,
2938 &mouse_face_end_row);
2939 mouse_face_window = window;
2941 mouse_face_face_id
2942 = face_at_buffer_position (w, pos, 0, 0,
2943 &ignore, pos + 1, 1, -1);
2945 /* Display it as active. */
2946 term_show_mouse_face (DRAW_MOUSE_FACE);
2950 /* Look for a `help-echo' property. */
2952 Lisp_Object help;
2953 extern Lisp_Object Qhelp_echo;
2955 /* Check overlays first. */
2956 help = Qnil;
2957 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
2959 overlay = overlay_vec[i];
2960 help = Foverlay_get (overlay, Qhelp_echo);
2963 if (!NILP (help))
2965 help_echo_string = help;
2966 help_echo_window = window;
2967 help_echo_object = overlay;
2968 help_echo_pos = pos;
2970 /* Try text properties. */
2971 else if (NILP (help)
2972 && ((STRINGP (glyph->object)
2973 && glyph->charpos >= 0
2974 && glyph->charpos < SCHARS (glyph->object))
2975 || (BUFFERP (glyph->object)
2976 && glyph->charpos >= BEGV
2977 && glyph->charpos < ZV)))
2979 help = Fget_text_property (make_number (glyph->charpos),
2980 Qhelp_echo, glyph->object);
2981 if (!NILP (help))
2983 help_echo_string = help;
2984 help_echo_window = window;
2985 help_echo_object = glyph->object;
2986 help_echo_pos = glyph->charpos;
2991 BEGV = obegv;
2992 ZV = ozv;
2993 current_buffer = obuf;
2998 static int
2999 term_mouse_movement (FRAME_PTR frame, Gpm_Event *event)
3001 /* Has the mouse moved off the glyph it was on at the last sighting? */
3002 if (event->x != last_mouse_x || event->y != last_mouse_y)
3004 frame->mouse_moved = 1;
3005 term_mouse_highlight (frame, event->x, event->y);
3006 /* Remember which glyph we're now on. */
3007 last_mouse_x = event->x;
3008 last_mouse_y = event->y;
3009 return 1;
3011 return 0;
3014 /* Return the current position of the mouse.
3016 Set *f to the frame the mouse is in, or zero if the mouse is in no
3017 Emacs frame. If it is set to zero, all the other arguments are
3018 garbage.
3020 Set *bar_window to Qnil, and *x and *y to the column and
3021 row of the character cell the mouse is over.
3023 Set *time to the time the mouse was at the returned position.
3025 This clears mouse_moved until the next motion
3026 event arrives. */
3027 static void
3028 term_mouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
3029 enum scroll_bar_part *part, Lisp_Object *x,
3030 Lisp_Object *y, unsigned long *time)
3032 struct timeval now;
3034 *fp = SELECTED_FRAME ();
3035 (*fp)->mouse_moved = 0;
3037 *bar_window = Qnil;
3038 *part = 0;
3040 XSETINT (*x, last_mouse_x);
3041 XSETINT (*y, last_mouse_y);
3042 gettimeofday(&now, 0);
3043 *time = (now.tv_sec * 1000) + (now.tv_usec / 1000);
3046 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3048 If the event is a button press, then note that we have grabbed
3049 the mouse. */
3051 static Lisp_Object
3052 term_mouse_click (struct input_event *result, Gpm_Event *event,
3053 struct frame *f)
3055 struct timeval now;
3056 int i, j;
3058 result->kind = GPM_CLICK_EVENT;
3059 for (i = 0, j = GPM_B_LEFT; i < 3; i++, j >>= 1 )
3061 if (event->buttons & j) {
3062 result->code = i; /* button number */
3063 break;
3066 gettimeofday(&now, 0);
3067 result->timestamp = (now.tv_sec * 1000) + (now.tv_usec / 1000);
3069 if (event->type & GPM_UP)
3070 result->modifiers = up_modifier;
3071 else if (event->type & GPM_DOWN)
3072 result->modifiers = down_modifier;
3073 else
3074 result->modifiers = 0;
3076 if (event->type & GPM_SINGLE)
3077 result->modifiers |= click_modifier;
3079 if (event->type & GPM_DOUBLE)
3080 result->modifiers |= double_modifier;
3082 if (event->type & GPM_TRIPLE)
3083 result->modifiers |= triple_modifier;
3085 if (event->type & GPM_DRAG)
3086 result->modifiers |= drag_modifier;
3088 if (!(event->type & (GPM_MOVE | GPM_DRAG))) {
3090 /* 1 << KG_SHIFT */
3091 if (event->modifiers & (1 << 0))
3092 result->modifiers |= shift_modifier;
3094 /* 1 << KG_CTRL */
3095 if (event->modifiers & (1 << 2))
3096 result->modifiers |= ctrl_modifier;
3098 /* 1 << KG_ALT || KG_ALTGR */
3099 if (event->modifiers & (1 << 3)
3100 || event->modifiers & (1 << 1))
3101 result->modifiers |= meta_modifier;
3104 XSETINT (result->x, event->x);
3105 XSETINT (result->y, event->y);
3106 XSETFRAME (result->frame_or_window, f);
3107 result->arg = Qnil;
3108 return Qnil;
3112 handle_one_term_event (struct tty_display_info *tty, Gpm_Event *event, struct input_event* hold_quit)
3114 struct frame *f = XFRAME (tty->top_frame);
3115 struct input_event ie;
3116 int do_help = 0;
3117 int count = 0;
3119 EVENT_INIT (ie);
3120 ie.kind = NO_EVENT;
3121 ie.arg = Qnil;
3123 if (event->type & (GPM_MOVE | GPM_DRAG)) {
3124 previous_help_echo_string = help_echo_string;
3125 help_echo_string = Qnil;
3127 Gpm_DrawPointer (event->x, event->y, fileno (tty->output));
3129 if (!term_mouse_movement (f, event))
3130 help_echo_string = previous_help_echo_string;
3132 /* If the contents of the global variable help_echo_string
3133 has changed, generate a HELP_EVENT. */
3134 if (!NILP (help_echo_string)
3135 || !NILP (previous_help_echo_string))
3136 do_help = 1;
3138 goto done;
3140 else {
3141 f->mouse_moved = 0;
3142 term_mouse_click (&ie, event, f);
3145 done:
3146 if (ie.kind != NO_EVENT)
3148 kbd_buffer_store_event_hold (&ie, hold_quit);
3149 count++;
3152 if (do_help
3153 && !(hold_quit && hold_quit->kind != NO_EVENT))
3155 Lisp_Object frame;
3157 if (f)
3158 XSETFRAME (frame, f);
3159 else
3160 frame = Qnil;
3162 gen_help_event (help_echo_string, frame, help_echo_window,
3163 help_echo_object, help_echo_pos);
3164 count++;
3167 return count;
3170 DEFUN ("gpm-mouse-start", Fgpm_mouse_start, Sgpm_mouse_start,
3171 0, 0, 0,
3172 doc: /* Open a connection to Gpm.
3173 Gpm-mouse can only be activated for one tty at a time. */)
3176 struct frame *f = SELECTED_FRAME ();
3177 struct tty_display_info *tty
3178 = ((f)->output_method == output_termcap
3179 ? (f)->terminal->display_info.tty : NULL);
3180 Gpm_Connect connection;
3182 if (!tty)
3183 error ("Gpm-mouse only works in the GNU/Linux console");
3184 if (gpm_tty == tty)
3185 return Qnil; /* Already activated, nothing to do. */
3186 if (gpm_tty)
3187 error ("Gpm-mouse can only be activated for one tty at a time");
3189 connection.eventMask = ~0;
3190 connection.defaultMask = ~GPM_HARD;
3191 connection.maxMod = ~0;
3192 connection.minMod = 0;
3193 gpm_zerobased = 1;
3195 if (Gpm_Open (&connection, 0) < 0)
3196 error ("Gpm-mouse failed to connect to the gpm daemon");
3197 else
3199 gpm_tty = tty;
3200 /* `init_sys_modes' arranges for mouse movements sent through gpm_fd
3201 to generate SIGIOs. Apparently we need to call reset_sys_modes
3202 before calling init_sys_modes. */
3203 reset_sys_modes (tty);
3204 init_sys_modes (tty);
3205 add_gpm_wait_descriptor (gpm_fd);
3206 return Qnil;
3210 void
3211 close_gpm (int fd)
3213 if (fd >= 0)
3214 delete_gpm_wait_descriptor (fd);
3215 while (Gpm_Close()); /* close all the stack */
3216 gpm_tty = NULL;
3219 DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop, Sgpm_mouse_stop,
3220 0, 0, 0,
3221 doc: /* Close a connection to Gpm. */)
3224 struct frame *f = SELECTED_FRAME ();
3225 struct tty_display_info *tty
3226 = ((f)->output_method == output_termcap
3227 ? (f)->terminal->display_info.tty : NULL);
3229 if (!tty || gpm_tty != tty)
3230 return Qnil; /* Not activated on this terminal, nothing to do. */
3232 close_gpm (gpm_fd);
3233 return Qnil;
3235 #endif /* HAVE_GPM */
3238 #ifndef MSDOS
3239 /***********************************************************************
3240 Initialization
3241 ***********************************************************************/
3243 /* Initialize the tty-dependent part of frame F. The frame must
3244 already have its device initialized. */
3246 void
3247 create_tty_output (struct frame *f)
3249 struct tty_output *t;
3251 if (! FRAME_TERMCAP_P (f))
3252 abort ();
3254 t = xmalloc (sizeof (struct tty_output));
3255 bzero (t, sizeof (struct tty_output));
3257 t->display_info = FRAME_TERMINAL (f)->display_info.tty;
3259 f->output_data.tty = t;
3262 /* Delete frame F's face cache, and its tty-dependent part. */
3264 static void
3265 tty_free_frame_resources (struct frame *f)
3267 if (! FRAME_TERMCAP_P (f))
3268 abort ();
3270 if (FRAME_FACE_CACHE (f))
3271 free_frame_faces (f);
3273 xfree (f->output_data.tty);
3276 #else /* MSDOS */
3278 /* Delete frame F's face cache. */
3280 static void
3281 tty_free_frame_resources (struct frame *f)
3283 if (! FRAME_TERMCAP_P (f) && ! FRAME_MSDOS_P (f))
3284 abort ();
3286 if (FRAME_FACE_CACHE (f))
3287 free_frame_faces (f);
3289 #endif /* MSDOS */
3291 /* Reset the hooks in TERMINAL. */
3293 static void
3294 clear_tty_hooks (struct terminal *terminal)
3296 terminal->rif = 0;
3297 terminal->cursor_to_hook = 0;
3298 terminal->raw_cursor_to_hook = 0;
3299 terminal->clear_to_end_hook = 0;
3300 terminal->clear_frame_hook = 0;
3301 terminal->clear_end_of_line_hook = 0;
3302 terminal->ins_del_lines_hook = 0;
3303 terminal->insert_glyphs_hook = 0;
3304 terminal->write_glyphs_hook = 0;
3305 terminal->delete_glyphs_hook = 0;
3306 terminal->ring_bell_hook = 0;
3307 terminal->reset_terminal_modes_hook = 0;
3308 terminal->set_terminal_modes_hook = 0;
3309 terminal->update_begin_hook = 0;
3310 terminal->update_end_hook = 0;
3311 terminal->set_terminal_window_hook = 0;
3312 terminal->mouse_position_hook = 0;
3313 terminal->frame_rehighlight_hook = 0;
3314 terminal->frame_raise_lower_hook = 0;
3315 terminal->fullscreen_hook = 0;
3316 terminal->set_vertical_scroll_bar_hook = 0;
3317 terminal->condemn_scroll_bars_hook = 0;
3318 terminal->redeem_scroll_bar_hook = 0;
3319 terminal->judge_scroll_bars_hook = 0;
3320 terminal->read_socket_hook = 0;
3321 terminal->frame_up_to_date_hook = 0;
3323 /* Leave these two set, or suspended frames are not deleted
3324 correctly. */
3325 terminal->delete_frame_hook = &tty_free_frame_resources;
3326 terminal->delete_terminal_hook = &delete_tty;
3329 /* Initialize hooks in TERMINAL with the values needed for a tty. */
3331 static void
3332 set_tty_hooks (struct terminal *terminal)
3334 terminal->rif = 0; /* ttys don't support window-based redisplay. */
3336 terminal->cursor_to_hook = &tty_cursor_to;
3337 terminal->raw_cursor_to_hook = &tty_raw_cursor_to;
3339 terminal->clear_to_end_hook = &tty_clear_to_end;
3340 terminal->clear_frame_hook = &tty_clear_frame;
3341 terminal->clear_end_of_line_hook = &tty_clear_end_of_line;
3343 terminal->ins_del_lines_hook = &tty_ins_del_lines;
3345 terminal->insert_glyphs_hook = &tty_insert_glyphs;
3346 terminal->write_glyphs_hook = &tty_write_glyphs;
3347 terminal->delete_glyphs_hook = &tty_delete_glyphs;
3349 terminal->ring_bell_hook = &tty_ring_bell;
3351 terminal->reset_terminal_modes_hook = &tty_reset_terminal_modes;
3352 terminal->set_terminal_modes_hook = &tty_set_terminal_modes;
3353 terminal->update_begin_hook = 0; /* Not needed. */
3354 terminal->update_end_hook = &tty_update_end;
3355 terminal->set_terminal_window_hook = &tty_set_terminal_window;
3357 terminal->mouse_position_hook = 0; /* Not needed. */
3358 terminal->frame_rehighlight_hook = 0; /* Not needed. */
3359 terminal->frame_raise_lower_hook = 0; /* Not needed. */
3361 terminal->set_vertical_scroll_bar_hook = 0; /* Not needed. */
3362 terminal->condemn_scroll_bars_hook = 0; /* Not needed. */
3363 terminal->redeem_scroll_bar_hook = 0; /* Not needed. */
3364 terminal->judge_scroll_bars_hook = 0; /* Not needed. */
3366 terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */
3367 terminal->frame_up_to_date_hook = 0; /* Not needed. */
3369 terminal->delete_frame_hook = &tty_free_frame_resources;
3370 terminal->delete_terminal_hook = &delete_tty;
3373 /* Drop the controlling terminal if fd is the same device. */
3374 static void
3375 dissociate_if_controlling_tty (int fd)
3377 #ifndef DOS_NT
3378 int pgid;
3379 EMACS_GET_TTY_PGRP (fd, &pgid); /* If tcgetpgrp succeeds, fd is the ctty. */
3380 if (pgid != -1)
3382 #if defined (USG)
3383 setpgrp ();
3384 no_controlling_tty = 1;
3385 #elif defined (CYGWIN)
3386 setsid ();
3387 no_controlling_tty = 1;
3388 #else
3389 #ifdef TIOCNOTTY /* Try BSD ioctls. */
3390 sigblock (sigmask (SIGTTOU));
3391 fd = emacs_open (DEV_TTY, O_RDWR, 0);
3392 if (fd != -1 && ioctl (fd, TIOCNOTTY, 0) != -1)
3394 no_controlling_tty = 1;
3396 if (fd != -1)
3397 emacs_close (fd);
3398 sigunblock (sigmask (SIGTTOU));
3399 #else
3400 /* Unknown system. */
3401 croak ();
3402 #endif /* ! TIOCNOTTY */
3403 #endif /* ! USG */
3405 #endif /* !DOS_NT */
3408 static void maybe_fatal();
3410 /* Create a termcap display on the tty device with the given name and
3411 type.
3413 If NAME is NULL, then use the controlling tty, i.e., "/dev/tty".
3414 Otherwise NAME should be a path to the tty device file,
3415 e.g. "/dev/pts/7".
3417 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
3419 If MUST_SUCCEED is true, then all errors are fatal. */
3421 struct terminal *
3422 init_tty (char *name, char *terminal_type, int must_succeed)
3424 char *area = NULL;
3425 char **address = &area;
3426 int buffer_size = 4096;
3427 register char *p = NULL;
3428 int status;
3429 struct tty_display_info *tty = NULL;
3430 struct terminal *terminal = NULL;
3431 int ctty = 0; /* 1 if asked to open controlling tty. */
3433 if (!terminal_type)
3434 maybe_fatal (must_succeed, 0,
3435 "Unknown terminal type",
3436 "Unknown terminal type");
3438 if (name == NULL)
3439 name = DEV_TTY;
3440 if (!strcmp (name, DEV_TTY))
3441 ctty = 1;
3443 /* If we already have a terminal on the given device, use that. If
3444 all such terminals are suspended, create a new one instead. */
3445 /* XXX Perhaps this should be made explicit by having init_tty
3446 always create a new terminal and separating terminal and frame
3447 creation on Lisp level. */
3448 terminal = get_named_tty (name);
3449 if (terminal)
3450 return terminal;
3452 terminal = create_terminal ();
3453 #ifdef MSDOS
3454 if (been_here > 0)
3455 maybe_fatal (1, 0, "Attempt to create another terminal %s", "",
3456 name, "");
3457 been_here = 1;
3458 tty = &the_only_display_info;
3459 #else
3460 tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info));
3461 #endif
3462 bzero (tty, sizeof (struct tty_display_info));
3463 tty->next = tty_list;
3464 tty_list = tty;
3466 terminal->type = output_termcap;
3467 terminal->display_info.tty = tty;
3468 tty->terminal = terminal;
3470 tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
3471 Wcm_clear (tty);
3473 #ifndef DOS_NT
3474 set_tty_hooks (terminal);
3477 int fd;
3478 FILE *file;
3480 #ifdef O_IGNORE_CTTY
3481 if (!ctty)
3482 /* Open the terminal device. Don't recognize it as our
3483 controlling terminal, and don't make it the controlling tty
3484 if we don't have one at the moment. */
3485 fd = emacs_open (name, O_RDWR | O_IGNORE_CTTY | O_NOCTTY, 0);
3486 else
3487 #else
3488 /* Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
3489 defined on Hurd. On other systems, we need to explicitly
3490 dissociate ourselves from the controlling tty when we want to
3491 open a frame on the same terminal. */
3492 fd = emacs_open (name, O_RDWR | O_NOCTTY, 0);
3493 #endif /* O_IGNORE_CTTY */
3495 tty->name = xstrdup (name);
3496 terminal->name = xstrdup (name);
3498 if (fd < 0)
3499 maybe_fatal (must_succeed, terminal,
3500 "Could not open file: %s",
3501 "Could not open file: %s",
3502 name);
3503 if (!isatty (fd))
3505 close (fd);
3506 maybe_fatal (must_succeed, terminal,
3507 "Not a tty device: %s",
3508 "Not a tty device: %s",
3509 name);
3512 #ifndef O_IGNORE_CTTY
3513 if (!ctty)
3514 dissociate_if_controlling_tty (fd);
3515 #endif
3517 file = fdopen (fd, "w+");
3518 tty->input = file;
3519 tty->output = file;
3522 tty->type = xstrdup (terminal_type);
3524 add_keyboard_wait_descriptor (fileno (tty->input));
3526 #endif /* !DOS_NT */
3528 encode_terminal_src_size = 0;
3529 encode_terminal_dst_size = 0;
3531 #ifdef HAVE_GPM
3532 terminal->mouse_position_hook = term_mouse_position;
3533 mouse_face_window = Qnil;
3534 #endif
3536 #ifdef DOS_NT
3537 #ifdef WINDOWSNT
3538 initialize_w32_display (terminal);
3539 #else /* MSDOS */
3540 if (strcmp (terminal_type, "internal") == 0)
3541 terminal->type = output_msdos_raw;
3542 initialize_msdos_display (terminal);
3543 #endif /* MSDOS */
3544 tty->output = stdout;
3545 tty->input = stdin;
3546 /* The following two are inaccessible from w32console.c. */
3547 terminal->delete_frame_hook = &tty_free_frame_resources;
3548 terminal->delete_terminal_hook = &delete_tty;
3550 tty->name = xstrdup (name);
3551 terminal->name = xstrdup (name);
3552 tty->type = xstrdup (terminal_type);
3554 #ifdef subprocesses
3555 add_keyboard_wait_descriptor (0);
3556 #endif
3558 Wcm_clear (tty);
3560 #ifdef WINDOWSNT
3562 struct frame *f = XFRAME (selected_frame);
3564 FrameRows (tty) = FRAME_LINES (f);
3565 FrameCols (tty) = FRAME_COLS (f);
3566 tty->specified_window = FRAME_LINES (f);
3568 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
3569 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
3571 #else /* MSDOS */
3573 int height, width;
3574 get_tty_size (fileno (tty->input), &width, &height);
3575 FrameCols (tty) = width;
3576 FrameRows (tty) = height;
3578 #endif /* MSDOS */
3579 tty->delete_in_insert_mode = 1;
3581 UseTabs (tty) = 0;
3582 terminal->scroll_region_ok = 0;
3584 /* Seems to insert lines when it's not supposed to, messing up the
3585 display. In doing a trace, it didn't seem to be called much, so I
3586 don't think we're losing anything by turning it off. */
3587 terminal->line_ins_del_ok = 0;
3588 #ifdef WINDOWSNT
3589 terminal->char_ins_del_ok = 1;
3590 baud_rate = 19200;
3591 #else /* MSDOS */
3592 terminal->char_ins_del_ok = 0;
3593 init_baud_rate (fileno (tty->input));
3594 #endif /* MSDOS */
3596 tty->TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
3598 #else /* not DOS_NT */
3600 Wcm_clear (tty);
3602 tty->termcap_term_buffer = (char *) xmalloc (buffer_size);
3604 /* On some systems, tgetent tries to access the controlling
3605 terminal. */
3606 sigblock (sigmask (SIGTTOU));
3607 status = tgetent (tty->termcap_term_buffer, terminal_type);
3608 sigunblock (sigmask (SIGTTOU));
3610 if (status < 0)
3612 #ifdef TERMINFO
3613 maybe_fatal (must_succeed, terminal,
3614 "Cannot open terminfo database file",
3615 "Cannot open terminfo database file");
3616 #else
3617 maybe_fatal (must_succeed, terminal,
3618 "Cannot open termcap database file",
3619 "Cannot open termcap database file");
3620 #endif
3622 if (status == 0)
3624 maybe_fatal (must_succeed, terminal,
3625 "Terminal type %s is not defined",
3626 "Terminal type %s is not defined.\n\
3627 If that is not the actual type of terminal you have,\n\
3628 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3629 `setenv TERM ...') to specify the correct type. It may be necessary\n"
3630 #ifdef TERMINFO
3631 "to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3632 #else
3633 "to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3634 #endif
3635 terminal_type);
3638 #ifndef TERMINFO
3639 if (strlen (tty->termcap_term_buffer) >= buffer_size)
3640 abort ();
3641 buffer_size = strlen (tty->termcap_term_buffer);
3642 #endif
3643 tty->termcap_strings_buffer = area = (char *) xmalloc (buffer_size);
3644 tty->TS_ins_line = tgetstr ("al", address);
3645 tty->TS_ins_multi_lines = tgetstr ("AL", address);
3646 tty->TS_bell = tgetstr ("bl", address);
3647 BackTab (tty) = tgetstr ("bt", address);
3648 tty->TS_clr_to_bottom = tgetstr ("cd", address);
3649 tty->TS_clr_line = tgetstr ("ce", address);
3650 tty->TS_clr_frame = tgetstr ("cl", address);
3651 ColPosition (tty) = NULL; /* tgetstr ("ch", address); */
3652 AbsPosition (tty) = tgetstr ("cm", address);
3653 CR (tty) = tgetstr ("cr", address);
3654 tty->TS_set_scroll_region = tgetstr ("cs", address);
3655 tty->TS_set_scroll_region_1 = tgetstr ("cS", address);
3656 RowPosition (tty) = tgetstr ("cv", address);
3657 tty->TS_del_char = tgetstr ("dc", address);
3658 tty->TS_del_multi_chars = tgetstr ("DC", address);
3659 tty->TS_del_line = tgetstr ("dl", address);
3660 tty->TS_del_multi_lines = tgetstr ("DL", address);
3661 tty->TS_delete_mode = tgetstr ("dm", address);
3662 tty->TS_end_delete_mode = tgetstr ("ed", address);
3663 tty->TS_end_insert_mode = tgetstr ("ei", address);
3664 Home (tty) = tgetstr ("ho", address);
3665 tty->TS_ins_char = tgetstr ("ic", address);
3666 tty->TS_ins_multi_chars = tgetstr ("IC", address);
3667 tty->TS_insert_mode = tgetstr ("im", address);
3668 tty->TS_pad_inserted_char = tgetstr ("ip", address);
3669 tty->TS_end_keypad_mode = tgetstr ("ke", address);
3670 tty->TS_keypad_mode = tgetstr ("ks", address);
3671 LastLine (tty) = tgetstr ("ll", address);
3672 Right (tty) = tgetstr ("nd", address);
3673 Down (tty) = tgetstr ("do", address);
3674 if (!Down (tty))
3675 Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do" */
3676 if (tgetflag ("bs"))
3677 Left (tty) = "\b"; /* can't possibly be longer! */
3678 else /* (Actually, "bs" is obsolete...) */
3679 Left (tty) = tgetstr ("le", address);
3680 if (!Left (tty))
3681 Left (tty) = tgetstr ("bc", address); /* Obsolete name for "le" */
3682 tty->TS_pad_char = tgetstr ("pc", address);
3683 tty->TS_repeat = tgetstr ("rp", address);
3684 tty->TS_end_standout_mode = tgetstr ("se", address);
3685 tty->TS_fwd_scroll = tgetstr ("sf", address);
3686 tty->TS_standout_mode = tgetstr ("so", address);
3687 tty->TS_rev_scroll = tgetstr ("sr", address);
3688 tty->Wcm->cm_tab = tgetstr ("ta", address);
3689 tty->TS_end_termcap_modes = tgetstr ("te", address);
3690 tty->TS_termcap_modes = tgetstr ("ti", address);
3691 Up (tty) = tgetstr ("up", address);
3692 tty->TS_visible_bell = tgetstr ("vb", address);
3693 tty->TS_cursor_normal = tgetstr ("ve", address);
3694 tty->TS_cursor_visible = tgetstr ("vs", address);
3695 tty->TS_cursor_invisible = tgetstr ("vi", address);
3696 tty->TS_set_window = tgetstr ("wi", address);
3698 tty->TS_enter_underline_mode = tgetstr ("us", address);
3699 tty->TS_exit_underline_mode = tgetstr ("ue", address);
3700 tty->TS_enter_bold_mode = tgetstr ("md", address);
3701 tty->TS_enter_dim_mode = tgetstr ("mh", address);
3702 tty->TS_enter_blink_mode = tgetstr ("mb", address);
3703 tty->TS_enter_reverse_mode = tgetstr ("mr", address);
3704 tty->TS_enter_alt_charset_mode = tgetstr ("as", address);
3705 tty->TS_exit_alt_charset_mode = tgetstr ("ae", address);
3706 tty->TS_exit_attribute_mode = tgetstr ("me", address);
3708 MultiUp (tty) = tgetstr ("UP", address);
3709 MultiDown (tty) = tgetstr ("DO", address);
3710 MultiLeft (tty) = tgetstr ("LE", address);
3711 MultiRight (tty) = tgetstr ("RI", address);
3713 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
3714 color because we can't switch back to the default foreground and
3715 background. */
3716 tty->TS_orig_pair = tgetstr ("op", address);
3717 if (tty->TS_orig_pair)
3719 tty->TS_set_foreground = tgetstr ("AF", address);
3720 tty->TS_set_background = tgetstr ("AB", address);
3721 if (!tty->TS_set_foreground)
3723 /* SVr4. */
3724 tty->TS_set_foreground = tgetstr ("Sf", address);
3725 tty->TS_set_background = tgetstr ("Sb", address);
3728 tty->TN_max_colors = tgetnum ("Co");
3729 tty->TN_max_pairs = tgetnum ("pa");
3731 tty->TN_no_color_video = tgetnum ("NC");
3732 if (tty->TN_no_color_video == -1)
3733 tty->TN_no_color_video = 0;
3736 tty_default_color_capabilities (tty, 1);
3738 MagicWrap (tty) = tgetflag ("xn");
3739 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
3740 the former flag imply the latter. */
3741 AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
3742 terminal->memory_below_frame = tgetflag ("db");
3743 tty->TF_hazeltine = tgetflag ("hz");
3744 terminal->must_write_spaces = tgetflag ("in");
3745 tty->meta_key = tgetflag ("km") || tgetflag ("MT");
3746 tty->TF_insmode_motion = tgetflag ("mi");
3747 tty->TF_standout_motion = tgetflag ("ms");
3748 tty->TF_underscore = tgetflag ("ul");
3749 tty->TF_teleray = tgetflag ("xt");
3751 #endif /* !DOS_NT */
3752 terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
3753 init_kboard (terminal->kboard);
3754 terminal->kboard->Vwindow_system = Qnil;
3755 terminal->kboard->next_kboard = all_kboards;
3756 all_kboards = terminal->kboard;
3757 terminal->kboard->reference_count++;
3758 /* Don't let the initial kboard remain current longer than necessary.
3759 That would cause problems if a file loaded on startup tries to
3760 prompt in the mini-buffer. */
3761 if (current_kboard == initial_kboard)
3762 current_kboard = terminal->kboard;
3763 #ifndef DOS_NT
3764 term_get_fkeys (address, terminal->kboard);
3766 /* Get frame size from system, or else from termcap. */
3768 int height, width;
3769 get_tty_size (fileno (tty->input), &width, &height);
3770 FrameCols (tty) = width;
3771 FrameRows (tty) = height;
3774 if (FrameCols (tty) <= 0)
3775 FrameCols (tty) = tgetnum ("co");
3776 if (FrameRows (tty) <= 0)
3777 FrameRows (tty) = tgetnum ("li");
3779 if (FrameRows (tty) < 3 || FrameCols (tty) < 3)
3780 maybe_fatal (must_succeed, terminal,
3781 "Screen size %dx%d is too small"
3782 "Screen size %dx%d is too small",
3783 FrameCols (tty), FrameRows (tty));
3785 TabWidth (tty) = tgetnum ("tw");
3787 if (!tty->TS_bell)
3788 tty->TS_bell = "\07";
3790 if (!tty->TS_fwd_scroll)
3791 tty->TS_fwd_scroll = Down (tty);
3793 PC = tty->TS_pad_char ? *tty->TS_pad_char : 0;
3795 if (TabWidth (tty) < 0)
3796 TabWidth (tty) = 8;
3798 /* Turned off since /etc/termcap seems to have :ta= for most terminals
3799 and newer termcap doc does not seem to say there is a default.
3800 if (!tty->Wcm->cm_tab)
3801 tty->Wcm->cm_tab = "\t";
3804 /* We don't support standout modes that use `magic cookies', so
3805 turn off any that do. */
3806 if (tty->TS_standout_mode && tgetnum ("sg") >= 0)
3808 tty->TS_standout_mode = 0;
3809 tty->TS_end_standout_mode = 0;
3811 if (tty->TS_enter_underline_mode && tgetnum ("ug") >= 0)
3813 tty->TS_enter_underline_mode = 0;
3814 tty->TS_exit_underline_mode = 0;
3817 /* If there's no standout mode, try to use underlining instead. */
3818 if (tty->TS_standout_mode == 0)
3820 tty->TS_standout_mode = tty->TS_enter_underline_mode;
3821 tty->TS_end_standout_mode = tty->TS_exit_underline_mode;
3824 /* If no `se' string, try using a `me' string instead.
3825 If that fails, we can't use standout mode at all. */
3826 if (tty->TS_end_standout_mode == 0)
3828 char *s = tgetstr ("me", address);
3829 if (s != 0)
3830 tty->TS_end_standout_mode = s;
3831 else
3832 tty->TS_standout_mode = 0;
3835 if (tty->TF_teleray)
3837 tty->Wcm->cm_tab = 0;
3838 /* We can't support standout mode, because it uses magic cookies. */
3839 tty->TS_standout_mode = 0;
3840 /* But that means we cannot rely on ^M to go to column zero! */
3841 CR (tty) = 0;
3842 /* LF can't be trusted either -- can alter hpos */
3843 /* if move at column 0 thru a line with TS_standout_mode */
3844 Down (tty) = 0;
3847 /* Special handling for certain terminal types known to need it */
3849 if (!strcmp (terminal_type, "supdup"))
3851 terminal->memory_below_frame = 1;
3852 tty->Wcm->cm_losewrap = 1;
3854 if (!strncmp (terminal_type, "c10", 3)
3855 || !strcmp (terminal_type, "perq"))
3857 /* Supply a makeshift :wi string.
3858 This string is not valid in general since it works only
3859 for windows starting at the upper left corner;
3860 but that is all Emacs uses.
3862 This string works only if the frame is using
3863 the top of the video memory, because addressing is memory-relative.
3864 So first check the :ti string to see if that is true.
3866 It would be simpler if the :wi string could go in the termcap
3867 entry, but it can't because it is not fully valid.
3868 If it were in the termcap entry, it would confuse other programs. */
3869 if (!tty->TS_set_window)
3871 p = tty->TS_termcap_modes;
3872 while (*p && strcmp (p, "\033v "))
3873 p++;
3874 if (*p)
3875 tty->TS_set_window = "\033v%C %C %C %C ";
3877 /* Termcap entry often fails to have :in: flag */
3878 terminal->must_write_spaces = 1;
3879 /* :ti string typically fails to have \E^G! in it */
3880 /* This limits scope of insert-char to one line. */
3881 strcpy (area, tty->TS_termcap_modes);
3882 strcat (area, "\033\007!");
3883 tty->TS_termcap_modes = area;
3884 area += strlen (area) + 1;
3885 p = AbsPosition (tty);
3886 /* Change all %+ parameters to %C, to handle
3887 values above 96 correctly for the C100. */
3888 while (*p)
3890 if (p[0] == '%' && p[1] == '+')
3891 p[1] = 'C';
3892 p++;
3896 tty->specified_window = FrameRows (tty);
3898 if (Wcm_init (tty) == -1) /* can't do cursor motion */
3900 maybe_fatal (must_succeed, terminal,
3901 "Terminal type \"%s\" is not powerful enough to run Emacs",
3902 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3903 It lacks the ability to position the cursor.\n\
3904 If that is not the actual type of terminal you have,\n\
3905 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3906 `setenv TERM ...') to specify the correct type. It may be necessary\n"
3907 # ifdef TERMINFO
3908 "to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3909 # else /* TERMCAP */
3910 "to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3911 # endif /* TERMINFO */
3912 terminal_type);
3915 if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
3916 maybe_fatal (must_succeed, terminal,
3917 "Could not determine the frame size",
3918 "Could not determine the frame size");
3920 tty->delete_in_insert_mode
3921 = tty->TS_delete_mode && tty->TS_insert_mode
3922 && !strcmp (tty->TS_delete_mode, tty->TS_insert_mode);
3924 tty->se_is_so = (tty->TS_standout_mode
3925 && tty->TS_end_standout_mode
3926 && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode));
3928 UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8;
3930 terminal->scroll_region_ok
3931 = (tty->Wcm->cm_abs
3932 && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
3934 terminal->line_ins_del_ok
3935 = (((tty->TS_ins_line || tty->TS_ins_multi_lines)
3936 && (tty->TS_del_line || tty->TS_del_multi_lines))
3937 || (terminal->scroll_region_ok
3938 && tty->TS_fwd_scroll && tty->TS_rev_scroll));
3940 terminal->char_ins_del_ok
3941 = ((tty->TS_ins_char || tty->TS_insert_mode
3942 || tty->TS_pad_inserted_char || tty->TS_ins_multi_chars)
3943 && (tty->TS_del_char || tty->TS_del_multi_chars));
3945 terminal->fast_clear_end_of_line = tty->TS_clr_line != 0;
3947 init_baud_rate (fileno (tty->input));
3949 #endif /* not DOS_NT */
3951 /* Init system terminal modes (RAW or CBREAK, etc.). */
3952 init_sys_modes (tty);
3954 return terminal;
3957 /* Auxiliary error-handling function for init_tty.
3958 Delete TERMINAL, then call error or fatal with str1 or str2,
3959 respectively, according to MUST_SUCCEED. */
3961 static void
3962 maybe_fatal (must_succeed, terminal, str1, str2, arg1, arg2)
3963 int must_succeed;
3964 struct terminal *terminal;
3965 char *str1, *str2, *arg1, *arg2;
3967 if (terminal)
3968 delete_tty (terminal);
3970 if (must_succeed)
3971 fatal (str2, arg1, arg2);
3972 else
3973 error (str1, arg1, arg2);
3975 abort ();
3978 void
3979 fatal (const char *str, ...)
3981 va_list ap;
3982 va_start (ap, str);
3983 fprintf (stderr, "emacs: ");
3984 vfprintf (stderr, str, ap);
3985 if (!(strlen (str) > 0 && str[strlen (str) - 1] == '\n'))
3986 fprintf (stderr, "\n");
3987 va_end (ap);
3988 fflush (stderr);
3989 exit (1);
3994 /* Delete the given tty terminal, closing all frames on it. */
3996 static void
3997 delete_tty (struct terminal *terminal)
3999 struct tty_display_info *tty;
4001 /* Protect against recursive calls. delete_frame in
4002 delete_terminal calls us back when it deletes our last frame. */
4003 if (!terminal->name)
4004 return;
4006 if (terminal->type != output_termcap)
4007 abort ();
4009 tty = terminal->display_info.tty;
4011 if (tty == tty_list)
4012 tty_list = tty->next;
4013 else
4015 struct tty_display_info *p;
4016 for (p = tty_list; p && p->next != tty; p = p->next)
4019 if (! p)
4020 /* This should not happen. */
4021 abort ();
4023 p->next = tty->next;
4024 tty->next = 0;
4027 /* reset_sys_modes needs a valid device, so this call needs to be
4028 before delete_terminal. */
4029 reset_sys_modes (tty);
4031 delete_terminal (terminal);
4033 xfree (tty->name);
4034 xfree (tty->type);
4036 if (tty->input)
4038 #ifdef subprocesses
4039 delete_keyboard_wait_descriptor (fileno (tty->input));
4040 #endif
4041 if (tty->input != stdin)
4042 fclose (tty->input);
4044 if (tty->output && tty->output != stdout && tty->output != tty->input)
4045 fclose (tty->output);
4046 if (tty->termscript)
4047 fclose (tty->termscript);
4049 xfree (tty->old_tty);
4050 xfree (tty->Wcm);
4051 xfree (tty->termcap_strings_buffer);
4052 xfree (tty->termcap_term_buffer);
4054 bzero (tty, sizeof (struct tty_display_info));
4055 xfree (tty);
4060 /* Mark the pointers in the tty_display_info objects.
4061 Called by the Fgarbage_collector. */
4063 void
4064 mark_ttys (void)
4066 struct tty_display_info *tty;
4068 for (tty = tty_list; tty; tty = tty->next)
4069 mark_object (tty->top_frame);
4074 void
4075 syms_of_term ()
4077 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
4078 doc: /* Non-nil means the system uses terminfo rather than termcap.
4079 This variable can be used by terminal emulator packages. */);
4080 #ifdef TERMINFO
4081 system_uses_terminfo = 1;
4082 #else
4083 system_uses_terminfo = 0;
4084 #endif
4086 DEFVAR_LISP ("suspend-tty-functions", &Vsuspend_tty_functions,
4087 doc: /* Functions to be run after suspending a tty.
4088 The functions are run with one argument, the terminal object to be suspended.
4089 See `suspend-tty'. */);
4090 Vsuspend_tty_functions = Qnil;
4093 DEFVAR_LISP ("resume-tty-functions", &Vresume_tty_functions,
4094 doc: /* Functions to be run after resuming a tty.
4095 The functions are run with one argument, the terminal object that was revived.
4096 See `resume-tty'. */);
4097 Vresume_tty_functions = Qnil;
4099 DEFVAR_BOOL ("visible-cursor", &visible_cursor,
4100 doc: /* Non-nil means to make the cursor very visible.
4101 This only has an effect when running in a text terminal.
4102 What means \"very visible\" is up to your terminal. It may make the cursor
4103 bigger, or it may make it blink, or it may do nothing at all. */);
4104 visible_cursor = 1;
4106 defsubr (&Stty_display_color_p);
4107 defsubr (&Stty_display_color_cells);
4108 defsubr (&Stty_no_underline);
4109 defsubr (&Stty_type);
4110 defsubr (&Scontrolling_tty_p);
4111 defsubr (&Ssuspend_tty);
4112 defsubr (&Sresume_tty);
4113 #ifdef HAVE_GPM
4114 defsubr (&Sgpm_mouse_start);
4115 defsubr (&Sgpm_mouse_stop);
4117 staticpro (&mouse_face_window);
4118 #endif /* HAVE_GPM */
4120 #ifndef DOS_NT
4121 default_orig_pair = NULL;
4122 default_set_foreground = NULL;
4123 default_set_background = NULL;
4124 #endif /* !DOS_NT */
4126 encode_terminal_src = NULL;
4127 encode_terminal_dst = NULL;
4132 /* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193
4133 (do not change this comment) */