term.c (encode_terminal_code): Encode byte chars to the correspnding bytes.
[emacs.git] / src / term.c
blob868b596dc1a0f4abcf488b582ed117ef4d4b8fd8
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. */
70 #if defined HAVE_TERMCAP_H && 0
71 #include <termcap.h>
72 #else
73 extern void tputs P_ ((const char *, int, int (*)(int)));
74 extern int tgetent P_ ((char *, const char *));
75 extern int tgetflag P_ ((char *id));
76 extern int tgetnum P_ ((char *id));
77 #endif
79 #include "cm.h"
80 #ifdef HAVE_X_WINDOWS
81 #include "xterm.h"
82 #endif
84 #ifndef O_RDWR
85 #define O_RDWR 2
86 #endif
88 #ifndef O_NOCTTY
89 #define O_NOCTTY 0
90 #endif
92 /* The name of the default console device. */
93 #ifdef WINDOWSNT
94 #define DEV_TTY "CONOUT$"
95 #else
96 #define DEV_TTY "/dev/tty"
97 #endif
99 static void tty_set_scroll_region P_ ((struct frame *f, int start, int stop));
100 static void turn_on_face P_ ((struct frame *, int face_id));
101 static void turn_off_face P_ ((struct frame *, int face_id));
102 static void tty_show_cursor P_ ((struct tty_display_info *));
103 static void tty_hide_cursor P_ ((struct tty_display_info *));
104 static void tty_background_highlight P_ ((struct tty_display_info *tty));
105 static void clear_tty_hooks P_ ((struct terminal *terminal));
106 static void set_tty_hooks P_ ((struct terminal *terminal));
107 static void dissociate_if_controlling_tty P_ ((int fd));
108 static void delete_tty P_ ((struct terminal *));
110 #define OUTPUT(tty, a) \
111 emacs_tputs ((tty), a, \
112 (int) (FRAME_LINES (XFRAME (selected_frame)) \
113 - curY (tty)), \
114 cmputc)
116 #define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
117 #define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
119 #define OUTPUT_IF(tty, a) \
120 do { \
121 if (a) \
122 emacs_tputs ((tty), a, \
123 (int) (FRAME_LINES (XFRAME (selected_frame)) \
124 - curY (tty) ), \
125 cmputc); \
126 } while (0)
128 #define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
130 /* If true, use "vs", otherwise use "ve" to make the cursor visible. */
132 static int visible_cursor;
134 /* Display space properties */
136 extern Lisp_Object Qspace, QCalign_to, QCwidth;
138 /* Functions to call after suspending a tty. */
139 Lisp_Object Vsuspend_tty_functions;
141 /* Functions to call after resuming a tty. */
142 Lisp_Object Vresume_tty_functions;
144 /* Chain of all tty device parameters. */
145 struct tty_display_info *tty_list;
147 /* Nonzero means no need to redraw the entire frame on resuming a
148 suspended Emacs. This is useful on terminals with multiple
149 pages, where one page is used for Emacs and another for all
150 else. */
151 int no_redraw_on_reenter;
153 /* Meaning of bits in no_color_video. Each bit set means that the
154 corresponding attribute cannot be combined with colors. */
156 enum no_color_bit
158 NC_STANDOUT = 1 << 0,
159 NC_UNDERLINE = 1 << 1,
160 NC_REVERSE = 1 << 2,
161 NC_BLINK = 1 << 3,
162 NC_DIM = 1 << 4,
163 NC_BOLD = 1 << 5,
164 NC_INVIS = 1 << 6,
165 NC_PROTECT = 1 << 7,
166 NC_ALT_CHARSET = 1 << 8
169 /* internal state */
171 /* The largest frame width in any call to calculate_costs. */
173 int max_frame_cols;
175 /* The largest frame height in any call to calculate_costs. */
177 int max_frame_lines;
179 /* Non-zero if we have dropped our controlling tty and therefore
180 should not open a frame on stdout. */
181 static int no_controlling_tty;
183 /* Provided for lisp packages. */
185 static int system_uses_terminfo;
187 char *tparam ();
189 extern char *tgetstr ();
192 #ifdef HAVE_GPM
193 #include <sys/fcntl.h>
195 static void term_clear_mouse_face ();
196 static void term_mouse_highlight (struct frame *f, int x, int y);
198 /* The device for which we have enabled gpm support (or NULL). */
199 struct tty_display_info *gpm_tty = NULL;
201 /* These variables describe the range of text currently shown in its
202 mouse-face, together with the window they apply to. As long as
203 the mouse stays within this range, we need not redraw anything on
204 its account. Rows and columns are glyph matrix positions in
205 MOUSE_FACE_WINDOW. */
206 static int mouse_face_beg_row, mouse_face_beg_col;
207 static int mouse_face_end_row, mouse_face_end_col;
208 static int mouse_face_past_end;
209 static Lisp_Object mouse_face_window;
210 static int mouse_face_face_id;
212 static int pos_x, pos_y;
213 static int last_mouse_x, last_mouse_y;
214 #endif /* HAVE_GPM */
216 /* Ring the bell on a tty. */
218 static void
219 tty_ring_bell (struct frame *f)
221 struct tty_display_info *tty = FRAME_TTY (f);
223 if (tty->output)
225 OUTPUT (tty, (tty->TS_visible_bell && visible_bell
226 ? tty->TS_visible_bell
227 : tty->TS_bell));
228 fflush (tty->output);
232 /* Set up termcap modes for Emacs. */
234 void
235 tty_set_terminal_modes (struct terminal *terminal)
237 struct tty_display_info *tty = terminal->display_info.tty;
239 if (tty->output)
241 if (tty->TS_termcap_modes)
242 OUTPUT (tty, tty->TS_termcap_modes);
243 else
245 /* Output enough newlines to scroll all the old screen contents
246 off the screen, so it won't be overwritten and lost. */
247 int i;
248 current_tty = tty;
249 for (i = 0; i < FRAME_LINES (XFRAME (selected_frame)); i++)
250 cmputc ('\n');
253 OUTPUT_IF (tty, tty->TS_termcap_modes);
254 OUTPUT_IF (tty, visible_cursor ? tty->TS_cursor_visible : tty->TS_cursor_normal);
255 OUTPUT_IF (tty, tty->TS_keypad_mode);
256 losecursor (tty);
257 fflush (tty->output);
261 /* Reset termcap modes before exiting Emacs. */
263 void
264 tty_reset_terminal_modes (struct terminal *terminal)
266 struct tty_display_info *tty = terminal->display_info.tty;
268 if (tty->output)
270 tty_turn_off_highlight (tty);
271 tty_turn_off_insert (tty);
272 OUTPUT_IF (tty, tty->TS_end_keypad_mode);
273 OUTPUT_IF (tty, tty->TS_cursor_normal);
274 OUTPUT_IF (tty, tty->TS_end_termcap_modes);
275 OUTPUT_IF (tty, tty->TS_orig_pair);
276 /* Output raw CR so kernel can track the cursor hpos. */
277 current_tty = tty;
278 cmputc ('\r');
279 fflush (tty->output);
283 /* Flag the end of a display update on a termcap terminal. */
285 static void
286 tty_update_end (struct frame *f)
288 struct tty_display_info *tty = FRAME_TTY (f);
290 if (!XWINDOW (selected_window)->cursor_off_p)
291 tty_show_cursor (tty);
292 tty_turn_off_insert (tty);
293 tty_background_highlight (tty);
296 /* The implementation of set_terminal_window for termcap frames. */
298 static void
299 tty_set_terminal_window (struct frame *f, int size)
301 struct tty_display_info *tty = FRAME_TTY (f);
303 tty->specified_window = size ? size : FRAME_LINES (f);
304 if (FRAME_SCROLL_REGION_OK (f))
305 tty_set_scroll_region (f, 0, tty->specified_window);
308 static void
309 tty_set_scroll_region (struct frame *f, int start, int stop)
311 char *buf;
312 struct tty_display_info *tty = FRAME_TTY (f);
314 if (tty->TS_set_scroll_region)
315 buf = tparam (tty->TS_set_scroll_region, 0, 0, start, stop - 1);
316 else if (tty->TS_set_scroll_region_1)
317 buf = tparam (tty->TS_set_scroll_region_1, 0, 0,
318 FRAME_LINES (f), start,
319 FRAME_LINES (f) - stop,
320 FRAME_LINES (f));
321 else
322 buf = tparam (tty->TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (f));
324 OUTPUT (tty, buf);
325 xfree (buf);
326 losecursor (tty);
330 static void
331 tty_turn_on_insert (struct tty_display_info *tty)
333 if (!tty->insert_mode)
334 OUTPUT (tty, tty->TS_insert_mode);
335 tty->insert_mode = 1;
338 void
339 tty_turn_off_insert (struct tty_display_info *tty)
341 if (tty->insert_mode)
342 OUTPUT (tty, tty->TS_end_insert_mode);
343 tty->insert_mode = 0;
346 /* Handle highlighting. */
348 void
349 tty_turn_off_highlight (struct tty_display_info *tty)
351 if (tty->standout_mode)
352 OUTPUT_IF (tty, tty->TS_end_standout_mode);
353 tty->standout_mode = 0;
356 static void
357 tty_turn_on_highlight (struct tty_display_info *tty)
359 if (!tty->standout_mode)
360 OUTPUT_IF (tty, tty->TS_standout_mode);
361 tty->standout_mode = 1;
364 static void
365 tty_toggle_highlight (struct tty_display_info *tty)
367 if (tty->standout_mode)
368 tty_turn_off_highlight (tty);
369 else
370 tty_turn_on_highlight (tty);
374 /* Make cursor invisible. */
376 static void
377 tty_hide_cursor (struct tty_display_info *tty)
379 if (tty->cursor_hidden == 0)
381 tty->cursor_hidden = 1;
382 OUTPUT_IF (tty, tty->TS_cursor_invisible);
387 /* Ensure that cursor is visible. */
389 static void
390 tty_show_cursor (struct tty_display_info *tty)
392 if (tty->cursor_hidden)
394 tty->cursor_hidden = 0;
395 OUTPUT_IF (tty, tty->TS_cursor_normal);
396 if (visible_cursor)
397 OUTPUT_IF (tty, tty->TS_cursor_visible);
402 /* Set standout mode to the state it should be in for
403 empty space inside windows. What this is,
404 depends on the user option inverse-video. */
406 static void
407 tty_background_highlight (struct tty_display_info *tty)
409 if (inverse_video)
410 tty_turn_on_highlight (tty);
411 else
412 tty_turn_off_highlight (tty);
415 /* Set standout mode to the mode specified for the text to be output. */
417 static void
418 tty_highlight_if_desired (struct tty_display_info *tty)
420 if (inverse_video)
421 tty_turn_on_highlight (tty);
422 else
423 tty_turn_off_highlight (tty);
427 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
428 frame-relative coordinates. */
430 static void
431 tty_cursor_to (struct frame *f, int vpos, int hpos)
433 struct tty_display_info *tty = FRAME_TTY (f);
435 /* Detect the case where we are called from reset_sys_modes
436 and the costs have never been calculated. Do nothing. */
437 if (! tty->costs_set)
438 return;
440 if (curY (tty) == vpos
441 && curX (tty) == hpos)
442 return;
443 if (!tty->TF_standout_motion)
444 tty_background_highlight (tty);
445 if (!tty->TF_insmode_motion)
446 tty_turn_off_insert (tty);
447 cmgoto (tty, vpos, hpos);
450 /* Similar but don't take any account of the wasted characters. */
452 static void
453 tty_raw_cursor_to (struct frame *f, int row, int col)
455 struct tty_display_info *tty = FRAME_TTY (f);
457 if (curY (tty) == row
458 && curX (tty) == col)
459 return;
460 if (!tty->TF_standout_motion)
461 tty_background_highlight (tty);
462 if (!tty->TF_insmode_motion)
463 tty_turn_off_insert (tty);
464 cmgoto (tty, row, col);
467 /* Erase operations */
469 /* Clear from cursor to end of frame on a termcap device. */
471 static void
472 tty_clear_to_end (struct frame *f)
474 register int i;
475 struct tty_display_info *tty = FRAME_TTY (f);
477 if (tty->TS_clr_to_bottom)
479 tty_background_highlight (tty);
480 OUTPUT (tty, tty->TS_clr_to_bottom);
482 else
484 for (i = curY (tty); i < FRAME_LINES (f); i++)
486 cursor_to (f, i, 0);
487 clear_end_of_line (f, FRAME_COLS (f));
492 /* Clear an entire termcap frame. */
494 static void
495 tty_clear_frame (struct frame *f)
497 struct tty_display_info *tty = FRAME_TTY (f);
499 if (tty->TS_clr_frame)
501 tty_background_highlight (tty);
502 OUTPUT (tty, tty->TS_clr_frame);
503 cmat (tty, 0, 0);
505 else
507 cursor_to (f, 0, 0);
508 clear_to_end (f);
512 /* An implementation of clear_end_of_line for termcap frames.
514 Note that the cursor may be moved, on terminals lacking a `ce' string. */
516 static void
517 tty_clear_end_of_line (struct frame *f, int first_unused_hpos)
519 register int i;
520 struct tty_display_info *tty = FRAME_TTY (f);
522 /* Detect the case where we are called from reset_sys_modes
523 and the costs have never been calculated. Do nothing. */
524 if (! tty->costs_set)
525 return;
527 if (curX (tty) >= first_unused_hpos)
528 return;
529 tty_background_highlight (tty);
530 if (tty->TS_clr_line)
532 OUTPUT1 (tty, tty->TS_clr_line);
534 else
535 { /* have to do it the hard way */
536 tty_turn_off_insert (tty);
538 /* Do not write in last row last col with Auto-wrap on. */
539 if (AutoWrap (tty)
540 && curY (tty) == FrameRows (tty) - 1
541 && first_unused_hpos == FrameCols (tty))
542 first_unused_hpos--;
544 for (i = curX (tty); i < first_unused_hpos; i++)
546 if (tty->termscript)
547 fputc (' ', tty->termscript);
548 fputc (' ', tty->output);
550 cmplus (tty, first_unused_hpos - curX (tty));
554 /* Buffers to store the source and result of code conversion for terminal. */
555 static unsigned char *encode_terminal_src;
556 static unsigned char *encode_terminal_dst;
557 /* Allocated sizes of the above buffers. */
558 static int encode_terminal_src_size;
559 static int encode_terminal_dst_size;
561 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes.
562 Set CODING->produced to the byte-length of the resulting byte
563 sequence, and return a pointer to that byte sequence. */
565 unsigned char *
566 encode_terminal_code (src, src_len, coding)
567 struct glyph *src;
568 int src_len;
569 struct coding_system *coding;
571 struct glyph *src_end = src + src_len;
572 unsigned char *buf;
573 int nchars, nbytes, required;
574 register int tlen = GLYPH_TABLE_LENGTH;
575 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
576 Lisp_Object charset_list;
578 /* Allocate sufficient size of buffer to store all characters in
579 multibyte-form. But, it may be enlarged on demand if
580 Vglyph_table contains a string or a composite glyph is
581 encountered. */
582 required = MAX_MULTIBYTE_LENGTH * src_len;
583 if (encode_terminal_src_size < required)
585 if (encode_terminal_src)
586 encode_terminal_src = xrealloc (encode_terminal_src, required);
587 else
588 encode_terminal_src = xmalloc (required);
589 encode_terminal_src_size = required;
592 charset_list = coding_charset_list (coding);
594 buf = encode_terminal_src;
595 nchars = 0;
596 while (src < src_end)
598 if (src->type == COMPOSITE_GLYPH)
600 struct composition *cmp;
601 Lisp_Object gstring;
602 int i;
604 nbytes = buf - encode_terminal_src;
605 if (src->u.cmp.automatic)
607 gstring = composition_gstring_from_id (src->u.cmp.id);
608 required = src->u.cmp.to + 1 - src->u.cmp.from;
610 else
612 cmp = composition_table[src->u.cmp.id];
613 required = MAX_MULTIBYTE_LENGTH * cmp->glyph_len;
616 if (encode_terminal_src_size < nbytes + required)
618 encode_terminal_src_size = nbytes + required;
619 encode_terminal_src = xrealloc (encode_terminal_src,
620 encode_terminal_src_size);
621 buf = encode_terminal_src + nbytes;
624 if (src->u.cmp.automatic)
625 for (i = src->u.cmp.from; i <= src->u.cmp.to; i++)
627 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
628 int c = LGLYPH_CHAR (g);
630 if (! char_charset (c, charset_list, NULL))
631 c = '?';
632 buf += CHAR_STRING (c, buf);
633 nchars++;
635 else
636 for (i = 0; i < cmp->glyph_len; i++)
638 int c = COMPOSITION_GLYPH (cmp, i);
640 if (c == '\t')
641 continue;
642 if (char_charset (c, charset_list, NULL))
644 if (CHAR_WIDTH (c) == 0
645 && i > 0 && COMPOSITION_GLYPH (cmp, i - 1) == '\t')
646 /* Should be left-padded */
648 buf += CHAR_STRING (' ', buf);
649 nchars++;
652 else
653 c = '?';
654 buf += CHAR_STRING (c, buf);
655 nchars++;
658 /* We must skip glyphs to be padded for a wide character. */
659 else if (! CHAR_GLYPH_PADDING_P (*src))
661 GLYPH g;
662 int c;
663 Lisp_Object string;
665 string = Qnil;
666 SET_GLYPH_FROM_CHAR_GLYPH (g, src[0]);
668 if (GLYPH_INVALID_P (g) || GLYPH_SIMPLE_P (tbase, tlen, g))
670 /* This glyph doesn't have an entry in Vglyph_table. */
671 c = src->u.ch;
673 else
675 /* This glyph has an entry in Vglyph_table,
676 so process any alias before testing for simpleness. */
677 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
679 if (GLYPH_SIMPLE_P (tbase, tlen, g))
680 /* We set the multi-byte form of a character in G
681 (that should be an ASCII character) at WORKBUF. */
682 c = GLYPH_CHAR (g);
683 else
684 /* We have a string in Vglyph_table. */
685 string = tbase[GLYPH_CHAR (g)];
688 if (NILP (string))
690 nbytes = buf - encode_terminal_src;
691 if (encode_terminal_src_size < nbytes + MAX_MULTIBYTE_LENGTH)
693 encode_terminal_src_size = nbytes + MAX_MULTIBYTE_LENGTH;
694 encode_terminal_src = xrealloc (encode_terminal_src,
695 encode_terminal_src_size);
696 buf = encode_terminal_src + nbytes;
698 if (CHAR_BYTE8_P (c))
700 *buf++ = CHAR_TO_BYTE8 (c);
701 nchars++;
703 else if (char_charset (c, charset_list, NULL))
705 /* Store the multibyte form of C at BUF. */
706 buf += CHAR_STRING (c, buf);
707 nchars++;
709 else
711 /* C is not encodable. */
712 *buf++ = '?';
713 nchars++;
714 while (src + 1 < src_end && CHAR_GLYPH_PADDING_P (src[1]))
716 *buf++ = '?';
717 nchars++;
718 src++;
722 else
724 unsigned char *p = SDATA (string), *pend = p + SBYTES (string);
726 if (! STRING_MULTIBYTE (string))
727 string = string_to_multibyte (string);
728 nbytes = buf - encode_terminal_src;
729 if (encode_terminal_src_size < nbytes + SBYTES (string))
731 encode_terminal_src_size = nbytes + SBYTES (string);
732 encode_terminal_src = xrealloc (encode_terminal_src,
733 encode_terminal_src_size);
734 buf = encode_terminal_src + nbytes;
736 bcopy (SDATA (string), buf, SBYTES (string));
737 buf += SBYTES (string);
738 nchars += SCHARS (string);
741 src++;
744 if (nchars == 0)
746 coding->produced = 0;
747 return NULL;
750 nbytes = buf - encode_terminal_src;
751 coding->source = encode_terminal_src;
752 if (encode_terminal_dst_size == 0)
754 encode_terminal_dst_size = encode_terminal_src_size;
755 if (encode_terminal_dst)
756 encode_terminal_dst = xrealloc (encode_terminal_dst,
757 encode_terminal_dst_size);
758 else
759 encode_terminal_dst = xmalloc (encode_terminal_dst_size);
761 coding->destination = encode_terminal_dst;
762 coding->dst_bytes = encode_terminal_dst_size;
763 encode_coding_object (coding, Qnil, 0, 0, nchars, nbytes, Qnil);
764 /* coding->destination may have been reallocated. */
765 encode_terminal_dst = coding->destination;
766 encode_terminal_dst_size = coding->dst_bytes;
768 return (encode_terminal_dst);
773 /* An implementation of write_glyphs for termcap frames. */
775 static void
776 tty_write_glyphs (struct frame *f, struct glyph *string, int len)
778 unsigned char *conversion_buffer;
779 struct coding_system *coding;
781 struct tty_display_info *tty = FRAME_TTY (f);
783 tty_turn_off_insert (tty);
784 tty_hide_cursor (tty);
786 /* Don't dare write in last column of bottom line, if Auto-Wrap,
787 since that would scroll the whole frame on some terminals. */
789 if (AutoWrap (tty)
790 && curY (tty) + 1 == FRAME_LINES (f)
791 && (curX (tty) + len) == FRAME_COLS (f))
792 len --;
793 if (len <= 0)
794 return;
796 cmplus (tty, len);
798 /* If terminal_coding does any conversion, use it, otherwise use
799 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
800 because it always return 1 if the member src_multibyte is 1. */
801 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
802 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
803 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
804 the tail. */
805 coding->mode &= ~CODING_MODE_LAST_BLOCK;
807 while (len > 0)
809 /* Identify a run of glyphs with the same face. */
810 int face_id = string->face_id;
811 int n;
813 for (n = 1; n < len; ++n)
814 if (string[n].face_id != face_id)
815 break;
817 /* Turn appearance modes of the face of the run on. */
818 tty_highlight_if_desired (tty);
819 turn_on_face (f, face_id);
821 if (n == len)
822 /* This is the last run. */
823 coding->mode |= CODING_MODE_LAST_BLOCK;
824 conversion_buffer = encode_terminal_code (string, n, coding);
825 if (coding->produced > 0)
827 BLOCK_INPUT;
828 fwrite (conversion_buffer, 1, coding->produced, tty->output);
829 if (ferror (tty->output))
830 clearerr (tty->output);
831 if (tty->termscript)
832 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
833 UNBLOCK_INPUT;
835 len -= n;
836 string += n;
838 /* Turn appearance modes off. */
839 turn_off_face (f, face_id);
840 tty_turn_off_highlight (tty);
843 cmcheckmagic (tty);
846 #ifdef HAVE_GPM /* Only used by GPM code. */
848 static void
849 tty_write_glyphs_with_face (f, string, len, face_id)
850 register struct frame *f;
851 register struct glyph *string;
852 register int len, face_id;
854 unsigned char *conversion_buffer;
855 struct coding_system *coding;
857 struct tty_display_info *tty = FRAME_TTY (f);
859 tty_turn_off_insert (tty);
860 tty_hide_cursor (tty);
862 /* Don't dare write in last column of bottom line, if Auto-Wrap,
863 since that would scroll the whole frame on some terminals. */
865 if (AutoWrap (tty)
866 && curY (tty) + 1 == FRAME_LINES (f)
867 && (curX (tty) + len) == FRAME_COLS (f))
868 len --;
869 if (len <= 0)
870 return;
872 cmplus (tty, len);
874 /* If terminal_coding does any conversion, use it, otherwise use
875 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
876 because it always return 1 if the member src_multibyte is 1. */
877 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
878 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
879 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
880 the tail. */
881 coding->mode &= ~CODING_MODE_LAST_BLOCK;
883 /* Turn appearance modes of the face. */
884 tty_highlight_if_desired (tty);
885 turn_on_face (f, face_id);
887 coding->mode |= CODING_MODE_LAST_BLOCK;
888 conversion_buffer = encode_terminal_code (string, len, coding);
889 if (coding->produced > 0)
891 BLOCK_INPUT;
892 fwrite (conversion_buffer, 1, coding->produced, tty->output);
893 if (ferror (tty->output))
894 clearerr (tty->output);
895 if (tty->termscript)
896 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
897 UNBLOCK_INPUT;
900 /* Turn appearance modes off. */
901 turn_off_face (f, face_id);
902 tty_turn_off_highlight (tty);
904 cmcheckmagic (tty);
906 #endif
908 /* An implementation of insert_glyphs for termcap frames. */
910 static void
911 tty_insert_glyphs (struct frame *f, struct glyph *start, int len)
913 char *buf;
914 struct glyph *glyph = NULL;
915 unsigned char *conversion_buffer;
916 unsigned char space[1];
917 struct coding_system *coding;
919 struct tty_display_info *tty = FRAME_TTY (f);
921 if (tty->TS_ins_multi_chars)
923 buf = tparam (tty->TS_ins_multi_chars, 0, 0, len);
924 OUTPUT1 (tty, buf);
925 xfree (buf);
926 if (start)
927 write_glyphs (f, start, len);
928 return;
931 tty_turn_on_insert (tty);
932 cmplus (tty, len);
934 if (! start)
935 space[0] = SPACEGLYPH;
937 /* If terminal_coding does any conversion, use it, otherwise use
938 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
939 because it always return 1 if the member src_multibyte is 1. */
940 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
941 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
942 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
943 the tail. */
944 coding->mode &= ~CODING_MODE_LAST_BLOCK;
946 while (len-- > 0)
948 OUTPUT1_IF (tty, tty->TS_ins_char);
949 if (!start)
951 conversion_buffer = space;
952 coding->produced = 1;
954 else
956 tty_highlight_if_desired (tty);
957 turn_on_face (f, start->face_id);
958 glyph = start;
959 ++start;
960 /* We must open sufficient space for a character which
961 occupies more than one column. */
962 while (len && CHAR_GLYPH_PADDING_P (*start))
964 OUTPUT1_IF (tty, tty->TS_ins_char);
965 start++, len--;
968 if (len <= 0)
969 /* This is the last glyph. */
970 coding->mode |= CODING_MODE_LAST_BLOCK;
972 conversion_buffer = encode_terminal_code (glyph, 1, coding);
975 if (coding->produced > 0)
977 BLOCK_INPUT;
978 fwrite (conversion_buffer, 1, coding->produced, tty->output);
979 if (ferror (tty->output))
980 clearerr (tty->output);
981 if (tty->termscript)
982 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
983 UNBLOCK_INPUT;
986 OUTPUT1_IF (tty, tty->TS_pad_inserted_char);
987 if (start)
989 turn_off_face (f, glyph->face_id);
990 tty_turn_off_highlight (tty);
994 cmcheckmagic (tty);
997 /* An implementation of delete_glyphs for termcap frames. */
999 static void
1000 tty_delete_glyphs (struct frame *f, int n)
1002 char *buf;
1003 register int i;
1005 struct tty_display_info *tty = FRAME_TTY (f);
1007 if (tty->delete_in_insert_mode)
1009 tty_turn_on_insert (tty);
1011 else
1013 tty_turn_off_insert (tty);
1014 OUTPUT_IF (tty, tty->TS_delete_mode);
1017 if (tty->TS_del_multi_chars)
1019 buf = tparam (tty->TS_del_multi_chars, 0, 0, n);
1020 OUTPUT1 (tty, buf);
1021 xfree (buf);
1023 else
1024 for (i = 0; i < n; i++)
1025 OUTPUT1 (tty, tty->TS_del_char);
1026 if (!tty->delete_in_insert_mode)
1027 OUTPUT_IF (tty, tty->TS_end_delete_mode);
1030 /* An implementation of ins_del_lines for termcap frames. */
1032 static void
1033 tty_ins_del_lines (struct frame *f, int vpos, int n)
1035 struct tty_display_info *tty = FRAME_TTY (f);
1036 char *multi = n > 0 ? tty->TS_ins_multi_lines : tty->TS_del_multi_lines;
1037 char *single = n > 0 ? tty->TS_ins_line : tty->TS_del_line;
1038 char *scroll = n > 0 ? tty->TS_rev_scroll : tty->TS_fwd_scroll;
1040 register int i = n > 0 ? n : -n;
1041 register char *buf;
1043 /* If the lines below the insertion are being pushed
1044 into the end of the window, this is the same as clearing;
1045 and we know the lines are already clear, since the matching
1046 deletion has already been done. So can ignore this. */
1047 /* If the lines below the deletion are blank lines coming
1048 out of the end of the window, don't bother,
1049 as there will be a matching inslines later that will flush them. */
1050 if (FRAME_SCROLL_REGION_OK (f)
1051 && vpos + i >= tty->specified_window)
1052 return;
1053 if (!FRAME_MEMORY_BELOW_FRAME (f)
1054 && vpos + i >= FRAME_LINES (f))
1055 return;
1057 if (multi)
1059 raw_cursor_to (f, vpos, 0);
1060 tty_background_highlight (tty);
1061 buf = tparam (multi, 0, 0, i);
1062 OUTPUT (tty, buf);
1063 xfree (buf);
1065 else if (single)
1067 raw_cursor_to (f, vpos, 0);
1068 tty_background_highlight (tty);
1069 while (--i >= 0)
1070 OUTPUT (tty, single);
1071 if (tty->TF_teleray)
1072 curX (tty) = 0;
1074 else
1076 tty_set_scroll_region (f, vpos, tty->specified_window);
1077 if (n < 0)
1078 raw_cursor_to (f, tty->specified_window - 1, 0);
1079 else
1080 raw_cursor_to (f, vpos, 0);
1081 tty_background_highlight (tty);
1082 while (--i >= 0)
1083 OUTPUTL (tty, scroll, tty->specified_window - vpos);
1084 tty_set_scroll_region (f, 0, tty->specified_window);
1087 if (!FRAME_SCROLL_REGION_OK (f)
1088 && FRAME_MEMORY_BELOW_FRAME (f)
1089 && n < 0)
1091 cursor_to (f, FRAME_LINES (f) + n, 0);
1092 clear_to_end (f);
1096 /* Compute cost of sending "str", in characters,
1097 not counting any line-dependent padding. */
1100 string_cost (char *str)
1102 cost = 0;
1103 if (str)
1104 tputs (str, 0, evalcost);
1105 return cost;
1108 /* Compute cost of sending "str", in characters,
1109 counting any line-dependent padding at one line. */
1111 static int
1112 string_cost_one_line (char *str)
1114 cost = 0;
1115 if (str)
1116 tputs (str, 1, evalcost);
1117 return cost;
1120 /* Compute per line amount of line-dependent padding,
1121 in tenths of characters. */
1124 per_line_cost (char *str)
1126 cost = 0;
1127 if (str)
1128 tputs (str, 0, evalcost);
1129 cost = - cost;
1130 if (str)
1131 tputs (str, 10, evalcost);
1132 return cost;
1135 #ifndef old
1136 /* char_ins_del_cost[n] is cost of inserting N characters.
1137 char_ins_del_cost[-n] is cost of deleting N characters.
1138 The length of this vector is based on max_frame_cols. */
1140 int *char_ins_del_vector;
1142 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
1143 #endif
1145 /* ARGSUSED */
1146 static void
1147 calculate_ins_del_char_costs (struct frame *f)
1149 struct tty_display_info *tty = FRAME_TTY (f);
1150 int ins_startup_cost, del_startup_cost;
1151 int ins_cost_per_char, del_cost_per_char;
1152 register int i;
1153 register int *p;
1155 if (tty->TS_ins_multi_chars)
1157 ins_cost_per_char = 0;
1158 ins_startup_cost = string_cost_one_line (tty->TS_ins_multi_chars);
1160 else if (tty->TS_ins_char || tty->TS_pad_inserted_char
1161 || (tty->TS_insert_mode && tty->TS_end_insert_mode))
1163 ins_startup_cost = (30 * (string_cost (tty->TS_insert_mode)
1164 + string_cost (tty->TS_end_insert_mode))) / 100;
1165 ins_cost_per_char = (string_cost_one_line (tty->TS_ins_char)
1166 + string_cost_one_line (tty->TS_pad_inserted_char));
1168 else
1170 ins_startup_cost = 9999;
1171 ins_cost_per_char = 0;
1174 if (tty->TS_del_multi_chars)
1176 del_cost_per_char = 0;
1177 del_startup_cost = string_cost_one_line (tty->TS_del_multi_chars);
1179 else if (tty->TS_del_char)
1181 del_startup_cost = (string_cost (tty->TS_delete_mode)
1182 + string_cost (tty->TS_end_delete_mode));
1183 if (tty->delete_in_insert_mode)
1184 del_startup_cost /= 2;
1185 del_cost_per_char = string_cost_one_line (tty->TS_del_char);
1187 else
1189 del_startup_cost = 9999;
1190 del_cost_per_char = 0;
1193 /* Delete costs are at negative offsets */
1194 p = &char_ins_del_cost (f)[0];
1195 for (i = FRAME_COLS (f); --i >= 0;)
1196 *--p = (del_startup_cost += del_cost_per_char);
1198 /* Doing nothing is free */
1199 p = &char_ins_del_cost (f)[0];
1200 *p++ = 0;
1202 /* Insert costs are at positive offsets */
1203 for (i = FRAME_COLS (f); --i >= 0;)
1204 *p++ = (ins_startup_cost += ins_cost_per_char);
1207 void
1208 calculate_costs (struct frame *frame)
1210 FRAME_COST_BAUD_RATE (frame) = baud_rate;
1212 if (FRAME_TERMCAP_P (frame))
1214 struct tty_display_info *tty = FRAME_TTY (frame);
1215 register char *f = (tty->TS_set_scroll_region
1216 ? tty->TS_set_scroll_region
1217 : tty->TS_set_scroll_region_1);
1219 FRAME_SCROLL_REGION_COST (frame) = string_cost (f);
1221 tty->costs_set = 1;
1223 /* These variables are only used for terminal stuff. They are
1224 allocated once for the terminal frame of X-windows emacs, but not
1225 used afterwards.
1227 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1228 X turns off char_ins_del_ok. */
1230 max_frame_lines = max (max_frame_lines, FRAME_LINES (frame));
1231 max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
1233 if (char_ins_del_vector != 0)
1234 char_ins_del_vector
1235 = (int *) xrealloc (char_ins_del_vector,
1236 (sizeof (int)
1237 + 2 * max_frame_cols * sizeof (int)));
1238 else
1239 char_ins_del_vector
1240 = (int *) xmalloc (sizeof (int)
1241 + 2 * max_frame_cols * sizeof (int));
1243 bzero (char_ins_del_vector, (sizeof (int)
1244 + 2 * max_frame_cols * sizeof (int)));
1247 if (f && (!tty->TS_ins_line && !tty->TS_del_line))
1248 do_line_insertion_deletion_costs (frame,
1249 tty->TS_rev_scroll, tty->TS_ins_multi_lines,
1250 tty->TS_fwd_scroll, tty->TS_del_multi_lines,
1251 f, f, 1);
1252 else
1253 do_line_insertion_deletion_costs (frame,
1254 tty->TS_ins_line, tty->TS_ins_multi_lines,
1255 tty->TS_del_line, tty->TS_del_multi_lines,
1256 0, 0, 1);
1258 calculate_ins_del_char_costs (frame);
1260 /* Don't use TS_repeat if its padding is worse than sending the chars */
1261 if (tty->TS_repeat && per_line_cost (tty->TS_repeat) * baud_rate < 9000)
1262 tty->RPov = string_cost (tty->TS_repeat);
1263 else
1264 tty->RPov = FRAME_COLS (frame) * 2;
1266 cmcostinit (FRAME_TTY (frame)); /* set up cursor motion costs */
1270 struct fkey_table {
1271 char *cap, *name;
1274 /* Termcap capability names that correspond directly to X keysyms.
1275 Some of these (marked "terminfo") aren't supplied by old-style
1276 (Berkeley) termcap entries. They're listed in X keysym order;
1277 except we put the keypad keys first, so that if they clash with
1278 other keys (as on the IBM PC keyboard) they get overridden.
1281 static struct fkey_table keys[] =
1283 {"kh", "home"}, /* termcap */
1284 {"kl", "left"}, /* termcap */
1285 {"ku", "up"}, /* termcap */
1286 {"kr", "right"}, /* termcap */
1287 {"kd", "down"}, /* termcap */
1288 {"%8", "prior"}, /* terminfo */
1289 {"%5", "next"}, /* terminfo */
1290 {"@7", "end"}, /* terminfo */
1291 {"@1", "begin"}, /* terminfo */
1292 {"*6", "select"}, /* terminfo */
1293 {"%9", "print"}, /* terminfo */
1294 {"@4", "execute"}, /* terminfo --- actually the `command' key */
1296 * "insert" --- see below
1298 {"&8", "undo"}, /* terminfo */
1299 {"%0", "redo"}, /* terminfo */
1300 {"%7", "menu"}, /* terminfo --- actually the `options' key */
1301 {"@0", "find"}, /* terminfo */
1302 {"@2", "cancel"}, /* terminfo */
1303 {"%1", "help"}, /* terminfo */
1305 * "break" goes here, but can't be reliably intercepted with termcap
1307 {"&4", "reset"}, /* terminfo --- actually `restart' */
1309 * "system" and "user" --- no termcaps
1311 {"kE", "clearline"}, /* terminfo */
1312 {"kA", "insertline"}, /* terminfo */
1313 {"kL", "deleteline"}, /* terminfo */
1314 {"kI", "insertchar"}, /* terminfo */
1315 {"kD", "deletechar"}, /* terminfo */
1316 {"kB", "backtab"}, /* terminfo */
1318 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1320 {"@8", "kp-enter"}, /* terminfo */
1322 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1323 * "kp-multiply", "kp-add", "kp-separator",
1324 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1325 * --- no termcaps for any of these.
1327 {"K4", "kp-1"}, /* terminfo */
1329 * "kp-2" --- no termcap
1331 {"K5", "kp-3"}, /* terminfo */
1333 * "kp-4" --- no termcap
1335 {"K2", "kp-5"}, /* terminfo */
1337 * "kp-6" --- no termcap
1339 {"K1", "kp-7"}, /* terminfo */
1341 * "kp-8" --- no termcap
1343 {"K3", "kp-9"}, /* terminfo */
1345 * "kp-equal" --- no termcap
1347 {"k1", "f1"},
1348 {"k2", "f2"},
1349 {"k3", "f3"},
1350 {"k4", "f4"},
1351 {"k5", "f5"},
1352 {"k6", "f6"},
1353 {"k7", "f7"},
1354 {"k8", "f8"},
1355 {"k9", "f9"},
1357 {"&0", "S-cancel"}, /*shifted cancel key*/
1358 {"&9", "S-begin"}, /*shifted begin key*/
1359 {"*0", "S-find"}, /*shifted find key*/
1360 {"*1", "S-execute"}, /*shifted execute? actually shifted command key*/
1361 {"*4", "S-delete"}, /*shifted delete-character key*/
1362 {"*7", "S-end"}, /*shifted end key*/
1363 {"*8", "S-clearline"}, /*shifted clear-to end-of-line key*/
1364 {"#1", "S-help"}, /*shifted help key*/
1365 {"#2", "S-home"}, /*shifted home key*/
1366 {"#3", "S-insert"}, /*shifted insert-character key*/
1367 {"#4", "S-left"}, /*shifted left-arrow key*/
1368 {"%d", "S-menu"}, /*shifted menu? actually shifted options key*/
1369 {"%c", "S-next"}, /*shifted next key*/
1370 {"%e", "S-prior"}, /*shifted previous key*/
1371 {"%f", "S-print"}, /*shifted print key*/
1372 {"%g", "S-redo"}, /*shifted redo key*/
1373 {"%i", "S-right"}, /*shifted right-arrow key*/
1374 {"!3", "S-undo"} /*shifted undo key*/
1377 static char **term_get_fkeys_address;
1378 static KBOARD *term_get_fkeys_kboard;
1379 static Lisp_Object term_get_fkeys_1 ();
1381 /* Find the escape codes sent by the function keys for Vinput_decode_map.
1382 This function scans the termcap function key sequence entries, and
1383 adds entries to Vinput_decode_map for each function key it finds. */
1385 static void
1386 term_get_fkeys (address, kboard)
1387 char **address;
1388 KBOARD *kboard;
1390 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1391 errors during the call. The only errors should be from Fdefine_key
1392 when given a key sequence containing an invalid prefix key. If the
1393 termcap defines function keys which use a prefix that is already bound
1394 to a command by the default bindings, we should silently ignore that
1395 function key specification, rather than giving the user an error and
1396 refusing to run at all on such a terminal. */
1398 extern Lisp_Object Fidentity ();
1399 term_get_fkeys_address = address;
1400 term_get_fkeys_kboard = kboard;
1401 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1404 static Lisp_Object
1405 term_get_fkeys_1 ()
1407 int i;
1409 char **address = term_get_fkeys_address;
1410 KBOARD *kboard = term_get_fkeys_kboard;
1412 /* This can happen if CANNOT_DUMP or with strange options. */
1413 if (!KEYMAPP (kboard->Vinput_decode_map))
1414 kboard->Vinput_decode_map = Fmake_sparse_keymap (Qnil);
1416 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1418 char *sequence = tgetstr (keys[i].cap, address);
1419 if (sequence)
1420 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence),
1421 Fmake_vector (make_number (1),
1422 intern (keys[i].name)));
1425 /* The uses of the "k0" capability are inconsistent; sometimes it
1426 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1427 We will attempt to politely accommodate both systems by testing for
1428 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1431 char *k_semi = tgetstr ("k;", address);
1432 char *k0 = tgetstr ("k0", address);
1433 char *k0_name = "f10";
1435 if (k_semi)
1437 if (k0)
1438 /* Define f0 first, so that f10 takes precedence in case the
1439 key sequences happens to be the same. */
1440 Fdefine_key (kboard->Vinput_decode_map, build_string (k0),
1441 Fmake_vector (make_number (1), intern ("f0")));
1442 Fdefine_key (kboard->Vinput_decode_map, build_string (k_semi),
1443 Fmake_vector (make_number (1), intern ("f10")));
1445 else if (k0)
1446 Fdefine_key (kboard->Vinput_decode_map, build_string (k0),
1447 Fmake_vector (make_number (1), intern (k0_name)));
1450 /* Set up cookies for numbered function keys above f10. */
1452 char fcap[3], fkey[4];
1454 fcap[0] = 'F'; fcap[2] = '\0';
1455 for (i = 11; i < 64; i++)
1457 if (i <= 19)
1458 fcap[1] = '1' + i - 11;
1459 else if (i <= 45)
1460 fcap[1] = 'A' + i - 20;
1461 else
1462 fcap[1] = 'a' + i - 46;
1465 char *sequence = tgetstr (fcap, address);
1466 if (sequence)
1468 sprintf (fkey, "f%d", i);
1469 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence),
1470 Fmake_vector (make_number (1),
1471 intern (fkey)));
1478 * Various mappings to try and get a better fit.
1481 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1482 if (!tgetstr (cap1, address)) \
1484 char *sequence = tgetstr (cap2, address); \
1485 if (sequence) \
1486 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence), \
1487 Fmake_vector (make_number (1), \
1488 intern (sym))); \
1491 /* if there's no key_next keycap, map key_npage to `next' keysym */
1492 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1493 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1494 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1495 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1496 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1497 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1498 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1500 /* IBM has their own non-standard dialect of terminfo.
1501 If the standard name isn't found, try the IBM name. */
1502 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1503 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1504 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1505 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1506 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1507 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1508 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1509 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1510 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1511 #undef CONDITIONAL_REASSIGN
1514 return Qnil;
1518 /***********************************************************************
1519 Character Display Information
1520 ***********************************************************************/
1522 /* Avoid name clash with functions defined in xterm.c */
1523 #ifdef static
1524 #define append_glyph append_glyph_term
1525 #define produce_stretch_glyph produce_stretch_glyph_term
1526 #define append_composite_glyph append_composite_glyph_term
1527 #define produce_composite_glyph produce_composite_glyph_term
1528 #endif
1530 static void append_glyph P_ ((struct it *));
1531 static void produce_stretch_glyph P_ ((struct it *));
1532 static void append_composite_glyph P_ ((struct it *));
1533 static void produce_composite_glyph P_ ((struct it *));
1535 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1536 terminal frames if IT->glyph_row != NULL. IT->char_to_display is
1537 the character for which to produce glyphs; IT->face_id contains the
1538 character's face. Padding glyphs are appended if IT->c has a
1539 IT->pixel_width > 1. */
1541 static void
1542 append_glyph (it)
1543 struct it *it;
1545 struct glyph *glyph, *end;
1546 int i;
1548 xassert (it->glyph_row);
1549 glyph = (it->glyph_row->glyphs[it->area]
1550 + it->glyph_row->used[it->area]);
1551 end = it->glyph_row->glyphs[1 + it->area];
1553 for (i = 0;
1554 i < it->pixel_width && glyph < end;
1555 ++i)
1557 glyph->type = CHAR_GLYPH;
1558 glyph->pixel_width = 1;
1559 glyph->u.ch = it->char_to_display;
1560 glyph->face_id = it->face_id;
1561 glyph->padding_p = i > 0;
1562 glyph->charpos = CHARPOS (it->position);
1563 glyph->object = it->object;
1565 ++it->glyph_row->used[it->area];
1566 ++glyph;
1571 /* Produce glyphs for the display element described by IT. *IT
1572 specifies what we want to produce a glyph for (character, image, ...),
1573 and where in the glyph matrix we currently are (glyph row and hpos).
1574 produce_glyphs fills in output fields of *IT with information such as the
1575 pixel width and height of a character, and maybe output actual glyphs at
1576 the same time if IT->glyph_row is non-null. For an overview, see
1577 the explanation in dispextern.h, before the definition of the
1578 display_element_type enumeration.
1580 produce_glyphs also stores the result of glyph width, ascent
1581 etc. computations in *IT.
1583 IT->glyph_row may be null, in which case produce_glyphs does not
1584 actually fill in the glyphs. This is used in the move_* functions
1585 in xdisp.c for text width and height computations.
1587 Callers usually don't call produce_glyphs directly;
1588 instead they use the macro PRODUCE_GLYPHS. */
1590 void
1591 produce_glyphs (it)
1592 struct it *it;
1594 /* If a hook is installed, let it do the work. */
1596 /* Nothing but characters are supported on terminal frames. */
1597 xassert (it->what == IT_CHARACTER
1598 || it->what == IT_COMPOSITION
1599 || it->what == IT_STRETCH);
1601 if (it->what == IT_STRETCH)
1603 produce_stretch_glyph (it);
1604 goto done;
1607 if (it->what == IT_COMPOSITION)
1609 produce_composite_glyph (it);
1610 goto done;
1613 /* Maybe translate single-byte characters to multibyte. */
1614 it->char_to_display = it->c;
1616 if (it->c >= 040 && it->c < 0177)
1618 it->pixel_width = it->nglyphs = 1;
1619 if (it->glyph_row)
1620 append_glyph (it);
1622 else if (it->c == '\n')
1623 it->pixel_width = it->nglyphs = 0;
1624 else if (it->c == '\t')
1626 int absolute_x = (it->current_x
1627 + it->continuation_lines_width);
1628 int next_tab_x
1629 = (((1 + absolute_x + it->tab_width - 1)
1630 / it->tab_width)
1631 * it->tab_width);
1632 int nspaces;
1634 /* If part of the TAB has been displayed on the previous line
1635 which is continued now, continuation_lines_width will have
1636 been incremented already by the part that fitted on the
1637 continued line. So, we will get the right number of spaces
1638 here. */
1639 nspaces = next_tab_x - absolute_x;
1641 if (it->glyph_row)
1643 int n = nspaces;
1645 it->char_to_display = ' ';
1646 it->pixel_width = it->len = 1;
1648 while (n--)
1649 append_glyph (it);
1652 it->pixel_width = nspaces;
1653 it->nglyphs = nspaces;
1655 else if (CHAR_BYTE8_P (it->c))
1657 if (unibyte_display_via_language_environment
1658 && (it->c >= 0240))
1660 it->char_to_display = BYTE8_TO_CHAR (it->c);
1661 it->pixel_width = CHAR_WIDTH (it->char_to_display);
1662 it->nglyphs = it->pixel_width;
1663 if (it->glyph_row)
1664 append_glyph (it);
1666 else
1668 /* Coming here means that it->c is from display table, thus
1669 we must send the raw 8-bit byte as is to the terminal.
1670 Although there's no way to know how many columns it
1671 occupies on a screen, it is a good assumption that a
1672 single byte code has 1-column width. */
1673 it->pixel_width = it->nglyphs = 1;
1674 if (it->glyph_row)
1675 append_glyph (it);
1678 else
1680 it->pixel_width = CHAR_WIDTH (it->c);
1681 it->nglyphs = it->pixel_width;
1683 if (it->glyph_row)
1684 append_glyph (it);
1687 done:
1688 /* Advance current_x by the pixel width as a convenience for
1689 the caller. */
1690 if (it->area == TEXT_AREA)
1691 it->current_x += it->pixel_width;
1692 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1693 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
1697 /* Produce a stretch glyph for iterator IT. IT->object is the value
1698 of the glyph property displayed. The value must be a list
1699 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1700 being recognized:
1702 1. `:width WIDTH' specifies that the space should be WIDTH *
1703 canonical char width wide. WIDTH may be an integer or floating
1704 point number.
1706 2. `:align-to HPOS' specifies that the space should be wide enough
1707 to reach HPOS, a value in canonical character units. */
1709 static void
1710 produce_stretch_glyph (it)
1711 struct it *it;
1713 /* (space :width WIDTH ...) */
1714 Lisp_Object prop, plist;
1715 int width = 0, align_to = -1;
1716 int zero_width_ok_p = 0;
1717 double tem;
1719 /* List should start with `space'. */
1720 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1721 plist = XCDR (it->object);
1723 /* Compute the width of the stretch. */
1724 if ((prop = Fplist_get (plist, QCwidth), !NILP (prop))
1725 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, 0))
1727 /* Absolute width `:width WIDTH' specified and valid. */
1728 zero_width_ok_p = 1;
1729 width = (int)(tem + 0.5);
1731 else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
1732 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, &align_to))
1734 if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
1735 align_to = (align_to < 0
1737 : align_to - window_box_left_offset (it->w, TEXT_AREA));
1738 else if (align_to < 0)
1739 align_to = window_box_left_offset (it->w, TEXT_AREA);
1740 width = max (0, (int)(tem + 0.5) + align_to - it->current_x);
1741 zero_width_ok_p = 1;
1743 else
1744 /* Nothing specified -> width defaults to canonical char width. */
1745 width = FRAME_COLUMN_WIDTH (it->f);
1747 if (width <= 0 && (width < 0 || !zero_width_ok_p))
1748 width = 1;
1750 if (width > 0 && it->line_wrap != TRUNCATE
1751 && it->current_x + width > it->last_visible_x)
1752 width = it->last_visible_x - it->current_x - 1;
1754 if (width > 0 && it->glyph_row)
1756 Lisp_Object o_object = it->object;
1757 Lisp_Object object = it->stack[it->sp - 1].string;
1758 int n = width;
1760 if (!STRINGP (object))
1761 object = it->w->buffer;
1762 it->object = object;
1763 it->char_to_display = ' ';
1764 it->pixel_width = it->len = 1;
1765 while (n--)
1766 append_glyph (it);
1767 it->object = o_object;
1769 it->pixel_width = width;
1770 it->nglyphs = width;
1774 /* Append glyphs to IT's glyph_row for the composition IT->cmp_id.
1775 Called from produce_composite_glyph for terminal frames if
1776 IT->glyph_row != NULL. IT->face_id contains the character's
1777 face. */
1779 static void
1780 append_composite_glyph (it)
1781 struct it *it;
1783 struct glyph *glyph;
1785 xassert (it->glyph_row);
1786 glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
1787 if (glyph < it->glyph_row->glyphs[1 + it->area])
1789 glyph->type = COMPOSITE_GLYPH;
1790 glyph->pixel_width = it->pixel_width;
1791 glyph->u.cmp.id = it->cmp_it.id;
1792 if (it->cmp_it.ch < 0)
1794 glyph->u.cmp.automatic = 0;
1795 glyph->u.cmp.id = it->cmp_it.id;
1797 else
1799 glyph->u.cmp.automatic = 1;
1800 glyph->u.cmp.id = it->cmp_it.id;
1801 glyph->u.cmp.from = it->cmp_it.from;
1802 glyph->u.cmp.to = it->cmp_it.to - 1;
1805 glyph->face_id = it->face_id;
1806 glyph->padding_p = 0;
1807 glyph->charpos = CHARPOS (it->position);
1808 glyph->object = it->object;
1810 ++it->glyph_row->used[it->area];
1811 ++glyph;
1816 /* Produce a composite glyph for iterator IT. IT->cmp_id is the ID of
1817 the composition. We simply produces components of the composition
1818 assuming that the terminal has a capability to layout/render it
1819 correctly. */
1821 static void
1822 produce_composite_glyph (it)
1823 struct it *it;
1825 int c;
1827 if (it->cmp_it.ch < 0)
1829 struct composition *cmp = composition_table[it->cmp_it.id];
1831 it->pixel_width = cmp->width;
1833 else
1835 Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id);
1837 it->pixel_width = composition_gstring_width (gstring, it->cmp_it.from,
1838 it->cmp_it.to, NULL);
1840 it->nglyphs = 1;
1841 if (it->glyph_row)
1842 append_composite_glyph (it);
1846 /* Get information about special display element WHAT in an
1847 environment described by IT. WHAT is one of IT_TRUNCATION or
1848 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1849 non-null glyph_row member. This function ensures that fields like
1850 face_id, c, len of IT are left untouched. */
1852 void
1853 produce_special_glyphs (it, what)
1854 struct it *it;
1855 enum display_element_type what;
1857 struct it temp_it;
1858 Lisp_Object gc;
1859 GLYPH glyph;
1861 temp_it = *it;
1862 temp_it.dp = NULL;
1863 temp_it.what = IT_CHARACTER;
1864 temp_it.len = 1;
1865 temp_it.object = make_number (0);
1866 bzero (&temp_it.current, sizeof temp_it.current);
1868 if (what == IT_CONTINUATION)
1870 /* Continuation glyph. */
1871 SET_GLYPH_FROM_CHAR (glyph, '\\');
1872 if (it->dp
1873 && (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc))
1874 && GLYPH_CODE_CHAR_VALID_P (gc))
1876 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
1877 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
1880 else if (what == IT_TRUNCATION)
1882 /* Truncation glyph. */
1883 SET_GLYPH_FROM_CHAR (glyph, '$');
1884 if (it->dp
1885 && (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc))
1886 && GLYPH_CODE_CHAR_VALID_P (gc))
1888 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
1889 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
1892 else
1893 abort ();
1895 temp_it.c = GLYPH_CHAR (glyph);
1896 temp_it.face_id = GLYPH_FACE (glyph);
1897 temp_it.len = CHAR_BYTES (temp_it.c);
1899 produce_glyphs (&temp_it);
1900 it->pixel_width = temp_it.pixel_width;
1901 it->nglyphs = temp_it.pixel_width;
1906 /***********************************************************************
1907 Faces
1908 ***********************************************************************/
1910 /* Value is non-zero if attribute ATTR may be used. ATTR should be
1911 one of the enumerators from enum no_color_bit, or a bit set built
1912 from them. Some display attributes may not be used together with
1913 color; the termcap capability `NC' specifies which ones. */
1915 #define MAY_USE_WITH_COLORS_P(tty, ATTR) \
1916 (tty->TN_max_colors > 0 \
1917 ? (tty->TN_no_color_video & (ATTR)) == 0 \
1918 : 1)
1920 /* Turn appearances of face FACE_ID on tty frame F on.
1921 FACE_ID is a realized face ID number, in the face cache. */
1923 static void
1924 turn_on_face (f, face_id)
1925 struct frame *f;
1926 int face_id;
1928 struct face *face = FACE_FROM_ID (f, face_id);
1929 long fg = face->foreground;
1930 long bg = face->background;
1931 struct tty_display_info *tty = FRAME_TTY (f);
1933 /* Do this first because TS_end_standout_mode may be the same
1934 as TS_exit_attribute_mode, which turns all appearances off. */
1935 if (MAY_USE_WITH_COLORS_P (tty, NC_REVERSE))
1937 if (tty->TN_max_colors > 0)
1939 if (fg >= 0 && bg >= 0)
1941 /* If the terminal supports colors, we can set them
1942 below without using reverse video. The face's fg
1943 and bg colors are set as they should appear on
1944 the screen, i.e. they take the inverse-video'ness
1945 of the face already into account. */
1947 else if (inverse_video)
1949 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1950 || bg == FACE_TTY_DEFAULT_BG_COLOR)
1951 tty_toggle_highlight (tty);
1953 else
1955 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1956 || bg == FACE_TTY_DEFAULT_FG_COLOR)
1957 tty_toggle_highlight (tty);
1960 else
1962 /* If we can't display colors, use reverse video
1963 if the face specifies that. */
1964 if (inverse_video)
1966 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1967 || bg == FACE_TTY_DEFAULT_BG_COLOR)
1968 tty_toggle_highlight (tty);
1970 else
1972 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1973 || bg == FACE_TTY_DEFAULT_FG_COLOR)
1974 tty_toggle_highlight (tty);
1979 if (face->tty_bold_p && MAY_USE_WITH_COLORS_P (tty, NC_BOLD))
1980 OUTPUT1_IF (tty, tty->TS_enter_bold_mode);
1982 if (face->tty_dim_p && MAY_USE_WITH_COLORS_P (tty, NC_DIM))
1983 OUTPUT1_IF (tty, tty->TS_enter_dim_mode);
1985 /* Alternate charset and blinking not yet used. */
1986 if (face->tty_alt_charset_p
1987 && MAY_USE_WITH_COLORS_P (tty, NC_ALT_CHARSET))
1988 OUTPUT1_IF (tty, tty->TS_enter_alt_charset_mode);
1990 if (face->tty_blinking_p
1991 && MAY_USE_WITH_COLORS_P (tty, NC_BLINK))
1992 OUTPUT1_IF (tty, tty->TS_enter_blink_mode);
1994 if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (tty, NC_UNDERLINE))
1995 OUTPUT1_IF (tty, tty->TS_enter_underline_mode);
1997 if (tty->TN_max_colors > 0)
1999 char *ts, *p;
2001 ts = tty->standout_mode ? tty->TS_set_background : tty->TS_set_foreground;
2002 if (fg >= 0 && ts)
2004 p = tparam (ts, NULL, 0, (int) fg);
2005 OUTPUT (tty, p);
2006 xfree (p);
2009 ts = tty->standout_mode ? tty->TS_set_foreground : tty->TS_set_background;
2010 if (bg >= 0 && ts)
2012 p = tparam (ts, NULL, 0, (int) bg);
2013 OUTPUT (tty, p);
2014 xfree (p);
2020 /* Turn off appearances of face FACE_ID on tty frame F. */
2022 static void
2023 turn_off_face (f, face_id)
2024 struct frame *f;
2025 int face_id;
2027 struct face *face = FACE_FROM_ID (f, face_id);
2028 struct tty_display_info *tty = FRAME_TTY (f);
2030 xassert (face != NULL);
2032 if (tty->TS_exit_attribute_mode)
2034 /* Capability "me" will turn off appearance modes double-bright,
2035 half-bright, reverse-video, standout, underline. It may or
2036 may not turn off alt-char-mode. */
2037 if (face->tty_bold_p
2038 || face->tty_dim_p
2039 || face->tty_reverse_p
2040 || face->tty_alt_charset_p
2041 || face->tty_blinking_p
2042 || face->tty_underline_p)
2044 OUTPUT1_IF (tty, tty->TS_exit_attribute_mode);
2045 if (strcmp (tty->TS_exit_attribute_mode, tty->TS_end_standout_mode) == 0)
2046 tty->standout_mode = 0;
2049 if (face->tty_alt_charset_p)
2050 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
2052 else
2054 /* If we don't have "me" we can only have those appearances
2055 that have exit sequences defined. */
2056 if (face->tty_alt_charset_p)
2057 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
2059 if (face->tty_underline_p)
2060 OUTPUT_IF (tty, tty->TS_exit_underline_mode);
2063 /* Switch back to default colors. */
2064 if (tty->TN_max_colors > 0
2065 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
2066 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
2067 || (face->background != FACE_TTY_DEFAULT_COLOR
2068 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
2069 OUTPUT1_IF (tty, tty->TS_orig_pair);
2073 /* Return non-zero if the terminal on frame F supports all of the
2074 capabilities in CAPS simultaneously, with foreground and background
2075 colors FG and BG. */
2078 tty_capable_p (tty, caps, fg, bg)
2079 struct tty_display_info *tty;
2080 unsigned caps;
2081 unsigned long fg, bg;
2083 #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
2084 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
2085 return 0;
2087 TTY_CAPABLE_P_TRY (tty, TTY_CAP_INVERSE, tty->TS_standout_mode, NC_REVERSE);
2088 TTY_CAPABLE_P_TRY (tty, TTY_CAP_UNDERLINE, tty->TS_enter_underline_mode, NC_UNDERLINE);
2089 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BOLD, tty->TS_enter_bold_mode, NC_BOLD);
2090 TTY_CAPABLE_P_TRY (tty, TTY_CAP_DIM, tty->TS_enter_dim_mode, NC_DIM);
2091 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BLINK, tty->TS_enter_blink_mode, NC_BLINK);
2092 TTY_CAPABLE_P_TRY (tty, TTY_CAP_ALT_CHARSET, tty->TS_enter_alt_charset_mode, NC_ALT_CHARSET);
2094 /* We can do it! */
2095 return 1;
2098 /* Return non-zero if the terminal is capable to display colors. */
2100 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
2101 0, 1, 0,
2102 doc: /* Return non-nil if the tty device TERMINAL can display colors.
2104 TERMINAL can be a terminal object, a frame, or nil (meaning the
2105 selected frame's terminal). This function always returns nil if
2106 TERMINAL does not refer to a text-only terminal. */)
2107 (terminal)
2108 Lisp_Object terminal;
2110 struct terminal *t = get_tty_terminal (terminal, 0);
2111 if (!t)
2112 return Qnil;
2113 else
2114 return t->display_info.tty->TN_max_colors > 0 ? Qt : Qnil;
2117 /* Return the number of supported colors. */
2118 DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
2119 Stty_display_color_cells, 0, 1, 0,
2120 doc: /* Return the number of colors supported by the tty device TERMINAL.
2122 TERMINAL can be a terminal object, a frame, or nil (meaning the
2123 selected frame's terminal). This function always returns 0 if
2124 TERMINAL does not refer to a text-only terminal. */)
2125 (terminal)
2126 Lisp_Object terminal;
2128 struct terminal *t = get_tty_terminal (terminal, 0);
2129 if (!t)
2130 return make_number (0);
2131 else
2132 return make_number (t->display_info.tty->TN_max_colors);
2135 #ifndef DOS_NT
2137 /* Declare here rather than in the function, as in the rest of Emacs,
2138 to work around an HPUX compiler bug (?). See
2139 http://lists.gnu.org/archive/html/emacs-devel/2007-08/msg00410.html */
2140 static int default_max_colors;
2141 static int default_max_pairs;
2142 static int default_no_color_video;
2143 static char *default_orig_pair;
2144 static char *default_set_foreground;
2145 static char *default_set_background;
2147 /* Save or restore the default color-related capabilities of this
2148 terminal. */
2149 static void
2150 tty_default_color_capabilities (struct tty_display_info *tty, int save)
2153 if (save)
2155 xfree (default_orig_pair);
2156 default_orig_pair = tty->TS_orig_pair ? xstrdup (tty->TS_orig_pair) : NULL;
2158 xfree (default_set_foreground);
2159 default_set_foreground = tty->TS_set_foreground ? xstrdup (tty->TS_set_foreground)
2160 : NULL;
2162 xfree (default_set_background);
2163 default_set_background = tty->TS_set_background ? xstrdup (tty->TS_set_background)
2164 : NULL;
2166 default_max_colors = tty->TN_max_colors;
2167 default_max_pairs = tty->TN_max_pairs;
2168 default_no_color_video = tty->TN_no_color_video;
2170 else
2172 tty->TS_orig_pair = default_orig_pair;
2173 tty->TS_set_foreground = default_set_foreground;
2174 tty->TS_set_background = default_set_background;
2175 tty->TN_max_colors = default_max_colors;
2176 tty->TN_max_pairs = default_max_pairs;
2177 tty->TN_no_color_video = default_no_color_video;
2181 /* Setup one of the standard tty color schemes according to MODE.
2182 MODE's value is generally the number of colors which we want to
2183 support; zero means set up for the default capabilities, the ones
2184 we saw at init_tty time; -1 means turn off color support. */
2185 static void
2186 tty_setup_colors (struct tty_display_info *tty, int mode)
2188 /* Canonicalize all negative values of MODE. */
2189 if (mode < -1)
2190 mode = -1;
2192 switch (mode)
2194 case -1: /* no colors at all */
2195 tty->TN_max_colors = 0;
2196 tty->TN_max_pairs = 0;
2197 tty->TN_no_color_video = 0;
2198 tty->TS_set_foreground = tty->TS_set_background = tty->TS_orig_pair = NULL;
2199 break;
2200 case 0: /* default colors, if any */
2201 default:
2202 tty_default_color_capabilities (tty, 0);
2203 break;
2204 case 8: /* 8 standard ANSI colors */
2205 tty->TS_orig_pair = "\033[0m";
2206 #ifdef TERMINFO
2207 tty->TS_set_foreground = "\033[3%p1%dm";
2208 tty->TS_set_background = "\033[4%p1%dm";
2209 #else
2210 tty->TS_set_foreground = "\033[3%dm";
2211 tty->TS_set_background = "\033[4%dm";
2212 #endif
2213 tty->TN_max_colors = 8;
2214 tty->TN_max_pairs = 64;
2215 tty->TN_no_color_video = 0;
2216 break;
2220 void
2221 set_tty_color_mode (tty, f)
2222 struct tty_display_info *tty;
2223 struct frame *f;
2225 Lisp_Object tem, val, color_mode_spec;
2226 Lisp_Object color_mode;
2227 int mode;
2228 extern Lisp_Object Qtty_color_mode;
2229 Lisp_Object tty_color_mode_alist
2230 = Fintern_soft (build_string ("tty-color-mode-alist"), Qnil);
2232 tem = assq_no_quit (Qtty_color_mode, f->param_alist);
2233 val = CONSP (tem) ? XCDR (tem) : Qnil;
2235 if (INTEGERP (val))
2236 color_mode = val;
2237 else
2239 tem = (NILP (tty_color_mode_alist) ? Qnil
2240 : Fassq (val, XSYMBOL (tty_color_mode_alist)->value));
2241 color_mode = CONSP (tem) ? XCDR (tem) : Qnil;
2244 mode = INTEGERP (color_mode) ? XINT (color_mode) : 0;
2246 if (mode != tty->previous_color_mode)
2248 Lisp_Object funsym = intern ("tty-set-up-initial-frame-faces");
2249 tty->previous_color_mode = mode;
2250 tty_setup_colors (tty , mode);
2251 /* This recomputes all the faces given the new color definitions. */
2252 safe_call (1, &funsym);
2256 #endif /* !DOS_NT */
2260 /* Return the tty display object specified by TERMINAL. */
2262 struct terminal *
2263 get_tty_terminal (Lisp_Object terminal, int throw)
2265 struct terminal *t = get_terminal (terminal, throw);
2267 if (t && t->type != output_termcap && t->type != output_msdos_raw)
2269 if (throw)
2270 error ("Device %d is not a termcap terminal device", t->id);
2271 else
2272 return NULL;
2275 return t;
2278 /* Return an active termcap device that uses the tty device with the
2279 given name.
2281 This function ignores suspended devices.
2283 Returns NULL if the named terminal device is not opened. */
2285 struct terminal *
2286 get_named_tty (name)
2287 char *name;
2289 struct terminal *t;
2291 if (!name)
2292 abort ();
2294 for (t = terminal_list; t; t = t->next_terminal)
2296 if ((t->type == output_termcap || t->type == output_msdos_raw)
2297 && !strcmp (t->display_info.tty->name, name)
2298 && TERMINAL_ACTIVE_P (t))
2299 return t;
2302 return 0;
2306 DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0,
2307 doc: /* Return the type of the tty device that TERMINAL uses.
2308 Returns nil if TERMINAL is not on a tty device.
2310 TERMINAL can be a terminal object, a frame, or nil (meaning the
2311 selected frame's terminal). */)
2312 (terminal)
2313 Lisp_Object terminal;
2315 struct terminal *t = get_terminal (terminal, 1);
2317 if (t->type != output_termcap && t->type != output_msdos_raw)
2318 return Qnil;
2320 if (t->display_info.tty->type)
2321 return build_string (t->display_info.tty->type);
2322 else
2323 return Qnil;
2326 DEFUN ("controlling-tty-p", Fcontrolling_tty_p, Scontrolling_tty_p, 0, 1, 0,
2327 doc: /* Return non-nil if TERMINAL is the controlling tty of the Emacs process.
2329 TERMINAL can be a terminal object, a frame, or nil (meaning the
2330 selected frame's terminal). This function always returns nil if
2331 TERMINAL is not on a tty device. */)
2332 (terminal)
2333 Lisp_Object terminal;
2335 struct terminal *t = get_terminal (terminal, 1);
2337 if ((t->type != output_termcap && t->type != output_msdos_raw)
2338 || strcmp (t->display_info.tty->name, DEV_TTY) != 0)
2339 return Qnil;
2340 else
2341 return Qt;
2344 DEFUN ("tty-no-underline", Ftty_no_underline, Stty_no_underline, 0, 1, 0,
2345 doc: /* Declare that the tty used by TERMINAL does not handle underlining.
2346 This is used to override the terminfo data, for certain terminals that
2347 do not really do underlining, but say that they do. This function has
2348 no effect if used on a non-tty terminal.
2350 TERMINAL can be a terminal object, a frame or nil (meaning the
2351 selected frame's terminal). This function always returns nil if
2352 TERMINAL does not refer to a text-only terminal. */)
2353 (terminal)
2354 Lisp_Object terminal;
2356 struct terminal *t = get_terminal (terminal, 1);
2358 if (t->type == output_termcap)
2359 t->display_info.tty->TS_enter_underline_mode = 0;
2360 return Qnil;
2365 DEFUN ("suspend-tty", Fsuspend_tty, Ssuspend_tty, 0, 1, 0,
2366 doc: /* Suspend the terminal device TTY.
2368 The device is restored to its default state, and Emacs ceases all
2369 access to the tty device. Frames that use the device are not deleted,
2370 but input is not read from them and if they change, their display is
2371 not updated.
2373 TTY may be a terminal object, a frame, or nil for the terminal device
2374 of the currently selected frame.
2376 This function runs `suspend-tty-functions' after suspending the
2377 device. The functions are run with one arg, the id of the suspended
2378 terminal device.
2380 `suspend-tty' does nothing if it is called on a device that is already
2381 suspended.
2383 A suspended tty may be resumed by calling `resume-tty' on it. */)
2384 (tty)
2385 Lisp_Object tty;
2387 struct terminal *t = get_tty_terminal (tty, 1);
2388 FILE *f;
2390 if (!t)
2391 error ("Unknown tty device");
2393 f = t->display_info.tty->input;
2395 if (f)
2397 /* First run `suspend-tty-functions' and then clean up the tty
2398 state because `suspend-tty-functions' might need to change
2399 the tty state. */
2400 if (!NILP (Vrun_hooks))
2402 Lisp_Object args[2];
2403 args[0] = intern ("suspend-tty-functions");
2404 XSETTERMINAL (args[1], t);
2405 Frun_hook_with_args (2, args);
2408 reset_sys_modes (t->display_info.tty);
2410 #ifdef subprocesses
2411 delete_keyboard_wait_descriptor (fileno (f));
2412 #endif
2414 #ifndef MSDOS
2415 fclose (f);
2416 if (f != t->display_info.tty->output)
2417 fclose (t->display_info.tty->output);
2418 #endif
2420 t->display_info.tty->input = 0;
2421 t->display_info.tty->output = 0;
2423 if (FRAMEP (t->display_info.tty->top_frame))
2424 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0);
2428 /* Clear display hooks to prevent further output. */
2429 clear_tty_hooks (t);
2431 return Qnil;
2434 DEFUN ("resume-tty", Fresume_tty, Sresume_tty, 0, 1, 0,
2435 doc: /* Resume the previously suspended terminal device TTY.
2436 The terminal is opened and reinitialized. Frames that are on the
2437 suspended terminal are revived.
2439 It is an error to resume a terminal while another terminal is active
2440 on the same device.
2442 This function runs `resume-tty-functions' after resuming the terminal.
2443 The functions are run with one arg, the id of the resumed terminal
2444 device.
2446 `resume-tty' does nothing if it is called on a device that is not
2447 suspended.
2449 TTY may be a terminal object, a frame, or nil (meaning the selected
2450 frame's terminal). */)
2451 (tty)
2452 Lisp_Object tty;
2454 struct terminal *t = get_tty_terminal (tty, 1);
2455 int fd;
2457 if (!t)
2458 error ("Unknown tty device");
2460 if (!t->display_info.tty->input)
2462 if (get_named_tty (t->display_info.tty->name))
2463 error ("Cannot resume display while another display is active on the same device");
2465 #ifdef MSDOS
2466 t->display_info.tty->output = stdout;
2467 t->display_info.tty->input = stdin;
2468 #else /* !MSDOS */
2469 fd = emacs_open (t->display_info.tty->name, O_RDWR | O_NOCTTY, 0);
2471 if (fd == -1)
2472 error ("Can not reopen tty device %s: %s", t->display_info.tty->name, strerror (errno));
2474 if (strcmp (t->display_info.tty->name, DEV_TTY))
2475 dissociate_if_controlling_tty (fd);
2477 t->display_info.tty->output = fdopen (fd, "w+");
2478 t->display_info.tty->input = t->display_info.tty->output;
2479 #endif
2481 #ifdef subprocesses
2482 add_keyboard_wait_descriptor (fd);
2483 #endif
2485 if (FRAMEP (t->display_info.tty->top_frame))
2487 struct frame *f = XFRAME (t->display_info.tty->top_frame);
2488 int width, height;
2489 int old_height = FRAME_COLS (f);
2490 int old_width = FRAME_LINES (f);
2492 /* Check if terminal/window size has changed while the frame
2493 was suspended. */
2494 get_tty_size (fileno (t->display_info.tty->input), &width, &height);
2495 if (width != old_width || height != old_height)
2496 change_frame_size (f, height, width, 0, 0, 0);
2497 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
2500 init_sys_modes (t->display_info.tty);
2502 /* Run `resume-tty-functions'. */
2503 if (!NILP (Vrun_hooks))
2505 Lisp_Object args[2];
2506 args[0] = intern ("resume-tty-functions");
2507 XSETTERMINAL (args[1], t);
2508 Frun_hook_with_args (2, args);
2512 set_tty_hooks (t);
2514 return Qnil;
2518 /***********************************************************************
2519 Mouse
2520 ***********************************************************************/
2522 #ifdef HAVE_GPM
2523 void
2524 term_mouse_moveto (int x, int y)
2526 /* TODO: how to set mouse position?
2527 const char *name;
2528 int fd;
2529 name = (const char *) ttyname (0);
2530 fd = open (name, O_WRONLY);
2531 SOME_FUNCTION (x, y, fd);
2532 close (fd);
2533 last_mouse_x = x;
2534 last_mouse_y = y; */
2537 static void
2538 term_show_mouse_face (enum draw_glyphs_face draw)
2540 struct window *w = XWINDOW (mouse_face_window);
2541 int save_x, save_y;
2542 int i;
2544 struct frame *f = XFRAME (w->frame);
2545 struct tty_display_info *tty = FRAME_TTY (f);
2547 if (/* If window is in the process of being destroyed, don't bother
2548 to do anything. */
2549 w->current_matrix != NULL
2550 /* Recognize when we are called to operate on rows that don't exist
2551 anymore. This can happen when a window is split. */
2552 && mouse_face_end_row < w->current_matrix->nrows)
2554 /* write_glyphs writes at cursor position, so we need to
2555 temporarily move cursor coordinates to the beginning of
2556 the highlight region. */
2558 /* Save current cursor co-ordinates */
2559 save_y = curY (tty);
2560 save_x = curX (tty);
2562 /* Note that mouse_face_beg_row etc. are window relative. */
2563 for (i = mouse_face_beg_row; i <= mouse_face_end_row; i++)
2565 int start_hpos, end_hpos, nglyphs;
2566 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
2568 /* Don't do anything if row doesn't have valid contents. */
2569 if (!row->enabled_p)
2570 continue;
2572 /* For all but the first row, the highlight starts at column 0. */
2573 if (i == mouse_face_beg_row)
2574 start_hpos = mouse_face_beg_col;
2575 else
2576 start_hpos = 0;
2578 if (i == mouse_face_end_row)
2579 end_hpos = mouse_face_end_col;
2580 else
2582 end_hpos = row->used[TEXT_AREA];
2583 if (draw == DRAW_NORMAL_TEXT)
2584 row->fill_line_p = 1; /* Clear to end of line */
2587 if (end_hpos <= start_hpos)
2588 continue;
2589 /* Record that some glyphs of this row are displayed in
2590 mouse-face. */
2591 row->mouse_face_p = draw > 0;
2593 nglyphs = end_hpos - start_hpos;
2595 if (end_hpos >= row->used[TEXT_AREA])
2596 nglyphs = row->used[TEXT_AREA] - start_hpos;
2598 pos_y = row->y + WINDOW_TOP_EDGE_Y (w);
2599 pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos
2600 + WINDOW_LEFT_EDGE_X (w);
2602 cursor_to (f, pos_y, pos_x);
2604 if (draw == DRAW_MOUSE_FACE)
2606 tty_write_glyphs_with_face (f, row->glyphs[TEXT_AREA] + start_hpos,
2607 nglyphs, mouse_face_face_id);
2609 else /* draw == DRAW_NORMAL_TEXT */
2610 write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
2612 cursor_to (f, save_y, save_x);
2616 static void
2617 term_clear_mouse_face ()
2619 if (!NILP (mouse_face_window))
2620 term_show_mouse_face (DRAW_NORMAL_TEXT);
2622 mouse_face_beg_row = mouse_face_beg_col = -1;
2623 mouse_face_end_row = mouse_face_end_col = -1;
2624 mouse_face_window = Qnil;
2627 /* Find the glyph matrix position of buffer position POS in window W.
2628 *HPOS and *VPOS are set to the positions found. W's current glyphs
2629 must be up to date. If POS is above window start return (0, 0).
2630 If POS is after end of W, return end of last line in W.
2631 - taken from msdos.c */
2632 static int
2633 fast_find_position (struct window *w, int pos, int *hpos, int *vpos)
2635 int i, lastcol, line_start_position, maybe_next_line_p = 0;
2636 int yb = window_text_bottom_y (w);
2637 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0), *best_row = row;
2639 while (row->y < yb)
2641 if (row->used[TEXT_AREA])
2642 line_start_position = row->glyphs[TEXT_AREA]->charpos;
2643 else
2644 line_start_position = 0;
2646 if (line_start_position > pos)
2647 break;
2648 /* If the position sought is the end of the buffer,
2649 don't include the blank lines at the bottom of the window. */
2650 else if (line_start_position == pos
2651 && pos == BUF_ZV (XBUFFER (w->buffer)))
2653 maybe_next_line_p = 1;
2654 break;
2656 else if (line_start_position > 0)
2657 best_row = row;
2659 /* Don't overstep the last matrix row, lest we get into the
2660 never-never land... */
2661 if (row->y + 1 >= yb)
2662 break;
2664 ++row;
2667 /* Find the right column within BEST_ROW. */
2668 lastcol = 0;
2669 row = best_row;
2670 for (i = 0; i < row->used[TEXT_AREA]; i++)
2672 struct glyph *glyph = row->glyphs[TEXT_AREA] + i;
2673 int charpos;
2675 charpos = glyph->charpos;
2676 if (charpos == pos)
2678 *hpos = i;
2679 *vpos = row->y;
2680 return 1;
2682 else if (charpos > pos)
2683 break;
2684 else if (charpos > 0)
2685 lastcol = i;
2688 /* If we're looking for the end of the buffer,
2689 and we didn't find it in the line we scanned,
2690 use the start of the following line. */
2691 if (maybe_next_line_p)
2693 ++row;
2694 lastcol = 0;
2697 *vpos = row->y;
2698 *hpos = lastcol + 1;
2699 return 0;
2702 static void
2703 term_mouse_highlight (struct frame *f, int x, int y)
2705 enum window_part part;
2706 Lisp_Object window;
2707 struct window *w;
2708 struct buffer *b;
2710 if (NILP (Vmouse_highlight)
2711 || !f->glyphs_initialized_p)
2712 return;
2714 /* Which window is that in? */
2715 window = window_from_coordinates (f, x, y, &part, &x, &y, 0);
2717 /* Not on a window -> return. */
2718 if (!WINDOWP (window))
2719 return;
2721 if (!EQ (window, mouse_face_window))
2722 term_clear_mouse_face ();
2724 w = XWINDOW (window);
2726 /* Are we in a window whose display is up to date?
2727 And verify the buffer's text has not changed. */
2728 b = XBUFFER (w->buffer);
2729 if (part == ON_TEXT
2730 && EQ (w->window_end_valid, w->buffer)
2731 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
2732 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
2734 int pos, i, nrows = w->current_matrix->nrows;
2735 struct glyph_row *row;
2736 struct glyph *glyph;
2738 /* Find the glyph under X/Y. */
2739 glyph = NULL;
2740 if (y >= 0 && y < nrows)
2742 row = MATRIX_ROW (w->current_matrix, y);
2743 /* Give up if some row before the one we are looking for is
2744 not enabled. */
2745 for (i = 0; i <= y; i++)
2746 if (!MATRIX_ROW (w->current_matrix, i)->enabled_p)
2747 break;
2748 if (i > y /* all rows upto and including the one at Y are enabled */
2749 && row->displays_text_p
2750 && x < window_box_width (w, TEXT_AREA))
2752 glyph = row->glyphs[TEXT_AREA];
2753 if (x >= row->used[TEXT_AREA])
2754 glyph = NULL;
2755 else
2757 glyph += x;
2758 if (!BUFFERP (glyph->object))
2759 glyph = NULL;
2764 /* Clear mouse face if X/Y not over text. */
2765 if (glyph == NULL)
2767 term_clear_mouse_face ();
2768 return;
2771 if (!BUFFERP (glyph->object))
2772 abort ();
2773 pos = glyph->charpos;
2775 /* Check for mouse-face. */
2777 extern Lisp_Object Qmouse_face;
2778 Lisp_Object mouse_face, overlay, position, *overlay_vec;
2779 int noverlays, obegv, ozv;
2780 struct buffer *obuf;
2782 /* If we get an out-of-range value, return now; avoid an error. */
2783 if (pos > BUF_Z (b))
2784 return;
2786 /* Make the window's buffer temporarily current for
2787 overlays_at and compute_char_face. */
2788 obuf = current_buffer;
2789 current_buffer = b;
2790 obegv = BEGV;
2791 ozv = ZV;
2792 BEGV = BEG;
2793 ZV = Z;
2795 /* Is this char mouse-active? */
2796 XSETINT (position, pos);
2798 /* Put all the overlays we want in a vector in overlay_vec. */
2799 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL, 0);
2800 /* Sort overlays into increasing priority order. */
2801 noverlays = sort_overlays (overlay_vec, noverlays, w);
2803 /* Check mouse-face highlighting. */
2804 if (!(EQ (window, mouse_face_window)
2805 && y >= mouse_face_beg_row
2806 && y <= mouse_face_end_row
2807 && (y > mouse_face_beg_row
2808 || x >= mouse_face_beg_col)
2809 && (y < mouse_face_end_row
2810 || x < mouse_face_end_col
2811 || mouse_face_past_end)))
2813 /* Clear the display of the old active region, if any. */
2814 term_clear_mouse_face ();
2816 /* Find the highest priority overlay that has a mouse-face
2817 property. */
2818 overlay = Qnil;
2819 for (i = noverlays - 1; i >= 0; --i)
2821 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
2822 if (!NILP (mouse_face))
2824 overlay = overlay_vec[i];
2825 break;
2829 /* If no overlay applies, get a text property. */
2830 if (NILP (overlay))
2831 mouse_face = Fget_text_property (position, Qmouse_face,
2832 w->buffer);
2834 /* Handle the overlay case. */
2835 if (!NILP (overlay))
2837 /* Find the range of text around this char that
2838 should be active. */
2839 Lisp_Object before, after;
2840 EMACS_INT ignore;
2843 before = Foverlay_start (overlay);
2844 after = Foverlay_end (overlay);
2845 /* Record this as the current active region. */
2846 fast_find_position (w, XFASTINT (before),
2847 &mouse_face_beg_col,
2848 &mouse_face_beg_row);
2850 mouse_face_past_end
2851 = !fast_find_position (w, XFASTINT (after),
2852 &mouse_face_end_col,
2853 &mouse_face_end_row);
2854 mouse_face_window = window;
2856 mouse_face_face_id
2857 = face_at_buffer_position (w, pos, 0, 0,
2858 &ignore, pos + 1, 1, -1);
2860 /* Display it as active. */
2861 term_show_mouse_face (DRAW_MOUSE_FACE);
2863 /* Handle the text property case. */
2864 else if (!NILP (mouse_face))
2866 /* Find the range of text around this char that
2867 should be active. */
2868 Lisp_Object before, after, beginning, end;
2869 EMACS_INT ignore;
2871 beginning = Fmarker_position (w->start);
2872 XSETINT (end, (BUF_Z (b) - XFASTINT (w->window_end_pos)));
2873 before
2874 = Fprevious_single_property_change (make_number (pos + 1),
2875 Qmouse_face,
2876 w->buffer, beginning);
2877 after
2878 = Fnext_single_property_change (position, Qmouse_face,
2879 w->buffer, end);
2881 /* Record this as the current active region. */
2882 fast_find_position (w, XFASTINT (before),
2883 &mouse_face_beg_col,
2884 &mouse_face_beg_row);
2885 mouse_face_past_end
2886 = !fast_find_position (w, XFASTINT (after),
2887 &mouse_face_end_col,
2888 &mouse_face_end_row);
2889 mouse_face_window = window;
2891 mouse_face_face_id
2892 = face_at_buffer_position (w, pos, 0, 0,
2893 &ignore, pos + 1, 1, -1);
2895 /* Display it as active. */
2896 term_show_mouse_face (DRAW_MOUSE_FACE);
2900 /* Look for a `help-echo' property. */
2902 Lisp_Object help;
2903 extern Lisp_Object Qhelp_echo;
2905 /* Check overlays first. */
2906 help = Qnil;
2907 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
2909 overlay = overlay_vec[i];
2910 help = Foverlay_get (overlay, Qhelp_echo);
2913 if (!NILP (help))
2915 help_echo_string = help;
2916 help_echo_window = window;
2917 help_echo_object = overlay;
2918 help_echo_pos = pos;
2920 /* Try text properties. */
2921 else if (NILP (help)
2922 && ((STRINGP (glyph->object)
2923 && glyph->charpos >= 0
2924 && glyph->charpos < SCHARS (glyph->object))
2925 || (BUFFERP (glyph->object)
2926 && glyph->charpos >= BEGV
2927 && glyph->charpos < ZV)))
2929 help = Fget_text_property (make_number (glyph->charpos),
2930 Qhelp_echo, glyph->object);
2931 if (!NILP (help))
2933 help_echo_string = help;
2934 help_echo_window = window;
2935 help_echo_object = glyph->object;
2936 help_echo_pos = glyph->charpos;
2941 BEGV = obegv;
2942 ZV = ozv;
2943 current_buffer = obuf;
2948 static int
2949 term_mouse_movement (FRAME_PTR frame, Gpm_Event *event)
2951 /* Has the mouse moved off the glyph it was on at the last sighting? */
2952 if (event->x != last_mouse_x || event->y != last_mouse_y)
2954 frame->mouse_moved = 1;
2955 term_mouse_highlight (frame, event->x, event->y);
2956 /* Remember which glyph we're now on. */
2957 last_mouse_x = event->x;
2958 last_mouse_y = event->y;
2959 return 1;
2961 return 0;
2964 /* Return the current position of the mouse.
2966 Set *f to the frame the mouse is in, or zero if the mouse is in no
2967 Emacs frame. If it is set to zero, all the other arguments are
2968 garbage.
2970 Set *bar_window to Qnil, and *x and *y to the column and
2971 row of the character cell the mouse is over.
2973 Set *time to the time the mouse was at the returned position.
2975 This clears mouse_moved until the next motion
2976 event arrives. */
2977 static void
2978 term_mouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
2979 enum scroll_bar_part *part, Lisp_Object *x,
2980 Lisp_Object *y, unsigned long *time)
2982 struct timeval now;
2984 *fp = SELECTED_FRAME ();
2985 (*fp)->mouse_moved = 0;
2987 *bar_window = Qnil;
2988 *part = 0;
2990 XSETINT (*x, last_mouse_x);
2991 XSETINT (*y, last_mouse_y);
2992 gettimeofday(&now, 0);
2993 *time = (now.tv_sec * 1000) + (now.tv_usec / 1000);
2996 /* Prepare a mouse-event in *RESULT for placement in the input queue.
2998 If the event is a button press, then note that we have grabbed
2999 the mouse. */
3001 static Lisp_Object
3002 term_mouse_click (struct input_event *result, Gpm_Event *event,
3003 struct frame *f)
3005 struct timeval now;
3006 int i, j;
3008 result->kind = GPM_CLICK_EVENT;
3009 for (i = 0, j = GPM_B_LEFT; i < 3; i++, j >>= 1 )
3011 if (event->buttons & j) {
3012 result->code = i; /* button number */
3013 break;
3016 gettimeofday(&now, 0);
3017 result->timestamp = (now.tv_sec * 1000) + (now.tv_usec / 1000);
3019 if (event->type & GPM_UP)
3020 result->modifiers = up_modifier;
3021 else if (event->type & GPM_DOWN)
3022 result->modifiers = down_modifier;
3023 else
3024 result->modifiers = 0;
3026 if (event->type & GPM_SINGLE)
3027 result->modifiers |= click_modifier;
3029 if (event->type & GPM_DOUBLE)
3030 result->modifiers |= double_modifier;
3032 if (event->type & GPM_TRIPLE)
3033 result->modifiers |= triple_modifier;
3035 if (event->type & GPM_DRAG)
3036 result->modifiers |= drag_modifier;
3038 if (!(event->type & (GPM_MOVE | GPM_DRAG))) {
3040 /* 1 << KG_SHIFT */
3041 if (event->modifiers & (1 << 0))
3042 result->modifiers |= shift_modifier;
3044 /* 1 << KG_CTRL */
3045 if (event->modifiers & (1 << 2))
3046 result->modifiers |= ctrl_modifier;
3048 /* 1 << KG_ALT || KG_ALTGR */
3049 if (event->modifiers & (1 << 3)
3050 || event->modifiers & (1 << 1))
3051 result->modifiers |= meta_modifier;
3054 XSETINT (result->x, event->x);
3055 XSETINT (result->y, event->y);
3056 XSETFRAME (result->frame_or_window, f);
3057 result->arg = Qnil;
3058 return Qnil;
3062 handle_one_term_event (struct tty_display_info *tty, Gpm_Event *event, struct input_event* hold_quit)
3064 struct frame *f = XFRAME (tty->top_frame);
3065 struct input_event ie;
3066 int do_help = 0;
3067 int count = 0;
3069 EVENT_INIT (ie);
3070 ie.kind = NO_EVENT;
3071 ie.arg = Qnil;
3073 if (event->type & (GPM_MOVE | GPM_DRAG)) {
3074 previous_help_echo_string = help_echo_string;
3075 help_echo_string = Qnil;
3077 Gpm_DrawPointer (event->x, event->y, fileno (tty->output));
3079 if (!term_mouse_movement (f, event))
3080 help_echo_string = previous_help_echo_string;
3082 /* If the contents of the global variable help_echo_string
3083 has changed, generate a HELP_EVENT. */
3084 if (!NILP (help_echo_string)
3085 || !NILP (previous_help_echo_string))
3086 do_help = 1;
3088 goto done;
3090 else {
3091 f->mouse_moved = 0;
3092 term_mouse_click (&ie, event, f);
3095 done:
3096 if (ie.kind != NO_EVENT)
3098 kbd_buffer_store_event_hold (&ie, hold_quit);
3099 count++;
3102 if (do_help
3103 && !(hold_quit && hold_quit->kind != NO_EVENT))
3105 Lisp_Object frame;
3107 if (f)
3108 XSETFRAME (frame, f);
3109 else
3110 frame = Qnil;
3112 gen_help_event (help_echo_string, frame, help_echo_window,
3113 help_echo_object, help_echo_pos);
3114 count++;
3117 return count;
3120 DEFUN ("gpm-mouse-start", Fgpm_mouse_start, Sgpm_mouse_start,
3121 0, 0, 0,
3122 doc: /* Open a connection to Gpm.
3123 Gpm-mouse can only be activated for one tty at a time. */)
3126 struct frame *f = SELECTED_FRAME ();
3127 struct tty_display_info *tty
3128 = ((f)->output_method == output_termcap
3129 ? (f)->terminal->display_info.tty : NULL);
3130 Gpm_Connect connection;
3132 if (!tty)
3133 error ("Gpm-mouse only works in the GNU/Linux console");
3134 if (gpm_tty == tty)
3135 return Qnil; /* Already activated, nothing to do. */
3136 if (gpm_tty)
3137 error ("Gpm-mouse can only be activated for one tty at a time");
3139 connection.eventMask = ~0;
3140 connection.defaultMask = ~GPM_HARD;
3141 connection.maxMod = ~0;
3142 connection.minMod = 0;
3143 gpm_zerobased = 1;
3145 if (Gpm_Open (&connection, 0) < 0)
3146 error ("Gpm-mouse failed to connect to the gpm daemon");
3147 else
3149 gpm_tty = tty;
3150 /* `init_sys_modes' arranges for mouse movements sent through gpm_fd
3151 to generate SIGIOs. Apparently we need to call reset_sys_modes
3152 before calling init_sys_modes. */
3153 reset_sys_modes (tty);
3154 init_sys_modes (tty);
3155 add_gpm_wait_descriptor (gpm_fd);
3156 return Qnil;
3160 void
3161 close_gpm (int fd)
3163 if (fd >= 0)
3164 delete_gpm_wait_descriptor (fd);
3165 while (Gpm_Close()); /* close all the stack */
3166 gpm_tty = NULL;
3169 DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop, Sgpm_mouse_stop,
3170 0, 0, 0,
3171 doc: /* Close a connection to Gpm. */)
3174 struct frame *f = SELECTED_FRAME ();
3175 struct tty_display_info *tty
3176 = ((f)->output_method == output_termcap
3177 ? (f)->terminal->display_info.tty : NULL);
3179 if (!tty || gpm_tty != tty)
3180 return Qnil; /* Not activated on this terminal, nothing to do. */
3182 close_gpm (gpm_fd);
3183 return Qnil;
3185 #endif /* HAVE_GPM */
3188 #ifndef MSDOS
3189 /***********************************************************************
3190 Initialization
3191 ***********************************************************************/
3193 /* Initialize the tty-dependent part of frame F. The frame must
3194 already have its device initialized. */
3196 void
3197 create_tty_output (struct frame *f)
3199 struct tty_output *t;
3201 if (! FRAME_TERMCAP_P (f))
3202 abort ();
3204 t = xmalloc (sizeof (struct tty_output));
3205 bzero (t, sizeof (struct tty_output));
3207 t->display_info = FRAME_TERMINAL (f)->display_info.tty;
3209 f->output_data.tty = t;
3212 /* Delete frame F's face cache, and its tty-dependent part. */
3214 static void
3215 tty_free_frame_resources (struct frame *f)
3217 if (! FRAME_TERMCAP_P (f))
3218 abort ();
3220 if (FRAME_FACE_CACHE (f))
3221 free_frame_faces (f);
3223 xfree (f->output_data.tty);
3226 #else /* MSDOS */
3228 /* Delete frame F's face cache. */
3230 static void
3231 tty_free_frame_resources (struct frame *f)
3233 if (! FRAME_TERMCAP_P (f) && ! FRAME_MSDOS_P (f))
3234 abort ();
3236 if (FRAME_FACE_CACHE (f))
3237 free_frame_faces (f);
3239 #endif /* MSDOS */
3241 /* Reset the hooks in TERMINAL. */
3243 static void
3244 clear_tty_hooks (struct terminal *terminal)
3246 terminal->rif = 0;
3247 terminal->cursor_to_hook = 0;
3248 terminal->raw_cursor_to_hook = 0;
3249 terminal->clear_to_end_hook = 0;
3250 terminal->clear_frame_hook = 0;
3251 terminal->clear_end_of_line_hook = 0;
3252 terminal->ins_del_lines_hook = 0;
3253 terminal->insert_glyphs_hook = 0;
3254 terminal->write_glyphs_hook = 0;
3255 terminal->delete_glyphs_hook = 0;
3256 terminal->ring_bell_hook = 0;
3257 terminal->reset_terminal_modes_hook = 0;
3258 terminal->set_terminal_modes_hook = 0;
3259 terminal->update_begin_hook = 0;
3260 terminal->update_end_hook = 0;
3261 terminal->set_terminal_window_hook = 0;
3262 terminal->mouse_position_hook = 0;
3263 terminal->frame_rehighlight_hook = 0;
3264 terminal->frame_raise_lower_hook = 0;
3265 terminal->fullscreen_hook = 0;
3266 terminal->set_vertical_scroll_bar_hook = 0;
3267 terminal->condemn_scroll_bars_hook = 0;
3268 terminal->redeem_scroll_bar_hook = 0;
3269 terminal->judge_scroll_bars_hook = 0;
3270 terminal->read_socket_hook = 0;
3271 terminal->frame_up_to_date_hook = 0;
3273 /* Leave these two set, or suspended frames are not deleted
3274 correctly. */
3275 terminal->delete_frame_hook = &tty_free_frame_resources;
3276 terminal->delete_terminal_hook = &delete_tty;
3279 /* Initialize hooks in TERMINAL with the values needed for a tty. */
3281 static void
3282 set_tty_hooks (struct terminal *terminal)
3284 terminal->rif = 0; /* ttys don't support window-based redisplay. */
3286 terminal->cursor_to_hook = &tty_cursor_to;
3287 terminal->raw_cursor_to_hook = &tty_raw_cursor_to;
3289 terminal->clear_to_end_hook = &tty_clear_to_end;
3290 terminal->clear_frame_hook = &tty_clear_frame;
3291 terminal->clear_end_of_line_hook = &tty_clear_end_of_line;
3293 terminal->ins_del_lines_hook = &tty_ins_del_lines;
3295 terminal->insert_glyphs_hook = &tty_insert_glyphs;
3296 terminal->write_glyphs_hook = &tty_write_glyphs;
3297 terminal->delete_glyphs_hook = &tty_delete_glyphs;
3299 terminal->ring_bell_hook = &tty_ring_bell;
3301 terminal->reset_terminal_modes_hook = &tty_reset_terminal_modes;
3302 terminal->set_terminal_modes_hook = &tty_set_terminal_modes;
3303 terminal->update_begin_hook = 0; /* Not needed. */
3304 terminal->update_end_hook = &tty_update_end;
3305 terminal->set_terminal_window_hook = &tty_set_terminal_window;
3307 terminal->mouse_position_hook = 0; /* Not needed. */
3308 terminal->frame_rehighlight_hook = 0; /* Not needed. */
3309 terminal->frame_raise_lower_hook = 0; /* Not needed. */
3311 terminal->set_vertical_scroll_bar_hook = 0; /* Not needed. */
3312 terminal->condemn_scroll_bars_hook = 0; /* Not needed. */
3313 terminal->redeem_scroll_bar_hook = 0; /* Not needed. */
3314 terminal->judge_scroll_bars_hook = 0; /* Not needed. */
3316 terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */
3317 terminal->frame_up_to_date_hook = 0; /* Not needed. */
3319 terminal->delete_frame_hook = &tty_free_frame_resources;
3320 terminal->delete_terminal_hook = &delete_tty;
3323 /* Drop the controlling terminal if fd is the same device. */
3324 static void
3325 dissociate_if_controlling_tty (int fd)
3327 #ifndef DOS_NT
3328 int pgid;
3329 EMACS_GET_TTY_PGRP (fd, &pgid); /* If tcgetpgrp succeeds, fd is the ctty. */
3330 if (pgid != -1)
3332 #if defined (USG) && !defined (BSD_PGRPS)
3333 setpgrp ();
3334 no_controlling_tty = 1;
3335 #elif defined (CYGWIN)
3336 setsid ();
3337 no_controlling_tty = 1;
3338 #else
3339 #ifdef TIOCNOTTY /* Try BSD ioctls. */
3340 sigblock (sigmask (SIGTTOU));
3341 fd = emacs_open (DEV_TTY, O_RDWR, 0);
3342 if (fd != -1 && ioctl (fd, TIOCNOTTY, 0) != -1)
3344 no_controlling_tty = 1;
3346 if (fd != -1)
3347 emacs_close (fd);
3348 sigunblock (sigmask (SIGTTOU));
3349 #else
3350 /* Unknown system. */
3351 croak ();
3352 #endif /* ! TIOCNOTTY */
3353 #endif /* ! USG */
3355 #endif /* !DOS_NT */
3358 static void maybe_fatal();
3360 /* Create a termcap display on the tty device with the given name and
3361 type.
3363 If NAME is NULL, then use the controlling tty, i.e., "/dev/tty".
3364 Otherwise NAME should be a path to the tty device file,
3365 e.g. "/dev/pts/7".
3367 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
3369 If MUST_SUCCEED is true, then all errors are fatal. */
3371 struct terminal *
3372 init_tty (char *name, char *terminal_type, int must_succeed)
3374 char *area = NULL;
3375 char **address = &area;
3376 int buffer_size = 4096;
3377 register char *p = NULL;
3378 int status;
3379 struct tty_display_info *tty = NULL;
3380 struct terminal *terminal = NULL;
3381 int ctty = 0; /* 1 if asked to open controlling tty. */
3383 if (!terminal_type)
3384 maybe_fatal (must_succeed, 0,
3385 "Unknown terminal type",
3386 "Unknown terminal type");
3388 if (name == NULL)
3389 name = DEV_TTY;
3390 if (!strcmp (name, DEV_TTY))
3391 ctty = 1;
3393 /* If we already have a terminal on the given device, use that. If
3394 all such terminals are suspended, create a new one instead. */
3395 /* XXX Perhaps this should be made explicit by having init_tty
3396 always create a new terminal and separating terminal and frame
3397 creation on Lisp level. */
3398 terminal = get_named_tty (name);
3399 if (terminal)
3400 return terminal;
3402 terminal = create_terminal ();
3403 #ifdef MSDOS
3404 if (been_here > 0)
3405 maybe_fatal (1, 0, "Attempt to create another terminal %s", "",
3406 name, "");
3407 been_here = 1;
3408 tty = &the_only_display_info;
3409 #else
3410 tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info));
3411 #endif
3412 bzero (tty, sizeof (struct tty_display_info));
3413 tty->next = tty_list;
3414 tty_list = tty;
3416 terminal->type = output_termcap;
3417 terminal->display_info.tty = tty;
3418 tty->terminal = terminal;
3420 tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
3421 Wcm_clear (tty);
3423 #ifndef DOS_NT
3424 set_tty_hooks (terminal);
3427 int fd;
3428 FILE *file;
3430 #ifdef O_IGNORE_CTTY
3431 if (!ctty)
3432 /* Open the terminal device. Don't recognize it as our
3433 controlling terminal, and don't make it the controlling tty
3434 if we don't have one at the moment. */
3435 fd = emacs_open (name, O_RDWR | O_IGNORE_CTTY | O_NOCTTY, 0);
3436 else
3437 #else
3438 /* Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
3439 defined on Hurd. On other systems, we need to explicitly
3440 dissociate ourselves from the controlling tty when we want to
3441 open a frame on the same terminal. */
3442 fd = emacs_open (name, O_RDWR | O_NOCTTY, 0);
3443 #endif /* O_IGNORE_CTTY */
3445 tty->name = xstrdup (name);
3446 terminal->name = xstrdup (name);
3448 if (fd < 0)
3449 maybe_fatal (must_succeed, terminal,
3450 "Could not open file: %s",
3451 "Could not open file: %s",
3452 name);
3453 if (!isatty (fd))
3455 close (fd);
3456 maybe_fatal (must_succeed, terminal,
3457 "Not a tty device: %s",
3458 "Not a tty device: %s",
3459 name);
3462 #ifndef O_IGNORE_CTTY
3463 if (!ctty)
3464 dissociate_if_controlling_tty (fd);
3465 #endif
3467 file = fdopen (fd, "w+");
3468 tty->input = file;
3469 tty->output = file;
3472 tty->type = xstrdup (terminal_type);
3474 add_keyboard_wait_descriptor (fileno (tty->input));
3476 #endif /* !DOS_NT */
3478 encode_terminal_src_size = 0;
3479 encode_terminal_dst_size = 0;
3481 #ifdef HAVE_GPM
3482 terminal->mouse_position_hook = term_mouse_position;
3483 mouse_face_window = Qnil;
3484 #endif
3486 #ifdef DOS_NT
3487 #ifdef WINDOWSNT
3488 initialize_w32_display (terminal);
3489 #else /* MSDOS */
3490 if (strcmp (terminal_type, "internal") == 0)
3491 terminal->type = output_msdos_raw;
3492 initialize_msdos_display (terminal);
3493 #endif /* MSDOS */
3494 tty->output = stdout;
3495 tty->input = stdin;
3496 /* The following two are inaccessible from w32console.c. */
3497 terminal->delete_frame_hook = &tty_free_frame_resources;
3498 terminal->delete_terminal_hook = &delete_tty;
3500 tty->name = xstrdup (name);
3501 terminal->name = xstrdup (name);
3502 tty->type = xstrdup (terminal_type);
3504 #ifdef subprocesses
3505 add_keyboard_wait_descriptor (0);
3506 #endif
3508 Wcm_clear (tty);
3510 #ifdef WINDOWSNT
3512 struct frame *f = XFRAME (selected_frame);
3514 FrameRows (tty) = FRAME_LINES (f);
3515 FrameCols (tty) = FRAME_COLS (f);
3516 tty->specified_window = FRAME_LINES (f);
3518 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
3519 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
3521 #else /* MSDOS */
3523 int height, width;
3524 get_tty_size (fileno (tty->input), &width, &height);
3525 FrameCols (tty) = width;
3526 FrameRows (tty) = height;
3528 #endif /* MSDOS */
3529 tty->delete_in_insert_mode = 1;
3531 UseTabs (tty) = 0;
3532 terminal->scroll_region_ok = 0;
3534 /* Seems to insert lines when it's not supposed to, messing up the
3535 display. In doing a trace, it didn't seem to be called much, so I
3536 don't think we're losing anything by turning it off. */
3537 terminal->line_ins_del_ok = 0;
3538 #ifdef WINDOWSNT
3539 terminal->char_ins_del_ok = 1;
3540 baud_rate = 19200;
3541 #else /* MSDOS */
3542 terminal->char_ins_del_ok = 0;
3543 init_baud_rate (fileno (tty->input));
3544 #endif /* MSDOS */
3546 tty->TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
3548 #else /* not DOS_NT */
3550 Wcm_clear (tty);
3552 tty->termcap_term_buffer = (char *) xmalloc (buffer_size);
3554 /* On some systems, tgetent tries to access the controlling
3555 terminal. */
3556 sigblock (sigmask (SIGTTOU));
3557 status = tgetent (tty->termcap_term_buffer, terminal_type);
3558 sigunblock (sigmask (SIGTTOU));
3560 if (status < 0)
3562 #ifdef TERMINFO
3563 maybe_fatal (must_succeed, terminal,
3564 "Cannot open terminfo database file",
3565 "Cannot open terminfo database file");
3566 #else
3567 maybe_fatal (must_succeed, terminal,
3568 "Cannot open termcap database file",
3569 "Cannot open termcap database file");
3570 #endif
3572 if (status == 0)
3574 #ifdef TERMINFO
3575 maybe_fatal (must_succeed, terminal,
3576 "Terminal type %s is not defined",
3577 "Terminal type %s is not defined.\n\
3578 If that is not the actual type of terminal you have,\n\
3579 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3580 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3581 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3582 terminal_type);
3583 #else
3584 maybe_fatal (must_succeed, terminal,
3585 "Terminal type %s is not defined",
3586 "Terminal type %s is not defined.\n\
3587 If that is not the actual type of terminal you have,\n\
3588 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3589 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3590 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3591 terminal_type);
3592 #endif
3595 #ifndef TERMINFO
3596 if (strlen (tty->termcap_term_buffer) >= buffer_size)
3597 abort ();
3598 buffer_size = strlen (tty->termcap_term_buffer);
3599 #endif
3600 tty->termcap_strings_buffer = area = (char *) xmalloc (buffer_size);
3601 tty->TS_ins_line = tgetstr ("al", address);
3602 tty->TS_ins_multi_lines = tgetstr ("AL", address);
3603 tty->TS_bell = tgetstr ("bl", address);
3604 BackTab (tty) = tgetstr ("bt", address);
3605 tty->TS_clr_to_bottom = tgetstr ("cd", address);
3606 tty->TS_clr_line = tgetstr ("ce", address);
3607 tty->TS_clr_frame = tgetstr ("cl", address);
3608 ColPosition (tty) = NULL; /* tgetstr ("ch", address); */
3609 AbsPosition (tty) = tgetstr ("cm", address);
3610 CR (tty) = tgetstr ("cr", address);
3611 tty->TS_set_scroll_region = tgetstr ("cs", address);
3612 tty->TS_set_scroll_region_1 = tgetstr ("cS", address);
3613 RowPosition (tty) = tgetstr ("cv", address);
3614 tty->TS_del_char = tgetstr ("dc", address);
3615 tty->TS_del_multi_chars = tgetstr ("DC", address);
3616 tty->TS_del_line = tgetstr ("dl", address);
3617 tty->TS_del_multi_lines = tgetstr ("DL", address);
3618 tty->TS_delete_mode = tgetstr ("dm", address);
3619 tty->TS_end_delete_mode = tgetstr ("ed", address);
3620 tty->TS_end_insert_mode = tgetstr ("ei", address);
3621 Home (tty) = tgetstr ("ho", address);
3622 tty->TS_ins_char = tgetstr ("ic", address);
3623 tty->TS_ins_multi_chars = tgetstr ("IC", address);
3624 tty->TS_insert_mode = tgetstr ("im", address);
3625 tty->TS_pad_inserted_char = tgetstr ("ip", address);
3626 tty->TS_end_keypad_mode = tgetstr ("ke", address);
3627 tty->TS_keypad_mode = tgetstr ("ks", address);
3628 LastLine (tty) = tgetstr ("ll", address);
3629 Right (tty) = tgetstr ("nd", address);
3630 Down (tty) = tgetstr ("do", address);
3631 if (!Down (tty))
3632 Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do" */
3633 if (tgetflag ("bs"))
3634 Left (tty) = "\b"; /* can't possibly be longer! */
3635 else /* (Actually, "bs" is obsolete...) */
3636 Left (tty) = tgetstr ("le", address);
3637 if (!Left (tty))
3638 Left (tty) = tgetstr ("bc", address); /* Obsolete name for "le" */
3639 tty->TS_pad_char = tgetstr ("pc", address);
3640 tty->TS_repeat = tgetstr ("rp", address);
3641 tty->TS_end_standout_mode = tgetstr ("se", address);
3642 tty->TS_fwd_scroll = tgetstr ("sf", address);
3643 tty->TS_standout_mode = tgetstr ("so", address);
3644 tty->TS_rev_scroll = tgetstr ("sr", address);
3645 tty->Wcm->cm_tab = tgetstr ("ta", address);
3646 tty->TS_end_termcap_modes = tgetstr ("te", address);
3647 tty->TS_termcap_modes = tgetstr ("ti", address);
3648 Up (tty) = tgetstr ("up", address);
3649 tty->TS_visible_bell = tgetstr ("vb", address);
3650 tty->TS_cursor_normal = tgetstr ("ve", address);
3651 tty->TS_cursor_visible = tgetstr ("vs", address);
3652 tty->TS_cursor_invisible = tgetstr ("vi", address);
3653 tty->TS_set_window = tgetstr ("wi", address);
3655 tty->TS_enter_underline_mode = tgetstr ("us", address);
3656 tty->TS_exit_underline_mode = tgetstr ("ue", address);
3657 tty->TS_enter_bold_mode = tgetstr ("md", address);
3658 tty->TS_enter_dim_mode = tgetstr ("mh", address);
3659 tty->TS_enter_blink_mode = tgetstr ("mb", address);
3660 tty->TS_enter_reverse_mode = tgetstr ("mr", address);
3661 tty->TS_enter_alt_charset_mode = tgetstr ("as", address);
3662 tty->TS_exit_alt_charset_mode = tgetstr ("ae", address);
3663 tty->TS_exit_attribute_mode = tgetstr ("me", address);
3665 MultiUp (tty) = tgetstr ("UP", address);
3666 MultiDown (tty) = tgetstr ("DO", address);
3667 MultiLeft (tty) = tgetstr ("LE", address);
3668 MultiRight (tty) = tgetstr ("RI", address);
3670 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
3671 color because we can't switch back to the default foreground and
3672 background. */
3673 tty->TS_orig_pair = tgetstr ("op", address);
3674 if (tty->TS_orig_pair)
3676 tty->TS_set_foreground = tgetstr ("AF", address);
3677 tty->TS_set_background = tgetstr ("AB", address);
3678 if (!tty->TS_set_foreground)
3680 /* SVr4. */
3681 tty->TS_set_foreground = tgetstr ("Sf", address);
3682 tty->TS_set_background = tgetstr ("Sb", address);
3685 tty->TN_max_colors = tgetnum ("Co");
3686 tty->TN_max_pairs = tgetnum ("pa");
3688 tty->TN_no_color_video = tgetnum ("NC");
3689 if (tty->TN_no_color_video == -1)
3690 tty->TN_no_color_video = 0;
3693 tty_default_color_capabilities (tty, 1);
3695 MagicWrap (tty) = tgetflag ("xn");
3696 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
3697 the former flag imply the latter. */
3698 AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
3699 terminal->memory_below_frame = tgetflag ("db");
3700 tty->TF_hazeltine = tgetflag ("hz");
3701 terminal->must_write_spaces = tgetflag ("in");
3702 tty->meta_key = tgetflag ("km") || tgetflag ("MT");
3703 tty->TF_insmode_motion = tgetflag ("mi");
3704 tty->TF_standout_motion = tgetflag ("ms");
3705 tty->TF_underscore = tgetflag ("ul");
3706 tty->TF_teleray = tgetflag ("xt");
3708 #endif /* !DOS_NT */
3709 terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
3710 init_kboard (terminal->kboard);
3711 terminal->kboard->Vwindow_system = Qnil;
3712 terminal->kboard->next_kboard = all_kboards;
3713 all_kboards = terminal->kboard;
3714 terminal->kboard->reference_count++;
3715 /* Don't let the initial kboard remain current longer than necessary.
3716 That would cause problems if a file loaded on startup tries to
3717 prompt in the mini-buffer. */
3718 if (current_kboard == initial_kboard)
3719 current_kboard = terminal->kboard;
3720 #ifndef DOS_NT
3721 term_get_fkeys (address, terminal->kboard);
3723 /* Get frame size from system, or else from termcap. */
3725 int height, width;
3726 get_tty_size (fileno (tty->input), &width, &height);
3727 FrameCols (tty) = width;
3728 FrameRows (tty) = height;
3731 if (FrameCols (tty) <= 0)
3732 FrameCols (tty) = tgetnum ("co");
3733 if (FrameRows (tty) <= 0)
3734 FrameRows (tty) = tgetnum ("li");
3736 if (FrameRows (tty) < 3 || FrameCols (tty) < 3)
3737 maybe_fatal (must_succeed, terminal,
3738 "Screen size %dx%d is too small"
3739 "Screen size %dx%d is too small",
3740 FrameCols (tty), FrameRows (tty));
3742 TabWidth (tty) = tgetnum ("tw");
3744 if (!tty->TS_bell)
3745 tty->TS_bell = "\07";
3747 if (!tty->TS_fwd_scroll)
3748 tty->TS_fwd_scroll = Down (tty);
3750 PC = tty->TS_pad_char ? *tty->TS_pad_char : 0;
3752 if (TabWidth (tty) < 0)
3753 TabWidth (tty) = 8;
3755 /* Turned off since /etc/termcap seems to have :ta= for most terminals
3756 and newer termcap doc does not seem to say there is a default.
3757 if (!tty->Wcm->cm_tab)
3758 tty->Wcm->cm_tab = "\t";
3761 /* We don't support standout modes that use `magic cookies', so
3762 turn off any that do. */
3763 if (tty->TS_standout_mode && tgetnum ("sg") >= 0)
3765 tty->TS_standout_mode = 0;
3766 tty->TS_end_standout_mode = 0;
3768 if (tty->TS_enter_underline_mode && tgetnum ("ug") >= 0)
3770 tty->TS_enter_underline_mode = 0;
3771 tty->TS_exit_underline_mode = 0;
3774 /* If there's no standout mode, try to use underlining instead. */
3775 if (tty->TS_standout_mode == 0)
3777 tty->TS_standout_mode = tty->TS_enter_underline_mode;
3778 tty->TS_end_standout_mode = tty->TS_exit_underline_mode;
3781 /* If no `se' string, try using a `me' string instead.
3782 If that fails, we can't use standout mode at all. */
3783 if (tty->TS_end_standout_mode == 0)
3785 char *s = tgetstr ("me", address);
3786 if (s != 0)
3787 tty->TS_end_standout_mode = s;
3788 else
3789 tty->TS_standout_mode = 0;
3792 if (tty->TF_teleray)
3794 tty->Wcm->cm_tab = 0;
3795 /* We can't support standout mode, because it uses magic cookies. */
3796 tty->TS_standout_mode = 0;
3797 /* But that means we cannot rely on ^M to go to column zero! */
3798 CR (tty) = 0;
3799 /* LF can't be trusted either -- can alter hpos */
3800 /* if move at column 0 thru a line with TS_standout_mode */
3801 Down (tty) = 0;
3804 /* Special handling for certain terminal types known to need it */
3806 if (!strcmp (terminal_type, "supdup"))
3808 terminal->memory_below_frame = 1;
3809 tty->Wcm->cm_losewrap = 1;
3811 if (!strncmp (terminal_type, "c10", 3)
3812 || !strcmp (terminal_type, "perq"))
3814 /* Supply a makeshift :wi string.
3815 This string is not valid in general since it works only
3816 for windows starting at the upper left corner;
3817 but that is all Emacs uses.
3819 This string works only if the frame is using
3820 the top of the video memory, because addressing is memory-relative.
3821 So first check the :ti string to see if that is true.
3823 It would be simpler if the :wi string could go in the termcap
3824 entry, but it can't because it is not fully valid.
3825 If it were in the termcap entry, it would confuse other programs. */
3826 if (!tty->TS_set_window)
3828 p = tty->TS_termcap_modes;
3829 while (*p && strcmp (p, "\033v "))
3830 p++;
3831 if (*p)
3832 tty->TS_set_window = "\033v%C %C %C %C ";
3834 /* Termcap entry often fails to have :in: flag */
3835 terminal->must_write_spaces = 1;
3836 /* :ti string typically fails to have \E^G! in it */
3837 /* This limits scope of insert-char to one line. */
3838 strcpy (area, tty->TS_termcap_modes);
3839 strcat (area, "\033\007!");
3840 tty->TS_termcap_modes = area;
3841 area += strlen (area) + 1;
3842 p = AbsPosition (tty);
3843 /* Change all %+ parameters to %C, to handle
3844 values above 96 correctly for the C100. */
3845 while (*p)
3847 if (p[0] == '%' && p[1] == '+')
3848 p[1] = 'C';
3849 p++;
3853 tty->specified_window = FrameRows (tty);
3855 if (Wcm_init (tty) == -1) /* can't do cursor motion */
3857 maybe_fatal (must_succeed, terminal,
3858 "Terminal type \"%s\" is not powerful enough to run Emacs",
3859 # ifdef TERMINFO
3860 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3861 It lacks the ability to position the cursor.\n\
3862 If that is not the actual type of terminal you have,\n\
3863 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3864 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3865 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3866 # else /* TERMCAP */
3867 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3868 It lacks the ability to position the cursor.\n\
3869 If that is not the actual type of terminal you have,\n\
3870 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3871 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3872 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3873 # endif /* TERMINFO */
3874 terminal_type);
3877 if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
3878 maybe_fatal (must_succeed, terminal,
3879 "Could not determine the frame size",
3880 "Could not determine the frame size");
3882 tty->delete_in_insert_mode
3883 = tty->TS_delete_mode && tty->TS_insert_mode
3884 && !strcmp (tty->TS_delete_mode, tty->TS_insert_mode);
3886 tty->se_is_so = (tty->TS_standout_mode
3887 && tty->TS_end_standout_mode
3888 && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode));
3890 UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8;
3892 terminal->scroll_region_ok
3893 = (tty->Wcm->cm_abs
3894 && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
3896 terminal->line_ins_del_ok
3897 = (((tty->TS_ins_line || tty->TS_ins_multi_lines)
3898 && (tty->TS_del_line || tty->TS_del_multi_lines))
3899 || (terminal->scroll_region_ok
3900 && tty->TS_fwd_scroll && tty->TS_rev_scroll));
3902 terminal->char_ins_del_ok
3903 = ((tty->TS_ins_char || tty->TS_insert_mode
3904 || tty->TS_pad_inserted_char || tty->TS_ins_multi_chars)
3905 && (tty->TS_del_char || tty->TS_del_multi_chars));
3907 terminal->fast_clear_end_of_line = tty->TS_clr_line != 0;
3909 init_baud_rate (fileno (tty->input));
3911 #endif /* not DOS_NT */
3913 /* Init system terminal modes (RAW or CBREAK, etc.). */
3914 init_sys_modes (tty);
3916 return terminal;
3919 /* Auxiliary error-handling function for init_tty.
3920 Delete TERMINAL, then call error or fatal with str1 or str2,
3921 respectively, according to MUST_SUCCEED. */
3923 static void
3924 maybe_fatal (must_succeed, terminal, str1, str2, arg1, arg2)
3925 int must_succeed;
3926 struct terminal *terminal;
3927 char *str1, *str2, *arg1, *arg2;
3929 if (terminal)
3930 delete_tty (terminal);
3932 if (must_succeed)
3933 fatal (str2, arg1, arg2);
3934 else
3935 error (str1, arg1, arg2);
3937 abort ();
3940 void
3941 fatal (const char *str, ...)
3943 va_list ap;
3944 va_start (ap, str);
3945 fprintf (stderr, "emacs: ");
3946 vfprintf (stderr, str, ap);
3947 if (!(strlen (str) > 0 && str[strlen (str) - 1] == '\n'))
3948 fprintf (stderr, "\n");
3949 va_end (ap);
3950 fflush (stderr);
3951 exit (1);
3956 /* Delete the given tty terminal, closing all frames on it. */
3958 static void
3959 delete_tty (struct terminal *terminal)
3961 struct tty_display_info *tty;
3963 /* Protect against recursive calls. delete_frame in
3964 delete_terminal calls us back when it deletes our last frame. */
3965 if (!terminal->name)
3966 return;
3968 if (terminal->type != output_termcap)
3969 abort ();
3971 tty = terminal->display_info.tty;
3973 if (tty == tty_list)
3974 tty_list = tty->next;
3975 else
3977 struct tty_display_info *p;
3978 for (p = tty_list; p && p->next != tty; p = p->next)
3981 if (! p)
3982 /* This should not happen. */
3983 abort ();
3985 p->next = tty->next;
3986 tty->next = 0;
3989 /* reset_sys_modes needs a valid device, so this call needs to be
3990 before delete_terminal. */
3991 reset_sys_modes (tty);
3993 delete_terminal (terminal);
3995 xfree (tty->name);
3996 xfree (tty->type);
3998 if (tty->input)
4000 #ifdef subprocesses
4001 delete_keyboard_wait_descriptor (fileno (tty->input));
4002 #endif
4003 if (tty->input != stdin)
4004 fclose (tty->input);
4006 if (tty->output && tty->output != stdout && tty->output != tty->input)
4007 fclose (tty->output);
4008 if (tty->termscript)
4009 fclose (tty->termscript);
4011 xfree (tty->old_tty);
4012 xfree (tty->Wcm);
4013 xfree (tty->termcap_strings_buffer);
4014 xfree (tty->termcap_term_buffer);
4016 bzero (tty, sizeof (struct tty_display_info));
4017 xfree (tty);
4022 /* Mark the pointers in the tty_display_info objects.
4023 Called by the Fgarbage_collector. */
4025 void
4026 mark_ttys (void)
4028 struct tty_display_info *tty;
4030 for (tty = tty_list; tty; tty = tty->next)
4031 mark_object (tty->top_frame);
4036 void
4037 syms_of_term ()
4039 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
4040 doc: /* Non-nil means the system uses terminfo rather than termcap.
4041 This variable can be used by terminal emulator packages. */);
4042 #ifdef TERMINFO
4043 system_uses_terminfo = 1;
4044 #else
4045 system_uses_terminfo = 0;
4046 #endif
4048 DEFVAR_LISP ("suspend-tty-functions", &Vsuspend_tty_functions,
4049 doc: /* Functions to be run after suspending a tty.
4050 The functions are run with one argument, the terminal object to be suspended.
4051 See `suspend-tty'. */);
4052 Vsuspend_tty_functions = Qnil;
4055 DEFVAR_LISP ("resume-tty-functions", &Vresume_tty_functions,
4056 doc: /* Functions to be run after resuming a tty.
4057 The functions are run with one argument, the terminal object that was revived.
4058 See `resume-tty'. */);
4059 Vresume_tty_functions = Qnil;
4061 DEFVAR_BOOL ("visible-cursor", &visible_cursor,
4062 doc: /* Non-nil means to make the cursor very visible.
4063 This only has an effect when running in a text terminal.
4064 What means \"very visible\" is up to your terminal. It may make the cursor
4065 bigger, or it may make it blink, or it may do nothing at all. */);
4066 visible_cursor = 1;
4068 defsubr (&Stty_display_color_p);
4069 defsubr (&Stty_display_color_cells);
4070 defsubr (&Stty_no_underline);
4071 defsubr (&Stty_type);
4072 defsubr (&Scontrolling_tty_p);
4073 defsubr (&Ssuspend_tty);
4074 defsubr (&Sresume_tty);
4075 #ifdef HAVE_GPM
4076 defsubr (&Sgpm_mouse_start);
4077 defsubr (&Sgpm_mouse_stop);
4079 staticpro (&mouse_face_window);
4080 #endif /* HAVE_GPM */
4082 #ifndef DOS_NT
4083 default_orig_pair = NULL;
4084 default_set_foreground = NULL;
4085 default_set_background = NULL;
4086 #endif /* !DOS_NT */
4088 encode_terminal_src = NULL;
4089 encode_terminal_dst = NULL;
4094 /* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193
4095 (do not change this comment) */