Make gnus-start-draft-setup interactive.
[emacs.git] / src / term.c
blob4f326234956cedf5d0a2fd664433fed0fe76925a
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
37 #ifdef HAVE_SYS_IOCTL_H
38 #include <sys/ioctl.h>
39 #endif
41 #include <signal.h>
42 #include <stdarg.h>
43 #include <setjmp.h>
45 #include "lisp.h"
46 #include "termchar.h"
47 #include "termopts.h"
48 #include "buffer.h"
49 #include "character.h"
50 #include "charset.h"
51 #include "coding.h"
52 #include "composite.h"
53 #include "keyboard.h"
54 #include "frame.h"
55 #include "disptab.h"
56 #include "termhooks.h"
57 #include "dispextern.h"
58 #include "window.h"
59 #include "keymap.h"
60 #include "blockinput.h"
61 #include "syssignal.h"
62 #include "systty.h"
63 #include "intervals.h"
64 #ifdef MSDOS
65 #include "msdos.h"
66 static int been_here = -1;
67 #endif
69 /* For now, don't try to include termcap.h. On some systems,
70 configure finds a non-standard termcap.h that the main build
71 won't find. */
72 extern void tputs (const char *, int, int (*)(int));
73 extern int tgetent (char *, const char *);
74 extern int tgetflag (char *id);
75 extern int tgetnum (char *id);
77 #include "cm.h"
78 #ifdef HAVE_X_WINDOWS
79 #include "xterm.h"
80 #endif
82 #ifndef O_RDWR
83 #define O_RDWR 2
84 #endif
86 #ifndef O_NOCTTY
87 #define O_NOCTTY 0
88 #endif
90 /* The name of the default console device. */
91 #ifdef WINDOWSNT
92 #define DEV_TTY "CONOUT$"
93 #else
94 #define DEV_TTY "/dev/tty"
95 #endif
97 static void tty_set_scroll_region (struct frame *f, int start, int stop);
98 static void turn_on_face (struct frame *, int face_id);
99 static void turn_off_face (struct frame *, int face_id);
100 static void tty_show_cursor (struct tty_display_info *);
101 static void tty_hide_cursor (struct tty_display_info *);
102 static void tty_background_highlight (struct tty_display_info *tty);
103 static void clear_tty_hooks (struct terminal *terminal);
104 static void set_tty_hooks (struct terminal *terminal);
105 static void dissociate_if_controlling_tty (int fd);
106 static void delete_tty (struct terminal *);
107 static void maybe_fatal (int must_succeed, struct terminal *terminal,
108 const char *str1, const char *str2, ...) NO_RETURN;
109 static void vfatal (const char *str, va_list ap) NO_RETURN;
112 #define OUTPUT(tty, a) \
113 emacs_tputs ((tty), a, \
114 (int) (FRAME_LINES (XFRAME (selected_frame)) \
115 - curY (tty)), \
116 cmputc)
118 #define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
119 #define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
121 #define OUTPUT_IF(tty, a) \
122 do { \
123 if (a) \
124 emacs_tputs ((tty), a, \
125 (int) (FRAME_LINES (XFRAME (selected_frame)) \
126 - curY (tty) ), \
127 cmputc); \
128 } while (0)
130 #define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
132 /* If true, use "vs", otherwise use "ve" to make the cursor visible. */
134 static int visible_cursor;
136 /* Display space properties */
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 (char *, char *, int, int, ...);
189 extern char *tgetstr (char *, char **);
192 #ifdef HAVE_GPM
193 #include <sys/fcntl.h>
195 static void term_clear_mouse_face (void);
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 (struct glyph *src, int src_len, struct coding_system *coding)
568 struct glyph *src_end = src + src_len;
569 unsigned char *buf;
570 int nchars, nbytes, required;
571 register int tlen = GLYPH_TABLE_LENGTH;
572 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
573 Lisp_Object charset_list;
575 /* Allocate sufficient size of buffer to store all characters in
576 multibyte-form. But, it may be enlarged on demand if
577 Vglyph_table contains a string or a composite glyph is
578 encountered. */
579 required = MAX_MULTIBYTE_LENGTH * src_len;
580 if (encode_terminal_src_size < required)
582 if (encode_terminal_src)
583 encode_terminal_src = xrealloc (encode_terminal_src, required);
584 else
585 encode_terminal_src = xmalloc (required);
586 encode_terminal_src_size = required;
589 charset_list = coding_charset_list (coding);
591 buf = encode_terminal_src;
592 nchars = 0;
593 while (src < src_end)
595 if (src->type == COMPOSITE_GLYPH)
597 struct composition *cmp;
598 Lisp_Object gstring;
599 int i;
601 nbytes = buf - encode_terminal_src;
602 if (src->u.cmp.automatic)
604 gstring = composition_gstring_from_id (src->u.cmp.id);
605 required = src->u.cmp.to + 1 - src->u.cmp.from;
607 else
609 cmp = composition_table[src->u.cmp.id];
610 required = MAX_MULTIBYTE_LENGTH * cmp->glyph_len;
613 if (encode_terminal_src_size < nbytes + required)
615 encode_terminal_src_size = nbytes + required;
616 encode_terminal_src = xrealloc (encode_terminal_src,
617 encode_terminal_src_size);
618 buf = encode_terminal_src + nbytes;
621 if (src->u.cmp.automatic)
622 for (i = src->u.cmp.from; i <= src->u.cmp.to; i++)
624 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
625 int c = LGLYPH_CHAR (g);
627 if (! char_charset (c, charset_list, NULL))
628 c = '?';
629 buf += CHAR_STRING (c, buf);
630 nchars++;
632 else
633 for (i = 0; i < cmp->glyph_len; i++)
635 int c = COMPOSITION_GLYPH (cmp, i);
637 if (c == '\t')
638 continue;
639 if (char_charset (c, charset_list, NULL))
641 if (CHAR_WIDTH (c) == 0
642 && i > 0 && COMPOSITION_GLYPH (cmp, i - 1) == '\t')
643 /* Should be left-padded */
645 buf += CHAR_STRING (' ', buf);
646 nchars++;
649 else
650 c = '?';
651 buf += CHAR_STRING (c, buf);
652 nchars++;
655 /* We must skip glyphs to be padded for a wide character. */
656 else if (! CHAR_GLYPH_PADDING_P (*src))
658 GLYPH g;
659 int c;
660 Lisp_Object string;
662 string = Qnil;
663 SET_GLYPH_FROM_CHAR_GLYPH (g, src[0]);
665 if (GLYPH_INVALID_P (g) || GLYPH_SIMPLE_P (tbase, tlen, g))
667 /* This glyph doesn't have an entry in Vglyph_table. */
668 c = src->u.ch;
670 else
672 /* This glyph has an entry in Vglyph_table,
673 so process any alias before testing for simpleness. */
674 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
676 if (GLYPH_SIMPLE_P (tbase, tlen, g))
677 /* We set the multi-byte form of a character in G
678 (that should be an ASCII character) at WORKBUF. */
679 c = GLYPH_CHAR (g);
680 else
681 /* We have a string in Vglyph_table. */
682 string = tbase[GLYPH_CHAR (g)];
685 if (NILP (string))
687 nbytes = buf - encode_terminal_src;
688 if (encode_terminal_src_size < nbytes + MAX_MULTIBYTE_LENGTH)
690 encode_terminal_src_size = nbytes + MAX_MULTIBYTE_LENGTH;
691 encode_terminal_src = xrealloc (encode_terminal_src,
692 encode_terminal_src_size);
693 buf = encode_terminal_src + nbytes;
695 if (char_charset (c, charset_list, NULL))
697 /* Store the multibyte form of C at BUF. */
698 buf += CHAR_STRING (c, buf);
699 nchars++;
701 else
703 /* C is not encodable. */
704 *buf++ = '?';
705 nchars++;
706 while (src + 1 < src_end && CHAR_GLYPH_PADDING_P (src[1]))
708 *buf++ = '?';
709 nchars++;
710 src++;
714 else
716 unsigned char *p = SDATA (string);
718 if (! STRING_MULTIBYTE (string))
719 string = string_to_multibyte (string);
720 nbytes = buf - encode_terminal_src;
721 if (encode_terminal_src_size < nbytes + SBYTES (string))
723 encode_terminal_src_size = nbytes + SBYTES (string);
724 encode_terminal_src = xrealloc (encode_terminal_src,
725 encode_terminal_src_size);
726 buf = encode_terminal_src + nbytes;
728 memcpy (buf, SDATA (string), SBYTES (string));
729 buf += SBYTES (string);
730 nchars += SCHARS (string);
733 src++;
736 if (nchars == 0)
738 coding->produced = 0;
739 return NULL;
742 nbytes = buf - encode_terminal_src;
743 coding->source = encode_terminal_src;
744 if (encode_terminal_dst_size == 0)
746 encode_terminal_dst_size = encode_terminal_src_size;
747 if (encode_terminal_dst)
748 encode_terminal_dst = xrealloc (encode_terminal_dst,
749 encode_terminal_dst_size);
750 else
751 encode_terminal_dst = xmalloc (encode_terminal_dst_size);
753 coding->destination = encode_terminal_dst;
754 coding->dst_bytes = encode_terminal_dst_size;
755 encode_coding_object (coding, Qnil, 0, 0, nchars, nbytes, Qnil);
756 /* coding->destination may have been reallocated. */
757 encode_terminal_dst = coding->destination;
758 encode_terminal_dst_size = coding->dst_bytes;
760 return (encode_terminal_dst);
765 /* An implementation of write_glyphs for termcap frames. */
767 static void
768 tty_write_glyphs (struct frame *f, struct glyph *string, int len)
770 unsigned char *conversion_buffer;
771 struct coding_system *coding;
773 struct tty_display_info *tty = FRAME_TTY (f);
775 tty_turn_off_insert (tty);
776 tty_hide_cursor (tty);
778 /* Don't dare write in last column of bottom line, if Auto-Wrap,
779 since that would scroll the whole frame on some terminals. */
781 if (AutoWrap (tty)
782 && curY (tty) + 1 == FRAME_LINES (f)
783 && (curX (tty) + len) == FRAME_COLS (f))
784 len --;
785 if (len <= 0)
786 return;
788 cmplus (tty, len);
790 /* If terminal_coding does any conversion, use it, otherwise use
791 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
792 because it always return 1 if the member src_multibyte is 1. */
793 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
794 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
795 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
796 the tail. */
797 coding->mode &= ~CODING_MODE_LAST_BLOCK;
799 while (len > 0)
801 /* Identify a run of glyphs with the same face. */
802 int face_id = string->face_id;
803 int n;
805 for (n = 1; n < len; ++n)
806 if (string[n].face_id != face_id)
807 break;
809 /* Turn appearance modes of the face of the run on. */
810 tty_highlight_if_desired (tty);
811 turn_on_face (f, face_id);
813 if (n == len)
814 /* This is the last run. */
815 coding->mode |= CODING_MODE_LAST_BLOCK;
816 conversion_buffer = encode_terminal_code (string, n, coding);
817 if (coding->produced > 0)
819 BLOCK_INPUT;
820 fwrite (conversion_buffer, 1, coding->produced, tty->output);
821 if (ferror (tty->output))
822 clearerr (tty->output);
823 if (tty->termscript)
824 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
825 UNBLOCK_INPUT;
827 len -= n;
828 string += n;
830 /* Turn appearance modes off. */
831 turn_off_face (f, face_id);
832 tty_turn_off_highlight (tty);
835 cmcheckmagic (tty);
838 #ifdef HAVE_GPM /* Only used by GPM code. */
840 static void
841 tty_write_glyphs_with_face (register struct frame *f, register struct glyph *string,
842 register int len, register int face_id)
844 unsigned char *conversion_buffer;
845 struct coding_system *coding;
847 struct tty_display_info *tty = FRAME_TTY (f);
849 tty_turn_off_insert (tty);
850 tty_hide_cursor (tty);
852 /* Don't dare write in last column of bottom line, if Auto-Wrap,
853 since that would scroll the whole frame on some terminals. */
855 if (AutoWrap (tty)
856 && curY (tty) + 1 == FRAME_LINES (f)
857 && (curX (tty) + len) == FRAME_COLS (f))
858 len --;
859 if (len <= 0)
860 return;
862 cmplus (tty, len);
864 /* If terminal_coding does any conversion, use it, otherwise use
865 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
866 because it always return 1 if the member src_multibyte is 1. */
867 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
868 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
869 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
870 the tail. */
871 coding->mode &= ~CODING_MODE_LAST_BLOCK;
873 /* Turn appearance modes of the face. */
874 tty_highlight_if_desired (tty);
875 turn_on_face (f, face_id);
877 coding->mode |= CODING_MODE_LAST_BLOCK;
878 conversion_buffer = encode_terminal_code (string, len, coding);
879 if (coding->produced > 0)
881 BLOCK_INPUT;
882 fwrite (conversion_buffer, 1, coding->produced, tty->output);
883 if (ferror (tty->output))
884 clearerr (tty->output);
885 if (tty->termscript)
886 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
887 UNBLOCK_INPUT;
890 /* Turn appearance modes off. */
891 turn_off_face (f, face_id);
892 tty_turn_off_highlight (tty);
894 cmcheckmagic (tty);
896 #endif
898 /* An implementation of insert_glyphs for termcap frames. */
900 static void
901 tty_insert_glyphs (struct frame *f, struct glyph *start, int len)
903 char *buf;
904 struct glyph *glyph = NULL;
905 unsigned char *conversion_buffer;
906 unsigned char space[1];
907 struct coding_system *coding;
909 struct tty_display_info *tty = FRAME_TTY (f);
911 if (tty->TS_ins_multi_chars)
913 buf = tparam (tty->TS_ins_multi_chars, 0, 0, len);
914 OUTPUT1 (tty, buf);
915 xfree (buf);
916 if (start)
917 write_glyphs (f, start, len);
918 return;
921 tty_turn_on_insert (tty);
922 cmplus (tty, len);
924 if (! start)
925 space[0] = SPACEGLYPH;
927 /* If terminal_coding does any conversion, use it, otherwise use
928 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
929 because it always return 1 if the member src_multibyte is 1. */
930 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
931 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
932 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
933 the tail. */
934 coding->mode &= ~CODING_MODE_LAST_BLOCK;
936 while (len-- > 0)
938 OUTPUT1_IF (tty, tty->TS_ins_char);
939 if (!start)
941 conversion_buffer = space;
942 coding->produced = 1;
944 else
946 tty_highlight_if_desired (tty);
947 turn_on_face (f, start->face_id);
948 glyph = start;
949 ++start;
950 /* We must open sufficient space for a character which
951 occupies more than one column. */
952 while (len && CHAR_GLYPH_PADDING_P (*start))
954 OUTPUT1_IF (tty, tty->TS_ins_char);
955 start++, len--;
958 if (len <= 0)
959 /* This is the last glyph. */
960 coding->mode |= CODING_MODE_LAST_BLOCK;
962 conversion_buffer = encode_terminal_code (glyph, 1, coding);
965 if (coding->produced > 0)
967 BLOCK_INPUT;
968 fwrite (conversion_buffer, 1, coding->produced, tty->output);
969 if (ferror (tty->output))
970 clearerr (tty->output);
971 if (tty->termscript)
972 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
973 UNBLOCK_INPUT;
976 OUTPUT1_IF (tty, tty->TS_pad_inserted_char);
977 if (start)
979 turn_off_face (f, glyph->face_id);
980 tty_turn_off_highlight (tty);
984 cmcheckmagic (tty);
987 /* An implementation of delete_glyphs for termcap frames. */
989 static void
990 tty_delete_glyphs (struct frame *f, int n)
992 char *buf;
993 register int i;
995 struct tty_display_info *tty = FRAME_TTY (f);
997 if (tty->delete_in_insert_mode)
999 tty_turn_on_insert (tty);
1001 else
1003 tty_turn_off_insert (tty);
1004 OUTPUT_IF (tty, tty->TS_delete_mode);
1007 if (tty->TS_del_multi_chars)
1009 buf = tparam (tty->TS_del_multi_chars, 0, 0, n);
1010 OUTPUT1 (tty, buf);
1011 xfree (buf);
1013 else
1014 for (i = 0; i < n; i++)
1015 OUTPUT1 (tty, tty->TS_del_char);
1016 if (!tty->delete_in_insert_mode)
1017 OUTPUT_IF (tty, tty->TS_end_delete_mode);
1020 /* An implementation of ins_del_lines for termcap frames. */
1022 static void
1023 tty_ins_del_lines (struct frame *f, int vpos, int n)
1025 struct tty_display_info *tty = FRAME_TTY (f);
1026 char *multi = n > 0 ? tty->TS_ins_multi_lines : tty->TS_del_multi_lines;
1027 char *single = n > 0 ? tty->TS_ins_line : tty->TS_del_line;
1028 char *scroll = n > 0 ? tty->TS_rev_scroll : tty->TS_fwd_scroll;
1030 register int i = n > 0 ? n : -n;
1031 register char *buf;
1033 /* If the lines below the insertion are being pushed
1034 into the end of the window, this is the same as clearing;
1035 and we know the lines are already clear, since the matching
1036 deletion has already been done. So can ignore this. */
1037 /* If the lines below the deletion are blank lines coming
1038 out of the end of the window, don't bother,
1039 as there will be a matching inslines later that will flush them. */
1040 if (FRAME_SCROLL_REGION_OK (f)
1041 && vpos + i >= tty->specified_window)
1042 return;
1043 if (!FRAME_MEMORY_BELOW_FRAME (f)
1044 && vpos + i >= FRAME_LINES (f))
1045 return;
1047 if (multi)
1049 raw_cursor_to (f, vpos, 0);
1050 tty_background_highlight (tty);
1051 buf = tparam (multi, 0, 0, i);
1052 OUTPUT (tty, buf);
1053 xfree (buf);
1055 else if (single)
1057 raw_cursor_to (f, vpos, 0);
1058 tty_background_highlight (tty);
1059 while (--i >= 0)
1060 OUTPUT (tty, single);
1061 if (tty->TF_teleray)
1062 curX (tty) = 0;
1064 else
1066 tty_set_scroll_region (f, vpos, tty->specified_window);
1067 if (n < 0)
1068 raw_cursor_to (f, tty->specified_window - 1, 0);
1069 else
1070 raw_cursor_to (f, vpos, 0);
1071 tty_background_highlight (tty);
1072 while (--i >= 0)
1073 OUTPUTL (tty, scroll, tty->specified_window - vpos);
1074 tty_set_scroll_region (f, 0, tty->specified_window);
1077 if (!FRAME_SCROLL_REGION_OK (f)
1078 && FRAME_MEMORY_BELOW_FRAME (f)
1079 && n < 0)
1081 cursor_to (f, FRAME_LINES (f) + n, 0);
1082 clear_to_end (f);
1086 /* Compute cost of sending "str", in characters,
1087 not counting any line-dependent padding. */
1090 string_cost (const char *str)
1092 cost = 0;
1093 if (str)
1094 tputs (str, 0, evalcost);
1095 return cost;
1098 /* Compute cost of sending "str", in characters,
1099 counting any line-dependent padding at one line. */
1101 static int
1102 string_cost_one_line (const char *str)
1104 cost = 0;
1105 if (str)
1106 tputs (str, 1, evalcost);
1107 return cost;
1110 /* Compute per line amount of line-dependent padding,
1111 in tenths of characters. */
1114 per_line_cost (const char *str)
1116 cost = 0;
1117 if (str)
1118 tputs (str, 0, evalcost);
1119 cost = - cost;
1120 if (str)
1121 tputs (str, 10, evalcost);
1122 return cost;
1125 /* char_ins_del_cost[n] is cost of inserting N characters.
1126 char_ins_del_cost[-n] is cost of deleting N characters.
1127 The length of this vector is based on max_frame_cols. */
1129 int *char_ins_del_vector;
1131 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
1133 /* ARGSUSED */
1134 static void
1135 calculate_ins_del_char_costs (struct frame *f)
1137 struct tty_display_info *tty = FRAME_TTY (f);
1138 int ins_startup_cost, del_startup_cost;
1139 int ins_cost_per_char, del_cost_per_char;
1140 register int i;
1141 register int *p;
1143 if (tty->TS_ins_multi_chars)
1145 ins_cost_per_char = 0;
1146 ins_startup_cost = string_cost_one_line (tty->TS_ins_multi_chars);
1148 else if (tty->TS_ins_char || tty->TS_pad_inserted_char
1149 || (tty->TS_insert_mode && tty->TS_end_insert_mode))
1151 ins_startup_cost = (30 * (string_cost (tty->TS_insert_mode)
1152 + string_cost (tty->TS_end_insert_mode))) / 100;
1153 ins_cost_per_char = (string_cost_one_line (tty->TS_ins_char)
1154 + string_cost_one_line (tty->TS_pad_inserted_char));
1156 else
1158 ins_startup_cost = 9999;
1159 ins_cost_per_char = 0;
1162 if (tty->TS_del_multi_chars)
1164 del_cost_per_char = 0;
1165 del_startup_cost = string_cost_one_line (tty->TS_del_multi_chars);
1167 else if (tty->TS_del_char)
1169 del_startup_cost = (string_cost (tty->TS_delete_mode)
1170 + string_cost (tty->TS_end_delete_mode));
1171 if (tty->delete_in_insert_mode)
1172 del_startup_cost /= 2;
1173 del_cost_per_char = string_cost_one_line (tty->TS_del_char);
1175 else
1177 del_startup_cost = 9999;
1178 del_cost_per_char = 0;
1181 /* Delete costs are at negative offsets */
1182 p = &char_ins_del_cost (f)[0];
1183 for (i = FRAME_COLS (f); --i >= 0;)
1184 *--p = (del_startup_cost += del_cost_per_char);
1186 /* Doing nothing is free */
1187 p = &char_ins_del_cost (f)[0];
1188 *p++ = 0;
1190 /* Insert costs are at positive offsets */
1191 for (i = FRAME_COLS (f); --i >= 0;)
1192 *p++ = (ins_startup_cost += ins_cost_per_char);
1195 void
1196 calculate_costs (struct frame *frame)
1198 FRAME_COST_BAUD_RATE (frame) = baud_rate;
1200 if (FRAME_TERMCAP_P (frame))
1202 struct tty_display_info *tty = FRAME_TTY (frame);
1203 register char *f = (tty->TS_set_scroll_region
1204 ? tty->TS_set_scroll_region
1205 : tty->TS_set_scroll_region_1);
1207 FRAME_SCROLL_REGION_COST (frame) = string_cost (f);
1209 tty->costs_set = 1;
1211 /* These variables are only used for terminal stuff. They are
1212 allocated once for the terminal frame of X-windows emacs, but not
1213 used afterwards.
1215 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1216 X turns off char_ins_del_ok. */
1218 max_frame_lines = max (max_frame_lines, FRAME_LINES (frame));
1219 max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
1221 if (char_ins_del_vector != 0)
1222 char_ins_del_vector
1223 = (int *) xrealloc (char_ins_del_vector,
1224 (sizeof (int)
1225 + 2 * max_frame_cols * sizeof (int)));
1226 else
1227 char_ins_del_vector
1228 = (int *) xmalloc (sizeof (int)
1229 + 2 * max_frame_cols * sizeof (int));
1231 memset (char_ins_del_vector, 0,
1232 (sizeof (int) + 2 * max_frame_cols * sizeof (int)));
1235 if (f && (!tty->TS_ins_line && !tty->TS_del_line))
1236 do_line_insertion_deletion_costs (frame,
1237 tty->TS_rev_scroll, tty->TS_ins_multi_lines,
1238 tty->TS_fwd_scroll, tty->TS_del_multi_lines,
1239 f, f, 1);
1240 else
1241 do_line_insertion_deletion_costs (frame,
1242 tty->TS_ins_line, tty->TS_ins_multi_lines,
1243 tty->TS_del_line, tty->TS_del_multi_lines,
1244 0, 0, 1);
1246 calculate_ins_del_char_costs (frame);
1248 /* Don't use TS_repeat if its padding is worse than sending the chars */
1249 if (tty->TS_repeat && per_line_cost (tty->TS_repeat) * baud_rate < 9000)
1250 tty->RPov = string_cost (tty->TS_repeat);
1251 else
1252 tty->RPov = FRAME_COLS (frame) * 2;
1254 cmcostinit (FRAME_TTY (frame)); /* set up cursor motion costs */
1258 struct fkey_table {
1259 char *cap, *name;
1262 /* Termcap capability names that correspond directly to X keysyms.
1263 Some of these (marked "terminfo") aren't supplied by old-style
1264 (Berkeley) termcap entries. They're listed in X keysym order;
1265 except we put the keypad keys first, so that if they clash with
1266 other keys (as on the IBM PC keyboard) they get overridden.
1269 static const struct fkey_table keys[] =
1271 {"kh", "home"}, /* termcap */
1272 {"kl", "left"}, /* termcap */
1273 {"ku", "up"}, /* termcap */
1274 {"kr", "right"}, /* termcap */
1275 {"kd", "down"}, /* termcap */
1276 {"%8", "prior"}, /* terminfo */
1277 {"%5", "next"}, /* terminfo */
1278 {"@7", "end"}, /* terminfo */
1279 {"@1", "begin"}, /* terminfo */
1280 {"*6", "select"}, /* terminfo */
1281 {"%9", "print"}, /* terminfo */
1282 {"@4", "execute"}, /* terminfo --- actually the `command' key */
1284 * "insert" --- see below
1286 {"&8", "undo"}, /* terminfo */
1287 {"%0", "redo"}, /* terminfo */
1288 {"%7", "menu"}, /* terminfo --- actually the `options' key */
1289 {"@0", "find"}, /* terminfo */
1290 {"@2", "cancel"}, /* terminfo */
1291 {"%1", "help"}, /* terminfo */
1293 * "break" goes here, but can't be reliably intercepted with termcap
1295 {"&4", "reset"}, /* terminfo --- actually `restart' */
1297 * "system" and "user" --- no termcaps
1299 {"kE", "clearline"}, /* terminfo */
1300 {"kA", "insertline"}, /* terminfo */
1301 {"kL", "deleteline"}, /* terminfo */
1302 {"kI", "insertchar"}, /* terminfo */
1303 {"kD", "deletechar"}, /* terminfo */
1304 {"kB", "backtab"}, /* terminfo */
1306 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1308 {"@8", "kp-enter"}, /* terminfo */
1310 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1311 * "kp-multiply", "kp-add", "kp-separator",
1312 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1313 * --- no termcaps for any of these.
1315 {"K4", "kp-1"}, /* terminfo */
1317 * "kp-2" --- no termcap
1319 {"K5", "kp-3"}, /* terminfo */
1321 * "kp-4" --- no termcap
1323 {"K2", "kp-5"}, /* terminfo */
1325 * "kp-6" --- no termcap
1327 {"K1", "kp-7"}, /* terminfo */
1329 * "kp-8" --- no termcap
1331 {"K3", "kp-9"}, /* terminfo */
1333 * "kp-equal" --- no termcap
1335 {"k1", "f1"},
1336 {"k2", "f2"},
1337 {"k3", "f3"},
1338 {"k4", "f4"},
1339 {"k5", "f5"},
1340 {"k6", "f6"},
1341 {"k7", "f7"},
1342 {"k8", "f8"},
1343 {"k9", "f9"},
1345 {"&0", "S-cancel"}, /*shifted cancel key*/
1346 {"&9", "S-begin"}, /*shifted begin key*/
1347 {"*0", "S-find"}, /*shifted find key*/
1348 {"*1", "S-execute"}, /*shifted execute? actually shifted command key*/
1349 {"*4", "S-delete"}, /*shifted delete-character key*/
1350 {"*7", "S-end"}, /*shifted end key*/
1351 {"*8", "S-clearline"}, /*shifted clear-to end-of-line key*/
1352 {"#1", "S-help"}, /*shifted help key*/
1353 {"#2", "S-home"}, /*shifted home key*/
1354 {"#3", "S-insert"}, /*shifted insert-character key*/
1355 {"#4", "S-left"}, /*shifted left-arrow key*/
1356 {"%d", "S-menu"}, /*shifted menu? actually shifted options key*/
1357 {"%c", "S-next"}, /*shifted next key*/
1358 {"%e", "S-prior"}, /*shifted previous key*/
1359 {"%f", "S-print"}, /*shifted print key*/
1360 {"%g", "S-redo"}, /*shifted redo key*/
1361 {"%i", "S-right"}, /*shifted right-arrow key*/
1362 {"!3", "S-undo"} /*shifted undo key*/
1365 #ifndef DOS_NT
1366 static char **term_get_fkeys_address;
1367 static KBOARD *term_get_fkeys_kboard;
1368 static Lisp_Object term_get_fkeys_1 (void);
1370 /* Find the escape codes sent by the function keys for Vinput_decode_map.
1371 This function scans the termcap function key sequence entries, and
1372 adds entries to Vinput_decode_map for each function key it finds. */
1374 static void
1375 term_get_fkeys (char **address, KBOARD *kboard)
1377 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1378 errors during the call. The only errors should be from Fdefine_key
1379 when given a key sequence containing an invalid prefix key. If the
1380 termcap defines function keys which use a prefix that is already bound
1381 to a command by the default bindings, we should silently ignore that
1382 function key specification, rather than giving the user an error and
1383 refusing to run at all on such a terminal. */
1385 term_get_fkeys_address = address;
1386 term_get_fkeys_kboard = kboard;
1387 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1390 static Lisp_Object
1391 term_get_fkeys_1 (void)
1393 int i;
1395 char **address = term_get_fkeys_address;
1396 KBOARD *kboard = term_get_fkeys_kboard;
1398 /* This can happen if CANNOT_DUMP or with strange options. */
1399 if (!KEYMAPP (kboard->Vinput_decode_map))
1400 kboard->Vinput_decode_map = Fmake_sparse_keymap (Qnil);
1402 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1404 char *sequence = tgetstr (keys[i].cap, address);
1405 if (sequence)
1406 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence),
1407 Fmake_vector (make_number (1),
1408 intern (keys[i].name)));
1411 /* The uses of the "k0" capability are inconsistent; sometimes it
1412 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1413 We will attempt to politely accommodate both systems by testing for
1414 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1417 char *k_semi = tgetstr ("k;", address);
1418 char *k0 = tgetstr ("k0", address);
1419 char *k0_name = "f10";
1421 if (k_semi)
1423 if (k0)
1424 /* Define f0 first, so that f10 takes precedence in case the
1425 key sequences happens to be the same. */
1426 Fdefine_key (kboard->Vinput_decode_map, build_string (k0),
1427 Fmake_vector (make_number (1), intern ("f0")));
1428 Fdefine_key (kboard->Vinput_decode_map, build_string (k_semi),
1429 Fmake_vector (make_number (1), intern ("f10")));
1431 else if (k0)
1432 Fdefine_key (kboard->Vinput_decode_map, build_string (k0),
1433 Fmake_vector (make_number (1), intern (k0_name)));
1436 /* Set up cookies for numbered function keys above f10. */
1438 char fcap[3], fkey[4];
1440 fcap[0] = 'F'; fcap[2] = '\0';
1441 for (i = 11; i < 64; i++)
1443 if (i <= 19)
1444 fcap[1] = '1' + i - 11;
1445 else if (i <= 45)
1446 fcap[1] = 'A' + i - 20;
1447 else
1448 fcap[1] = 'a' + i - 46;
1451 char *sequence = tgetstr (fcap, address);
1452 if (sequence)
1454 sprintf (fkey, "f%d", i);
1455 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence),
1456 Fmake_vector (make_number (1),
1457 intern (fkey)));
1464 * Various mappings to try and get a better fit.
1467 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1468 if (!tgetstr (cap1, address)) \
1470 char *sequence = tgetstr (cap2, address); \
1471 if (sequence) \
1472 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence), \
1473 Fmake_vector (make_number (1), \
1474 intern (sym))); \
1477 /* if there's no key_next keycap, map key_npage to `next' keysym */
1478 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1479 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1480 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1481 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1482 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1483 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1484 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1486 /* IBM has their own non-standard dialect of terminfo.
1487 If the standard name isn't found, try the IBM name. */
1488 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1489 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1490 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1491 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1492 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1493 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1494 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1495 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1496 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1497 #undef CONDITIONAL_REASSIGN
1500 return Qnil;
1502 #endif /* not DOS_NT */
1505 /***********************************************************************
1506 Character Display Information
1507 ***********************************************************************/
1508 static void append_glyph (struct it *);
1509 static void produce_stretch_glyph (struct it *);
1510 static void append_composite_glyph (struct it *);
1511 static void produce_composite_glyph (struct it *);
1513 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1514 terminal frames if IT->glyph_row != NULL. IT->char_to_display is
1515 the character for which to produce glyphs; IT->face_id contains the
1516 character's face. Padding glyphs are appended if IT->c has a
1517 IT->pixel_width > 1. */
1519 static void
1520 append_glyph (struct it *it)
1522 struct glyph *glyph, *end;
1523 int i;
1525 xassert (it->glyph_row);
1526 glyph = (it->glyph_row->glyphs[it->area]
1527 + it->glyph_row->used[it->area]);
1528 end = it->glyph_row->glyphs[1 + it->area];
1530 /* If the glyph row is reversed, we need to prepend the glyph rather
1531 than append it. */
1532 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1534 struct glyph *g;
1535 int move_by = it->pixel_width;
1537 /* Make room for the new glyphs. */
1538 if (move_by > end - glyph) /* don't overstep end of this area */
1539 move_by = end - glyph;
1540 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1541 g[move_by] = *g;
1542 glyph = it->glyph_row->glyphs[it->area];
1543 end = glyph + move_by;
1546 /* BIDI Note: we put the glyphs of a "multi-pixel" character left to
1547 right, even in the REVERSED_P case, since (a) all of its u.ch are
1548 identical, and (b) the PADDING_P flag needs to be set for the
1549 leftmost one, because we write to the terminal left-to-right. */
1550 for (i = 0;
1551 i < it->pixel_width && glyph < end;
1552 ++i)
1554 glyph->type = CHAR_GLYPH;
1555 glyph->pixel_width = 1;
1556 glyph->u.ch = it->char_to_display;
1557 glyph->face_id = it->face_id;
1558 glyph->padding_p = i > 0;
1559 glyph->charpos = CHARPOS (it->position);
1560 glyph->object = it->object;
1561 if (it->bidi_p)
1563 glyph->resolved_level = it->bidi_it.resolved_level;
1564 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1565 abort ();
1566 glyph->bidi_type = it->bidi_it.type;
1568 else
1570 glyph->resolved_level = 0;
1571 glyph->bidi_type = UNKNOWN_BT;
1574 ++it->glyph_row->used[it->area];
1575 ++glyph;
1579 /* Produce glyphs for the display element described by IT. *IT
1580 specifies what we want to produce a glyph for (character, image, ...),
1581 and where in the glyph matrix we currently are (glyph row and hpos).
1582 produce_glyphs fills in output fields of *IT with information such as the
1583 pixel width and height of a character, and maybe output actual glyphs at
1584 the same time if IT->glyph_row is non-null. For an overview, see
1585 the explanation in dispextern.h, before the definition of the
1586 display_element_type enumeration.
1588 produce_glyphs also stores the result of glyph width, ascent
1589 etc. computations in *IT.
1591 IT->glyph_row may be null, in which case produce_glyphs does not
1592 actually fill in the glyphs. This is used in the move_* functions
1593 in xdisp.c for text width and height computations.
1595 Callers usually don't call produce_glyphs directly;
1596 instead they use the macro PRODUCE_GLYPHS. */
1598 void
1599 produce_glyphs (struct it *it)
1601 /* If a hook is installed, let it do the work. */
1603 /* Nothing but characters are supported on terminal frames. */
1604 xassert (it->what == IT_CHARACTER
1605 || it->what == IT_COMPOSITION
1606 || it->what == IT_STRETCH);
1608 if (it->what == IT_STRETCH)
1610 produce_stretch_glyph (it);
1611 goto done;
1614 if (it->what == IT_COMPOSITION)
1616 produce_composite_glyph (it);
1617 goto done;
1620 /* Maybe translate single-byte characters to multibyte. */
1621 it->char_to_display = it->c;
1623 if (it->c >= 040 && it->c < 0177)
1625 it->pixel_width = it->nglyphs = 1;
1626 if (it->glyph_row)
1627 append_glyph (it);
1629 else if (it->c == '\n')
1630 it->pixel_width = it->nglyphs = 0;
1631 else if (it->c == '\t')
1633 int absolute_x = (it->current_x
1634 + it->continuation_lines_width);
1635 int next_tab_x
1636 = (((1 + absolute_x + it->tab_width - 1)
1637 / it->tab_width)
1638 * it->tab_width);
1639 int nspaces;
1641 /* If part of the TAB has been displayed on the previous line
1642 which is continued now, continuation_lines_width will have
1643 been incremented already by the part that fitted on the
1644 continued line. So, we will get the right number of spaces
1645 here. */
1646 nspaces = next_tab_x - absolute_x;
1648 if (it->glyph_row)
1650 int n = nspaces;
1652 it->char_to_display = ' ';
1653 it->pixel_width = it->len = 1;
1655 while (n--)
1656 append_glyph (it);
1659 it->pixel_width = nspaces;
1660 it->nglyphs = nspaces;
1662 else if (CHAR_BYTE8_P (it->c))
1664 if (unibyte_display_via_language_environment
1665 && (it->c >= 0240))
1667 it->char_to_display = BYTE8_TO_CHAR (it->c);
1668 it->pixel_width = CHAR_WIDTH (it->char_to_display);
1669 it->nglyphs = it->pixel_width;
1670 if (it->glyph_row)
1671 append_glyph (it);
1673 else
1675 /* Coming here means that it->c is from display table, thus
1676 we must send the raw 8-bit byte as is to the terminal.
1677 Although there's no way to know how many columns it
1678 occupies on a screen, it is a good assumption that a
1679 single byte code has 1-column width. */
1680 it->pixel_width = it->nglyphs = 1;
1681 if (it->glyph_row)
1682 append_glyph (it);
1685 else
1687 it->pixel_width = CHAR_WIDTH (it->c);
1688 it->nglyphs = it->pixel_width;
1690 if (it->glyph_row)
1691 append_glyph (it);
1694 done:
1695 /* Advance current_x by the pixel width as a convenience for
1696 the caller. */
1697 if (it->area == TEXT_AREA)
1698 it->current_x += it->pixel_width;
1699 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1700 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
1704 /* Produce a stretch glyph for iterator IT. IT->object is the value
1705 of the glyph property displayed. The value must be a list
1706 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1707 being recognized:
1709 1. `:width WIDTH' specifies that the space should be WIDTH *
1710 canonical char width wide. WIDTH may be an integer or floating
1711 point number.
1713 2. `:align-to HPOS' specifies that the space should be wide enough
1714 to reach HPOS, a value in canonical character units. */
1716 static void
1717 produce_stretch_glyph (struct it *it)
1719 /* (space :width WIDTH ...) */
1720 Lisp_Object prop, plist;
1721 int width = 0, align_to = -1;
1722 int zero_width_ok_p = 0;
1723 double tem;
1725 /* List should start with `space'. */
1726 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1727 plist = XCDR (it->object);
1729 /* Compute the width of the stretch. */
1730 if ((prop = Fplist_get (plist, QCwidth), !NILP (prop))
1731 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, 0))
1733 /* Absolute width `:width WIDTH' specified and valid. */
1734 zero_width_ok_p = 1;
1735 width = (int)(tem + 0.5);
1737 else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
1738 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, &align_to))
1740 if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
1741 align_to = (align_to < 0
1743 : align_to - window_box_left_offset (it->w, TEXT_AREA));
1744 else if (align_to < 0)
1745 align_to = window_box_left_offset (it->w, TEXT_AREA);
1746 width = max (0, (int)(tem + 0.5) + align_to - it->current_x);
1747 zero_width_ok_p = 1;
1749 else
1750 /* Nothing specified -> width defaults to canonical char width. */
1751 width = FRAME_COLUMN_WIDTH (it->f);
1753 if (width <= 0 && (width < 0 || !zero_width_ok_p))
1754 width = 1;
1756 if (width > 0 && it->line_wrap != TRUNCATE
1757 && it->current_x + width > it->last_visible_x)
1758 width = it->last_visible_x - it->current_x - 1;
1760 if (width > 0 && it->glyph_row)
1762 Lisp_Object o_object = it->object;
1763 Lisp_Object object = it->stack[it->sp - 1].string;
1764 int n = width;
1766 if (!STRINGP (object))
1767 object = it->w->buffer;
1768 it->object = object;
1769 it->char_to_display = ' ';
1770 it->pixel_width = it->len = 1;
1771 while (n--)
1772 append_glyph (it);
1773 it->object = o_object;
1775 it->pixel_width = width;
1776 it->nglyphs = width;
1780 /* Append glyphs to IT's glyph_row for the composition IT->cmp_id.
1781 Called from produce_composite_glyph for terminal frames if
1782 IT->glyph_row != NULL. IT->face_id contains the character's
1783 face. */
1785 static void
1786 append_composite_glyph (struct it *it)
1788 struct glyph *glyph;
1790 xassert (it->glyph_row);
1791 glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
1792 if (glyph < it->glyph_row->glyphs[1 + it->area])
1794 /* If the glyph row is reversed, we need to prepend the glyph
1795 rather than append it. */
1796 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1798 struct glyph *g;
1800 /* Make room for the new glyph. */
1801 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1802 g[1] = *g;
1803 glyph = it->glyph_row->glyphs[it->area];
1805 glyph->type = COMPOSITE_GLYPH;
1806 glyph->pixel_width = it->pixel_width;
1807 glyph->u.cmp.id = it->cmp_it.id;
1808 if (it->cmp_it.ch < 0)
1810 glyph->u.cmp.automatic = 0;
1811 glyph->u.cmp.id = it->cmp_it.id;
1813 else
1815 glyph->u.cmp.automatic = 1;
1816 glyph->u.cmp.id = it->cmp_it.id;
1817 glyph->u.cmp.from = it->cmp_it.from;
1818 glyph->u.cmp.to = it->cmp_it.to - 1;
1821 glyph->face_id = it->face_id;
1822 glyph->padding_p = 0;
1823 glyph->charpos = CHARPOS (it->position);
1824 glyph->object = it->object;
1825 if (it->bidi_p)
1827 glyph->resolved_level = it->bidi_it.resolved_level;
1828 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1829 abort ();
1830 glyph->bidi_type = it->bidi_it.type;
1832 else
1834 glyph->resolved_level = 0;
1835 glyph->bidi_type = UNKNOWN_BT;
1838 ++it->glyph_row->used[it->area];
1839 ++glyph;
1844 /* Produce a composite glyph for iterator IT. IT->cmp_id is the ID of
1845 the composition. We simply produces components of the composition
1846 assuming that the terminal has a capability to layout/render it
1847 correctly. */
1849 static void
1850 produce_composite_glyph (struct it *it)
1852 if (it->cmp_it.ch < 0)
1854 struct composition *cmp = composition_table[it->cmp_it.id];
1856 it->pixel_width = cmp->width;
1858 else
1860 Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id);
1862 it->pixel_width = composition_gstring_width (gstring, it->cmp_it.from,
1863 it->cmp_it.to, NULL);
1865 it->nglyphs = 1;
1866 if (it->glyph_row)
1867 append_composite_glyph (it);
1871 /* Get information about special display element WHAT in an
1872 environment described by IT. WHAT is one of IT_TRUNCATION or
1873 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1874 non-null glyph_row member. This function ensures that fields like
1875 face_id, c, len of IT are left untouched. */
1877 void
1878 produce_special_glyphs (struct it *it, enum display_element_type what)
1880 struct it temp_it;
1881 Lisp_Object gc;
1882 GLYPH glyph;
1884 temp_it = *it;
1885 temp_it.dp = NULL;
1886 temp_it.what = IT_CHARACTER;
1887 temp_it.len = 1;
1888 temp_it.object = make_number (0);
1889 memset (&temp_it.current, 0, sizeof temp_it.current);
1891 if (what == IT_CONTINUATION)
1893 /* Continuation glyph. For R2L lines, we mirror it by hand. */
1894 if (it->bidi_it.paragraph_dir == R2L)
1895 SET_GLYPH_FROM_CHAR (glyph, '/');
1896 else
1897 SET_GLYPH_FROM_CHAR (glyph, '\\');
1898 if (it->dp
1899 && (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc))
1900 && GLYPH_CODE_CHAR_VALID_P (gc))
1902 /* FIXME: Should we mirror GC for R2L lines? */
1903 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
1904 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
1907 else if (what == IT_TRUNCATION)
1909 /* Truncation glyph. */
1910 SET_GLYPH_FROM_CHAR (glyph, '$');
1911 if (it->dp
1912 && (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc))
1913 && GLYPH_CODE_CHAR_VALID_P (gc))
1915 /* FIXME: Should we mirror GC for R2L lines? */
1916 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
1917 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
1920 else
1921 abort ();
1923 temp_it.c = GLYPH_CHAR (glyph);
1924 temp_it.face_id = GLYPH_FACE (glyph);
1925 temp_it.len = CHAR_BYTES (temp_it.c);
1927 produce_glyphs (&temp_it);
1928 it->pixel_width = temp_it.pixel_width;
1929 it->nglyphs = temp_it.pixel_width;
1934 /***********************************************************************
1935 Faces
1936 ***********************************************************************/
1938 /* Value is non-zero if attribute ATTR may be used. ATTR should be
1939 one of the enumerators from enum no_color_bit, or a bit set built
1940 from them. Some display attributes may not be used together with
1941 color; the termcap capability `NC' specifies which ones. */
1943 #define MAY_USE_WITH_COLORS_P(tty, ATTR) \
1944 (tty->TN_max_colors > 0 \
1945 ? (tty->TN_no_color_video & (ATTR)) == 0 \
1946 : 1)
1948 /* Turn appearances of face FACE_ID on tty frame F on.
1949 FACE_ID is a realized face ID number, in the face cache. */
1951 static void
1952 turn_on_face (struct frame *f, int face_id)
1954 struct face *face = FACE_FROM_ID (f, face_id);
1955 long fg = face->foreground;
1956 long bg = face->background;
1957 struct tty_display_info *tty = FRAME_TTY (f);
1959 /* Do this first because TS_end_standout_mode may be the same
1960 as TS_exit_attribute_mode, which turns all appearances off. */
1961 if (MAY_USE_WITH_COLORS_P (tty, NC_REVERSE))
1963 if (tty->TN_max_colors > 0)
1965 if (fg >= 0 && bg >= 0)
1967 /* If the terminal supports colors, we can set them
1968 below without using reverse video. The face's fg
1969 and bg colors are set as they should appear on
1970 the screen, i.e. they take the inverse-video'ness
1971 of the face already into account. */
1973 else if (inverse_video)
1975 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1976 || bg == FACE_TTY_DEFAULT_BG_COLOR)
1977 tty_toggle_highlight (tty);
1979 else
1981 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1982 || bg == FACE_TTY_DEFAULT_FG_COLOR)
1983 tty_toggle_highlight (tty);
1986 else
1988 /* If we can't display colors, use reverse video
1989 if the face specifies that. */
1990 if (inverse_video)
1992 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1993 || bg == FACE_TTY_DEFAULT_BG_COLOR)
1994 tty_toggle_highlight (tty);
1996 else
1998 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1999 || bg == FACE_TTY_DEFAULT_FG_COLOR)
2000 tty_toggle_highlight (tty);
2005 if (face->tty_bold_p && MAY_USE_WITH_COLORS_P (tty, NC_BOLD))
2006 OUTPUT1_IF (tty, tty->TS_enter_bold_mode);
2008 if (face->tty_dim_p && MAY_USE_WITH_COLORS_P (tty, NC_DIM))
2009 OUTPUT1_IF (tty, tty->TS_enter_dim_mode);
2011 /* Alternate charset and blinking not yet used. */
2012 if (face->tty_alt_charset_p
2013 && MAY_USE_WITH_COLORS_P (tty, NC_ALT_CHARSET))
2014 OUTPUT1_IF (tty, tty->TS_enter_alt_charset_mode);
2016 if (face->tty_blinking_p
2017 && MAY_USE_WITH_COLORS_P (tty, NC_BLINK))
2018 OUTPUT1_IF (tty, tty->TS_enter_blink_mode);
2020 if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (tty, NC_UNDERLINE))
2021 OUTPUT1_IF (tty, tty->TS_enter_underline_mode);
2023 if (tty->TN_max_colors > 0)
2025 char *ts, *p;
2027 ts = tty->standout_mode ? tty->TS_set_background : tty->TS_set_foreground;
2028 if (fg >= 0 && ts)
2030 p = tparam (ts, NULL, 0, (int) fg);
2031 OUTPUT (tty, p);
2032 xfree (p);
2035 ts = tty->standout_mode ? tty->TS_set_foreground : tty->TS_set_background;
2036 if (bg >= 0 && ts)
2038 p = tparam (ts, NULL, 0, (int) bg);
2039 OUTPUT (tty, p);
2040 xfree (p);
2046 /* Turn off appearances of face FACE_ID on tty frame F. */
2048 static void
2049 turn_off_face (struct frame *f, int face_id)
2051 struct face *face = FACE_FROM_ID (f, face_id);
2052 struct tty_display_info *tty = FRAME_TTY (f);
2054 xassert (face != NULL);
2056 if (tty->TS_exit_attribute_mode)
2058 /* Capability "me" will turn off appearance modes double-bright,
2059 half-bright, reverse-video, standout, underline. It may or
2060 may not turn off alt-char-mode. */
2061 if (face->tty_bold_p
2062 || face->tty_dim_p
2063 || face->tty_reverse_p
2064 || face->tty_alt_charset_p
2065 || face->tty_blinking_p
2066 || face->tty_underline_p)
2068 OUTPUT1_IF (tty, tty->TS_exit_attribute_mode);
2069 if (strcmp (tty->TS_exit_attribute_mode, tty->TS_end_standout_mode) == 0)
2070 tty->standout_mode = 0;
2073 if (face->tty_alt_charset_p)
2074 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
2076 else
2078 /* If we don't have "me" we can only have those appearances
2079 that have exit sequences defined. */
2080 if (face->tty_alt_charset_p)
2081 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
2083 if (face->tty_underline_p)
2084 OUTPUT_IF (tty, tty->TS_exit_underline_mode);
2087 /* Switch back to default colors. */
2088 if (tty->TN_max_colors > 0
2089 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
2090 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
2091 || (face->background != FACE_TTY_DEFAULT_COLOR
2092 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
2093 OUTPUT1_IF (tty, tty->TS_orig_pair);
2097 /* Return non-zero if the terminal on frame F supports all of the
2098 capabilities in CAPS simultaneously, with foreground and background
2099 colors FG and BG. */
2102 tty_capable_p (struct tty_display_info *tty, unsigned int caps,
2103 unsigned long fg, unsigned long bg)
2105 #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
2106 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
2107 return 0;
2109 TTY_CAPABLE_P_TRY (tty, TTY_CAP_INVERSE, tty->TS_standout_mode, NC_REVERSE);
2110 TTY_CAPABLE_P_TRY (tty, TTY_CAP_UNDERLINE, tty->TS_enter_underline_mode, NC_UNDERLINE);
2111 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BOLD, tty->TS_enter_bold_mode, NC_BOLD);
2112 TTY_CAPABLE_P_TRY (tty, TTY_CAP_DIM, tty->TS_enter_dim_mode, NC_DIM);
2113 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BLINK, tty->TS_enter_blink_mode, NC_BLINK);
2114 TTY_CAPABLE_P_TRY (tty, TTY_CAP_ALT_CHARSET, tty->TS_enter_alt_charset_mode, NC_ALT_CHARSET);
2116 /* We can do it! */
2117 return 1;
2120 /* Return non-zero if the terminal is capable to display colors. */
2122 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
2123 0, 1, 0,
2124 doc: /* Return non-nil if the tty device TERMINAL can display colors.
2126 TERMINAL can be a terminal object, a frame, or nil (meaning the
2127 selected frame's terminal). This function always returns nil if
2128 TERMINAL does not refer to a text-only terminal. */)
2129 (Lisp_Object terminal)
2131 struct terminal *t = get_tty_terminal (terminal, 0);
2132 if (!t)
2133 return Qnil;
2134 else
2135 return t->display_info.tty->TN_max_colors > 0 ? Qt : Qnil;
2138 /* Return the number of supported colors. */
2139 DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
2140 Stty_display_color_cells, 0, 1, 0,
2141 doc: /* Return the number of colors supported by the tty device TERMINAL.
2143 TERMINAL can be a terminal object, a frame, or nil (meaning the
2144 selected frame's terminal). This function always returns 0 if
2145 TERMINAL does not refer to a text-only terminal. */)
2146 (Lisp_Object terminal)
2148 struct terminal *t = get_tty_terminal (terminal, 0);
2149 if (!t)
2150 return make_number (0);
2151 else
2152 return make_number (t->display_info.tty->TN_max_colors);
2155 #ifndef DOS_NT
2157 /* Declare here rather than in the function, as in the rest of Emacs,
2158 to work around an HPUX compiler bug (?). See
2159 http://lists.gnu.org/archive/html/emacs-devel/2007-08/msg00410.html */
2160 static int default_max_colors;
2161 static int default_max_pairs;
2162 static int default_no_color_video;
2163 static char *default_orig_pair;
2164 static char *default_set_foreground;
2165 static char *default_set_background;
2167 /* Save or restore the default color-related capabilities of this
2168 terminal. */
2169 static void
2170 tty_default_color_capabilities (struct tty_display_info *tty, int save)
2173 if (save)
2175 xfree (default_orig_pair);
2176 default_orig_pair = tty->TS_orig_pair ? xstrdup (tty->TS_orig_pair) : NULL;
2178 xfree (default_set_foreground);
2179 default_set_foreground = tty->TS_set_foreground ? xstrdup (tty->TS_set_foreground)
2180 : NULL;
2182 xfree (default_set_background);
2183 default_set_background = tty->TS_set_background ? xstrdup (tty->TS_set_background)
2184 : NULL;
2186 default_max_colors = tty->TN_max_colors;
2187 default_max_pairs = tty->TN_max_pairs;
2188 default_no_color_video = tty->TN_no_color_video;
2190 else
2192 tty->TS_orig_pair = default_orig_pair;
2193 tty->TS_set_foreground = default_set_foreground;
2194 tty->TS_set_background = default_set_background;
2195 tty->TN_max_colors = default_max_colors;
2196 tty->TN_max_pairs = default_max_pairs;
2197 tty->TN_no_color_video = default_no_color_video;
2201 /* Setup one of the standard tty color schemes according to MODE.
2202 MODE's value is generally the number of colors which we want to
2203 support; zero means set up for the default capabilities, the ones
2204 we saw at init_tty time; -1 means turn off color support. */
2205 static void
2206 tty_setup_colors (struct tty_display_info *tty, int mode)
2208 /* Canonicalize all negative values of MODE. */
2209 if (mode < -1)
2210 mode = -1;
2212 switch (mode)
2214 case -1: /* no colors at all */
2215 tty->TN_max_colors = 0;
2216 tty->TN_max_pairs = 0;
2217 tty->TN_no_color_video = 0;
2218 tty->TS_set_foreground = tty->TS_set_background = tty->TS_orig_pair = NULL;
2219 break;
2220 case 0: /* default colors, if any */
2221 default:
2222 tty_default_color_capabilities (tty, 0);
2223 break;
2224 case 8: /* 8 standard ANSI colors */
2225 tty->TS_orig_pair = "\033[0m";
2226 #ifdef TERMINFO
2227 tty->TS_set_foreground = "\033[3%p1%dm";
2228 tty->TS_set_background = "\033[4%p1%dm";
2229 #else
2230 tty->TS_set_foreground = "\033[3%dm";
2231 tty->TS_set_background = "\033[4%dm";
2232 #endif
2233 tty->TN_max_colors = 8;
2234 tty->TN_max_pairs = 64;
2235 tty->TN_no_color_video = 0;
2236 break;
2240 void
2241 set_tty_color_mode (struct tty_display_info *tty, struct frame *f)
2243 Lisp_Object tem, val;
2244 Lisp_Object color_mode;
2245 int mode;
2246 Lisp_Object tty_color_mode_alist
2247 = Fintern_soft (build_string ("tty-color-mode-alist"), Qnil);
2249 tem = assq_no_quit (Qtty_color_mode, f->param_alist);
2250 val = CONSP (tem) ? XCDR (tem) : Qnil;
2252 if (INTEGERP (val))
2253 color_mode = val;
2254 else if (SYMBOLP (tty_color_mode_alist))
2256 tem = Fassq (val, Fsymbol_value (tty_color_mode_alist));
2257 color_mode = CONSP (tem) ? XCDR (tem) : Qnil;
2259 else
2260 color_mode = Qnil;
2262 mode = INTEGERP (color_mode) ? XINT (color_mode) : 0;
2264 if (mode != tty->previous_color_mode)
2266 Lisp_Object funsym = intern ("tty-set-up-initial-frame-faces");
2267 tty->previous_color_mode = mode;
2268 tty_setup_colors (tty , mode);
2269 /* This recomputes all the faces given the new color definitions. */
2270 safe_call (1, &funsym);
2274 #endif /* !DOS_NT */
2278 /* Return the tty display object specified by TERMINAL. */
2280 struct terminal *
2281 get_tty_terminal (Lisp_Object terminal, int throw)
2283 struct terminal *t = get_terminal (terminal, throw);
2285 if (t && t->type != output_termcap && t->type != output_msdos_raw)
2287 if (throw)
2288 error ("Device %d is not a termcap terminal device", t->id);
2289 else
2290 return NULL;
2293 return t;
2296 /* Return an active termcap device that uses the tty device with the
2297 given name.
2299 This function ignores suspended devices.
2301 Returns NULL if the named terminal device is not opened. */
2303 struct terminal *
2304 get_named_tty (const char *name)
2306 struct terminal *t;
2308 if (!name)
2309 abort ();
2311 for (t = terminal_list; t; t = t->next_terminal)
2313 if ((t->type == output_termcap || t->type == output_msdos_raw)
2314 && !strcmp (t->display_info.tty->name, name)
2315 && TERMINAL_ACTIVE_P (t))
2316 return t;
2319 return 0;
2323 DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0,
2324 doc: /* Return the type of the tty device that TERMINAL uses.
2325 Returns nil if TERMINAL is not on a tty device.
2327 TERMINAL can be a terminal object, a frame, or nil (meaning the
2328 selected frame's terminal). */)
2329 (Lisp_Object terminal)
2331 struct terminal *t = get_terminal (terminal, 1);
2333 if (t->type != output_termcap && t->type != output_msdos_raw)
2334 return Qnil;
2336 if (t->display_info.tty->type)
2337 return build_string (t->display_info.tty->type);
2338 else
2339 return Qnil;
2342 DEFUN ("controlling-tty-p", Fcontrolling_tty_p, Scontrolling_tty_p, 0, 1, 0,
2343 doc: /* Return non-nil if TERMINAL is the controlling tty of the Emacs process.
2345 TERMINAL can be a terminal object, a frame, or nil (meaning the
2346 selected frame's terminal). This function always returns nil if
2347 TERMINAL is not on a tty device. */)
2348 (Lisp_Object terminal)
2350 struct terminal *t = get_terminal (terminal, 1);
2352 if ((t->type != output_termcap && t->type != output_msdos_raw)
2353 || strcmp (t->display_info.tty->name, DEV_TTY) != 0)
2354 return Qnil;
2355 else
2356 return Qt;
2359 DEFUN ("tty-no-underline", Ftty_no_underline, Stty_no_underline, 0, 1, 0,
2360 doc: /* Declare that the tty used by TERMINAL does not handle underlining.
2361 This is used to override the terminfo data, for certain terminals that
2362 do not really do underlining, but say that they do. This function has
2363 no effect if used on a non-tty terminal.
2365 TERMINAL can be a terminal object, a frame or nil (meaning the
2366 selected frame's terminal). This function always returns nil if
2367 TERMINAL does not refer to a text-only terminal. */)
2368 (Lisp_Object terminal)
2370 struct terminal *t = get_terminal (terminal, 1);
2372 if (t->type == output_termcap)
2373 t->display_info.tty->TS_enter_underline_mode = 0;
2374 return Qnil;
2379 DEFUN ("suspend-tty", Fsuspend_tty, Ssuspend_tty, 0, 1, 0,
2380 doc: /* Suspend the terminal device TTY.
2382 The device is restored to its default state, and Emacs ceases all
2383 access to the tty device. Frames that use the device are not deleted,
2384 but input is not read from them and if they change, their display is
2385 not updated.
2387 TTY may be a terminal object, a frame, or nil for the terminal device
2388 of the currently selected frame.
2390 This function runs `suspend-tty-functions' after suspending the
2391 device. The functions are run with one arg, the id of the suspended
2392 terminal device.
2394 `suspend-tty' does nothing if it is called on a device that is already
2395 suspended.
2397 A suspended tty may be resumed by calling `resume-tty' on it. */)
2398 (Lisp_Object tty)
2400 struct terminal *t = get_tty_terminal (tty, 1);
2401 FILE *f;
2403 if (!t)
2404 error ("Unknown tty device");
2406 f = t->display_info.tty->input;
2408 if (f)
2410 /* First run `suspend-tty-functions' and then clean up the tty
2411 state because `suspend-tty-functions' might need to change
2412 the tty state. */
2413 if (!NILP (Vrun_hooks))
2415 Lisp_Object args[2];
2416 args[0] = intern ("suspend-tty-functions");
2417 XSETTERMINAL (args[1], t);
2418 Frun_hook_with_args (2, args);
2421 reset_sys_modes (t->display_info.tty);
2422 delete_keyboard_wait_descriptor (fileno (f));
2424 #ifndef MSDOS
2425 fclose (f);
2426 if (f != t->display_info.tty->output)
2427 fclose (t->display_info.tty->output);
2428 #endif
2430 t->display_info.tty->input = 0;
2431 t->display_info.tty->output = 0;
2433 if (FRAMEP (t->display_info.tty->top_frame))
2434 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0);
2438 /* Clear display hooks to prevent further output. */
2439 clear_tty_hooks (t);
2441 return Qnil;
2444 DEFUN ("resume-tty", Fresume_tty, Sresume_tty, 0, 1, 0,
2445 doc: /* Resume the previously suspended terminal device TTY.
2446 The terminal is opened and reinitialized. Frames that are on the
2447 suspended terminal are revived.
2449 It is an error to resume a terminal while another terminal is active
2450 on the same device.
2452 This function runs `resume-tty-functions' after resuming the terminal.
2453 The functions are run with one arg, the id of the resumed terminal
2454 device.
2456 `resume-tty' does nothing if it is called on a device that is not
2457 suspended.
2459 TTY may be a terminal object, a frame, or nil (meaning the selected
2460 frame's terminal). */)
2461 (Lisp_Object tty)
2463 struct terminal *t = get_tty_terminal (tty, 1);
2464 int fd;
2466 if (!t)
2467 error ("Unknown tty device");
2469 if (!t->display_info.tty->input)
2471 if (get_named_tty (t->display_info.tty->name))
2472 error ("Cannot resume display while another display is active on the same device");
2474 #ifdef MSDOS
2475 t->display_info.tty->output = stdout;
2476 t->display_info.tty->input = stdin;
2477 #else /* !MSDOS */
2478 fd = emacs_open (t->display_info.tty->name, O_RDWR | O_NOCTTY, 0);
2480 if (fd == -1)
2481 error ("Can not reopen tty device %s: %s", t->display_info.tty->name, strerror (errno));
2483 if (strcmp (t->display_info.tty->name, DEV_TTY))
2484 dissociate_if_controlling_tty (fd);
2486 t->display_info.tty->output = fdopen (fd, "w+");
2487 t->display_info.tty->input = t->display_info.tty->output;
2488 #endif
2490 add_keyboard_wait_descriptor (fd);
2492 if (FRAMEP (t->display_info.tty->top_frame))
2494 struct frame *f = XFRAME (t->display_info.tty->top_frame);
2495 int width, height;
2496 int old_height = FRAME_COLS (f);
2497 int old_width = FRAME_LINES (f);
2499 /* Check if terminal/window size has changed while the frame
2500 was suspended. */
2501 get_tty_size (fileno (t->display_info.tty->input), &width, &height);
2502 if (width != old_width || height != old_height)
2503 change_frame_size (f, height, width, 0, 0, 0);
2504 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
2507 init_sys_modes (t->display_info.tty);
2509 /* Run `resume-tty-functions'. */
2510 if (!NILP (Vrun_hooks))
2512 Lisp_Object args[2];
2513 args[0] = intern ("resume-tty-functions");
2514 XSETTERMINAL (args[1], t);
2515 Frun_hook_with_args (2, args);
2519 set_tty_hooks (t);
2521 return Qnil;
2525 /***********************************************************************
2526 Mouse
2527 ***********************************************************************/
2529 #ifdef HAVE_GPM
2530 void
2531 term_mouse_moveto (int x, int y)
2533 /* TODO: how to set mouse position?
2534 const char *name;
2535 int fd;
2536 name = (const char *) ttyname (0);
2537 fd = open (name, O_WRONLY);
2538 SOME_FUNCTION (x, y, fd);
2539 close (fd);
2540 last_mouse_x = x;
2541 last_mouse_y = y; */
2544 static void
2545 term_show_mouse_face (enum draw_glyphs_face draw)
2547 struct window *w = XWINDOW (mouse_face_window);
2548 int save_x, save_y;
2549 int i;
2551 struct frame *f = XFRAME (w->frame);
2552 struct tty_display_info *tty = FRAME_TTY (f);
2554 if (/* If window is in the process of being destroyed, don't bother
2555 to do anything. */
2556 w->current_matrix != NULL
2557 /* Recognize when we are called to operate on rows that don't exist
2558 anymore. This can happen when a window is split. */
2559 && mouse_face_end_row < w->current_matrix->nrows)
2561 /* write_glyphs writes at cursor position, so we need to
2562 temporarily move cursor coordinates to the beginning of
2563 the highlight region. */
2565 /* Save current cursor co-ordinates */
2566 save_y = curY (tty);
2567 save_x = curX (tty);
2569 /* Note that mouse_face_beg_row etc. are window relative. */
2570 for (i = mouse_face_beg_row; i <= mouse_face_end_row; i++)
2572 int start_hpos, end_hpos, nglyphs;
2573 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
2575 /* Don't do anything if row doesn't have valid contents. */
2576 if (!row->enabled_p)
2577 continue;
2579 /* For all but the first row, the highlight starts at column 0. */
2580 if (i == mouse_face_beg_row)
2581 start_hpos = mouse_face_beg_col;
2582 else
2583 start_hpos = 0;
2585 if (i == mouse_face_end_row)
2586 end_hpos = mouse_face_end_col;
2587 else
2589 end_hpos = row->used[TEXT_AREA];
2590 if (draw == DRAW_NORMAL_TEXT)
2591 row->fill_line_p = 1; /* Clear to end of line */
2594 if (end_hpos <= start_hpos)
2595 continue;
2596 /* Record that some glyphs of this row are displayed in
2597 mouse-face. */
2598 row->mouse_face_p = draw > 0;
2600 nglyphs = end_hpos - start_hpos;
2602 if (end_hpos >= row->used[TEXT_AREA])
2603 nglyphs = row->used[TEXT_AREA] - start_hpos;
2605 pos_y = row->y + WINDOW_TOP_EDGE_Y (w);
2606 pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos
2607 + WINDOW_LEFT_EDGE_X (w);
2609 cursor_to (f, pos_y, pos_x);
2611 if (draw == DRAW_MOUSE_FACE)
2613 tty_write_glyphs_with_face (f, row->glyphs[TEXT_AREA] + start_hpos,
2614 nglyphs, mouse_face_face_id);
2616 else /* draw == DRAW_NORMAL_TEXT */
2617 write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
2619 cursor_to (f, save_y, save_x);
2623 static void
2624 term_clear_mouse_face (void)
2626 if (!NILP (mouse_face_window))
2627 term_show_mouse_face (DRAW_NORMAL_TEXT);
2629 mouse_face_beg_row = mouse_face_beg_col = -1;
2630 mouse_face_end_row = mouse_face_end_col = -1;
2631 mouse_face_window = Qnil;
2634 /* Find the glyph matrix position of buffer position POS in window W.
2635 *HPOS and *VPOS are set to the positions found. W's current glyphs
2636 must be up to date. If POS is above window start return (0, 0).
2637 If POS is after end of W, return end of last line in W.
2638 - taken from msdos.c */
2639 static int
2640 fast_find_position (struct window *w, int pos, int *hpos, int *vpos)
2642 int i, lastcol, line_start_position, maybe_next_line_p = 0;
2643 int yb = window_text_bottom_y (w);
2644 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0), *best_row = row;
2646 while (row->y < yb)
2648 if (row->used[TEXT_AREA])
2649 line_start_position = row->glyphs[TEXT_AREA]->charpos;
2650 else
2651 line_start_position = 0;
2653 if (line_start_position > pos)
2654 break;
2655 /* If the position sought is the end of the buffer,
2656 don't include the blank lines at the bottom of the window. */
2657 else if (line_start_position == pos
2658 && pos == BUF_ZV (XBUFFER (w->buffer)))
2660 maybe_next_line_p = 1;
2661 break;
2663 else if (line_start_position > 0)
2664 best_row = row;
2666 /* Don't overstep the last matrix row, lest we get into the
2667 never-never land... */
2668 if (row->y + 1 >= yb)
2669 break;
2671 ++row;
2674 /* Find the right column within BEST_ROW. */
2675 lastcol = 0;
2676 row = best_row;
2677 for (i = 0; i < row->used[TEXT_AREA]; i++)
2679 struct glyph *glyph = row->glyphs[TEXT_AREA] + i;
2680 int charpos;
2682 charpos = glyph->charpos;
2683 if (charpos == pos)
2685 *hpos = i;
2686 *vpos = row->y;
2687 return 1;
2689 else if (charpos > pos)
2690 break;
2691 else if (charpos > 0)
2692 lastcol = i;
2695 /* If we're looking for the end of the buffer,
2696 and we didn't find it in the line we scanned,
2697 use the start of the following line. */
2698 if (maybe_next_line_p)
2700 ++row;
2701 lastcol = 0;
2704 *vpos = row->y;
2705 *hpos = lastcol + 1;
2706 return 0;
2709 static void
2710 term_mouse_highlight (struct frame *f, int x, int y)
2712 enum window_part part;
2713 Lisp_Object window;
2714 struct window *w;
2715 struct buffer *b;
2717 if (NILP (Vmouse_highlight)
2718 || !f->glyphs_initialized_p)
2719 return;
2721 /* Which window is that in? */
2722 window = window_from_coordinates (f, x, y, &part, &x, &y, 0);
2724 /* Not on a window -> return. */
2725 if (!WINDOWP (window))
2726 return;
2728 if (!EQ (window, mouse_face_window))
2729 term_clear_mouse_face ();
2731 w = XWINDOW (window);
2733 /* Are we in a window whose display is up to date?
2734 And verify the buffer's text has not changed. */
2735 b = XBUFFER (w->buffer);
2736 if (part == ON_TEXT
2737 && EQ (w->window_end_valid, w->buffer)
2738 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
2739 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
2741 int pos, i, nrows = w->current_matrix->nrows;
2742 struct glyph_row *row;
2743 struct glyph *glyph;
2745 /* Find the glyph under X/Y. */
2746 glyph = NULL;
2747 if (y >= 0 && y < nrows)
2749 row = MATRIX_ROW (w->current_matrix, y);
2750 /* Give up if some row before the one we are looking for is
2751 not enabled. */
2752 for (i = 0; i <= y; i++)
2753 if (!MATRIX_ROW (w->current_matrix, i)->enabled_p)
2754 break;
2755 if (i > y /* all rows upto and including the one at Y are enabled */
2756 && row->displays_text_p
2757 && x < window_box_width (w, TEXT_AREA))
2759 glyph = row->glyphs[TEXT_AREA];
2760 if (x >= row->used[TEXT_AREA])
2761 glyph = NULL;
2762 else
2764 glyph += x;
2765 if (!BUFFERP (glyph->object))
2766 glyph = NULL;
2771 /* Clear mouse face if X/Y not over text. */
2772 if (glyph == NULL)
2774 term_clear_mouse_face ();
2775 return;
2778 if (!BUFFERP (glyph->object))
2779 abort ();
2780 pos = glyph->charpos;
2782 /* Check for mouse-face. */
2784 Lisp_Object mouse_face, overlay, position, *overlay_vec;
2785 int noverlays, obegv, ozv;
2786 struct buffer *obuf;
2788 /* If we get an out-of-range value, return now; avoid an error. */
2789 if (pos > BUF_Z (b))
2790 return;
2792 /* Make the window's buffer temporarily current for
2793 overlays_at and compute_char_face. */
2794 obuf = current_buffer;
2795 current_buffer = b;
2796 obegv = BEGV;
2797 ozv = ZV;
2798 BEGV = BEG;
2799 ZV = Z;
2801 /* Is this char mouse-active? */
2802 XSETINT (position, pos);
2804 /* Put all the overlays we want in a vector in overlay_vec. */
2805 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL, 0);
2806 /* Sort overlays into increasing priority order. */
2807 noverlays = sort_overlays (overlay_vec, noverlays, w);
2809 /* Check mouse-face highlighting. */
2810 if (!(EQ (window, mouse_face_window)
2811 && y >= mouse_face_beg_row
2812 && y <= mouse_face_end_row
2813 && (y > mouse_face_beg_row
2814 || x >= mouse_face_beg_col)
2815 && (y < mouse_face_end_row
2816 || x < mouse_face_end_col
2817 || mouse_face_past_end)))
2819 /* Clear the display of the old active region, if any. */
2820 term_clear_mouse_face ();
2822 /* Find the highest priority overlay that has a mouse-face
2823 property. */
2824 overlay = Qnil;
2825 for (i = noverlays - 1; i >= 0; --i)
2827 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
2828 if (!NILP (mouse_face))
2830 overlay = overlay_vec[i];
2831 break;
2835 /* If no overlay applies, get a text property. */
2836 if (NILP (overlay))
2837 mouse_face = Fget_text_property (position, Qmouse_face,
2838 w->buffer);
2840 /* Handle the overlay case. */
2841 if (!NILP (overlay))
2843 /* Find the range of text around this char that
2844 should be active. */
2845 Lisp_Object before, after;
2846 EMACS_INT ignore;
2849 before = Foverlay_start (overlay);
2850 after = Foverlay_end (overlay);
2851 /* Record this as the current active region. */
2852 fast_find_position (w, XFASTINT (before),
2853 &mouse_face_beg_col,
2854 &mouse_face_beg_row);
2856 mouse_face_past_end
2857 = !fast_find_position (w, XFASTINT (after),
2858 &mouse_face_end_col,
2859 &mouse_face_end_row);
2860 mouse_face_window = window;
2862 mouse_face_face_id
2863 = face_at_buffer_position (w, pos, 0, 0,
2864 &ignore, pos + 1, 1, -1);
2866 /* Display it as active. */
2867 term_show_mouse_face (DRAW_MOUSE_FACE);
2869 /* Handle the text property case. */
2870 else if (!NILP (mouse_face))
2872 /* Find the range of text around this char that
2873 should be active. */
2874 Lisp_Object before, after, beginning, end;
2875 EMACS_INT ignore;
2877 beginning = Fmarker_position (w->start);
2878 XSETINT (end, (BUF_Z (b) - XFASTINT (w->window_end_pos)));
2879 before
2880 = Fprevious_single_property_change (make_number (pos + 1),
2881 Qmouse_face,
2882 w->buffer, beginning);
2883 after
2884 = Fnext_single_property_change (position, Qmouse_face,
2885 w->buffer, end);
2887 /* Record this as the current active region. */
2888 fast_find_position (w, XFASTINT (before),
2889 &mouse_face_beg_col,
2890 &mouse_face_beg_row);
2891 mouse_face_past_end
2892 = !fast_find_position (w, XFASTINT (after),
2893 &mouse_face_end_col,
2894 &mouse_face_end_row);
2895 mouse_face_window = window;
2897 mouse_face_face_id
2898 = face_at_buffer_position (w, pos, 0, 0,
2899 &ignore, pos + 1, 1, -1);
2901 /* Display it as active. */
2902 term_show_mouse_face (DRAW_MOUSE_FACE);
2906 /* Look for a `help-echo' property. */
2908 Lisp_Object help;
2910 /* Check overlays first. */
2911 help = Qnil;
2912 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
2914 overlay = overlay_vec[i];
2915 help = Foverlay_get (overlay, Qhelp_echo);
2918 if (!NILP (help))
2920 help_echo_string = help;
2921 help_echo_window = window;
2922 help_echo_object = overlay;
2923 help_echo_pos = pos;
2925 /* Try text properties. */
2926 else if (NILP (help)
2927 && ((STRINGP (glyph->object)
2928 && glyph->charpos >= 0
2929 && glyph->charpos < SCHARS (glyph->object))
2930 || (BUFFERP (glyph->object)
2931 && glyph->charpos >= BEGV
2932 && glyph->charpos < ZV)))
2934 help = Fget_text_property (make_number (glyph->charpos),
2935 Qhelp_echo, glyph->object);
2936 if (!NILP (help))
2938 help_echo_string = help;
2939 help_echo_window = window;
2940 help_echo_object = glyph->object;
2941 help_echo_pos = glyph->charpos;
2946 BEGV = obegv;
2947 ZV = ozv;
2948 current_buffer = obuf;
2953 static int
2954 term_mouse_movement (FRAME_PTR frame, Gpm_Event *event)
2956 /* Has the mouse moved off the glyph it was on at the last sighting? */
2957 if (event->x != last_mouse_x || event->y != last_mouse_y)
2959 frame->mouse_moved = 1;
2960 term_mouse_highlight (frame, event->x, event->y);
2961 /* Remember which glyph we're now on. */
2962 last_mouse_x = event->x;
2963 last_mouse_y = event->y;
2964 return 1;
2966 return 0;
2969 /* Return the current position of the mouse.
2971 Set *f to the frame the mouse is in, or zero if the mouse is in no
2972 Emacs frame. If it is set to zero, all the other arguments are
2973 garbage.
2975 Set *bar_window to Qnil, and *x and *y to the column and
2976 row of the character cell the mouse is over.
2978 Set *time to the time the mouse was at the returned position.
2980 This clears mouse_moved until the next motion
2981 event arrives. */
2982 static void
2983 term_mouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
2984 enum scroll_bar_part *part, Lisp_Object *x,
2985 Lisp_Object *y, unsigned long *time)
2987 struct timeval now;
2989 *fp = SELECTED_FRAME ();
2990 (*fp)->mouse_moved = 0;
2992 *bar_window = Qnil;
2993 *part = 0;
2995 XSETINT (*x, last_mouse_x);
2996 XSETINT (*y, last_mouse_y);
2997 gettimeofday(&now, 0);
2998 *time = (now.tv_sec * 1000) + (now.tv_usec / 1000);
3001 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3003 If the event is a button press, then note that we have grabbed
3004 the mouse. */
3006 static Lisp_Object
3007 term_mouse_click (struct input_event *result, Gpm_Event *event,
3008 struct frame *f)
3010 struct timeval now;
3011 int i, j;
3013 result->kind = GPM_CLICK_EVENT;
3014 for (i = 0, j = GPM_B_LEFT; i < 3; i++, j >>= 1 )
3016 if (event->buttons & j) {
3017 result->code = i; /* button number */
3018 break;
3021 gettimeofday(&now, 0);
3022 result->timestamp = (now.tv_sec * 1000) + (now.tv_usec / 1000);
3024 if (event->type & GPM_UP)
3025 result->modifiers = up_modifier;
3026 else if (event->type & GPM_DOWN)
3027 result->modifiers = down_modifier;
3028 else
3029 result->modifiers = 0;
3031 if (event->type & GPM_SINGLE)
3032 result->modifiers |= click_modifier;
3034 if (event->type & GPM_DOUBLE)
3035 result->modifiers |= double_modifier;
3037 if (event->type & GPM_TRIPLE)
3038 result->modifiers |= triple_modifier;
3040 if (event->type & GPM_DRAG)
3041 result->modifiers |= drag_modifier;
3043 if (!(event->type & (GPM_MOVE | GPM_DRAG))) {
3045 /* 1 << KG_SHIFT */
3046 if (event->modifiers & (1 << 0))
3047 result->modifiers |= shift_modifier;
3049 /* 1 << KG_CTRL */
3050 if (event->modifiers & (1 << 2))
3051 result->modifiers |= ctrl_modifier;
3053 /* 1 << KG_ALT || KG_ALTGR */
3054 if (event->modifiers & (1 << 3)
3055 || event->modifiers & (1 << 1))
3056 result->modifiers |= meta_modifier;
3059 XSETINT (result->x, event->x);
3060 XSETINT (result->y, event->y);
3061 XSETFRAME (result->frame_or_window, f);
3062 result->arg = Qnil;
3063 return Qnil;
3067 handle_one_term_event (struct tty_display_info *tty, Gpm_Event *event, struct input_event* hold_quit)
3069 struct frame *f = XFRAME (tty->top_frame);
3070 struct input_event ie;
3071 int do_help = 0;
3072 int count = 0;
3074 EVENT_INIT (ie);
3075 ie.kind = NO_EVENT;
3076 ie.arg = Qnil;
3078 if (event->type & (GPM_MOVE | GPM_DRAG)) {
3079 previous_help_echo_string = help_echo_string;
3080 help_echo_string = Qnil;
3082 Gpm_DrawPointer (event->x, event->y, fileno (tty->output));
3084 if (!term_mouse_movement (f, event))
3085 help_echo_string = previous_help_echo_string;
3087 /* If the contents of the global variable help_echo_string
3088 has changed, generate a HELP_EVENT. */
3089 if (!NILP (help_echo_string)
3090 || !NILP (previous_help_echo_string))
3091 do_help = 1;
3093 goto done;
3095 else {
3096 f->mouse_moved = 0;
3097 term_mouse_click (&ie, event, f);
3100 done:
3101 if (ie.kind != NO_EVENT)
3103 kbd_buffer_store_event_hold (&ie, hold_quit);
3104 count++;
3107 if (do_help
3108 && !(hold_quit && hold_quit->kind != NO_EVENT))
3110 Lisp_Object frame;
3112 if (f)
3113 XSETFRAME (frame, f);
3114 else
3115 frame = Qnil;
3117 gen_help_event (help_echo_string, frame, help_echo_window,
3118 help_echo_object, help_echo_pos);
3119 count++;
3122 return count;
3125 DEFUN ("gpm-mouse-start", Fgpm_mouse_start, Sgpm_mouse_start,
3126 0, 0, 0,
3127 doc: /* Open a connection to Gpm.
3128 Gpm-mouse can only be activated for one tty at a time. */)
3129 (void)
3131 struct frame *f = SELECTED_FRAME ();
3132 struct tty_display_info *tty
3133 = ((f)->output_method == output_termcap
3134 ? (f)->terminal->display_info.tty : NULL);
3135 Gpm_Connect connection;
3137 if (!tty)
3138 error ("Gpm-mouse only works in the GNU/Linux console");
3139 if (gpm_tty == tty)
3140 return Qnil; /* Already activated, nothing to do. */
3141 if (gpm_tty)
3142 error ("Gpm-mouse can only be activated for one tty at a time");
3144 connection.eventMask = ~0;
3145 connection.defaultMask = ~GPM_HARD;
3146 connection.maxMod = ~0;
3147 connection.minMod = 0;
3148 gpm_zerobased = 1;
3150 if (Gpm_Open (&connection, 0) < 0)
3151 error ("Gpm-mouse failed to connect to the gpm daemon");
3152 else
3154 gpm_tty = tty;
3155 /* `init_sys_modes' arranges for mouse movements sent through gpm_fd
3156 to generate SIGIOs. Apparently we need to call reset_sys_modes
3157 before calling init_sys_modes. */
3158 reset_sys_modes (tty);
3159 init_sys_modes (tty);
3160 add_gpm_wait_descriptor (gpm_fd);
3161 return Qnil;
3165 void
3166 close_gpm (int fd)
3168 if (fd >= 0)
3169 delete_gpm_wait_descriptor (fd);
3170 while (Gpm_Close()); /* close all the stack */
3171 gpm_tty = NULL;
3174 DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop, Sgpm_mouse_stop,
3175 0, 0, 0,
3176 doc: /* Close a connection to Gpm. */)
3177 (void)
3179 struct frame *f = SELECTED_FRAME ();
3180 struct tty_display_info *tty
3181 = ((f)->output_method == output_termcap
3182 ? (f)->terminal->display_info.tty : NULL);
3184 if (!tty || gpm_tty != tty)
3185 return Qnil; /* Not activated on this terminal, nothing to do. */
3187 close_gpm (gpm_fd);
3188 return Qnil;
3190 #endif /* HAVE_GPM */
3193 #ifndef MSDOS
3194 /***********************************************************************
3195 Initialization
3196 ***********************************************************************/
3198 /* Initialize the tty-dependent part of frame F. The frame must
3199 already have its device initialized. */
3201 void
3202 create_tty_output (struct frame *f)
3204 struct tty_output *t;
3206 if (! FRAME_TERMCAP_P (f))
3207 abort ();
3209 t = xmalloc (sizeof (struct tty_output));
3210 memset (t, 0, sizeof (struct tty_output));
3212 t->display_info = FRAME_TERMINAL (f)->display_info.tty;
3214 f->output_data.tty = t;
3217 /* Delete frame F's face cache, and its tty-dependent part. */
3219 static void
3220 tty_free_frame_resources (struct frame *f)
3222 if (! FRAME_TERMCAP_P (f))
3223 abort ();
3225 if (FRAME_FACE_CACHE (f))
3226 free_frame_faces (f);
3228 xfree (f->output_data.tty);
3231 #else /* MSDOS */
3233 /* Delete frame F's face cache. */
3235 static void
3236 tty_free_frame_resources (struct frame *f)
3238 if (! FRAME_TERMCAP_P (f) && ! FRAME_MSDOS_P (f))
3239 abort ();
3241 if (FRAME_FACE_CACHE (f))
3242 free_frame_faces (f);
3244 #endif /* MSDOS */
3246 /* Reset the hooks in TERMINAL. */
3248 static void
3249 clear_tty_hooks (struct terminal *terminal)
3251 terminal->rif = 0;
3252 terminal->cursor_to_hook = 0;
3253 terminal->raw_cursor_to_hook = 0;
3254 terminal->clear_to_end_hook = 0;
3255 terminal->clear_frame_hook = 0;
3256 terminal->clear_end_of_line_hook = 0;
3257 terminal->ins_del_lines_hook = 0;
3258 terminal->insert_glyphs_hook = 0;
3259 terminal->write_glyphs_hook = 0;
3260 terminal->delete_glyphs_hook = 0;
3261 terminal->ring_bell_hook = 0;
3262 terminal->reset_terminal_modes_hook = 0;
3263 terminal->set_terminal_modes_hook = 0;
3264 terminal->update_begin_hook = 0;
3265 terminal->update_end_hook = 0;
3266 terminal->set_terminal_window_hook = 0;
3267 terminal->mouse_position_hook = 0;
3268 terminal->frame_rehighlight_hook = 0;
3269 terminal->frame_raise_lower_hook = 0;
3270 terminal->fullscreen_hook = 0;
3271 terminal->set_vertical_scroll_bar_hook = 0;
3272 terminal->condemn_scroll_bars_hook = 0;
3273 terminal->redeem_scroll_bar_hook = 0;
3274 terminal->judge_scroll_bars_hook = 0;
3275 terminal->read_socket_hook = 0;
3276 terminal->frame_up_to_date_hook = 0;
3278 /* Leave these two set, or suspended frames are not deleted
3279 correctly. */
3280 terminal->delete_frame_hook = &tty_free_frame_resources;
3281 terminal->delete_terminal_hook = &delete_tty;
3284 /* Initialize hooks in TERMINAL with the values needed for a tty. */
3286 static void
3287 set_tty_hooks (struct terminal *terminal)
3289 terminal->rif = 0; /* ttys don't support window-based redisplay. */
3291 terminal->cursor_to_hook = &tty_cursor_to;
3292 terminal->raw_cursor_to_hook = &tty_raw_cursor_to;
3294 terminal->clear_to_end_hook = &tty_clear_to_end;
3295 terminal->clear_frame_hook = &tty_clear_frame;
3296 terminal->clear_end_of_line_hook = &tty_clear_end_of_line;
3298 terminal->ins_del_lines_hook = &tty_ins_del_lines;
3300 terminal->insert_glyphs_hook = &tty_insert_glyphs;
3301 terminal->write_glyphs_hook = &tty_write_glyphs;
3302 terminal->delete_glyphs_hook = &tty_delete_glyphs;
3304 terminal->ring_bell_hook = &tty_ring_bell;
3306 terminal->reset_terminal_modes_hook = &tty_reset_terminal_modes;
3307 terminal->set_terminal_modes_hook = &tty_set_terminal_modes;
3308 terminal->update_begin_hook = 0; /* Not needed. */
3309 terminal->update_end_hook = &tty_update_end;
3310 terminal->set_terminal_window_hook = &tty_set_terminal_window;
3312 terminal->mouse_position_hook = 0; /* Not needed. */
3313 terminal->frame_rehighlight_hook = 0; /* Not needed. */
3314 terminal->frame_raise_lower_hook = 0; /* Not needed. */
3316 terminal->set_vertical_scroll_bar_hook = 0; /* Not needed. */
3317 terminal->condemn_scroll_bars_hook = 0; /* Not needed. */
3318 terminal->redeem_scroll_bar_hook = 0; /* Not needed. */
3319 terminal->judge_scroll_bars_hook = 0; /* Not needed. */
3321 terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */
3322 terminal->frame_up_to_date_hook = 0; /* Not needed. */
3324 terminal->delete_frame_hook = &tty_free_frame_resources;
3325 terminal->delete_terminal_hook = &delete_tty;
3328 /* Drop the controlling terminal if fd is the same device. */
3329 static void
3330 dissociate_if_controlling_tty (int fd)
3332 #ifndef DOS_NT
3333 int pgid;
3334 EMACS_GET_TTY_PGRP (fd, &pgid); /* If tcgetpgrp succeeds, fd is the ctty. */
3335 if (pgid != -1)
3337 #if defined (USG5)
3338 setpgrp ();
3339 no_controlling_tty = 1;
3340 #elif defined (CYGWIN)
3341 setsid ();
3342 no_controlling_tty = 1;
3343 #else
3344 #ifdef TIOCNOTTY /* Try BSD ioctls. */
3345 sigblock (sigmask (SIGTTOU));
3346 fd = emacs_open (DEV_TTY, O_RDWR, 0);
3347 if (fd != -1 && ioctl (fd, TIOCNOTTY, 0) != -1)
3349 no_controlling_tty = 1;
3351 if (fd != -1)
3352 emacs_close (fd);
3353 sigunblock (sigmask (SIGTTOU));
3354 #else
3355 /* Unknown system. */
3356 croak ();
3357 #endif /* ! TIOCNOTTY */
3358 #endif /* ! USG */
3360 #endif /* !DOS_NT */
3363 /* Create a termcap display on the tty device with the given name and
3364 type.
3366 If NAME is NULL, then use the controlling tty, i.e., "/dev/tty".
3367 Otherwise NAME should be a path to the tty device file,
3368 e.g. "/dev/pts/7".
3370 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
3372 If MUST_SUCCEED is true, then all errors are fatal. */
3374 struct terminal *
3375 init_tty (const char *name, const char *terminal_type, int must_succeed)
3377 char *area = NULL;
3378 char **address = &area;
3379 int buffer_size = 4096;
3380 register char *p = NULL;
3381 int status;
3382 struct tty_display_info *tty = NULL;
3383 struct terminal *terminal = NULL;
3384 int ctty = 0; /* 1 if asked to open controlling tty. */
3386 if (!terminal_type)
3387 maybe_fatal (must_succeed, 0,
3388 "Unknown terminal type",
3389 "Unknown terminal type");
3391 if (name == NULL)
3392 name = DEV_TTY;
3393 if (!strcmp (name, DEV_TTY))
3394 ctty = 1;
3396 /* If we already have a terminal on the given device, use that. If
3397 all such terminals are suspended, create a new one instead. */
3398 /* XXX Perhaps this should be made explicit by having init_tty
3399 always create a new terminal and separating terminal and frame
3400 creation on Lisp level. */
3401 terminal = get_named_tty (name);
3402 if (terminal)
3403 return terminal;
3405 terminal = create_terminal ();
3406 #ifdef MSDOS
3407 if (been_here > 0)
3408 maybe_fatal (1, 0, "Attempt to create another terminal %s", "",
3409 name, "");
3410 been_here = 1;
3411 tty = &the_only_display_info;
3412 #else
3413 tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info));
3414 #endif
3415 memset (tty, 0, sizeof (struct tty_display_info));
3416 tty->next = tty_list;
3417 tty_list = tty;
3419 terminal->type = output_termcap;
3420 terminal->display_info.tty = tty;
3421 tty->terminal = terminal;
3423 tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
3424 Wcm_clear (tty);
3426 #ifndef DOS_NT
3427 set_tty_hooks (terminal);
3430 int fd;
3431 FILE *file;
3433 #ifdef O_IGNORE_CTTY
3434 if (!ctty)
3435 /* Open the terminal device. Don't recognize it as our
3436 controlling terminal, and don't make it the controlling tty
3437 if we don't have one at the moment. */
3438 fd = emacs_open (name, O_RDWR | O_IGNORE_CTTY | O_NOCTTY, 0);
3439 else
3440 #else
3441 /* Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
3442 defined on Hurd. On other systems, we need to explicitly
3443 dissociate ourselves from the controlling tty when we want to
3444 open a frame on the same terminal. */
3445 fd = emacs_open (name, O_RDWR | O_NOCTTY, 0);
3446 #endif /* O_IGNORE_CTTY */
3448 tty->name = xstrdup (name);
3449 terminal->name = xstrdup (name);
3451 if (fd < 0)
3452 maybe_fatal (must_succeed, terminal,
3453 "Could not open file: %s",
3454 "Could not open file: %s",
3455 name);
3456 if (!isatty (fd))
3458 close (fd);
3459 maybe_fatal (must_succeed, terminal,
3460 "Not a tty device: %s",
3461 "Not a tty device: %s",
3462 name);
3465 #ifndef O_IGNORE_CTTY
3466 if (!ctty)
3467 dissociate_if_controlling_tty (fd);
3468 #endif
3470 file = fdopen (fd, "w+");
3471 tty->input = file;
3472 tty->output = file;
3475 tty->type = xstrdup (terminal_type);
3477 add_keyboard_wait_descriptor (fileno (tty->input));
3479 #endif /* !DOS_NT */
3481 encode_terminal_src_size = 0;
3482 encode_terminal_dst_size = 0;
3484 #ifdef HAVE_GPM
3485 terminal->mouse_position_hook = term_mouse_position;
3486 mouse_face_window = Qnil;
3487 #endif
3489 #ifdef DOS_NT
3490 #ifdef WINDOWSNT
3491 initialize_w32_display (terminal);
3492 #else /* MSDOS */
3493 if (strcmp (terminal_type, "internal") == 0)
3494 terminal->type = output_msdos_raw;
3495 initialize_msdos_display (terminal);
3496 #endif /* MSDOS */
3497 tty->output = stdout;
3498 tty->input = stdin;
3499 /* The following two are inaccessible from w32console.c. */
3500 terminal->delete_frame_hook = &tty_free_frame_resources;
3501 terminal->delete_terminal_hook = &delete_tty;
3503 tty->name = xstrdup (name);
3504 terminal->name = xstrdup (name);
3505 tty->type = xstrdup (terminal_type);
3507 add_keyboard_wait_descriptor (0);
3509 Wcm_clear (tty);
3511 #ifdef WINDOWSNT
3513 struct frame *f = XFRAME (selected_frame);
3515 FrameRows (tty) = FRAME_LINES (f);
3516 FrameCols (tty) = FRAME_COLS (f);
3517 tty->specified_window = FRAME_LINES (f);
3519 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
3520 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
3522 #else /* MSDOS */
3524 int height, width;
3525 get_tty_size (fileno (tty->input), &width, &height);
3526 FrameCols (tty) = width;
3527 FrameRows (tty) = height;
3529 #endif /* MSDOS */
3530 tty->delete_in_insert_mode = 1;
3532 UseTabs (tty) = 0;
3533 terminal->scroll_region_ok = 0;
3535 /* Seems to insert lines when it's not supposed to, messing up the
3536 display. In doing a trace, it didn't seem to be called much, so I
3537 don't think we're losing anything by turning it off. */
3538 terminal->line_ins_del_ok = 0;
3539 #ifdef WINDOWSNT
3540 terminal->char_ins_del_ok = 1;
3541 baud_rate = 19200;
3542 #else /* MSDOS */
3543 terminal->char_ins_del_ok = 0;
3544 init_baud_rate (fileno (tty->input));
3545 #endif /* MSDOS */
3547 tty->TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
3549 #else /* not DOS_NT */
3551 Wcm_clear (tty);
3553 tty->termcap_term_buffer = (char *) xmalloc (buffer_size);
3555 /* On some systems, tgetent tries to access the controlling
3556 terminal. */
3557 sigblock (sigmask (SIGTTOU));
3558 status = tgetent (tty->termcap_term_buffer, terminal_type);
3559 sigunblock (sigmask (SIGTTOU));
3561 if (status < 0)
3563 #ifdef TERMINFO
3564 maybe_fatal (must_succeed, terminal,
3565 "Cannot open terminfo database file",
3566 "Cannot open terminfo database file");
3567 #else
3568 maybe_fatal (must_succeed, terminal,
3569 "Cannot open termcap database file",
3570 "Cannot open termcap database file");
3571 #endif
3573 if (status == 0)
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 #ifdef TERMINFO
3582 "to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3583 #else
3584 "to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3585 #endif
3586 terminal_type);
3589 #ifndef TERMINFO
3590 if (strlen (tty->termcap_term_buffer) >= buffer_size)
3591 abort ();
3592 buffer_size = strlen (tty->termcap_term_buffer);
3593 #endif
3594 tty->termcap_strings_buffer = area = (char *) xmalloc (buffer_size);
3595 tty->TS_ins_line = tgetstr ("al", address);
3596 tty->TS_ins_multi_lines = tgetstr ("AL", address);
3597 tty->TS_bell = tgetstr ("bl", address);
3598 BackTab (tty) = tgetstr ("bt", address);
3599 tty->TS_clr_to_bottom = tgetstr ("cd", address);
3600 tty->TS_clr_line = tgetstr ("ce", address);
3601 tty->TS_clr_frame = tgetstr ("cl", address);
3602 ColPosition (tty) = NULL; /* tgetstr ("ch", address); */
3603 AbsPosition (tty) = tgetstr ("cm", address);
3604 CR (tty) = tgetstr ("cr", address);
3605 tty->TS_set_scroll_region = tgetstr ("cs", address);
3606 tty->TS_set_scroll_region_1 = tgetstr ("cS", address);
3607 RowPosition (tty) = tgetstr ("cv", address);
3608 tty->TS_del_char = tgetstr ("dc", address);
3609 tty->TS_del_multi_chars = tgetstr ("DC", address);
3610 tty->TS_del_line = tgetstr ("dl", address);
3611 tty->TS_del_multi_lines = tgetstr ("DL", address);
3612 tty->TS_delete_mode = tgetstr ("dm", address);
3613 tty->TS_end_delete_mode = tgetstr ("ed", address);
3614 tty->TS_end_insert_mode = tgetstr ("ei", address);
3615 Home (tty) = tgetstr ("ho", address);
3616 tty->TS_ins_char = tgetstr ("ic", address);
3617 tty->TS_ins_multi_chars = tgetstr ("IC", address);
3618 tty->TS_insert_mode = tgetstr ("im", address);
3619 tty->TS_pad_inserted_char = tgetstr ("ip", address);
3620 tty->TS_end_keypad_mode = tgetstr ("ke", address);
3621 tty->TS_keypad_mode = tgetstr ("ks", address);
3622 LastLine (tty) = tgetstr ("ll", address);
3623 Right (tty) = tgetstr ("nd", address);
3624 Down (tty) = tgetstr ("do", address);
3625 if (!Down (tty))
3626 Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do" */
3627 if (tgetflag ("bs"))
3628 Left (tty) = "\b"; /* can't possibly be longer! */
3629 else /* (Actually, "bs" is obsolete...) */
3630 Left (tty) = tgetstr ("le", address);
3631 if (!Left (tty))
3632 Left (tty) = tgetstr ("bc", address); /* Obsolete name for "le" */
3633 tty->TS_pad_char = tgetstr ("pc", address);
3634 tty->TS_repeat = tgetstr ("rp", address);
3635 tty->TS_end_standout_mode = tgetstr ("se", address);
3636 tty->TS_fwd_scroll = tgetstr ("sf", address);
3637 tty->TS_standout_mode = tgetstr ("so", address);
3638 tty->TS_rev_scroll = tgetstr ("sr", address);
3639 tty->Wcm->cm_tab = tgetstr ("ta", address);
3640 tty->TS_end_termcap_modes = tgetstr ("te", address);
3641 tty->TS_termcap_modes = tgetstr ("ti", address);
3642 Up (tty) = tgetstr ("up", address);
3643 tty->TS_visible_bell = tgetstr ("vb", address);
3644 tty->TS_cursor_normal = tgetstr ("ve", address);
3645 tty->TS_cursor_visible = tgetstr ("vs", address);
3646 tty->TS_cursor_invisible = tgetstr ("vi", address);
3647 tty->TS_set_window = tgetstr ("wi", address);
3649 tty->TS_enter_underline_mode = tgetstr ("us", address);
3650 tty->TS_exit_underline_mode = tgetstr ("ue", address);
3651 tty->TS_enter_bold_mode = tgetstr ("md", address);
3652 tty->TS_enter_dim_mode = tgetstr ("mh", address);
3653 tty->TS_enter_blink_mode = tgetstr ("mb", address);
3654 tty->TS_enter_reverse_mode = tgetstr ("mr", address);
3655 tty->TS_enter_alt_charset_mode = tgetstr ("as", address);
3656 tty->TS_exit_alt_charset_mode = tgetstr ("ae", address);
3657 tty->TS_exit_attribute_mode = tgetstr ("me", address);
3659 MultiUp (tty) = tgetstr ("UP", address);
3660 MultiDown (tty) = tgetstr ("DO", address);
3661 MultiLeft (tty) = tgetstr ("LE", address);
3662 MultiRight (tty) = tgetstr ("RI", address);
3664 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
3665 color because we can't switch back to the default foreground and
3666 background. */
3667 tty->TS_orig_pair = tgetstr ("op", address);
3668 if (tty->TS_orig_pair)
3670 tty->TS_set_foreground = tgetstr ("AF", address);
3671 tty->TS_set_background = tgetstr ("AB", address);
3672 if (!tty->TS_set_foreground)
3674 /* SVr4. */
3675 tty->TS_set_foreground = tgetstr ("Sf", address);
3676 tty->TS_set_background = tgetstr ("Sb", address);
3679 tty->TN_max_colors = tgetnum ("Co");
3680 tty->TN_max_pairs = tgetnum ("pa");
3682 tty->TN_no_color_video = tgetnum ("NC");
3683 if (tty->TN_no_color_video == -1)
3684 tty->TN_no_color_video = 0;
3687 tty_default_color_capabilities (tty, 1);
3689 MagicWrap (tty) = tgetflag ("xn");
3690 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
3691 the former flag imply the latter. */
3692 AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
3693 terminal->memory_below_frame = tgetflag ("db");
3694 tty->TF_hazeltine = tgetflag ("hz");
3695 terminal->must_write_spaces = tgetflag ("in");
3696 tty->meta_key = tgetflag ("km") || tgetflag ("MT");
3697 tty->TF_insmode_motion = tgetflag ("mi");
3698 tty->TF_standout_motion = tgetflag ("ms");
3699 tty->TF_underscore = tgetflag ("ul");
3700 tty->TF_teleray = tgetflag ("xt");
3702 #endif /* !DOS_NT */
3703 terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
3704 init_kboard (terminal->kboard);
3705 terminal->kboard->Vwindow_system = Qnil;
3706 terminal->kboard->next_kboard = all_kboards;
3707 all_kboards = terminal->kboard;
3708 terminal->kboard->reference_count++;
3709 /* Don't let the initial kboard remain current longer than necessary.
3710 That would cause problems if a file loaded on startup tries to
3711 prompt in the mini-buffer. */
3712 if (current_kboard == initial_kboard)
3713 current_kboard = terminal->kboard;
3714 #ifndef DOS_NT
3715 term_get_fkeys (address, terminal->kboard);
3717 /* Get frame size from system, or else from termcap. */
3719 int height, width;
3720 get_tty_size (fileno (tty->input), &width, &height);
3721 FrameCols (tty) = width;
3722 FrameRows (tty) = height;
3725 if (FrameCols (tty) <= 0)
3726 FrameCols (tty) = tgetnum ("co");
3727 if (FrameRows (tty) <= 0)
3728 FrameRows (tty) = tgetnum ("li");
3730 if (FrameRows (tty) < 3 || FrameCols (tty) < 3)
3731 maybe_fatal (must_succeed, terminal,
3732 "Screen size %dx%d is too small",
3733 "Screen size %dx%d is too small",
3734 FrameCols (tty), FrameRows (tty));
3736 TabWidth (tty) = tgetnum ("tw");
3738 if (!tty->TS_bell)
3739 tty->TS_bell = "\07";
3741 if (!tty->TS_fwd_scroll)
3742 tty->TS_fwd_scroll = Down (tty);
3744 PC = tty->TS_pad_char ? *tty->TS_pad_char : 0;
3746 if (TabWidth (tty) < 0)
3747 TabWidth (tty) = 8;
3749 /* Turned off since /etc/termcap seems to have :ta= for most terminals
3750 and newer termcap doc does not seem to say there is a default.
3751 if (!tty->Wcm->cm_tab)
3752 tty->Wcm->cm_tab = "\t";
3755 /* We don't support standout modes that use `magic cookies', so
3756 turn off any that do. */
3757 if (tty->TS_standout_mode && tgetnum ("sg") >= 0)
3759 tty->TS_standout_mode = 0;
3760 tty->TS_end_standout_mode = 0;
3762 if (tty->TS_enter_underline_mode && tgetnum ("ug") >= 0)
3764 tty->TS_enter_underline_mode = 0;
3765 tty->TS_exit_underline_mode = 0;
3768 /* If there's no standout mode, try to use underlining instead. */
3769 if (tty->TS_standout_mode == 0)
3771 tty->TS_standout_mode = tty->TS_enter_underline_mode;
3772 tty->TS_end_standout_mode = tty->TS_exit_underline_mode;
3775 /* If no `se' string, try using a `me' string instead.
3776 If that fails, we can't use standout mode at all. */
3777 if (tty->TS_end_standout_mode == 0)
3779 char *s = tgetstr ("me", address);
3780 if (s != 0)
3781 tty->TS_end_standout_mode = s;
3782 else
3783 tty->TS_standout_mode = 0;
3786 if (tty->TF_teleray)
3788 tty->Wcm->cm_tab = 0;
3789 /* We can't support standout mode, because it uses magic cookies. */
3790 tty->TS_standout_mode = 0;
3791 /* But that means we cannot rely on ^M to go to column zero! */
3792 CR (tty) = 0;
3793 /* LF can't be trusted either -- can alter hpos */
3794 /* if move at column 0 thru a line with TS_standout_mode */
3795 Down (tty) = 0;
3798 /* Special handling for certain terminal types known to need it */
3800 if (!strcmp (terminal_type, "supdup"))
3802 terminal->memory_below_frame = 1;
3803 tty->Wcm->cm_losewrap = 1;
3805 if (!strncmp (terminal_type, "c10", 3)
3806 || !strcmp (terminal_type, "perq"))
3808 /* Supply a makeshift :wi string.
3809 This string is not valid in general since it works only
3810 for windows starting at the upper left corner;
3811 but that is all Emacs uses.
3813 This string works only if the frame is using
3814 the top of the video memory, because addressing is memory-relative.
3815 So first check the :ti string to see if that is true.
3817 It would be simpler if the :wi string could go in the termcap
3818 entry, but it can't because it is not fully valid.
3819 If it were in the termcap entry, it would confuse other programs. */
3820 if (!tty->TS_set_window)
3822 p = tty->TS_termcap_modes;
3823 while (*p && strcmp (p, "\033v "))
3824 p++;
3825 if (*p)
3826 tty->TS_set_window = "\033v%C %C %C %C ";
3828 /* Termcap entry often fails to have :in: flag */
3829 terminal->must_write_spaces = 1;
3830 /* :ti string typically fails to have \E^G! in it */
3831 /* This limits scope of insert-char to one line. */
3832 strcpy (area, tty->TS_termcap_modes);
3833 strcat (area, "\033\007!");
3834 tty->TS_termcap_modes = area;
3835 area += strlen (area) + 1;
3836 p = AbsPosition (tty);
3837 /* Change all %+ parameters to %C, to handle
3838 values above 96 correctly for the C100. */
3839 while (*p)
3841 if (p[0] == '%' && p[1] == '+')
3842 p[1] = 'C';
3843 p++;
3847 tty->specified_window = FrameRows (tty);
3849 if (Wcm_init (tty) == -1) /* can't do cursor motion */
3851 maybe_fatal (must_succeed, terminal,
3852 "Terminal type \"%s\" is not powerful enough to run Emacs",
3853 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3854 It lacks the ability to position the cursor.\n\
3855 If that is not the actual type of terminal you have,\n\
3856 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3857 `setenv TERM ...') to specify the correct type. It may be necessary\n"
3858 # ifdef TERMINFO
3859 "to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3860 # else /* TERMCAP */
3861 "to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3862 # endif /* TERMINFO */
3863 terminal_type);
3866 if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
3867 maybe_fatal (must_succeed, terminal,
3868 "Could not determine the frame size",
3869 "Could not determine the frame size");
3871 tty->delete_in_insert_mode
3872 = tty->TS_delete_mode && tty->TS_insert_mode
3873 && !strcmp (tty->TS_delete_mode, tty->TS_insert_mode);
3875 tty->se_is_so = (tty->TS_standout_mode
3876 && tty->TS_end_standout_mode
3877 && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode));
3879 UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8;
3881 terminal->scroll_region_ok
3882 = (tty->Wcm->cm_abs
3883 && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
3885 terminal->line_ins_del_ok
3886 = (((tty->TS_ins_line || tty->TS_ins_multi_lines)
3887 && (tty->TS_del_line || tty->TS_del_multi_lines))
3888 || (terminal->scroll_region_ok
3889 && tty->TS_fwd_scroll && tty->TS_rev_scroll));
3891 terminal->char_ins_del_ok
3892 = ((tty->TS_ins_char || tty->TS_insert_mode
3893 || tty->TS_pad_inserted_char || tty->TS_ins_multi_chars)
3894 && (tty->TS_del_char || tty->TS_del_multi_chars));
3896 terminal->fast_clear_end_of_line = tty->TS_clr_line != 0;
3898 init_baud_rate (fileno (tty->input));
3900 #endif /* not DOS_NT */
3902 /* Init system terminal modes (RAW or CBREAK, etc.). */
3903 init_sys_modes (tty);
3905 return terminal;
3909 static void
3910 vfatal (const char *str, va_list ap)
3912 fprintf (stderr, "emacs: ");
3913 vfprintf (stderr, str, ap);
3914 if (!(strlen (str) > 0 && str[strlen (str) - 1] == '\n'))
3915 fprintf (stderr, "\n");
3916 va_end (ap);
3917 fflush (stderr);
3918 exit (1);
3922 /* Auxiliary error-handling function for init_tty.
3923 Delete TERMINAL, then call error or fatal with str1 or str2,
3924 respectively, according to MUST_SUCCEED. */
3926 static void
3927 maybe_fatal (int must_succeed, struct terminal *terminal,
3928 const char *str1, const char *str2, ...)
3930 va_list ap;
3931 va_start (ap, str2);
3932 if (terminal)
3933 delete_tty (terminal);
3935 if (must_succeed)
3936 vfatal (str2, ap);
3937 else
3938 verror (str1, ap);
3940 va_end (ap);
3941 abort ();
3944 void
3945 fatal (const char *str, ...)
3947 va_list ap;
3948 va_start (ap, str);
3949 vfatal (str, ap);
3950 va_end (ap);
3955 /* Delete the given tty terminal, closing all frames on it. */
3957 static void
3958 delete_tty (struct terminal *terminal)
3960 struct tty_display_info *tty;
3962 /* Protect against recursive calls. delete_frame in
3963 delete_terminal calls us back when it deletes our last frame. */
3964 if (!terminal->name)
3965 return;
3967 if (terminal->type != output_termcap)
3968 abort ();
3970 tty = terminal->display_info.tty;
3972 if (tty == tty_list)
3973 tty_list = tty->next;
3974 else
3976 struct tty_display_info *p;
3977 for (p = tty_list; p && p->next != tty; p = p->next)
3980 if (! p)
3981 /* This should not happen. */
3982 abort ();
3984 p->next = tty->next;
3985 tty->next = 0;
3988 /* reset_sys_modes needs a valid device, so this call needs to be
3989 before delete_terminal. */
3990 reset_sys_modes (tty);
3992 delete_terminal (terminal);
3994 xfree (tty->name);
3995 xfree (tty->type);
3997 if (tty->input)
3999 delete_keyboard_wait_descriptor (fileno (tty->input));
4000 if (tty->input != stdin)
4001 fclose (tty->input);
4003 if (tty->output && tty->output != stdout && tty->output != tty->input)
4004 fclose (tty->output);
4005 if (tty->termscript)
4006 fclose (tty->termscript);
4008 xfree (tty->old_tty);
4009 xfree (tty->Wcm);
4010 xfree (tty->termcap_strings_buffer);
4011 xfree (tty->termcap_term_buffer);
4013 memset (tty, 0, sizeof (struct tty_display_info));
4014 xfree (tty);
4019 /* Mark the pointers in the tty_display_info objects.
4020 Called by the Fgarbage_collector. */
4022 void
4023 mark_ttys (void)
4025 struct tty_display_info *tty;
4027 for (tty = tty_list; tty; tty = tty->next)
4028 mark_object (tty->top_frame);
4033 void
4034 syms_of_term (void)
4036 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
4037 doc: /* Non-nil means the system uses terminfo rather than termcap.
4038 This variable can be used by terminal emulator packages. */);
4039 #ifdef TERMINFO
4040 system_uses_terminfo = 1;
4041 #else
4042 system_uses_terminfo = 0;
4043 #endif
4045 DEFVAR_LISP ("suspend-tty-functions", &Vsuspend_tty_functions,
4046 doc: /* Functions to be run after suspending a tty.
4047 The functions are run with one argument, the terminal object to be suspended.
4048 See `suspend-tty'. */);
4049 Vsuspend_tty_functions = Qnil;
4052 DEFVAR_LISP ("resume-tty-functions", &Vresume_tty_functions,
4053 doc: /* Functions to be run after resuming a tty.
4054 The functions are run with one argument, the terminal object that was revived.
4055 See `resume-tty'. */);
4056 Vresume_tty_functions = Qnil;
4058 DEFVAR_BOOL ("visible-cursor", &visible_cursor,
4059 doc: /* Non-nil means to make the cursor very visible.
4060 This only has an effect when running in a text terminal.
4061 What means \"very visible\" is up to your terminal. It may make the cursor
4062 bigger, or it may make it blink, or it may do nothing at all. */);
4063 visible_cursor = 1;
4065 defsubr (&Stty_display_color_p);
4066 defsubr (&Stty_display_color_cells);
4067 defsubr (&Stty_no_underline);
4068 defsubr (&Stty_type);
4069 defsubr (&Scontrolling_tty_p);
4070 defsubr (&Ssuspend_tty);
4071 defsubr (&Sresume_tty);
4072 #ifdef HAVE_GPM
4073 defsubr (&Sgpm_mouse_start);
4074 defsubr (&Sgpm_mouse_stop);
4076 staticpro (&mouse_face_window);
4077 #endif /* HAVE_GPM */
4079 #ifndef DOS_NT
4080 default_orig_pair = NULL;
4081 default_set_foreground = NULL;
4082 default_set_background = NULL;
4083 #endif /* !DOS_NT */
4085 encode_terminal_src = NULL;
4086 encode_terminal_dst = NULL;
4091 /* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193
4092 (do not change this comment) */