* alloc.c: Do not define struct catchtag.
[bpt/emacs.git] / src / term.c
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
4 Free Software Foundation, Inc.
5
6 This file is part of GNU Emacs.
7
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.
12
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.
17
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/>. */
20
21 /* New redisplay, TTY faces by Gerd Moellmann <gerd@gnu.org>. */
22
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>
29
30 #ifdef HAVE_UNISTD_H
31 #include <unistd.h>
32 #endif
33
34 #if HAVE_TERMIOS_H
35 #include <termios.h> /* For TIOCNOTTY. */
36 #endif
37
38 #include <signal.h>
39 #include <stdarg.h>
40 #include <setjmp.h>
41
42 #include "lisp.h"
43 #include "termchar.h"
44 #include "termopts.h"
45 #include "buffer.h"
46 #include "character.h"
47 #include "charset.h"
48 #include "coding.h"
49 #include "composite.h"
50 #include "keyboard.h"
51 #include "frame.h"
52 #include "disptab.h"
53 #include "termhooks.h"
54 #include "dispextern.h"
55 #include "window.h"
56 #include "keymap.h"
57 #include "blockinput.h"
58 #include "syssignal.h"
59 #include "systty.h"
60 #include "intervals.h"
61 #ifdef MSDOS
62 #include "msdos.h"
63 static int been_here = -1;
64 #endif
65
66 /* For now, don't try to include termcap.h. On some systems,
67 configure finds a non-standard termcap.h that the main build
68 won't find. */
69
70 #if defined HAVE_TERMCAP_H && 0
71 #include <termcap.h>
72 #else
73 extern void tputs P_ ((const char *, int, int (*)(int)));
74 extern int tgetent P_ ((char *, const char *));
75 extern int tgetflag P_ ((char *id));
76 extern int tgetnum P_ ((char *id));
77 #endif
78
79 #include "cm.h"
80 #ifdef HAVE_X_WINDOWS
81 #include "xterm.h"
82 #endif
83
84 #ifndef O_RDWR
85 #define O_RDWR 2
86 #endif
87
88 #ifndef O_NOCTTY
89 #define O_NOCTTY 0
90 #endif
91
92 /* The name of the default console device. */
93 #ifdef WINDOWSNT
94 #define DEV_TTY "CONOUT$"
95 #else
96 #define DEV_TTY "/dev/tty"
97 #endif
98
99 static void tty_set_scroll_region P_ ((struct frame *f, int start, int stop));
100 static void turn_on_face P_ ((struct frame *, int face_id));
101 static void turn_off_face P_ ((struct frame *, int face_id));
102 static void tty_show_cursor P_ ((struct tty_display_info *));
103 static void tty_hide_cursor P_ ((struct tty_display_info *));
104 static void tty_background_highlight P_ ((struct tty_display_info *tty));
105 static void clear_tty_hooks P_ ((struct terminal *terminal));
106 static void set_tty_hooks P_ ((struct terminal *terminal));
107 static void dissociate_if_controlling_tty P_ ((int fd));
108 static void delete_tty P_ ((struct terminal *));
109
110 #define OUTPUT(tty, a) \
111 emacs_tputs ((tty), a, \
112 (int) (FRAME_LINES (XFRAME (selected_frame)) \
113 - curY (tty)), \
114 cmputc)
115
116 #define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
117 #define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
118
119 #define OUTPUT_IF(tty, a) \
120 do { \
121 if (a) \
122 emacs_tputs ((tty), a, \
123 (int) (FRAME_LINES (XFRAME (selected_frame)) \
124 - curY (tty) ), \
125 cmputc); \
126 } while (0)
127
128 #define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
129
130 /* If true, use "vs", otherwise use "ve" to make the cursor visible. */
131
132 static int visible_cursor;
133
134 /* Display space properties */
135
136 extern Lisp_Object Qspace, QCalign_to, QCwidth;
137
138 /* Functions to call after suspending a tty. */
139 Lisp_Object Vsuspend_tty_functions;
140
141 /* Functions to call after resuming a tty. */
142 Lisp_Object Vresume_tty_functions;
143
144 /* Chain of all tty device parameters. */
145 struct tty_display_info *tty_list;
146
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;
152
153 /* Meaning of bits in no_color_video. Each bit set means that the
154 corresponding attribute cannot be combined with colors. */
155
156 enum no_color_bit
157 {
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
167 };
168
169 /* internal state */
170
171 /* The largest frame width in any call to calculate_costs. */
172
173 int max_frame_cols;
174
175 /* The largest frame height in any call to calculate_costs. */
176
177 int max_frame_lines;
178
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;
182
183 /* Provided for lisp packages. */
184
185 static int system_uses_terminfo;
186
187 char *tparam ();
188
189 extern char *tgetstr ();
190 \f
191
192 #ifdef HAVE_GPM
193 #include <sys/fcntl.h>
194
195 static void term_clear_mouse_face ();
196 static void term_mouse_highlight (struct frame *f, int x, int y);
197
198 /* The device for which we have enabled gpm support (or NULL). */
199 struct tty_display_info *gpm_tty = NULL;
200
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;
211
212 static int pos_x, pos_y;
213 static int last_mouse_x, last_mouse_y;
214 #endif /* HAVE_GPM */
215
216 /* Ring the bell on a tty. */
217
218 static void
219 tty_ring_bell (struct frame *f)
220 {
221 struct tty_display_info *tty = FRAME_TTY (f);
222
223 if (tty->output)
224 {
225 OUTPUT (tty, (tty->TS_visible_bell && visible_bell
226 ? tty->TS_visible_bell
227 : tty->TS_bell));
228 fflush (tty->output);
229 }
230 }
231
232 /* Set up termcap modes for Emacs. */
233
234 void
235 tty_set_terminal_modes (struct terminal *terminal)
236 {
237 struct tty_display_info *tty = terminal->display_info.tty;
238
239 if (tty->output)
240 {
241 if (tty->TS_termcap_modes)
242 OUTPUT (tty, tty->TS_termcap_modes);
243 else
244 {
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');
251 }
252
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);
258 }
259 }
260
261 /* Reset termcap modes before exiting Emacs. */
262
263 void
264 tty_reset_terminal_modes (struct terminal *terminal)
265 {
266 struct tty_display_info *tty = terminal->display_info.tty;
267
268 if (tty->output)
269 {
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);
280 }
281 }
282
283 /* Flag the end of a display update on a termcap terminal. */
284
285 static void
286 tty_update_end (struct frame *f)
287 {
288 struct tty_display_info *tty = FRAME_TTY (f);
289
290 if (!XWINDOW (selected_window)->cursor_off_p)
291 tty_show_cursor (tty);
292 tty_turn_off_insert (tty);
293 tty_background_highlight (tty);
294 }
295
296 /* The implementation of set_terminal_window for termcap frames. */
297
298 static void
299 tty_set_terminal_window (struct frame *f, int size)
300 {
301 struct tty_display_info *tty = FRAME_TTY (f);
302
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);
306 }
307
308 static void
309 tty_set_scroll_region (struct frame *f, int start, int stop)
310 {
311 char *buf;
312 struct tty_display_info *tty = FRAME_TTY (f);
313
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));
323
324 OUTPUT (tty, buf);
325 xfree (buf);
326 losecursor (tty);
327 }
328
329 \f
330 static void
331 tty_turn_on_insert (struct tty_display_info *tty)
332 {
333 if (!tty->insert_mode)
334 OUTPUT (tty, tty->TS_insert_mode);
335 tty->insert_mode = 1;
336 }
337
338 void
339 tty_turn_off_insert (struct tty_display_info *tty)
340 {
341 if (tty->insert_mode)
342 OUTPUT (tty, tty->TS_end_insert_mode);
343 tty->insert_mode = 0;
344 }
345 \f
346 /* Handle highlighting. */
347
348 void
349 tty_turn_off_highlight (struct tty_display_info *tty)
350 {
351 if (tty->standout_mode)
352 OUTPUT_IF (tty, tty->TS_end_standout_mode);
353 tty->standout_mode = 0;
354 }
355
356 static void
357 tty_turn_on_highlight (struct tty_display_info *tty)
358 {
359 if (!tty->standout_mode)
360 OUTPUT_IF (tty, tty->TS_standout_mode);
361 tty->standout_mode = 1;
362 }
363
364 static void
365 tty_toggle_highlight (struct tty_display_info *tty)
366 {
367 if (tty->standout_mode)
368 tty_turn_off_highlight (tty);
369 else
370 tty_turn_on_highlight (tty);
371 }
372
373
374 /* Make cursor invisible. */
375
376 static void
377 tty_hide_cursor (struct tty_display_info *tty)
378 {
379 if (tty->cursor_hidden == 0)
380 {
381 tty->cursor_hidden = 1;
382 OUTPUT_IF (tty, tty->TS_cursor_invisible);
383 }
384 }
385
386
387 /* Ensure that cursor is visible. */
388
389 static void
390 tty_show_cursor (struct tty_display_info *tty)
391 {
392 if (tty->cursor_hidden)
393 {
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);
398 }
399 }
400
401
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. */
405
406 static void
407 tty_background_highlight (struct tty_display_info *tty)
408 {
409 if (inverse_video)
410 tty_turn_on_highlight (tty);
411 else
412 tty_turn_off_highlight (tty);
413 }
414
415 /* Set standout mode to the mode specified for the text to be output. */
416
417 static void
418 tty_highlight_if_desired (struct tty_display_info *tty)
419 {
420 if (inverse_video)
421 tty_turn_on_highlight (tty);
422 else
423 tty_turn_off_highlight (tty);
424 }
425 \f
426
427 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
428 frame-relative coordinates. */
429
430 static void
431 tty_cursor_to (struct frame *f, int vpos, int hpos)
432 {
433 struct tty_display_info *tty = FRAME_TTY (f);
434
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;
439
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);
448 }
449
450 /* Similar but don't take any account of the wasted characters. */
451
452 static void
453 tty_raw_cursor_to (struct frame *f, int row, int col)
454 {
455 struct tty_display_info *tty = FRAME_TTY (f);
456
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);
465 }
466 \f
467 /* Erase operations */
468
469 /* Clear from cursor to end of frame on a termcap device. */
470
471 static void
472 tty_clear_to_end (struct frame *f)
473 {
474 register int i;
475 struct tty_display_info *tty = FRAME_TTY (f);
476
477 if (tty->TS_clr_to_bottom)
478 {
479 tty_background_highlight (tty);
480 OUTPUT (tty, tty->TS_clr_to_bottom);
481 }
482 else
483 {
484 for (i = curY (tty); i < FRAME_LINES (f); i++)
485 {
486 cursor_to (f, i, 0);
487 clear_end_of_line (f, FRAME_COLS (f));
488 }
489 }
490 }
491
492 /* Clear an entire termcap frame. */
493
494 static void
495 tty_clear_frame (struct frame *f)
496 {
497 struct tty_display_info *tty = FRAME_TTY (f);
498
499 if (tty->TS_clr_frame)
500 {
501 tty_background_highlight (tty);
502 OUTPUT (tty, tty->TS_clr_frame);
503 cmat (tty, 0, 0);
504 }
505 else
506 {
507 cursor_to (f, 0, 0);
508 clear_to_end (f);
509 }
510 }
511
512 /* An implementation of clear_end_of_line for termcap frames.
513
514 Note that the cursor may be moved, on terminals lacking a `ce' string. */
515
516 static void
517 tty_clear_end_of_line (struct frame *f, int first_unused_hpos)
518 {
519 register int i;
520 struct tty_display_info *tty = FRAME_TTY (f);
521
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;
526
527 if (curX (tty) >= first_unused_hpos)
528 return;
529 tty_background_highlight (tty);
530 if (tty->TS_clr_line)
531 {
532 OUTPUT1 (tty, tty->TS_clr_line);
533 }
534 else
535 { /* have to do it the hard way */
536 tty_turn_off_insert (tty);
537
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--;
543
544 for (i = curX (tty); i < first_unused_hpos; i++)
545 {
546 if (tty->termscript)
547 fputc (' ', tty->termscript);
548 fputc (' ', tty->output);
549 }
550 cmplus (tty, first_unused_hpos - curX (tty));
551 }
552 }
553 \f
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;
560
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. */
564
565 unsigned char *
566 encode_terminal_code (src, src_len, coding)
567 struct glyph *src;
568 int src_len;
569 struct coding_system *coding;
570 {
571 struct glyph *src_end = src + src_len;
572 unsigned char *buf;
573 int nchars, nbytes, required;
574 register int tlen = GLYPH_TABLE_LENGTH;
575 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
576 Lisp_Object charset_list;
577
578 /* Allocate sufficient size of buffer to store all characters in
579 multibyte-form. But, it may be enlarged on demand if
580 Vglyph_table contains a string or a composite glyph is
581 encountered. */
582 required = MAX_MULTIBYTE_LENGTH * src_len;
583 if (encode_terminal_src_size < required)
584 {
585 if (encode_terminal_src)
586 encode_terminal_src = xrealloc (encode_terminal_src, required);
587 else
588 encode_terminal_src = xmalloc (required);
589 encode_terminal_src_size = required;
590 }
591
592 charset_list = coding_charset_list (coding);
593
594 buf = encode_terminal_src;
595 nchars = 0;
596 while (src < src_end)
597 {
598 if (src->type == COMPOSITE_GLYPH)
599 {
600 struct composition *cmp;
601 Lisp_Object gstring;
602 int i;
603
604 nbytes = buf - encode_terminal_src;
605 if (src->u.cmp.automatic)
606 {
607 gstring = composition_gstring_from_id (src->u.cmp.id);
608 required = src->u.cmp.to + 1 - src->u.cmp.from;
609 }
610 else
611 {
612 cmp = composition_table[src->u.cmp.id];
613 required = MAX_MULTIBYTE_LENGTH * cmp->glyph_len;
614 }
615
616 if (encode_terminal_src_size < nbytes + required)
617 {
618 encode_terminal_src_size = nbytes + required;
619 encode_terminal_src = xrealloc (encode_terminal_src,
620 encode_terminal_src_size);
621 buf = encode_terminal_src + nbytes;
622 }
623
624 if (src->u.cmp.automatic)
625 for (i = src->u.cmp.from; i <= src->u.cmp.to; i++)
626 {
627 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
628 int c = LGLYPH_CHAR (g);
629
630 if (! char_charset (c, charset_list, NULL))
631 c = '?';
632 buf += CHAR_STRING (c, buf);
633 nchars++;
634 }
635 else
636 for (i = 0; i < cmp->glyph_len; i++)
637 {
638 int c = COMPOSITION_GLYPH (cmp, i);
639
640 if (c == '\t')
641 continue;
642 if (char_charset (c, charset_list, NULL))
643 {
644 if (CHAR_WIDTH (c) == 0
645 && i > 0 && COMPOSITION_GLYPH (cmp, i - 1) == '\t')
646 /* Should be left-padded */
647 {
648 buf += CHAR_STRING (' ', buf);
649 nchars++;
650 }
651 }
652 else
653 c = '?';
654 buf += CHAR_STRING (c, buf);
655 nchars++;
656 }
657 }
658 /* We must skip glyphs to be padded for a wide character. */
659 else if (! CHAR_GLYPH_PADDING_P (*src))
660 {
661 GLYPH g;
662 int c;
663 Lisp_Object string;
664
665 string = Qnil;
666 SET_GLYPH_FROM_CHAR_GLYPH (g, src[0]);
667
668 if (GLYPH_INVALID_P (g) || GLYPH_SIMPLE_P (tbase, tlen, g))
669 {
670 /* This glyph doesn't have an entry in Vglyph_table. */
671 c = src->u.ch;
672 }
673 else
674 {
675 /* This glyph has an entry in Vglyph_table,
676 so process any alias before testing for simpleness. */
677 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
678
679 if (GLYPH_SIMPLE_P (tbase, tlen, g))
680 /* We set the multi-byte form of a character in G
681 (that should be an ASCII character) at WORKBUF. */
682 c = GLYPH_CHAR (g);
683 else
684 /* We have a string in Vglyph_table. */
685 string = tbase[GLYPH_CHAR (g)];
686 }
687
688 if (NILP (string))
689 {
690 nbytes = buf - encode_terminal_src;
691 if (encode_terminal_src_size < nbytes + MAX_MULTIBYTE_LENGTH)
692 {
693 encode_terminal_src_size = nbytes + MAX_MULTIBYTE_LENGTH;
694 encode_terminal_src = xrealloc (encode_terminal_src,
695 encode_terminal_src_size);
696 buf = encode_terminal_src + nbytes;
697 }
698 if (char_charset (c, charset_list, NULL))
699 {
700 /* Store the multibyte form of C at BUF. */
701 buf += CHAR_STRING (c, buf);
702 nchars++;
703 }
704 else
705 {
706 /* C is not encodable. */
707 *buf++ = '?';
708 nchars++;
709 while (src + 1 < src_end && CHAR_GLYPH_PADDING_P (src[1]))
710 {
711 *buf++ = '?';
712 nchars++;
713 src++;
714 }
715 }
716 }
717 else
718 {
719 unsigned char *p = SDATA (string), *pend = p + SBYTES (string);
720
721 if (! STRING_MULTIBYTE (string))
722 string = string_to_multibyte (string);
723 nbytes = buf - encode_terminal_src;
724 if (encode_terminal_src_size < nbytes + SBYTES (string))
725 {
726 encode_terminal_src_size = nbytes + SBYTES (string);
727 encode_terminal_src = xrealloc (encode_terminal_src,
728 encode_terminal_src_size);
729 buf = encode_terminal_src + nbytes;
730 }
731 bcopy (SDATA (string), buf, SBYTES (string));
732 buf += SBYTES (string);
733 nchars += SCHARS (string);
734 }
735 }
736 src++;
737 }
738
739 if (nchars == 0)
740 {
741 coding->produced = 0;
742 return NULL;
743 }
744
745 nbytes = buf - encode_terminal_src;
746 coding->source = encode_terminal_src;
747 if (encode_terminal_dst_size == 0)
748 {
749 encode_terminal_dst_size = encode_terminal_src_size;
750 if (encode_terminal_dst)
751 encode_terminal_dst = xrealloc (encode_terminal_dst,
752 encode_terminal_dst_size);
753 else
754 encode_terminal_dst = xmalloc (encode_terminal_dst_size);
755 }
756 coding->destination = encode_terminal_dst;
757 coding->dst_bytes = encode_terminal_dst_size;
758 encode_coding_object (coding, Qnil, 0, 0, nchars, nbytes, Qnil);
759 /* coding->destination may have been reallocated. */
760 encode_terminal_dst = coding->destination;
761 encode_terminal_dst_size = coding->dst_bytes;
762
763 return (encode_terminal_dst);
764 }
765
766
767
768 /* An implementation of write_glyphs for termcap frames. */
769
770 static void
771 tty_write_glyphs (struct frame *f, struct glyph *string, int len)
772 {
773 unsigned char *conversion_buffer;
774 struct coding_system *coding;
775
776 struct tty_display_info *tty = FRAME_TTY (f);
777
778 tty_turn_off_insert (tty);
779 tty_hide_cursor (tty);
780
781 /* Don't dare write in last column of bottom line, if Auto-Wrap,
782 since that would scroll the whole frame on some terminals. */
783
784 if (AutoWrap (tty)
785 && curY (tty) + 1 == FRAME_LINES (f)
786 && (curX (tty) + len) == FRAME_COLS (f))
787 len --;
788 if (len <= 0)
789 return;
790
791 cmplus (tty, len);
792
793 /* If terminal_coding does any conversion, use it, otherwise use
794 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
795 because it always return 1 if the member src_multibyte is 1. */
796 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
797 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
798 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
799 the tail. */
800 coding->mode &= ~CODING_MODE_LAST_BLOCK;
801
802 while (len > 0)
803 {
804 /* Identify a run of glyphs with the same face. */
805 int face_id = string->face_id;
806 int n;
807
808 for (n = 1; n < len; ++n)
809 if (string[n].face_id != face_id)
810 break;
811
812 /* Turn appearance modes of the face of the run on. */
813 tty_highlight_if_desired (tty);
814 turn_on_face (f, face_id);
815
816 if (n == len)
817 /* This is the last run. */
818 coding->mode |= CODING_MODE_LAST_BLOCK;
819 conversion_buffer = encode_terminal_code (string, n, coding);
820 if (coding->produced > 0)
821 {
822 BLOCK_INPUT;
823 fwrite (conversion_buffer, 1, coding->produced, tty->output);
824 if (ferror (tty->output))
825 clearerr (tty->output);
826 if (tty->termscript)
827 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
828 UNBLOCK_INPUT;
829 }
830 len -= n;
831 string += n;
832
833 /* Turn appearance modes off. */
834 turn_off_face (f, face_id);
835 tty_turn_off_highlight (tty);
836 }
837
838 cmcheckmagic (tty);
839 }
840
841 #ifdef HAVE_GPM /* Only used by GPM code. */
842
843 static void
844 tty_write_glyphs_with_face (f, string, len, face_id)
845 register struct frame *f;
846 register struct glyph *string;
847 register int len, face_id;
848 {
849 unsigned char *conversion_buffer;
850 struct coding_system *coding;
851
852 struct tty_display_info *tty = FRAME_TTY (f);
853
854 tty_turn_off_insert (tty);
855 tty_hide_cursor (tty);
856
857 /* Don't dare write in last column of bottom line, if Auto-Wrap,
858 since that would scroll the whole frame on some terminals. */
859
860 if (AutoWrap (tty)
861 && curY (tty) + 1 == FRAME_LINES (f)
862 && (curX (tty) + len) == FRAME_COLS (f))
863 len --;
864 if (len <= 0)
865 return;
866
867 cmplus (tty, len);
868
869 /* If terminal_coding does any conversion, use it, otherwise use
870 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
871 because it always return 1 if the member src_multibyte is 1. */
872 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
873 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
874 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
875 the tail. */
876 coding->mode &= ~CODING_MODE_LAST_BLOCK;
877
878 /* Turn appearance modes of the face. */
879 tty_highlight_if_desired (tty);
880 turn_on_face (f, face_id);
881
882 coding->mode |= CODING_MODE_LAST_BLOCK;
883 conversion_buffer = encode_terminal_code (string, len, coding);
884 if (coding->produced > 0)
885 {
886 BLOCK_INPUT;
887 fwrite (conversion_buffer, 1, coding->produced, tty->output);
888 if (ferror (tty->output))
889 clearerr (tty->output);
890 if (tty->termscript)
891 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
892 UNBLOCK_INPUT;
893 }
894
895 /* Turn appearance modes off. */
896 turn_off_face (f, face_id);
897 tty_turn_off_highlight (tty);
898
899 cmcheckmagic (tty);
900 }
901 #endif
902
903 /* An implementation of insert_glyphs for termcap frames. */
904
905 static void
906 tty_insert_glyphs (struct frame *f, struct glyph *start, int len)
907 {
908 char *buf;
909 struct glyph *glyph = NULL;
910 unsigned char *conversion_buffer;
911 unsigned char space[1];
912 struct coding_system *coding;
913
914 struct tty_display_info *tty = FRAME_TTY (f);
915
916 if (tty->TS_ins_multi_chars)
917 {
918 buf = tparam (tty->TS_ins_multi_chars, 0, 0, len);
919 OUTPUT1 (tty, buf);
920 xfree (buf);
921 if (start)
922 write_glyphs (f, start, len);
923 return;
924 }
925
926 tty_turn_on_insert (tty);
927 cmplus (tty, len);
928
929 if (! start)
930 space[0] = SPACEGLYPH;
931
932 /* If terminal_coding does any conversion, use it, otherwise use
933 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
934 because it always return 1 if the member src_multibyte is 1. */
935 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
936 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
937 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
938 the tail. */
939 coding->mode &= ~CODING_MODE_LAST_BLOCK;
940
941 while (len-- > 0)
942 {
943 OUTPUT1_IF (tty, tty->TS_ins_char);
944 if (!start)
945 {
946 conversion_buffer = space;
947 coding->produced = 1;
948 }
949 else
950 {
951 tty_highlight_if_desired (tty);
952 turn_on_face (f, start->face_id);
953 glyph = start;
954 ++start;
955 /* We must open sufficient space for a character which
956 occupies more than one column. */
957 while (len && CHAR_GLYPH_PADDING_P (*start))
958 {
959 OUTPUT1_IF (tty, tty->TS_ins_char);
960 start++, len--;
961 }
962
963 if (len <= 0)
964 /* This is the last glyph. */
965 coding->mode |= CODING_MODE_LAST_BLOCK;
966
967 conversion_buffer = encode_terminal_code (glyph, 1, coding);
968 }
969
970 if (coding->produced > 0)
971 {
972 BLOCK_INPUT;
973 fwrite (conversion_buffer, 1, coding->produced, tty->output);
974 if (ferror (tty->output))
975 clearerr (tty->output);
976 if (tty->termscript)
977 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
978 UNBLOCK_INPUT;
979 }
980
981 OUTPUT1_IF (tty, tty->TS_pad_inserted_char);
982 if (start)
983 {
984 turn_off_face (f, glyph->face_id);
985 tty_turn_off_highlight (tty);
986 }
987 }
988
989 cmcheckmagic (tty);
990 }
991
992 /* An implementation of delete_glyphs for termcap frames. */
993
994 static void
995 tty_delete_glyphs (struct frame *f, int n)
996 {
997 char *buf;
998 register int i;
999
1000 struct tty_display_info *tty = FRAME_TTY (f);
1001
1002 if (tty->delete_in_insert_mode)
1003 {
1004 tty_turn_on_insert (tty);
1005 }
1006 else
1007 {
1008 tty_turn_off_insert (tty);
1009 OUTPUT_IF (tty, tty->TS_delete_mode);
1010 }
1011
1012 if (tty->TS_del_multi_chars)
1013 {
1014 buf = tparam (tty->TS_del_multi_chars, 0, 0, n);
1015 OUTPUT1 (tty, buf);
1016 xfree (buf);
1017 }
1018 else
1019 for (i = 0; i < n; i++)
1020 OUTPUT1 (tty, tty->TS_del_char);
1021 if (!tty->delete_in_insert_mode)
1022 OUTPUT_IF (tty, tty->TS_end_delete_mode);
1023 }
1024 \f
1025 /* An implementation of ins_del_lines for termcap frames. */
1026
1027 static void
1028 tty_ins_del_lines (struct frame *f, int vpos, int n)
1029 {
1030 struct tty_display_info *tty = FRAME_TTY (f);
1031 char *multi = n > 0 ? tty->TS_ins_multi_lines : tty->TS_del_multi_lines;
1032 char *single = n > 0 ? tty->TS_ins_line : tty->TS_del_line;
1033 char *scroll = n > 0 ? tty->TS_rev_scroll : tty->TS_fwd_scroll;
1034
1035 register int i = n > 0 ? n : -n;
1036 register char *buf;
1037
1038 /* If the lines below the insertion are being pushed
1039 into the end of the window, this is the same as clearing;
1040 and we know the lines are already clear, since the matching
1041 deletion has already been done. So can ignore this. */
1042 /* If the lines below the deletion are blank lines coming
1043 out of the end of the window, don't bother,
1044 as there will be a matching inslines later that will flush them. */
1045 if (FRAME_SCROLL_REGION_OK (f)
1046 && vpos + i >= tty->specified_window)
1047 return;
1048 if (!FRAME_MEMORY_BELOW_FRAME (f)
1049 && vpos + i >= FRAME_LINES (f))
1050 return;
1051
1052 if (multi)
1053 {
1054 raw_cursor_to (f, vpos, 0);
1055 tty_background_highlight (tty);
1056 buf = tparam (multi, 0, 0, i);
1057 OUTPUT (tty, buf);
1058 xfree (buf);
1059 }
1060 else if (single)
1061 {
1062 raw_cursor_to (f, vpos, 0);
1063 tty_background_highlight (tty);
1064 while (--i >= 0)
1065 OUTPUT (tty, single);
1066 if (tty->TF_teleray)
1067 curX (tty) = 0;
1068 }
1069 else
1070 {
1071 tty_set_scroll_region (f, vpos, tty->specified_window);
1072 if (n < 0)
1073 raw_cursor_to (f, tty->specified_window - 1, 0);
1074 else
1075 raw_cursor_to (f, vpos, 0);
1076 tty_background_highlight (tty);
1077 while (--i >= 0)
1078 OUTPUTL (tty, scroll, tty->specified_window - vpos);
1079 tty_set_scroll_region (f, 0, tty->specified_window);
1080 }
1081
1082 if (!FRAME_SCROLL_REGION_OK (f)
1083 && FRAME_MEMORY_BELOW_FRAME (f)
1084 && n < 0)
1085 {
1086 cursor_to (f, FRAME_LINES (f) + n, 0);
1087 clear_to_end (f);
1088 }
1089 }
1090 \f
1091 /* Compute cost of sending "str", in characters,
1092 not counting any line-dependent padding. */
1093
1094 int
1095 string_cost (char *str)
1096 {
1097 cost = 0;
1098 if (str)
1099 tputs (str, 0, evalcost);
1100 return cost;
1101 }
1102
1103 /* Compute cost of sending "str", in characters,
1104 counting any line-dependent padding at one line. */
1105
1106 static int
1107 string_cost_one_line (char *str)
1108 {
1109 cost = 0;
1110 if (str)
1111 tputs (str, 1, evalcost);
1112 return cost;
1113 }
1114
1115 /* Compute per line amount of line-dependent padding,
1116 in tenths of characters. */
1117
1118 int
1119 per_line_cost (char *str)
1120 {
1121 cost = 0;
1122 if (str)
1123 tputs (str, 0, evalcost);
1124 cost = - cost;
1125 if (str)
1126 tputs (str, 10, evalcost);
1127 return cost;
1128 }
1129
1130 #ifndef old
1131 /* char_ins_del_cost[n] is cost of inserting N characters.
1132 char_ins_del_cost[-n] is cost of deleting N characters.
1133 The length of this vector is based on max_frame_cols. */
1134
1135 int *char_ins_del_vector;
1136
1137 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
1138 #endif
1139
1140 /* ARGSUSED */
1141 static void
1142 calculate_ins_del_char_costs (struct frame *f)
1143 {
1144 struct tty_display_info *tty = FRAME_TTY (f);
1145 int ins_startup_cost, del_startup_cost;
1146 int ins_cost_per_char, del_cost_per_char;
1147 register int i;
1148 register int *p;
1149
1150 if (tty->TS_ins_multi_chars)
1151 {
1152 ins_cost_per_char = 0;
1153 ins_startup_cost = string_cost_one_line (tty->TS_ins_multi_chars);
1154 }
1155 else if (tty->TS_ins_char || tty->TS_pad_inserted_char
1156 || (tty->TS_insert_mode && tty->TS_end_insert_mode))
1157 {
1158 ins_startup_cost = (30 * (string_cost (tty->TS_insert_mode)
1159 + string_cost (tty->TS_end_insert_mode))) / 100;
1160 ins_cost_per_char = (string_cost_one_line (tty->TS_ins_char)
1161 + string_cost_one_line (tty->TS_pad_inserted_char));
1162 }
1163 else
1164 {
1165 ins_startup_cost = 9999;
1166 ins_cost_per_char = 0;
1167 }
1168
1169 if (tty->TS_del_multi_chars)
1170 {
1171 del_cost_per_char = 0;
1172 del_startup_cost = string_cost_one_line (tty->TS_del_multi_chars);
1173 }
1174 else if (tty->TS_del_char)
1175 {
1176 del_startup_cost = (string_cost (tty->TS_delete_mode)
1177 + string_cost (tty->TS_end_delete_mode));
1178 if (tty->delete_in_insert_mode)
1179 del_startup_cost /= 2;
1180 del_cost_per_char = string_cost_one_line (tty->TS_del_char);
1181 }
1182 else
1183 {
1184 del_startup_cost = 9999;
1185 del_cost_per_char = 0;
1186 }
1187
1188 /* Delete costs are at negative offsets */
1189 p = &char_ins_del_cost (f)[0];
1190 for (i = FRAME_COLS (f); --i >= 0;)
1191 *--p = (del_startup_cost += del_cost_per_char);
1192
1193 /* Doing nothing is free */
1194 p = &char_ins_del_cost (f)[0];
1195 *p++ = 0;
1196
1197 /* Insert costs are at positive offsets */
1198 for (i = FRAME_COLS (f); --i >= 0;)
1199 *p++ = (ins_startup_cost += ins_cost_per_char);
1200 }
1201
1202 void
1203 calculate_costs (struct frame *frame)
1204 {
1205 FRAME_COST_BAUD_RATE (frame) = baud_rate;
1206
1207 if (FRAME_TERMCAP_P (frame))
1208 {
1209 struct tty_display_info *tty = FRAME_TTY (frame);
1210 register char *f = (tty->TS_set_scroll_region
1211 ? tty->TS_set_scroll_region
1212 : tty->TS_set_scroll_region_1);
1213
1214 FRAME_SCROLL_REGION_COST (frame) = string_cost (f);
1215
1216 tty->costs_set = 1;
1217
1218 /* These variables are only used for terminal stuff. They are
1219 allocated once for the terminal frame of X-windows emacs, but not
1220 used afterwards.
1221
1222 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1223 X turns off char_ins_del_ok. */
1224
1225 max_frame_lines = max (max_frame_lines, FRAME_LINES (frame));
1226 max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
1227
1228 if (char_ins_del_vector != 0)
1229 char_ins_del_vector
1230 = (int *) xrealloc (char_ins_del_vector,
1231 (sizeof (int)
1232 + 2 * max_frame_cols * sizeof (int)));
1233 else
1234 char_ins_del_vector
1235 = (int *) xmalloc (sizeof (int)
1236 + 2 * max_frame_cols * sizeof (int));
1237
1238 bzero (char_ins_del_vector, (sizeof (int)
1239 + 2 * max_frame_cols * sizeof (int)));
1240
1241
1242 if (f && (!tty->TS_ins_line && !tty->TS_del_line))
1243 do_line_insertion_deletion_costs (frame,
1244 tty->TS_rev_scroll, tty->TS_ins_multi_lines,
1245 tty->TS_fwd_scroll, tty->TS_del_multi_lines,
1246 f, f, 1);
1247 else
1248 do_line_insertion_deletion_costs (frame,
1249 tty->TS_ins_line, tty->TS_ins_multi_lines,
1250 tty->TS_del_line, tty->TS_del_multi_lines,
1251 0, 0, 1);
1252
1253 calculate_ins_del_char_costs (frame);
1254
1255 /* Don't use TS_repeat if its padding is worse than sending the chars */
1256 if (tty->TS_repeat && per_line_cost (tty->TS_repeat) * baud_rate < 9000)
1257 tty->RPov = string_cost (tty->TS_repeat);
1258 else
1259 tty->RPov = FRAME_COLS (frame) * 2;
1260
1261 cmcostinit (FRAME_TTY (frame)); /* set up cursor motion costs */
1262 }
1263 }
1264 \f
1265 struct fkey_table {
1266 char *cap, *name;
1267 };
1268
1269 /* Termcap capability names that correspond directly to X keysyms.
1270 Some of these (marked "terminfo") aren't supplied by old-style
1271 (Berkeley) termcap entries. They're listed in X keysym order;
1272 except we put the keypad keys first, so that if they clash with
1273 other keys (as on the IBM PC keyboard) they get overridden.
1274 */
1275
1276 static struct fkey_table keys[] =
1277 {
1278 {"kh", "home"}, /* termcap */
1279 {"kl", "left"}, /* termcap */
1280 {"ku", "up"}, /* termcap */
1281 {"kr", "right"}, /* termcap */
1282 {"kd", "down"}, /* termcap */
1283 {"%8", "prior"}, /* terminfo */
1284 {"%5", "next"}, /* terminfo */
1285 {"@7", "end"}, /* terminfo */
1286 {"@1", "begin"}, /* terminfo */
1287 {"*6", "select"}, /* terminfo */
1288 {"%9", "print"}, /* terminfo */
1289 {"@4", "execute"}, /* terminfo --- actually the `command' key */
1290 /*
1291 * "insert" --- see below
1292 */
1293 {"&8", "undo"}, /* terminfo */
1294 {"%0", "redo"}, /* terminfo */
1295 {"%7", "menu"}, /* terminfo --- actually the `options' key */
1296 {"@0", "find"}, /* terminfo */
1297 {"@2", "cancel"}, /* terminfo */
1298 {"%1", "help"}, /* terminfo */
1299 /*
1300 * "break" goes here, but can't be reliably intercepted with termcap
1301 */
1302 {"&4", "reset"}, /* terminfo --- actually `restart' */
1303 /*
1304 * "system" and "user" --- no termcaps
1305 */
1306 {"kE", "clearline"}, /* terminfo */
1307 {"kA", "insertline"}, /* terminfo */
1308 {"kL", "deleteline"}, /* terminfo */
1309 {"kI", "insertchar"}, /* terminfo */
1310 {"kD", "deletechar"}, /* terminfo */
1311 {"kB", "backtab"}, /* terminfo */
1312 /*
1313 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1314 */
1315 {"@8", "kp-enter"}, /* terminfo */
1316 /*
1317 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1318 * "kp-multiply", "kp-add", "kp-separator",
1319 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1320 * --- no termcaps for any of these.
1321 */
1322 {"K4", "kp-1"}, /* terminfo */
1323 /*
1324 * "kp-2" --- no termcap
1325 */
1326 {"K5", "kp-3"}, /* terminfo */
1327 /*
1328 * "kp-4" --- no termcap
1329 */
1330 {"K2", "kp-5"}, /* terminfo */
1331 /*
1332 * "kp-6" --- no termcap
1333 */
1334 {"K1", "kp-7"}, /* terminfo */
1335 /*
1336 * "kp-8" --- no termcap
1337 */
1338 {"K3", "kp-9"}, /* terminfo */
1339 /*
1340 * "kp-equal" --- no termcap
1341 */
1342 {"k1", "f1"},
1343 {"k2", "f2"},
1344 {"k3", "f3"},
1345 {"k4", "f4"},
1346 {"k5", "f5"},
1347 {"k6", "f6"},
1348 {"k7", "f7"},
1349 {"k8", "f8"},
1350 {"k9", "f9"},
1351
1352 {"&0", "S-cancel"}, /*shifted cancel key*/
1353 {"&9", "S-begin"}, /*shifted begin key*/
1354 {"*0", "S-find"}, /*shifted find key*/
1355 {"*1", "S-execute"}, /*shifted execute? actually shifted command key*/
1356 {"*4", "S-delete"}, /*shifted delete-character key*/
1357 {"*7", "S-end"}, /*shifted end key*/
1358 {"*8", "S-clearline"}, /*shifted clear-to end-of-line key*/
1359 {"#1", "S-help"}, /*shifted help key*/
1360 {"#2", "S-home"}, /*shifted home key*/
1361 {"#3", "S-insert"}, /*shifted insert-character key*/
1362 {"#4", "S-left"}, /*shifted left-arrow key*/
1363 {"%d", "S-menu"}, /*shifted menu? actually shifted options key*/
1364 {"%c", "S-next"}, /*shifted next key*/
1365 {"%e", "S-prior"}, /*shifted previous key*/
1366 {"%f", "S-print"}, /*shifted print key*/
1367 {"%g", "S-redo"}, /*shifted redo key*/
1368 {"%i", "S-right"}, /*shifted right-arrow key*/
1369 {"!3", "S-undo"} /*shifted undo key*/
1370 };
1371
1372 static char **term_get_fkeys_address;
1373 static KBOARD *term_get_fkeys_kboard;
1374 static Lisp_Object term_get_fkeys_1 ();
1375
1376 /* Find the escape codes sent by the function keys for Vinput_decode_map.
1377 This function scans the termcap function key sequence entries, and
1378 adds entries to Vinput_decode_map for each function key it finds. */
1379
1380 static void
1381 term_get_fkeys (address, kboard)
1382 char **address;
1383 KBOARD *kboard;
1384 {
1385 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1386 errors during the call. The only errors should be from Fdefine_key
1387 when given a key sequence containing an invalid prefix key. If the
1388 termcap defines function keys which use a prefix that is already bound
1389 to a command by the default bindings, we should silently ignore that
1390 function key specification, rather than giving the user an error and
1391 refusing to run at all on such a terminal. */
1392
1393 extern Lisp_Object Fidentity ();
1394 term_get_fkeys_address = address;
1395 term_get_fkeys_kboard = kboard;
1396 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1397 }
1398
1399 static Lisp_Object
1400 term_get_fkeys_1 ()
1401 {
1402 int i;
1403
1404 char **address = term_get_fkeys_address;
1405 KBOARD *kboard = term_get_fkeys_kboard;
1406
1407 /* This can happen if CANNOT_DUMP or with strange options. */
1408 if (!KEYMAPP (kboard->Vinput_decode_map))
1409 kboard->Vinput_decode_map = Fmake_sparse_keymap (Qnil);
1410
1411 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1412 {
1413 char *sequence = tgetstr (keys[i].cap, address);
1414 if (sequence)
1415 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence),
1416 Fmake_vector (make_number (1),
1417 intern (keys[i].name)));
1418 }
1419
1420 /* The uses of the "k0" capability are inconsistent; sometimes it
1421 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1422 We will attempt to politely accommodate both systems by testing for
1423 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1424 */
1425 {
1426 char *k_semi = tgetstr ("k;", address);
1427 char *k0 = tgetstr ("k0", address);
1428 char *k0_name = "f10";
1429
1430 if (k_semi)
1431 {
1432 if (k0)
1433 /* Define f0 first, so that f10 takes precedence in case the
1434 key sequences happens to be the same. */
1435 Fdefine_key (kboard->Vinput_decode_map, build_string (k0),
1436 Fmake_vector (make_number (1), intern ("f0")));
1437 Fdefine_key (kboard->Vinput_decode_map, build_string (k_semi),
1438 Fmake_vector (make_number (1), intern ("f10")));
1439 }
1440 else if (k0)
1441 Fdefine_key (kboard->Vinput_decode_map, build_string (k0),
1442 Fmake_vector (make_number (1), intern (k0_name)));
1443 }
1444
1445 /* Set up cookies for numbered function keys above f10. */
1446 {
1447 char fcap[3], fkey[4];
1448
1449 fcap[0] = 'F'; fcap[2] = '\0';
1450 for (i = 11; i < 64; i++)
1451 {
1452 if (i <= 19)
1453 fcap[1] = '1' + i - 11;
1454 else if (i <= 45)
1455 fcap[1] = 'A' + i - 20;
1456 else
1457 fcap[1] = 'a' + i - 46;
1458
1459 {
1460 char *sequence = tgetstr (fcap, address);
1461 if (sequence)
1462 {
1463 sprintf (fkey, "f%d", i);
1464 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence),
1465 Fmake_vector (make_number (1),
1466 intern (fkey)));
1467 }
1468 }
1469 }
1470 }
1471
1472 /*
1473 * Various mappings to try and get a better fit.
1474 */
1475 {
1476 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1477 if (!tgetstr (cap1, address)) \
1478 { \
1479 char *sequence = tgetstr (cap2, address); \
1480 if (sequence) \
1481 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence), \
1482 Fmake_vector (make_number (1), \
1483 intern (sym))); \
1484 }
1485
1486 /* if there's no key_next keycap, map key_npage to `next' keysym */
1487 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1488 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1489 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1490 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1491 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1492 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1493 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1494
1495 /* IBM has their own non-standard dialect of terminfo.
1496 If the standard name isn't found, try the IBM name. */
1497 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1498 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1499 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1500 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1501 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1502 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1503 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1504 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1505 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1506 #undef CONDITIONAL_REASSIGN
1507 }
1508
1509 return Qnil;
1510 }
1511
1512 \f
1513 /***********************************************************************
1514 Character Display Information
1515 ***********************************************************************/
1516
1517 /* Avoid name clash with functions defined in xterm.c */
1518 #ifdef static
1519 #define append_glyph append_glyph_term
1520 #define produce_stretch_glyph produce_stretch_glyph_term
1521 #define append_composite_glyph append_composite_glyph_term
1522 #define produce_composite_glyph produce_composite_glyph_term
1523 #endif
1524
1525 static void append_glyph P_ ((struct it *));
1526 static void produce_stretch_glyph P_ ((struct it *));
1527 static void append_composite_glyph P_ ((struct it *));
1528 static void produce_composite_glyph P_ ((struct it *));
1529
1530 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1531 terminal frames if IT->glyph_row != NULL. IT->char_to_display is
1532 the character for which to produce glyphs; IT->face_id contains the
1533 character's face. Padding glyphs are appended if IT->c has a
1534 IT->pixel_width > 1. */
1535
1536 static void
1537 append_glyph (it)
1538 struct it *it;
1539 {
1540 struct glyph *glyph, *end;
1541 int i;
1542
1543 xassert (it->glyph_row);
1544 glyph = (it->glyph_row->glyphs[it->area]
1545 + it->glyph_row->used[it->area]);
1546 end = it->glyph_row->glyphs[1 + it->area];
1547
1548 for (i = 0;
1549 i < it->pixel_width && glyph < end;
1550 ++i)
1551 {
1552 glyph->type = CHAR_GLYPH;
1553 glyph->pixel_width = 1;
1554 glyph->u.ch = it->char_to_display;
1555 glyph->face_id = it->face_id;
1556 glyph->padding_p = i > 0;
1557 glyph->charpos = CHARPOS (it->position);
1558 glyph->object = it->object;
1559
1560 ++it->glyph_row->used[it->area];
1561 ++glyph;
1562 }
1563 }
1564
1565
1566 /* Produce glyphs for the display element described by IT. *IT
1567 specifies what we want to produce a glyph for (character, image, ...),
1568 and where in the glyph matrix we currently are (glyph row and hpos).
1569 produce_glyphs fills in output fields of *IT with information such as the
1570 pixel width and height of a character, and maybe output actual glyphs at
1571 the same time if IT->glyph_row is non-null. See the explanation of
1572 struct display_iterator in dispextern.h for an overview.
1573
1574 produce_glyphs also stores the result of glyph width, ascent
1575 etc. computations in *IT.
1576
1577 IT->glyph_row may be null, in which case produce_glyphs does not
1578 actually fill in the glyphs. This is used in the move_* functions
1579 in xdisp.c for text width and height computations.
1580
1581 Callers usually don't call produce_glyphs directly;
1582 instead they use the macro PRODUCE_GLYPHS. */
1583
1584 void
1585 produce_glyphs (it)
1586 struct it *it;
1587 {
1588 /* If a hook is installed, let it do the work. */
1589
1590 /* Nothing but characters are supported on terminal frames. */
1591 xassert (it->what == IT_CHARACTER
1592 || it->what == IT_COMPOSITION
1593 || it->what == IT_STRETCH);
1594
1595 if (it->what == IT_STRETCH)
1596 {
1597 produce_stretch_glyph (it);
1598 goto done;
1599 }
1600
1601 if (it->what == IT_COMPOSITION)
1602 {
1603 produce_composite_glyph (it);
1604 goto done;
1605 }
1606
1607 /* Maybe translate single-byte characters to multibyte. */
1608 it->char_to_display = it->c;
1609
1610 if (it->c >= 040 && it->c < 0177)
1611 {
1612 it->pixel_width = it->nglyphs = 1;
1613 if (it->glyph_row)
1614 append_glyph (it);
1615 }
1616 else if (it->c == '\n')
1617 it->pixel_width = it->nglyphs = 0;
1618 else if (it->c == '\t')
1619 {
1620 int absolute_x = (it->current_x
1621 + it->continuation_lines_width);
1622 int next_tab_x
1623 = (((1 + absolute_x + it->tab_width - 1)
1624 / it->tab_width)
1625 * it->tab_width);
1626 int nspaces;
1627
1628 /* If part of the TAB has been displayed on the previous line
1629 which is continued now, continuation_lines_width will have
1630 been incremented already by the part that fitted on the
1631 continued line. So, we will get the right number of spaces
1632 here. */
1633 nspaces = next_tab_x - absolute_x;
1634
1635 if (it->glyph_row)
1636 {
1637 int n = nspaces;
1638
1639 it->char_to_display = ' ';
1640 it->pixel_width = it->len = 1;
1641
1642 while (n--)
1643 append_glyph (it);
1644 }
1645
1646 it->pixel_width = nspaces;
1647 it->nglyphs = nspaces;
1648 }
1649 else if (CHAR_BYTE8_P (it->c))
1650 {
1651 if (unibyte_display_via_language_environment
1652 && (it->c >= 0240))
1653 {
1654 it->char_to_display = BYTE8_TO_CHAR (it->c);
1655 it->pixel_width = CHAR_WIDTH (it->char_to_display);
1656 it->nglyphs = it->pixel_width;
1657 if (it->glyph_row)
1658 append_glyph (it);
1659 }
1660 else
1661 {
1662 /* Coming here means that it->c is from display table, thus
1663 we must send the raw 8-bit byte as is to the terminal.
1664 Although there's no way to know how many columns it
1665 occupies on a screen, it is a good assumption that a
1666 single byte code has 1-column width. */
1667 it->pixel_width = it->nglyphs = 1;
1668 if (it->glyph_row)
1669 append_glyph (it);
1670 }
1671 }
1672 else
1673 {
1674 it->pixel_width = CHAR_WIDTH (it->c);
1675 it->nglyphs = it->pixel_width;
1676
1677 if (it->glyph_row)
1678 append_glyph (it);
1679 }
1680
1681 done:
1682 /* Advance current_x by the pixel width as a convenience for
1683 the caller. */
1684 if (it->area == TEXT_AREA)
1685 it->current_x += it->pixel_width;
1686 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1687 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
1688 }
1689
1690
1691 /* Produce a stretch glyph for iterator IT. IT->object is the value
1692 of the glyph property displayed. The value must be a list
1693 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1694 being recognized:
1695
1696 1. `:width WIDTH' specifies that the space should be WIDTH *
1697 canonical char width wide. WIDTH may be an integer or floating
1698 point number.
1699
1700 2. `:align-to HPOS' specifies that the space should be wide enough
1701 to reach HPOS, a value in canonical character units. */
1702
1703 static void
1704 produce_stretch_glyph (it)
1705 struct it *it;
1706 {
1707 /* (space :width WIDTH ...) */
1708 Lisp_Object prop, plist;
1709 int width = 0, align_to = -1;
1710 int zero_width_ok_p = 0;
1711 double tem;
1712
1713 /* List should start with `space'. */
1714 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1715 plist = XCDR (it->object);
1716
1717 /* Compute the width of the stretch. */
1718 if ((prop = Fplist_get (plist, QCwidth), !NILP (prop))
1719 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, 0))
1720 {
1721 /* Absolute width `:width WIDTH' specified and valid. */
1722 zero_width_ok_p = 1;
1723 width = (int)(tem + 0.5);
1724 }
1725 else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
1726 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, &align_to))
1727 {
1728 if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
1729 align_to = (align_to < 0
1730 ? 0
1731 : align_to - window_box_left_offset (it->w, TEXT_AREA));
1732 else if (align_to < 0)
1733 align_to = window_box_left_offset (it->w, TEXT_AREA);
1734 width = max (0, (int)(tem + 0.5) + align_to - it->current_x);
1735 zero_width_ok_p = 1;
1736 }
1737 else
1738 /* Nothing specified -> width defaults to canonical char width. */
1739 width = FRAME_COLUMN_WIDTH (it->f);
1740
1741 if (width <= 0 && (width < 0 || !zero_width_ok_p))
1742 width = 1;
1743
1744 if (width > 0 && it->line_wrap != TRUNCATE
1745 && it->current_x + width > it->last_visible_x)
1746 width = it->last_visible_x - it->current_x - 1;
1747
1748 if (width > 0 && it->glyph_row)
1749 {
1750 Lisp_Object o_object = it->object;
1751 Lisp_Object object = it->stack[it->sp - 1].string;
1752 int n = width;
1753
1754 if (!STRINGP (object))
1755 object = it->w->buffer;
1756 it->object = object;
1757 it->char_to_display = ' ';
1758 it->pixel_width = it->len = 1;
1759 while (n--)
1760 append_glyph (it);
1761 it->object = o_object;
1762 }
1763 it->pixel_width = width;
1764 it->nglyphs = width;
1765 }
1766
1767
1768 /* Append glyphs to IT's glyph_row for the composition IT->cmp_id.
1769 Called from produce_composite_glyph for terminal frames if
1770 IT->glyph_row != NULL. IT->face_id contains the character's
1771 face. */
1772
1773 static void
1774 append_composite_glyph (it)
1775 struct it *it;
1776 {
1777 struct glyph *glyph;
1778
1779 xassert (it->glyph_row);
1780 glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
1781 if (glyph < it->glyph_row->glyphs[1 + it->area])
1782 {
1783 glyph->type = COMPOSITE_GLYPH;
1784 glyph->pixel_width = it->pixel_width;
1785 glyph->u.cmp.id = it->cmp_it.id;
1786 if (it->cmp_it.ch < 0)
1787 {
1788 glyph->u.cmp.automatic = 0;
1789 glyph->u.cmp.id = it->cmp_it.id;
1790 }
1791 else
1792 {
1793 glyph->u.cmp.automatic = 1;
1794 glyph->u.cmp.id = it->cmp_it.id;
1795 glyph->u.cmp.from = it->cmp_it.from;
1796 glyph->u.cmp.to = it->cmp_it.to - 1;
1797 }
1798
1799 glyph->face_id = it->face_id;
1800 glyph->padding_p = 0;
1801 glyph->charpos = CHARPOS (it->position);
1802 glyph->object = it->object;
1803
1804 ++it->glyph_row->used[it->area];
1805 ++glyph;
1806 }
1807 }
1808
1809
1810 /* Produce a composite glyph for iterator IT. IT->cmp_id is the ID of
1811 the composition. We simply produces components of the composition
1812 assuming that the terminal has a capability to layout/render it
1813 correctly. */
1814
1815 static void
1816 produce_composite_glyph (it)
1817 struct it *it;
1818 {
1819 int c;
1820
1821 if (it->cmp_it.ch < 0)
1822 {
1823 struct composition *cmp = composition_table[it->cmp_it.id];
1824
1825 it->pixel_width = cmp->width;
1826 }
1827 else
1828 {
1829 Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id);
1830
1831 it->pixel_width = composition_gstring_width (gstring, it->cmp_it.from,
1832 it->cmp_it.to, NULL);
1833 }
1834 it->nglyphs = 1;
1835 if (it->glyph_row)
1836 append_composite_glyph (it);
1837 }
1838
1839
1840 /* Get information about special display element WHAT in an
1841 environment described by IT. WHAT is one of IT_TRUNCATION or
1842 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1843 non-null glyph_row member. This function ensures that fields like
1844 face_id, c, len of IT are left untouched. */
1845
1846 void
1847 produce_special_glyphs (it, what)
1848 struct it *it;
1849 enum display_element_type what;
1850 {
1851 struct it temp_it;
1852 Lisp_Object gc;
1853 GLYPH glyph;
1854
1855 temp_it = *it;
1856 temp_it.dp = NULL;
1857 temp_it.what = IT_CHARACTER;
1858 temp_it.len = 1;
1859 temp_it.object = make_number (0);
1860 bzero (&temp_it.current, sizeof temp_it.current);
1861
1862 if (what == IT_CONTINUATION)
1863 {
1864 /* Continuation glyph. */
1865 SET_GLYPH_FROM_CHAR (glyph, '\\');
1866 if (it->dp
1867 && (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc))
1868 && GLYPH_CODE_CHAR_VALID_P (gc))
1869 {
1870 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
1871 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
1872 }
1873 }
1874 else if (what == IT_TRUNCATION)
1875 {
1876 /* Truncation glyph. */
1877 SET_GLYPH_FROM_CHAR (glyph, '$');
1878 if (it->dp
1879 && (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc))
1880 && GLYPH_CODE_CHAR_VALID_P (gc))
1881 {
1882 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
1883 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
1884 }
1885 }
1886 else
1887 abort ();
1888
1889 temp_it.c = GLYPH_CHAR (glyph);
1890 temp_it.face_id = GLYPH_FACE (glyph);
1891 temp_it.len = CHAR_BYTES (temp_it.c);
1892
1893 produce_glyphs (&temp_it);
1894 it->pixel_width = temp_it.pixel_width;
1895 it->nglyphs = temp_it.pixel_width;
1896 }
1897
1898
1899 \f
1900 /***********************************************************************
1901 Faces
1902 ***********************************************************************/
1903
1904 /* Value is non-zero if attribute ATTR may be used. ATTR should be
1905 one of the enumerators from enum no_color_bit, or a bit set built
1906 from them. Some display attributes may not be used together with
1907 color; the termcap capability `NC' specifies which ones. */
1908
1909 #define MAY_USE_WITH_COLORS_P(tty, ATTR) \
1910 (tty->TN_max_colors > 0 \
1911 ? (tty->TN_no_color_video & (ATTR)) == 0 \
1912 : 1)
1913
1914 /* Turn appearances of face FACE_ID on tty frame F on.
1915 FACE_ID is a realized face ID number, in the face cache. */
1916
1917 static void
1918 turn_on_face (f, face_id)
1919 struct frame *f;
1920 int face_id;
1921 {
1922 struct face *face = FACE_FROM_ID (f, face_id);
1923 long fg = face->foreground;
1924 long bg = face->background;
1925 struct tty_display_info *tty = FRAME_TTY (f);
1926
1927 /* Do this first because TS_end_standout_mode may be the same
1928 as TS_exit_attribute_mode, which turns all appearances off. */
1929 if (MAY_USE_WITH_COLORS_P (tty, NC_REVERSE))
1930 {
1931 if (tty->TN_max_colors > 0)
1932 {
1933 if (fg >= 0 && bg >= 0)
1934 {
1935 /* If the terminal supports colors, we can set them
1936 below without using reverse video. The face's fg
1937 and bg colors are set as they should appear on
1938 the screen, i.e. they take the inverse-video'ness
1939 of the face already into account. */
1940 }
1941 else if (inverse_video)
1942 {
1943 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1944 || bg == FACE_TTY_DEFAULT_BG_COLOR)
1945 tty_toggle_highlight (tty);
1946 }
1947 else
1948 {
1949 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1950 || bg == FACE_TTY_DEFAULT_FG_COLOR)
1951 tty_toggle_highlight (tty);
1952 }
1953 }
1954 else
1955 {
1956 /* If we can't display colors, use reverse video
1957 if the face specifies that. */
1958 if (inverse_video)
1959 {
1960 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1961 || bg == FACE_TTY_DEFAULT_BG_COLOR)
1962 tty_toggle_highlight (tty);
1963 }
1964 else
1965 {
1966 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1967 || bg == FACE_TTY_DEFAULT_FG_COLOR)
1968 tty_toggle_highlight (tty);
1969 }
1970 }
1971 }
1972
1973 if (face->tty_bold_p && MAY_USE_WITH_COLORS_P (tty, NC_BOLD))
1974 OUTPUT1_IF (tty, tty->TS_enter_bold_mode);
1975
1976 if (face->tty_dim_p && MAY_USE_WITH_COLORS_P (tty, NC_DIM))
1977 OUTPUT1_IF (tty, tty->TS_enter_dim_mode);
1978
1979 /* Alternate charset and blinking not yet used. */
1980 if (face->tty_alt_charset_p
1981 && MAY_USE_WITH_COLORS_P (tty, NC_ALT_CHARSET))
1982 OUTPUT1_IF (tty, tty->TS_enter_alt_charset_mode);
1983
1984 if (face->tty_blinking_p
1985 && MAY_USE_WITH_COLORS_P (tty, NC_BLINK))
1986 OUTPUT1_IF (tty, tty->TS_enter_blink_mode);
1987
1988 if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (tty, NC_UNDERLINE))
1989 OUTPUT1_IF (tty, tty->TS_enter_underline_mode);
1990
1991 if (tty->TN_max_colors > 0)
1992 {
1993 char *ts, *p;
1994
1995 ts = tty->standout_mode ? tty->TS_set_background : tty->TS_set_foreground;
1996 if (fg >= 0 && ts)
1997 {
1998 p = tparam (ts, NULL, 0, (int) fg);
1999 OUTPUT (tty, p);
2000 xfree (p);
2001 }
2002
2003 ts = tty->standout_mode ? tty->TS_set_foreground : tty->TS_set_background;
2004 if (bg >= 0 && ts)
2005 {
2006 p = tparam (ts, NULL, 0, (int) bg);
2007 OUTPUT (tty, p);
2008 xfree (p);
2009 }
2010 }
2011 }
2012
2013
2014 /* Turn off appearances of face FACE_ID on tty frame F. */
2015
2016 static void
2017 turn_off_face (f, face_id)
2018 struct frame *f;
2019 int face_id;
2020 {
2021 struct face *face = FACE_FROM_ID (f, face_id);
2022 struct tty_display_info *tty = FRAME_TTY (f);
2023
2024 xassert (face != NULL);
2025
2026 if (tty->TS_exit_attribute_mode)
2027 {
2028 /* Capability "me" will turn off appearance modes double-bright,
2029 half-bright, reverse-video, standout, underline. It may or
2030 may not turn off alt-char-mode. */
2031 if (face->tty_bold_p
2032 || face->tty_dim_p
2033 || face->tty_reverse_p
2034 || face->tty_alt_charset_p
2035 || face->tty_blinking_p
2036 || face->tty_underline_p)
2037 {
2038 OUTPUT1_IF (tty, tty->TS_exit_attribute_mode);
2039 if (strcmp (tty->TS_exit_attribute_mode, tty->TS_end_standout_mode) == 0)
2040 tty->standout_mode = 0;
2041 }
2042
2043 if (face->tty_alt_charset_p)
2044 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
2045 }
2046 else
2047 {
2048 /* If we don't have "me" we can only have those appearances
2049 that have exit sequences defined. */
2050 if (face->tty_alt_charset_p)
2051 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
2052
2053 if (face->tty_underline_p)
2054 OUTPUT_IF (tty, tty->TS_exit_underline_mode);
2055 }
2056
2057 /* Switch back to default colors. */
2058 if (tty->TN_max_colors > 0
2059 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
2060 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
2061 || (face->background != FACE_TTY_DEFAULT_COLOR
2062 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
2063 OUTPUT1_IF (tty, tty->TS_orig_pair);
2064 }
2065
2066
2067 /* Return non-zero if the terminal on frame F supports all of the
2068 capabilities in CAPS simultaneously, with foreground and background
2069 colors FG and BG. */
2070
2071 int
2072 tty_capable_p (tty, caps, fg, bg)
2073 struct tty_display_info *tty;
2074 unsigned caps;
2075 unsigned long fg, bg;
2076 {
2077 #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
2078 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
2079 return 0;
2080
2081 TTY_CAPABLE_P_TRY (tty, TTY_CAP_INVERSE, tty->TS_standout_mode, NC_REVERSE);
2082 TTY_CAPABLE_P_TRY (tty, TTY_CAP_UNDERLINE, tty->TS_enter_underline_mode, NC_UNDERLINE);
2083 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BOLD, tty->TS_enter_bold_mode, NC_BOLD);
2084 TTY_CAPABLE_P_TRY (tty, TTY_CAP_DIM, tty->TS_enter_dim_mode, NC_DIM);
2085 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BLINK, tty->TS_enter_blink_mode, NC_BLINK);
2086 TTY_CAPABLE_P_TRY (tty, TTY_CAP_ALT_CHARSET, tty->TS_enter_alt_charset_mode, NC_ALT_CHARSET);
2087
2088 /* We can do it! */
2089 return 1;
2090 }
2091
2092 /* Return non-zero if the terminal is capable to display colors. */
2093
2094 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
2095 0, 1, 0,
2096 doc: /* Return non-nil if the tty device TERMINAL can display colors.
2097
2098 TERMINAL can be a terminal object, a frame, or nil (meaning the
2099 selected frame's terminal). This function always returns nil if
2100 TERMINAL does not refer to a text-only terminal. */)
2101 (terminal)
2102 Lisp_Object terminal;
2103 {
2104 struct terminal *t = get_tty_terminal (terminal, 0);
2105 if (!t)
2106 return Qnil;
2107 else
2108 return t->display_info.tty->TN_max_colors > 0 ? Qt : Qnil;
2109 }
2110
2111 /* Return the number of supported colors. */
2112 DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
2113 Stty_display_color_cells, 0, 1, 0,
2114 doc: /* Return the number of colors supported by the tty device TERMINAL.
2115
2116 TERMINAL can be a terminal object, a frame, or nil (meaning the
2117 selected frame's terminal). This function always returns 0 if
2118 TERMINAL does not refer to a text-only terminal. */)
2119 (terminal)
2120 Lisp_Object terminal;
2121 {
2122 struct terminal *t = get_tty_terminal (terminal, 0);
2123 if (!t)
2124 return make_number (0);
2125 else
2126 return make_number (t->display_info.tty->TN_max_colors);
2127 }
2128
2129 #ifndef DOS_NT
2130
2131 /* Declare here rather than in the function, as in the rest of Emacs,
2132 to work around an HPUX compiler bug (?). See
2133 http://lists.gnu.org/archive/html/emacs-devel/2007-08/msg00410.html */
2134 static int default_max_colors;
2135 static int default_max_pairs;
2136 static int default_no_color_video;
2137 static char *default_orig_pair;
2138 static char *default_set_foreground;
2139 static char *default_set_background;
2140
2141 /* Save or restore the default color-related capabilities of this
2142 terminal. */
2143 static void
2144 tty_default_color_capabilities (struct tty_display_info *tty, int save)
2145 {
2146
2147 if (save)
2148 {
2149 xfree (default_orig_pair);
2150 default_orig_pair = tty->TS_orig_pair ? xstrdup (tty->TS_orig_pair) : NULL;
2151
2152 xfree (default_set_foreground);
2153 default_set_foreground = tty->TS_set_foreground ? xstrdup (tty->TS_set_foreground)
2154 : NULL;
2155
2156 xfree (default_set_background);
2157 default_set_background = tty->TS_set_background ? xstrdup (tty->TS_set_background)
2158 : NULL;
2159
2160 default_max_colors = tty->TN_max_colors;
2161 default_max_pairs = tty->TN_max_pairs;
2162 default_no_color_video = tty->TN_no_color_video;
2163 }
2164 else
2165 {
2166 tty->TS_orig_pair = default_orig_pair;
2167 tty->TS_set_foreground = default_set_foreground;
2168 tty->TS_set_background = default_set_background;
2169 tty->TN_max_colors = default_max_colors;
2170 tty->TN_max_pairs = default_max_pairs;
2171 tty->TN_no_color_video = default_no_color_video;
2172 }
2173 }
2174
2175 /* Setup one of the standard tty color schemes according to MODE.
2176 MODE's value is generally the number of colors which we want to
2177 support; zero means set up for the default capabilities, the ones
2178 we saw at init_tty time; -1 means turn off color support. */
2179 static void
2180 tty_setup_colors (struct tty_display_info *tty, int mode)
2181 {
2182 /* Canonicalize all negative values of MODE. */
2183 if (mode < -1)
2184 mode = -1;
2185
2186 switch (mode)
2187 {
2188 case -1: /* no colors at all */
2189 tty->TN_max_colors = 0;
2190 tty->TN_max_pairs = 0;
2191 tty->TN_no_color_video = 0;
2192 tty->TS_set_foreground = tty->TS_set_background = tty->TS_orig_pair = NULL;
2193 break;
2194 case 0: /* default colors, if any */
2195 default:
2196 tty_default_color_capabilities (tty, 0);
2197 break;
2198 case 8: /* 8 standard ANSI colors */
2199 tty->TS_orig_pair = "\033[0m";
2200 #ifdef TERMINFO
2201 tty->TS_set_foreground = "\033[3%p1%dm";
2202 tty->TS_set_background = "\033[4%p1%dm";
2203 #else
2204 tty->TS_set_foreground = "\033[3%dm";
2205 tty->TS_set_background = "\033[4%dm";
2206 #endif
2207 tty->TN_max_colors = 8;
2208 tty->TN_max_pairs = 64;
2209 tty->TN_no_color_video = 0;
2210 break;
2211 }
2212 }
2213
2214 void
2215 set_tty_color_mode (tty, f)
2216 struct tty_display_info *tty;
2217 struct frame *f;
2218 {
2219 Lisp_Object tem, val, color_mode_spec;
2220 Lisp_Object color_mode;
2221 int mode;
2222 extern Lisp_Object Qtty_color_mode;
2223 Lisp_Object tty_color_mode_alist
2224 = Fintern_soft (build_string ("tty-color-mode-alist"), Qnil);
2225
2226 tem = assq_no_quit (Qtty_color_mode, f->param_alist);
2227 val = CONSP (tem) ? XCDR (tem) : Qnil;
2228
2229 if (INTEGERP (val))
2230 color_mode = val;
2231 else
2232 {
2233 tem = (NILP (tty_color_mode_alist) ? Qnil
2234 : Fassq (val, XSYMBOL (tty_color_mode_alist)->value));
2235 color_mode = CONSP (tem) ? XCDR (tem) : Qnil;
2236 }
2237
2238 mode = INTEGERP (color_mode) ? XINT (color_mode) : 0;
2239
2240 if (mode != tty->previous_color_mode)
2241 {
2242 Lisp_Object funsym = intern ("tty-set-up-initial-frame-faces");
2243 tty->previous_color_mode = mode;
2244 tty_setup_colors (tty , mode);
2245 /* This recomputes all the faces given the new color definitions. */
2246 safe_call (1, &funsym);
2247 }
2248 }
2249
2250 #endif /* !DOS_NT */
2251
2252 \f
2253
2254 /* Return the tty display object specified by TERMINAL. */
2255
2256 struct terminal *
2257 get_tty_terminal (Lisp_Object terminal, int throw)
2258 {
2259 struct terminal *t = get_terminal (terminal, throw);
2260
2261 if (t && t->type != output_termcap && t->type != output_msdos_raw)
2262 {
2263 if (throw)
2264 error ("Device %d is not a termcap terminal device", t->id);
2265 else
2266 return NULL;
2267 }
2268
2269 return t;
2270 }
2271
2272 /* Return an active termcap device that uses the tty device with the
2273 given name.
2274
2275 This function ignores suspended devices.
2276
2277 Returns NULL if the named terminal device is not opened. */
2278
2279 struct terminal *
2280 get_named_tty (name)
2281 char *name;
2282 {
2283 struct terminal *t;
2284
2285 if (!name)
2286 abort ();
2287
2288 for (t = terminal_list; t; t = t->next_terminal)
2289 {
2290 if ((t->type == output_termcap || t->type == output_msdos_raw)
2291 && !strcmp (t->display_info.tty->name, name)
2292 && TERMINAL_ACTIVE_P (t))
2293 return t;
2294 }
2295
2296 return 0;
2297 }
2298
2299 \f
2300 DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0,
2301 doc: /* Return the type of the tty device that TERMINAL uses.
2302 Returns nil if TERMINAL is not on a tty device.
2303
2304 TERMINAL can be a terminal object, a frame, or nil (meaning the
2305 selected frame's terminal). */)
2306 (terminal)
2307 Lisp_Object terminal;
2308 {
2309 struct terminal *t = get_terminal (terminal, 1);
2310
2311 if (t->type != output_termcap && t->type != output_msdos_raw)
2312 return Qnil;
2313
2314 if (t->display_info.tty->type)
2315 return build_string (t->display_info.tty->type);
2316 else
2317 return Qnil;
2318 }
2319
2320 DEFUN ("controlling-tty-p", Fcontrolling_tty_p, Scontrolling_tty_p, 0, 1, 0,
2321 doc: /* Return non-nil if TERMINAL is the controlling tty of the Emacs process.
2322
2323 TERMINAL can be a terminal object, a frame, or nil (meaning the
2324 selected frame's terminal). This function always returns nil if
2325 TERMINAL is not on a tty device. */)
2326 (terminal)
2327 Lisp_Object terminal;
2328 {
2329 struct terminal *t = get_terminal (terminal, 1);
2330
2331 if ((t->type != output_termcap && t->type != output_msdos_raw)
2332 || strcmp (t->display_info.tty->name, DEV_TTY) != 0)
2333 return Qnil;
2334 else
2335 return Qt;
2336 }
2337
2338 DEFUN ("tty-no-underline", Ftty_no_underline, Stty_no_underline, 0, 1, 0,
2339 doc: /* Declare that the tty used by TERMINAL does not handle underlining.
2340 This is used to override the terminfo data, for certain terminals that
2341 do not really do underlining, but say that they do. This function has
2342 no effect if used on a non-tty terminal.
2343
2344 TERMINAL can be a terminal object, a frame or nil (meaning the
2345 selected frame's terminal). This function always returns nil if
2346 TERMINAL does not refer to a text-only terminal. */)
2347 (terminal)
2348 Lisp_Object terminal;
2349 {
2350 struct terminal *t = get_terminal (terminal, 1);
2351
2352 if (t->type == output_termcap)
2353 t->display_info.tty->TS_enter_underline_mode = 0;
2354 return Qnil;
2355 }
2356
2357 \f
2358
2359 DEFUN ("suspend-tty", Fsuspend_tty, Ssuspend_tty, 0, 1, 0,
2360 doc: /* Suspend the terminal device TTY.
2361
2362 The device is restored to its default state, and Emacs ceases all
2363 access to the tty device. Frames that use the device are not deleted,
2364 but input is not read from them and if they change, their display is
2365 not updated.
2366
2367 TTY may be a terminal object, a frame, or nil for the terminal device
2368 of the currently selected frame.
2369
2370 This function runs `suspend-tty-functions' after suspending the
2371 device. The functions are run with one arg, the id of the suspended
2372 terminal device.
2373
2374 `suspend-tty' does nothing if it is called on a device that is already
2375 suspended.
2376
2377 A suspended tty may be resumed by calling `resume-tty' on it. */)
2378 (tty)
2379 Lisp_Object tty;
2380 {
2381 struct terminal *t = get_tty_terminal (tty, 1);
2382 FILE *f;
2383
2384 if (!t)
2385 error ("Unknown tty device");
2386
2387 f = t->display_info.tty->input;
2388
2389 if (f)
2390 {
2391 /* First run `suspend-tty-functions' and then clean up the tty
2392 state because `suspend-tty-functions' might need to change
2393 the tty state. */
2394 if (!NILP (Vrun_hooks))
2395 {
2396 Lisp_Object args[2];
2397 args[0] = intern ("suspend-tty-functions");
2398 XSETTERMINAL (args[1], t);
2399 Frun_hook_with_args (2, args);
2400 }
2401
2402 reset_sys_modes (t->display_info.tty);
2403
2404 #ifdef subprocesses
2405 delete_keyboard_wait_descriptor (fileno (f));
2406 #endif
2407
2408 #ifndef MSDOS
2409 fclose (f);
2410 if (f != t->display_info.tty->output)
2411 fclose (t->display_info.tty->output);
2412 #endif
2413
2414 t->display_info.tty->input = 0;
2415 t->display_info.tty->output = 0;
2416
2417 if (FRAMEP (t->display_info.tty->top_frame))
2418 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0);
2419
2420 }
2421
2422 /* Clear display hooks to prevent further output. */
2423 clear_tty_hooks (t);
2424
2425 return Qnil;
2426 }
2427
2428 DEFUN ("resume-tty", Fresume_tty, Sresume_tty, 0, 1, 0,
2429 doc: /* Resume the previously suspended terminal device TTY.
2430 The terminal is opened and reinitialized. Frames that are on the
2431 suspended terminal are revived.
2432
2433 It is an error to resume a terminal while another terminal is active
2434 on the same device.
2435
2436 This function runs `resume-tty-functions' after resuming the terminal.
2437 The functions are run with one arg, the id of the resumed terminal
2438 device.
2439
2440 `resume-tty' does nothing if it is called on a device that is not
2441 suspended.
2442
2443 TTY may be a terminal object, a frame, or nil (meaning the selected
2444 frame's terminal). */)
2445 (tty)
2446 Lisp_Object tty;
2447 {
2448 struct terminal *t = get_tty_terminal (tty, 1);
2449 int fd;
2450
2451 if (!t)
2452 error ("Unknown tty device");
2453
2454 if (!t->display_info.tty->input)
2455 {
2456 if (get_named_tty (t->display_info.tty->name))
2457 error ("Cannot resume display while another display is active on the same device");
2458
2459 #ifdef MSDOS
2460 t->display_info.tty->output = stdout;
2461 t->display_info.tty->input = stdin;
2462 #else /* !MSDOS */
2463 fd = emacs_open (t->display_info.tty->name, O_RDWR | O_NOCTTY, 0);
2464
2465 if (fd == -1)
2466 error ("Can not reopen tty device %s: %s", t->display_info.tty->name, strerror (errno));
2467
2468 if (strcmp (t->display_info.tty->name, DEV_TTY))
2469 dissociate_if_controlling_tty (fd);
2470
2471 t->display_info.tty->output = fdopen (fd, "w+");
2472 t->display_info.tty->input = t->display_info.tty->output;
2473 #endif
2474
2475 #ifdef subprocesses
2476 add_keyboard_wait_descriptor (fd);
2477 #endif
2478
2479 if (FRAMEP (t->display_info.tty->top_frame))
2480 {
2481 struct frame *f = XFRAME (t->display_info.tty->top_frame);
2482 int width, height;
2483 int old_height = FRAME_COLS (f);
2484 int old_width = FRAME_LINES (f);
2485
2486 /* Check if terminal/window size has changed while the frame
2487 was suspended. */
2488 get_tty_size (fileno (t->display_info.tty->input), &width, &height);
2489 if (width != old_width || height != old_height)
2490 change_frame_size (f, height, width, 0, 0, 0);
2491 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
2492 }
2493
2494 init_sys_modes (t->display_info.tty);
2495
2496 /* Run `resume-tty-functions'. */
2497 if (!NILP (Vrun_hooks))
2498 {
2499 Lisp_Object args[2];
2500 args[0] = intern ("resume-tty-functions");
2501 XSETTERMINAL (args[1], t);
2502 Frun_hook_with_args (2, args);
2503 }
2504 }
2505
2506 set_tty_hooks (t);
2507
2508 return Qnil;
2509 }
2510
2511 \f
2512 /***********************************************************************
2513 Mouse
2514 ***********************************************************************/
2515
2516 #ifdef HAVE_GPM
2517 void
2518 term_mouse_moveto (int x, int y)
2519 {
2520 /* TODO: how to set mouse position?
2521 const char *name;
2522 int fd;
2523 name = (const char *) ttyname (0);
2524 fd = open (name, O_WRONLY);
2525 SOME_FUNCTION (x, y, fd);
2526 close (fd);
2527 last_mouse_x = x;
2528 last_mouse_y = y; */
2529 }
2530
2531 static void
2532 term_show_mouse_face (enum draw_glyphs_face draw)
2533 {
2534 struct window *w = XWINDOW (mouse_face_window);
2535 int save_x, save_y;
2536 int i;
2537
2538 struct frame *f = XFRAME (w->frame);
2539 struct tty_display_info *tty = FRAME_TTY (f);
2540
2541 if (/* If window is in the process of being destroyed, don't bother
2542 to do anything. */
2543 w->current_matrix != NULL
2544 /* Recognize when we are called to operate on rows that don't exist
2545 anymore. This can happen when a window is split. */
2546 && mouse_face_end_row < w->current_matrix->nrows)
2547 {
2548 /* write_glyphs writes at cursor position, so we need to
2549 temporarily move cursor coordinates to the beginning of
2550 the highlight region. */
2551
2552 /* Save current cursor co-ordinates */
2553 save_y = curY (tty);
2554 save_x = curX (tty);
2555
2556 /* Note that mouse_face_beg_row etc. are window relative. */
2557 for (i = mouse_face_beg_row; i <= mouse_face_end_row; i++)
2558 {
2559 int start_hpos, end_hpos, nglyphs;
2560 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
2561
2562 /* Don't do anything if row doesn't have valid contents. */
2563 if (!row->enabled_p)
2564 continue;
2565
2566 /* For all but the first row, the highlight starts at column 0. */
2567 if (i == mouse_face_beg_row)
2568 start_hpos = mouse_face_beg_col;
2569 else
2570 start_hpos = 0;
2571
2572 if (i == mouse_face_end_row)
2573 end_hpos = mouse_face_end_col;
2574 else
2575 {
2576 end_hpos = row->used[TEXT_AREA];
2577 if (draw == DRAW_NORMAL_TEXT)
2578 row->fill_line_p = 1; /* Clear to end of line */
2579 }
2580
2581 if (end_hpos <= start_hpos)
2582 continue;
2583 /* Record that some glyphs of this row are displayed in
2584 mouse-face. */
2585 row->mouse_face_p = draw > 0;
2586
2587 nglyphs = end_hpos - start_hpos;
2588
2589 if (end_hpos >= row->used[TEXT_AREA])
2590 nglyphs = row->used[TEXT_AREA] - start_hpos;
2591
2592 pos_y = row->y + WINDOW_TOP_EDGE_Y (w);
2593 pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos
2594 + WINDOW_LEFT_EDGE_X (w);
2595
2596 cursor_to (f, pos_y, pos_x);
2597
2598 if (draw == DRAW_MOUSE_FACE)
2599 {
2600 tty_write_glyphs_with_face (f, row->glyphs[TEXT_AREA] + start_hpos,
2601 nglyphs, mouse_face_face_id);
2602 }
2603 else /* draw == DRAW_NORMAL_TEXT */
2604 write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
2605 }
2606 cursor_to (f, save_y, save_x);
2607 }
2608 }
2609
2610 static void
2611 term_clear_mouse_face ()
2612 {
2613 if (!NILP (mouse_face_window))
2614 term_show_mouse_face (DRAW_NORMAL_TEXT);
2615
2616 mouse_face_beg_row = mouse_face_beg_col = -1;
2617 mouse_face_end_row = mouse_face_end_col = -1;
2618 mouse_face_window = Qnil;
2619 }
2620
2621 /* Find the glyph matrix position of buffer position POS in window W.
2622 *HPOS and *VPOS are set to the positions found. W's current glyphs
2623 must be up to date. If POS is above window start return (0, 0).
2624 If POS is after end of W, return end of last line in W.
2625 - taken from msdos.c */
2626 static int
2627 fast_find_position (struct window *w, int pos, int *hpos, int *vpos)
2628 {
2629 int i, lastcol, line_start_position, maybe_next_line_p = 0;
2630 int yb = window_text_bottom_y (w);
2631 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0), *best_row = row;
2632
2633 while (row->y < yb)
2634 {
2635 if (row->used[TEXT_AREA])
2636 line_start_position = row->glyphs[TEXT_AREA]->charpos;
2637 else
2638 line_start_position = 0;
2639
2640 if (line_start_position > pos)
2641 break;
2642 /* If the position sought is the end of the buffer,
2643 don't include the blank lines at the bottom of the window. */
2644 else if (line_start_position == pos
2645 && pos == BUF_ZV (XBUFFER (w->buffer)))
2646 {
2647 maybe_next_line_p = 1;
2648 break;
2649 }
2650 else if (line_start_position > 0)
2651 best_row = row;
2652
2653 /* Don't overstep the last matrix row, lest we get into the
2654 never-never land... */
2655 if (row->y + 1 >= yb)
2656 break;
2657
2658 ++row;
2659 }
2660
2661 /* Find the right column within BEST_ROW. */
2662 lastcol = 0;
2663 row = best_row;
2664 for (i = 0; i < row->used[TEXT_AREA]; i++)
2665 {
2666 struct glyph *glyph = row->glyphs[TEXT_AREA] + i;
2667 int charpos;
2668
2669 charpos = glyph->charpos;
2670 if (charpos == pos)
2671 {
2672 *hpos = i;
2673 *vpos = row->y;
2674 return 1;
2675 }
2676 else if (charpos > pos)
2677 break;
2678 else if (charpos > 0)
2679 lastcol = i;
2680 }
2681
2682 /* If we're looking for the end of the buffer,
2683 and we didn't find it in the line we scanned,
2684 use the start of the following line. */
2685 if (maybe_next_line_p)
2686 {
2687 ++row;
2688 lastcol = 0;
2689 }
2690
2691 *vpos = row->y;
2692 *hpos = lastcol + 1;
2693 return 0;
2694 }
2695
2696 static void
2697 term_mouse_highlight (struct frame *f, int x, int y)
2698 {
2699 enum window_part part;
2700 Lisp_Object window;
2701 struct window *w;
2702 struct buffer *b;
2703
2704 if (NILP (Vmouse_highlight)
2705 || !f->glyphs_initialized_p)
2706 return;
2707
2708 /* Which window is that in? */
2709 window = window_from_coordinates (f, x, y, &part, &x, &y, 0);
2710
2711 /* Not on a window -> return. */
2712 if (!WINDOWP (window))
2713 return;
2714
2715 if (!EQ (window, mouse_face_window))
2716 term_clear_mouse_face ();
2717
2718 w = XWINDOW (window);
2719
2720 /* Are we in a window whose display is up to date?
2721 And verify the buffer's text has not changed. */
2722 b = XBUFFER (w->buffer);
2723 if (part == ON_TEXT
2724 && EQ (w->window_end_valid, w->buffer)
2725 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
2726 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
2727 {
2728 int pos, i, nrows = w->current_matrix->nrows;
2729 struct glyph_row *row;
2730 struct glyph *glyph;
2731
2732 /* Find the glyph under X/Y. */
2733 glyph = NULL;
2734 if (y >= 0 && y < nrows)
2735 {
2736 row = MATRIX_ROW (w->current_matrix, y);
2737 /* Give up if some row before the one we are looking for is
2738 not enabled. */
2739 for (i = 0; i <= y; i++)
2740 if (!MATRIX_ROW (w->current_matrix, i)->enabled_p)
2741 break;
2742 if (i > y /* all rows upto and including the one at Y are enabled */
2743 && row->displays_text_p
2744 && x < window_box_width (w, TEXT_AREA))
2745 {
2746 glyph = row->glyphs[TEXT_AREA];
2747 if (x >= row->used[TEXT_AREA])
2748 glyph = NULL;
2749 else
2750 {
2751 glyph += x;
2752 if (!BUFFERP (glyph->object))
2753 glyph = NULL;
2754 }
2755 }
2756 }
2757
2758 /* Clear mouse face if X/Y not over text. */
2759 if (glyph == NULL)
2760 {
2761 term_clear_mouse_face ();
2762 return;
2763 }
2764
2765 if (!BUFFERP (glyph->object))
2766 abort ();
2767 pos = glyph->charpos;
2768
2769 /* Check for mouse-face. */
2770 {
2771 extern Lisp_Object Qmouse_face;
2772 Lisp_Object mouse_face, overlay, position, *overlay_vec;
2773 int noverlays, obegv, ozv;
2774 struct buffer *obuf;
2775
2776 /* If we get an out-of-range value, return now; avoid an error. */
2777 if (pos > BUF_Z (b))
2778 return;
2779
2780 /* Make the window's buffer temporarily current for
2781 overlays_at and compute_char_face. */
2782 obuf = current_buffer;
2783 current_buffer = b;
2784 obegv = BEGV;
2785 ozv = ZV;
2786 BEGV = BEG;
2787 ZV = Z;
2788
2789 /* Is this char mouse-active? */
2790 XSETINT (position, pos);
2791
2792 /* Put all the overlays we want in a vector in overlay_vec. */
2793 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL, 0);
2794 /* Sort overlays into increasing priority order. */
2795 noverlays = sort_overlays (overlay_vec, noverlays, w);
2796
2797 /* Check mouse-face highlighting. */
2798 if (!(EQ (window, mouse_face_window)
2799 && y >= mouse_face_beg_row
2800 && y <= mouse_face_end_row
2801 && (y > mouse_face_beg_row
2802 || x >= mouse_face_beg_col)
2803 && (y < mouse_face_end_row
2804 || x < mouse_face_end_col
2805 || mouse_face_past_end)))
2806 {
2807 /* Clear the display of the old active region, if any. */
2808 term_clear_mouse_face ();
2809
2810 /* Find the highest priority overlay that has a mouse-face
2811 property. */
2812 overlay = Qnil;
2813 for (i = noverlays - 1; i >= 0; --i)
2814 {
2815 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
2816 if (!NILP (mouse_face))
2817 {
2818 overlay = overlay_vec[i];
2819 break;
2820 }
2821 }
2822
2823 /* If no overlay applies, get a text property. */
2824 if (NILP (overlay))
2825 mouse_face = Fget_text_property (position, Qmouse_face,
2826 w->buffer);
2827
2828 /* Handle the overlay case. */
2829 if (!NILP (overlay))
2830 {
2831 /* Find the range of text around this char that
2832 should be active. */
2833 Lisp_Object before, after;
2834 EMACS_INT ignore;
2835
2836
2837 before = Foverlay_start (overlay);
2838 after = Foverlay_end (overlay);
2839 /* Record this as the current active region. */
2840 fast_find_position (w, XFASTINT (before),
2841 &mouse_face_beg_col,
2842 &mouse_face_beg_row);
2843
2844 mouse_face_past_end
2845 = !fast_find_position (w, XFASTINT (after),
2846 &mouse_face_end_col,
2847 &mouse_face_end_row);
2848 mouse_face_window = window;
2849
2850 mouse_face_face_id
2851 = face_at_buffer_position (w, pos, 0, 0,
2852 &ignore, pos + 1, 1, -1);
2853
2854 /* Display it as active. */
2855 term_show_mouse_face (DRAW_MOUSE_FACE);
2856 }
2857 /* Handle the text property case. */
2858 else if (!NILP (mouse_face))
2859 {
2860 /* Find the range of text around this char that
2861 should be active. */
2862 Lisp_Object before, after, beginning, end;
2863 EMACS_INT ignore;
2864
2865 beginning = Fmarker_position (w->start);
2866 XSETINT (end, (BUF_Z (b) - XFASTINT (w->window_end_pos)));
2867 before
2868 = Fprevious_single_property_change (make_number (pos + 1),
2869 Qmouse_face,
2870 w->buffer, beginning);
2871 after
2872 = Fnext_single_property_change (position, Qmouse_face,
2873 w->buffer, end);
2874
2875 /* Record this as the current active region. */
2876 fast_find_position (w, XFASTINT (before),
2877 &mouse_face_beg_col,
2878 &mouse_face_beg_row);
2879 mouse_face_past_end
2880 = !fast_find_position (w, XFASTINT (after),
2881 &mouse_face_end_col,
2882 &mouse_face_end_row);
2883 mouse_face_window = window;
2884
2885 mouse_face_face_id
2886 = face_at_buffer_position (w, pos, 0, 0,
2887 &ignore, pos + 1, 1, -1);
2888
2889 /* Display it as active. */
2890 term_show_mouse_face (DRAW_MOUSE_FACE);
2891 }
2892 }
2893
2894 /* Look for a `help-echo' property. */
2895 {
2896 Lisp_Object help;
2897 extern Lisp_Object Qhelp_echo;
2898
2899 /* Check overlays first. */
2900 help = Qnil;
2901 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
2902 {
2903 overlay = overlay_vec[i];
2904 help = Foverlay_get (overlay, Qhelp_echo);
2905 }
2906
2907 if (!NILP (help))
2908 {
2909 help_echo_string = help;
2910 help_echo_window = window;
2911 help_echo_object = overlay;
2912 help_echo_pos = pos;
2913 }
2914 /* Try text properties. */
2915 else if (NILP (help)
2916 && ((STRINGP (glyph->object)
2917 && glyph->charpos >= 0
2918 && glyph->charpos < SCHARS (glyph->object))
2919 || (BUFFERP (glyph->object)
2920 && glyph->charpos >= BEGV
2921 && glyph->charpos < ZV)))
2922 {
2923 help = Fget_text_property (make_number (glyph->charpos),
2924 Qhelp_echo, glyph->object);
2925 if (!NILP (help))
2926 {
2927 help_echo_string = help;
2928 help_echo_window = window;
2929 help_echo_object = glyph->object;
2930 help_echo_pos = glyph->charpos;
2931 }
2932 }
2933 }
2934
2935 BEGV = obegv;
2936 ZV = ozv;
2937 current_buffer = obuf;
2938 }
2939 }
2940 }
2941
2942 static int
2943 term_mouse_movement (FRAME_PTR frame, Gpm_Event *event)
2944 {
2945 /* Has the mouse moved off the glyph it was on at the last sighting? */
2946 if (event->x != last_mouse_x || event->y != last_mouse_y)
2947 {
2948 frame->mouse_moved = 1;
2949 term_mouse_highlight (frame, event->x, event->y);
2950 /* Remember which glyph we're now on. */
2951 last_mouse_x = event->x;
2952 last_mouse_y = event->y;
2953 return 1;
2954 }
2955 return 0;
2956 }
2957
2958 /* Return the current position of the mouse.
2959
2960 Set *f to the frame the mouse is in, or zero if the mouse is in no
2961 Emacs frame. If it is set to zero, all the other arguments are
2962 garbage.
2963
2964 Set *bar_window to Qnil, and *x and *y to the column and
2965 row of the character cell the mouse is over.
2966
2967 Set *time to the time the mouse was at the returned position.
2968
2969 This clears mouse_moved until the next motion
2970 event arrives. */
2971 static void
2972 term_mouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
2973 enum scroll_bar_part *part, Lisp_Object *x,
2974 Lisp_Object *y, unsigned long *time)
2975 {
2976 struct timeval now;
2977
2978 *fp = SELECTED_FRAME ();
2979 (*fp)->mouse_moved = 0;
2980
2981 *bar_window = Qnil;
2982 *part = 0;
2983
2984 XSETINT (*x, last_mouse_x);
2985 XSETINT (*y, last_mouse_y);
2986 gettimeofday(&now, 0);
2987 *time = (now.tv_sec * 1000) + (now.tv_usec / 1000);
2988 }
2989
2990 /* Prepare a mouse-event in *RESULT for placement in the input queue.
2991
2992 If the event is a button press, then note that we have grabbed
2993 the mouse. */
2994
2995 static Lisp_Object
2996 term_mouse_click (struct input_event *result, Gpm_Event *event,
2997 struct frame *f)
2998 {
2999 struct timeval now;
3000 int i, j;
3001
3002 result->kind = GPM_CLICK_EVENT;
3003 for (i = 0, j = GPM_B_LEFT; i < 3; i++, j >>= 1 )
3004 {
3005 if (event->buttons & j) {
3006 result->code = i; /* button number */
3007 break;
3008 }
3009 }
3010 gettimeofday(&now, 0);
3011 result->timestamp = (now.tv_sec * 1000) + (now.tv_usec / 1000);
3012
3013 if (event->type & GPM_UP)
3014 result->modifiers = up_modifier;
3015 else if (event->type & GPM_DOWN)
3016 result->modifiers = down_modifier;
3017 else
3018 result->modifiers = 0;
3019
3020 if (event->type & GPM_SINGLE)
3021 result->modifiers |= click_modifier;
3022
3023 if (event->type & GPM_DOUBLE)
3024 result->modifiers |= double_modifier;
3025
3026 if (event->type & GPM_TRIPLE)
3027 result->modifiers |= triple_modifier;
3028
3029 if (event->type & GPM_DRAG)
3030 result->modifiers |= drag_modifier;
3031
3032 if (!(event->type & (GPM_MOVE | GPM_DRAG))) {
3033
3034 /* 1 << KG_SHIFT */
3035 if (event->modifiers & (1 << 0))
3036 result->modifiers |= shift_modifier;
3037
3038 /* 1 << KG_CTRL */
3039 if (event->modifiers & (1 << 2))
3040 result->modifiers |= ctrl_modifier;
3041
3042 /* 1 << KG_ALT || KG_ALTGR */
3043 if (event->modifiers & (1 << 3)
3044 || event->modifiers & (1 << 1))
3045 result->modifiers |= meta_modifier;
3046 }
3047
3048 XSETINT (result->x, event->x);
3049 XSETINT (result->y, event->y);
3050 XSETFRAME (result->frame_or_window, f);
3051 result->arg = Qnil;
3052 return Qnil;
3053 }
3054
3055 int
3056 handle_one_term_event (struct tty_display_info *tty, Gpm_Event *event, struct input_event* hold_quit)
3057 {
3058 struct frame *f = XFRAME (tty->top_frame);
3059 struct input_event ie;
3060 int do_help = 0;
3061 int count = 0;
3062
3063 EVENT_INIT (ie);
3064 ie.kind = NO_EVENT;
3065 ie.arg = Qnil;
3066
3067 if (event->type & (GPM_MOVE | GPM_DRAG)) {
3068 previous_help_echo_string = help_echo_string;
3069 help_echo_string = Qnil;
3070
3071 Gpm_DrawPointer (event->x, event->y, fileno (tty->output));
3072
3073 if (!term_mouse_movement (f, event))
3074 help_echo_string = previous_help_echo_string;
3075
3076 /* If the contents of the global variable help_echo_string
3077 has changed, generate a HELP_EVENT. */
3078 if (!NILP (help_echo_string)
3079 || !NILP (previous_help_echo_string))
3080 do_help = 1;
3081
3082 goto done;
3083 }
3084 else {
3085 f->mouse_moved = 0;
3086 term_mouse_click (&ie, event, f);
3087 }
3088
3089 done:
3090 if (ie.kind != NO_EVENT)
3091 {
3092 kbd_buffer_store_event_hold (&ie, hold_quit);
3093 count++;
3094 }
3095
3096 if (do_help
3097 && !(hold_quit && hold_quit->kind != NO_EVENT))
3098 {
3099 Lisp_Object frame;
3100
3101 if (f)
3102 XSETFRAME (frame, f);
3103 else
3104 frame = Qnil;
3105
3106 gen_help_event (help_echo_string, frame, help_echo_window,
3107 help_echo_object, help_echo_pos);
3108 count++;
3109 }
3110
3111 return count;
3112 }
3113
3114 DEFUN ("gpm-mouse-start", Fgpm_mouse_start, Sgpm_mouse_start,
3115 0, 0, 0,
3116 doc: /* Open a connection to Gpm.
3117 Gpm-mouse can only be activated for one tty at a time. */)
3118 ()
3119 {
3120 struct frame *f = SELECTED_FRAME ();
3121 struct tty_display_info *tty
3122 = ((f)->output_method == output_termcap
3123 ? (f)->terminal->display_info.tty : NULL);
3124 Gpm_Connect connection;
3125
3126 if (!tty)
3127 error ("Gpm-mouse only works in the GNU/Linux console");
3128 if (gpm_tty == tty)
3129 return Qnil; /* Already activated, nothing to do. */
3130 if (gpm_tty)
3131 error ("Gpm-mouse can only be activated for one tty at a time");
3132
3133 connection.eventMask = ~0;
3134 connection.defaultMask = ~GPM_HARD;
3135 connection.maxMod = ~0;
3136 connection.minMod = 0;
3137 gpm_zerobased = 1;
3138
3139 if (Gpm_Open (&connection, 0) < 0)
3140 error ("Gpm-mouse failed to connect to the gpm daemon");
3141 else
3142 {
3143 gpm_tty = tty;
3144 /* `init_sys_modes' arranges for mouse movements sent through gpm_fd
3145 to generate SIGIOs. Apparently we need to call reset_sys_modes
3146 before calling init_sys_modes. */
3147 reset_sys_modes (tty);
3148 init_sys_modes (tty);
3149 add_gpm_wait_descriptor (gpm_fd);
3150 return Qnil;
3151 }
3152 }
3153
3154 void
3155 close_gpm (int fd)
3156 {
3157 if (fd >= 0)
3158 delete_gpm_wait_descriptor (fd);
3159 while (Gpm_Close()); /* close all the stack */
3160 gpm_tty = NULL;
3161 }
3162
3163 DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop, Sgpm_mouse_stop,
3164 0, 0, 0,
3165 doc: /* Close a connection to Gpm. */)
3166 ()
3167 {
3168 struct frame *f = SELECTED_FRAME ();
3169 struct tty_display_info *tty
3170 = ((f)->output_method == output_termcap
3171 ? (f)->terminal->display_info.tty : NULL);
3172
3173 if (!tty || gpm_tty != tty)
3174 return Qnil; /* Not activated on this terminal, nothing to do. */
3175
3176 close_gpm (gpm_fd);
3177 return Qnil;
3178 }
3179 #endif /* HAVE_GPM */
3180
3181 \f
3182 #ifndef MSDOS
3183 /***********************************************************************
3184 Initialization
3185 ***********************************************************************/
3186
3187 /* Initialize the tty-dependent part of frame F. The frame must
3188 already have its device initialized. */
3189
3190 void
3191 create_tty_output (struct frame *f)
3192 {
3193 struct tty_output *t;
3194
3195 if (! FRAME_TERMCAP_P (f))
3196 abort ();
3197
3198 t = xmalloc (sizeof (struct tty_output));
3199 bzero (t, sizeof (struct tty_output));
3200
3201 t->display_info = FRAME_TERMINAL (f)->display_info.tty;
3202
3203 f->output_data.tty = t;
3204 }
3205
3206 /* Delete frame F's face cache, and its tty-dependent part. */
3207
3208 static void
3209 tty_free_frame_resources (struct frame *f)
3210 {
3211 if (! FRAME_TERMCAP_P (f))
3212 abort ();
3213
3214 if (FRAME_FACE_CACHE (f))
3215 free_frame_faces (f);
3216
3217 xfree (f->output_data.tty);
3218 }
3219
3220 #else /* MSDOS */
3221
3222 /* Delete frame F's face cache. */
3223
3224 static void
3225 tty_free_frame_resources (struct frame *f)
3226 {
3227 if (! FRAME_TERMCAP_P (f) && ! FRAME_MSDOS_P (f))
3228 abort ();
3229
3230 if (FRAME_FACE_CACHE (f))
3231 free_frame_faces (f);
3232 }
3233 #endif /* MSDOS */
3234 \f
3235 /* Reset the hooks in TERMINAL. */
3236
3237 static void
3238 clear_tty_hooks (struct terminal *terminal)
3239 {
3240 terminal->rif = 0;
3241 terminal->cursor_to_hook = 0;
3242 terminal->raw_cursor_to_hook = 0;
3243 terminal->clear_to_end_hook = 0;
3244 terminal->clear_frame_hook = 0;
3245 terminal->clear_end_of_line_hook = 0;
3246 terminal->ins_del_lines_hook = 0;
3247 terminal->insert_glyphs_hook = 0;
3248 terminal->write_glyphs_hook = 0;
3249 terminal->delete_glyphs_hook = 0;
3250 terminal->ring_bell_hook = 0;
3251 terminal->reset_terminal_modes_hook = 0;
3252 terminal->set_terminal_modes_hook = 0;
3253 terminal->update_begin_hook = 0;
3254 terminal->update_end_hook = 0;
3255 terminal->set_terminal_window_hook = 0;
3256 terminal->mouse_position_hook = 0;
3257 terminal->frame_rehighlight_hook = 0;
3258 terminal->frame_raise_lower_hook = 0;
3259 terminal->fullscreen_hook = 0;
3260 terminal->set_vertical_scroll_bar_hook = 0;
3261 terminal->condemn_scroll_bars_hook = 0;
3262 terminal->redeem_scroll_bar_hook = 0;
3263 terminal->judge_scroll_bars_hook = 0;
3264 terminal->read_socket_hook = 0;
3265 terminal->frame_up_to_date_hook = 0;
3266
3267 /* Leave these two set, or suspended frames are not deleted
3268 correctly. */
3269 terminal->delete_frame_hook = &tty_free_frame_resources;
3270 terminal->delete_terminal_hook = &delete_tty;
3271 }
3272
3273 /* Initialize hooks in TERMINAL with the values needed for a tty. */
3274
3275 static void
3276 set_tty_hooks (struct terminal *terminal)
3277 {
3278 terminal->rif = 0; /* ttys don't support window-based redisplay. */
3279
3280 terminal->cursor_to_hook = &tty_cursor_to;
3281 terminal->raw_cursor_to_hook = &tty_raw_cursor_to;
3282
3283 terminal->clear_to_end_hook = &tty_clear_to_end;
3284 terminal->clear_frame_hook = &tty_clear_frame;
3285 terminal->clear_end_of_line_hook = &tty_clear_end_of_line;
3286
3287 terminal->ins_del_lines_hook = &tty_ins_del_lines;
3288
3289 terminal->insert_glyphs_hook = &tty_insert_glyphs;
3290 terminal->write_glyphs_hook = &tty_write_glyphs;
3291 terminal->delete_glyphs_hook = &tty_delete_glyphs;
3292
3293 terminal->ring_bell_hook = &tty_ring_bell;
3294
3295 terminal->reset_terminal_modes_hook = &tty_reset_terminal_modes;
3296 terminal->set_terminal_modes_hook = &tty_set_terminal_modes;
3297 terminal->update_begin_hook = 0; /* Not needed. */
3298 terminal->update_end_hook = &tty_update_end;
3299 terminal->set_terminal_window_hook = &tty_set_terminal_window;
3300
3301 terminal->mouse_position_hook = 0; /* Not needed. */
3302 terminal->frame_rehighlight_hook = 0; /* Not needed. */
3303 terminal->frame_raise_lower_hook = 0; /* Not needed. */
3304
3305 terminal->set_vertical_scroll_bar_hook = 0; /* Not needed. */
3306 terminal->condemn_scroll_bars_hook = 0; /* Not needed. */
3307 terminal->redeem_scroll_bar_hook = 0; /* Not needed. */
3308 terminal->judge_scroll_bars_hook = 0; /* Not needed. */
3309
3310 terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */
3311 terminal->frame_up_to_date_hook = 0; /* Not needed. */
3312
3313 terminal->delete_frame_hook = &tty_free_frame_resources;
3314 terminal->delete_terminal_hook = &delete_tty;
3315 }
3316
3317 /* Drop the controlling terminal if fd is the same device. */
3318 static void
3319 dissociate_if_controlling_tty (int fd)
3320 {
3321 #ifndef DOS_NT
3322 int pgid;
3323 EMACS_GET_TTY_PGRP (fd, &pgid); /* If tcgetpgrp succeeds, fd is the ctty. */
3324 if (pgid != -1)
3325 {
3326 #if defined (USG) && !defined (BSD_PGRPS)
3327 setpgrp ();
3328 no_controlling_tty = 1;
3329 #elif defined (CYGWIN)
3330 setsid ();
3331 no_controlling_tty = 1;
3332 #else
3333 #ifdef TIOCNOTTY /* Try BSD ioctls. */
3334 sigblock (sigmask (SIGTTOU));
3335 fd = emacs_open (DEV_TTY, O_RDWR, 0);
3336 if (fd != -1 && ioctl (fd, TIOCNOTTY, 0) != -1)
3337 {
3338 no_controlling_tty = 1;
3339 }
3340 if (fd != -1)
3341 emacs_close (fd);
3342 sigunblock (sigmask (SIGTTOU));
3343 #else
3344 /* Unknown system. */
3345 croak ();
3346 #endif /* ! TIOCNOTTY */
3347 #endif /* ! USG */
3348 }
3349 #endif /* !DOS_NT */
3350 }
3351
3352 static void maybe_fatal();
3353
3354 /* Create a termcap display on the tty device with the given name and
3355 type.
3356
3357 If NAME is NULL, then use the controlling tty, i.e., "/dev/tty".
3358 Otherwise NAME should be a path to the tty device file,
3359 e.g. "/dev/pts/7".
3360
3361 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
3362
3363 If MUST_SUCCEED is true, then all errors are fatal. */
3364
3365 struct terminal *
3366 init_tty (char *name, char *terminal_type, int must_succeed)
3367 {
3368 char *area = NULL;
3369 char **address = &area;
3370 int buffer_size = 4096;
3371 register char *p = NULL;
3372 int status;
3373 struct tty_display_info *tty = NULL;
3374 struct terminal *terminal = NULL;
3375 int ctty = 0; /* 1 if asked to open controlling tty. */
3376
3377 if (!terminal_type)
3378 maybe_fatal (must_succeed, 0,
3379 "Unknown terminal type",
3380 "Unknown terminal type");
3381
3382 if (name == NULL)
3383 name = DEV_TTY;
3384 if (!strcmp (name, DEV_TTY))
3385 ctty = 1;
3386
3387 /* If we already have a terminal on the given device, use that. If
3388 all such terminals are suspended, create a new one instead. */
3389 /* XXX Perhaps this should be made explicit by having init_tty
3390 always create a new terminal and separating terminal and frame
3391 creation on Lisp level. */
3392 terminal = get_named_tty (name);
3393 if (terminal)
3394 return terminal;
3395
3396 terminal = create_terminal ();
3397 #ifdef MSDOS
3398 if (been_here > 0)
3399 maybe_fatal (1, 0, "Attempt to create another terminal %s", "",
3400 name, "");
3401 been_here = 1;
3402 tty = &the_only_display_info;
3403 #else
3404 tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info));
3405 #endif
3406 bzero (tty, sizeof (struct tty_display_info));
3407 tty->next = tty_list;
3408 tty_list = tty;
3409
3410 terminal->type = output_termcap;
3411 terminal->display_info.tty = tty;
3412 tty->terminal = terminal;
3413
3414 tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
3415 Wcm_clear (tty);
3416
3417 #ifndef DOS_NT
3418 set_tty_hooks (terminal);
3419
3420 {
3421 int fd;
3422 FILE *file;
3423
3424 #ifdef O_IGNORE_CTTY
3425 if (!ctty)
3426 /* Open the terminal device. Don't recognize it as our
3427 controlling terminal, and don't make it the controlling tty
3428 if we don't have one at the moment. */
3429 fd = emacs_open (name, O_RDWR | O_IGNORE_CTTY | O_NOCTTY, 0);
3430 else
3431 #else
3432 /* Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
3433 defined on Hurd. On other systems, we need to explicitly
3434 dissociate ourselves from the controlling tty when we want to
3435 open a frame on the same terminal. */
3436 fd = emacs_open (name, O_RDWR | O_NOCTTY, 0);
3437 #endif /* O_IGNORE_CTTY */
3438
3439 tty->name = xstrdup (name);
3440 terminal->name = xstrdup (name);
3441
3442 if (fd < 0)
3443 maybe_fatal (must_succeed, terminal,
3444 "Could not open file: %s",
3445 "Could not open file: %s",
3446 name);
3447 if (!isatty (fd))
3448 {
3449 close (fd);
3450 maybe_fatal (must_succeed, terminal,
3451 "Not a tty device: %s",
3452 "Not a tty device: %s",
3453 name);
3454 }
3455
3456 #ifndef O_IGNORE_CTTY
3457 if (!ctty)
3458 dissociate_if_controlling_tty (fd);
3459 #endif
3460
3461 file = fdopen (fd, "w+");
3462 tty->input = file;
3463 tty->output = file;
3464 }
3465
3466 tty->type = xstrdup (terminal_type);
3467
3468 add_keyboard_wait_descriptor (fileno (tty->input));
3469
3470 #endif /* !DOS_NT */
3471
3472 encode_terminal_src_size = 0;
3473 encode_terminal_dst_size = 0;
3474
3475 #ifdef HAVE_GPM
3476 terminal->mouse_position_hook = term_mouse_position;
3477 mouse_face_window = Qnil;
3478 #endif
3479
3480 #ifdef DOS_NT
3481 #ifdef WINDOWSNT
3482 initialize_w32_display (terminal);
3483 #else /* MSDOS */
3484 if (strcmp (terminal_type, "internal") == 0)
3485 terminal->type = output_msdos_raw;
3486 initialize_msdos_display (terminal);
3487 #endif /* MSDOS */
3488 tty->output = stdout;
3489 tty->input = stdin;
3490 /* The following two are inaccessible from w32console.c. */
3491 terminal->delete_frame_hook = &tty_free_frame_resources;
3492 terminal->delete_terminal_hook = &delete_tty;
3493
3494 tty->name = xstrdup (name);
3495 terminal->name = xstrdup (name);
3496 tty->type = xstrdup (terminal_type);
3497
3498 #ifdef subprocesses
3499 add_keyboard_wait_descriptor (0);
3500 #endif
3501
3502 Wcm_clear (tty);
3503
3504 #ifdef WINDOWSNT
3505 {
3506 struct frame *f = XFRAME (selected_frame);
3507
3508 FrameRows (tty) = FRAME_LINES (f);
3509 FrameCols (tty) = FRAME_COLS (f);
3510 tty->specified_window = FRAME_LINES (f);
3511
3512 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
3513 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
3514 }
3515 #else /* MSDOS */
3516 {
3517 int height, width;
3518 get_tty_size (fileno (tty->input), &width, &height);
3519 FrameCols (tty) = width;
3520 FrameRows (tty) = height;
3521 }
3522 #endif /* MSDOS */
3523 tty->delete_in_insert_mode = 1;
3524
3525 UseTabs (tty) = 0;
3526 terminal->scroll_region_ok = 0;
3527
3528 /* Seems to insert lines when it's not supposed to, messing up the
3529 display. In doing a trace, it didn't seem to be called much, so I
3530 don't think we're losing anything by turning it off. */
3531 terminal->line_ins_del_ok = 0;
3532 #ifdef WINDOWSNT
3533 terminal->char_ins_del_ok = 1;
3534 baud_rate = 19200;
3535 #else /* MSDOS */
3536 terminal->char_ins_del_ok = 0;
3537 init_baud_rate (fileno (tty->input));
3538 #endif /* MSDOS */
3539
3540 tty->TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
3541
3542 #else /* not DOS_NT */
3543
3544 Wcm_clear (tty);
3545
3546 tty->termcap_term_buffer = (char *) xmalloc (buffer_size);
3547
3548 /* On some systems, tgetent tries to access the controlling
3549 terminal. */
3550 sigblock (sigmask (SIGTTOU));
3551 status = tgetent (tty->termcap_term_buffer, terminal_type);
3552 sigunblock (sigmask (SIGTTOU));
3553
3554 if (status < 0)
3555 {
3556 #ifdef TERMINFO
3557 maybe_fatal (must_succeed, terminal,
3558 "Cannot open terminfo database file",
3559 "Cannot open terminfo database file");
3560 #else
3561 maybe_fatal (must_succeed, terminal,
3562 "Cannot open termcap database file",
3563 "Cannot open termcap database file");
3564 #endif
3565 }
3566 if (status == 0)
3567 {
3568 #ifdef TERMINFO
3569 maybe_fatal (must_succeed, terminal,
3570 "Terminal type %s is not defined",
3571 "Terminal type %s is not defined.\n\
3572 If that is not the actual type of terminal you have,\n\
3573 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3574 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3575 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3576 terminal_type);
3577 #else
3578 maybe_fatal (must_succeed, terminal,
3579 "Terminal type %s is not defined",
3580 "Terminal type %s is not defined.\n\
3581 If that is not the actual type of terminal you have,\n\
3582 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3583 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3584 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3585 terminal_type);
3586 #endif
3587 }
3588
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);
3648
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);
3658
3659 MultiUp (tty) = tgetstr ("UP", address);
3660 MultiDown (tty) = tgetstr ("DO", address);
3661 MultiLeft (tty) = tgetstr ("LE", address);
3662 MultiRight (tty) = tgetstr ("RI", address);
3663
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)
3669 {
3670 tty->TS_set_foreground = tgetstr ("AF", address);
3671 tty->TS_set_background = tgetstr ("AB", address);
3672 if (!tty->TS_set_foreground)
3673 {
3674 /* SVr4. */
3675 tty->TS_set_foreground = tgetstr ("Sf", address);
3676 tty->TS_set_background = tgetstr ("Sb", address);
3677 }
3678
3679 tty->TN_max_colors = tgetnum ("Co");
3680 tty->TN_max_pairs = tgetnum ("pa");
3681
3682 tty->TN_no_color_video = tgetnum ("NC");
3683 if (tty->TN_no_color_video == -1)
3684 tty->TN_no_color_video = 0;
3685 }
3686
3687 tty_default_color_capabilities (tty, 1);
3688
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");
3701
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);
3716
3717 /* Get frame size from system, or else from termcap. */
3718 {
3719 int height, width;
3720 get_tty_size (fileno (tty->input), &width, &height);
3721 FrameCols (tty) = width;
3722 FrameRows (tty) = height;
3723 }
3724
3725 if (FrameCols (tty) <= 0)
3726 FrameCols (tty) = tgetnum ("co");
3727 if (FrameRows (tty) <= 0)
3728 FrameRows (tty) = tgetnum ("li");
3729
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));
3735
3736 TabWidth (tty) = tgetnum ("tw");
3737
3738 if (!tty->TS_bell)
3739 tty->TS_bell = "\07";
3740
3741 if (!tty->TS_fwd_scroll)
3742 tty->TS_fwd_scroll = Down (tty);
3743
3744 PC = tty->TS_pad_char ? *tty->TS_pad_char : 0;
3745
3746 if (TabWidth (tty) < 0)
3747 TabWidth (tty) = 8;
3748
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";
3753 */
3754
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)
3758 {
3759 tty->TS_standout_mode = 0;
3760 tty->TS_end_standout_mode = 0;
3761 }
3762 if (tty->TS_enter_underline_mode && tgetnum ("ug") >= 0)
3763 {
3764 tty->TS_enter_underline_mode = 0;
3765 tty->TS_exit_underline_mode = 0;
3766 }
3767
3768 /* If there's no standout mode, try to use underlining instead. */
3769 if (tty->TS_standout_mode == 0)
3770 {
3771 tty->TS_standout_mode = tty->TS_enter_underline_mode;
3772 tty->TS_end_standout_mode = tty->TS_exit_underline_mode;
3773 }
3774
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)
3778 {
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;
3784 }
3785
3786 if (tty->TF_teleray)
3787 {
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;
3796 }
3797
3798 /* Special handling for certain terminal types known to need it */
3799
3800 if (!strcmp (terminal_type, "supdup"))
3801 {
3802 terminal->memory_below_frame = 1;
3803 tty->Wcm->cm_losewrap = 1;
3804 }
3805 if (!strncmp (terminal_type, "c10", 3)
3806 || !strcmp (terminal_type, "perq"))
3807 {
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.
3812
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.
3816
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)
3821 {
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 ";
3827 }
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)
3840 {
3841 if (p[0] == '%' && p[1] == '+')
3842 p[1] = 'C';
3843 p++;
3844 }
3845 }
3846
3847 tty->specified_window = FrameRows (tty);
3848
3849 if (Wcm_init (tty) == -1) /* can't do cursor motion */
3850 {
3851 maybe_fatal (must_succeed, terminal,
3852 "Terminal type \"%s\" is not powerful enough to run Emacs",
3853 # ifdef TERMINFO
3854 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3855 It lacks the ability to position the cursor.\n\
3856 If that is not the actual type of terminal you have,\n\
3857 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3858 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3859 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3860 # else /* TERMCAP */
3861 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3862 It lacks the ability to position the cursor.\n\
3863 If that is not the actual type of terminal you have,\n\
3864 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3865 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3866 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3867 # endif /* TERMINFO */
3868 terminal_type);
3869 }
3870
3871 if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
3872 maybe_fatal (must_succeed, terminal,
3873 "Could not determine the frame size",
3874 "Could not determine the frame size");
3875
3876 tty->delete_in_insert_mode
3877 = tty->TS_delete_mode && tty->TS_insert_mode
3878 && !strcmp (tty->TS_delete_mode, tty->TS_insert_mode);
3879
3880 tty->se_is_so = (tty->TS_standout_mode
3881 && tty->TS_end_standout_mode
3882 && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode));
3883
3884 UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8;
3885
3886 terminal->scroll_region_ok
3887 = (tty->Wcm->cm_abs
3888 && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
3889
3890 terminal->line_ins_del_ok
3891 = (((tty->TS_ins_line || tty->TS_ins_multi_lines)
3892 && (tty->TS_del_line || tty->TS_del_multi_lines))
3893 || (terminal->scroll_region_ok
3894 && tty->TS_fwd_scroll && tty->TS_rev_scroll));
3895
3896 terminal->char_ins_del_ok
3897 = ((tty->TS_ins_char || tty->TS_insert_mode
3898 || tty->TS_pad_inserted_char || tty->TS_ins_multi_chars)
3899 && (tty->TS_del_char || tty->TS_del_multi_chars));
3900
3901 terminal->fast_clear_end_of_line = tty->TS_clr_line != 0;
3902
3903 init_baud_rate (fileno (tty->input));
3904
3905 #endif /* not DOS_NT */
3906
3907 /* Init system terminal modes (RAW or CBREAK, etc.). */
3908 init_sys_modes (tty);
3909
3910 return terminal;
3911 }
3912
3913 /* Auxiliary error-handling function for init_tty.
3914 Delete TERMINAL, then call error or fatal with str1 or str2,
3915 respectively, according to MUST_SUCCEED. */
3916
3917 static void
3918 maybe_fatal (must_succeed, terminal, str1, str2, arg1, arg2)
3919 int must_succeed;
3920 struct terminal *terminal;
3921 char *str1, *str2, *arg1, *arg2;
3922 {
3923 if (terminal)
3924 delete_tty (terminal);
3925
3926 if (must_succeed)
3927 fatal (str2, arg1, arg2);
3928 else
3929 error (str1, arg1, arg2);
3930
3931 abort ();
3932 }
3933
3934 void
3935 fatal (const char *str, ...)
3936 {
3937 va_list ap;
3938 va_start (ap, str);
3939 fprintf (stderr, "emacs: ");
3940 vfprintf (stderr, str, ap);
3941 va_end (ap);
3942 fflush (stderr);
3943 exit (1);
3944 }
3945
3946 \f
3947
3948 /* Delete the given tty terminal, closing all frames on it. */
3949
3950 static void
3951 delete_tty (struct terminal *terminal)
3952 {
3953 struct tty_display_info *tty;
3954 Lisp_Object tail, frame;
3955 int last_terminal;
3956
3957 /* Protect against recursive calls. delete_frame in
3958 delete_terminal calls us back when it deletes our last frame. */
3959 if (!terminal->name)
3960 return;
3961
3962 if (terminal->type != output_termcap)
3963 abort ();
3964
3965 tty = terminal->display_info.tty;
3966
3967 last_terminal = 1;
3968 FOR_EACH_FRAME (tail, frame)
3969 {
3970 struct frame *f = XFRAME (frame);
3971 if (FRAME_LIVE_P (f) && (!FRAME_TERMCAP_P (f) || FRAME_TTY (f) != tty))
3972 {
3973 last_terminal = 0;
3974 break;
3975 }
3976 }
3977 if (last_terminal)
3978 error ("Attempt to delete the sole terminal device with live frames");
3979
3980 if (tty == tty_list)
3981 tty_list = tty->next;
3982 else
3983 {
3984 struct tty_display_info *p;
3985 for (p = tty_list; p && p->next != tty; p = p->next)
3986 ;
3987
3988 if (! p)
3989 /* This should not happen. */
3990 abort ();
3991
3992 p->next = tty->next;
3993 tty->next = 0;
3994 }
3995
3996 /* reset_sys_modes needs a valid device, so this call needs to be
3997 before delete_terminal. */
3998 reset_sys_modes (tty);
3999
4000 delete_terminal (terminal);
4001
4002 xfree (tty->name);
4003 xfree (tty->type);
4004
4005 if (tty->input)
4006 {
4007 #ifdef subprocesses
4008 delete_keyboard_wait_descriptor (fileno (tty->input));
4009 #endif
4010 if (tty->input != stdin)
4011 fclose (tty->input);
4012 }
4013 if (tty->output && tty->output != stdout && tty->output != tty->input)
4014 fclose (tty->output);
4015 if (tty->termscript)
4016 fclose (tty->termscript);
4017
4018 xfree (tty->old_tty);
4019 xfree (tty->Wcm);
4020 xfree (tty->termcap_strings_buffer);
4021 xfree (tty->termcap_term_buffer);
4022
4023 bzero (tty, sizeof (struct tty_display_info));
4024 xfree (tty);
4025 }
4026
4027 \f
4028
4029 /* Mark the pointers in the tty_display_info objects.
4030 Called by the Fgarbage_collector. */
4031
4032 void
4033 mark_ttys (void)
4034 {
4035 struct tty_display_info *tty;
4036
4037 for (tty = tty_list; tty; tty = tty->next)
4038 mark_object (tty->top_frame);
4039 }
4040
4041 \f
4042
4043 void
4044 syms_of_term ()
4045 {
4046 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
4047 doc: /* Non-nil means the system uses terminfo rather than termcap.
4048 This variable can be used by terminal emulator packages. */);
4049 #ifdef TERMINFO
4050 system_uses_terminfo = 1;
4051 #else
4052 system_uses_terminfo = 0;
4053 #endif
4054
4055 DEFVAR_LISP ("suspend-tty-functions", &Vsuspend_tty_functions,
4056 doc: /* Functions to be run after suspending a tty.
4057 The functions are run with one argument, the terminal object to be suspended.
4058 See `suspend-tty'. */);
4059 Vsuspend_tty_functions = Qnil;
4060
4061
4062 DEFVAR_LISP ("resume-tty-functions", &Vresume_tty_functions,
4063 doc: /* Functions to be run after resuming a tty.
4064 The functions are run with one argument, the terminal object that was revived.
4065 See `resume-tty'. */);
4066 Vresume_tty_functions = Qnil;
4067
4068 DEFVAR_BOOL ("visible-cursor", &visible_cursor,
4069 doc: /* Non-nil means to make the cursor very visible.
4070 This only has an effect when running in a text terminal.
4071 What means \"very visible\" is up to your terminal. It may make the cursor
4072 bigger, or it may make it blink, or it may do nothing at all. */);
4073 visible_cursor = 1;
4074
4075 defsubr (&Stty_display_color_p);
4076 defsubr (&Stty_display_color_cells);
4077 defsubr (&Stty_no_underline);
4078 defsubr (&Stty_type);
4079 defsubr (&Scontrolling_tty_p);
4080 defsubr (&Ssuspend_tty);
4081 defsubr (&Sresume_tty);
4082 #ifdef HAVE_GPM
4083 defsubr (&Sgpm_mouse_start);
4084 defsubr (&Sgpm_mouse_stop);
4085
4086 staticpro (&mouse_face_window);
4087 #endif /* HAVE_GPM */
4088
4089 #ifndef DOS_NT
4090 default_orig_pair = NULL;
4091 default_set_foreground = NULL;
4092 default_set_background = NULL;
4093 #endif /* !DOS_NT */
4094
4095 encode_terminal_src = NULL;
4096 encode_terminal_dst = NULL;
4097 }
4098
4099
4100
4101 /* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193
4102 (do not change this comment) */