]> code.delx.au - gnu-emacs/blob - src/term.c
Fix last set of Nextstep changes.
[gnu-emacs] / 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, 2010
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. For an overview, see
1572 the explanation in dispextern.h, before the definition of the
1573 display_element_type enumeration.
1574
1575 produce_glyphs also stores the result of glyph width, ascent
1576 etc. computations in *IT.
1577
1578 IT->glyph_row may be null, in which case produce_glyphs does not
1579 actually fill in the glyphs. This is used in the move_* functions
1580 in xdisp.c for text width and height computations.
1581
1582 Callers usually don't call produce_glyphs directly;
1583 instead they use the macro PRODUCE_GLYPHS. */
1584
1585 void
1586 produce_glyphs (it)
1587 struct it *it;
1588 {
1589 /* If a hook is installed, let it do the work. */
1590
1591 /* Nothing but characters are supported on terminal frames. */
1592 xassert (it->what == IT_CHARACTER
1593 || it->what == IT_COMPOSITION
1594 || it->what == IT_STRETCH);
1595
1596 if (it->what == IT_STRETCH)
1597 {
1598 produce_stretch_glyph (it);
1599 goto done;
1600 }
1601
1602 if (it->what == IT_COMPOSITION)
1603 {
1604 produce_composite_glyph (it);
1605 goto done;
1606 }
1607
1608 /* Maybe translate single-byte characters to multibyte. */
1609 it->char_to_display = it->c;
1610
1611 if (it->c >= 040 && it->c < 0177)
1612 {
1613 it->pixel_width = it->nglyphs = 1;
1614 if (it->glyph_row)
1615 append_glyph (it);
1616 }
1617 else if (it->c == '\n')
1618 it->pixel_width = it->nglyphs = 0;
1619 else if (it->c == '\t')
1620 {
1621 int absolute_x = (it->current_x
1622 + it->continuation_lines_width);
1623 int next_tab_x
1624 = (((1 + absolute_x + it->tab_width - 1)
1625 / it->tab_width)
1626 * it->tab_width);
1627 int nspaces;
1628
1629 /* If part of the TAB has been displayed on the previous line
1630 which is continued now, continuation_lines_width will have
1631 been incremented already by the part that fitted on the
1632 continued line. So, we will get the right number of spaces
1633 here. */
1634 nspaces = next_tab_x - absolute_x;
1635
1636 if (it->glyph_row)
1637 {
1638 int n = nspaces;
1639
1640 it->char_to_display = ' ';
1641 it->pixel_width = it->len = 1;
1642
1643 while (n--)
1644 append_glyph (it);
1645 }
1646
1647 it->pixel_width = nspaces;
1648 it->nglyphs = nspaces;
1649 }
1650 else if (CHAR_BYTE8_P (it->c))
1651 {
1652 if (unibyte_display_via_language_environment
1653 && (it->c >= 0240))
1654 {
1655 it->char_to_display = BYTE8_TO_CHAR (it->c);
1656 it->pixel_width = CHAR_WIDTH (it->char_to_display);
1657 it->nglyphs = it->pixel_width;
1658 if (it->glyph_row)
1659 append_glyph (it);
1660 }
1661 else
1662 {
1663 /* Coming here means that it->c is from display table, thus
1664 we must send the raw 8-bit byte as is to the terminal.
1665 Although there's no way to know how many columns it
1666 occupies on a screen, it is a good assumption that a
1667 single byte code has 1-column width. */
1668 it->pixel_width = it->nglyphs = 1;
1669 if (it->glyph_row)
1670 append_glyph (it);
1671 }
1672 }
1673 else
1674 {
1675 it->pixel_width = CHAR_WIDTH (it->c);
1676 it->nglyphs = it->pixel_width;
1677
1678 if (it->glyph_row)
1679 append_glyph (it);
1680 }
1681
1682 done:
1683 /* Advance current_x by the pixel width as a convenience for
1684 the caller. */
1685 if (it->area == TEXT_AREA)
1686 it->current_x += it->pixel_width;
1687 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1688 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
1689 }
1690
1691
1692 /* Produce a stretch glyph for iterator IT. IT->object is the value
1693 of the glyph property displayed. The value must be a list
1694 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1695 being recognized:
1696
1697 1. `:width WIDTH' specifies that the space should be WIDTH *
1698 canonical char width wide. WIDTH may be an integer or floating
1699 point number.
1700
1701 2. `:align-to HPOS' specifies that the space should be wide enough
1702 to reach HPOS, a value in canonical character units. */
1703
1704 static void
1705 produce_stretch_glyph (it)
1706 struct it *it;
1707 {
1708 /* (space :width WIDTH ...) */
1709 Lisp_Object prop, plist;
1710 int width = 0, align_to = -1;
1711 int zero_width_ok_p = 0;
1712 double tem;
1713
1714 /* List should start with `space'. */
1715 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1716 plist = XCDR (it->object);
1717
1718 /* Compute the width of the stretch. */
1719 if ((prop = Fplist_get (plist, QCwidth), !NILP (prop))
1720 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, 0))
1721 {
1722 /* Absolute width `:width WIDTH' specified and valid. */
1723 zero_width_ok_p = 1;
1724 width = (int)(tem + 0.5);
1725 }
1726 else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
1727 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, &align_to))
1728 {
1729 if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
1730 align_to = (align_to < 0
1731 ? 0
1732 : align_to - window_box_left_offset (it->w, TEXT_AREA));
1733 else if (align_to < 0)
1734 align_to = window_box_left_offset (it->w, TEXT_AREA);
1735 width = max (0, (int)(tem + 0.5) + align_to - it->current_x);
1736 zero_width_ok_p = 1;
1737 }
1738 else
1739 /* Nothing specified -> width defaults to canonical char width. */
1740 width = FRAME_COLUMN_WIDTH (it->f);
1741
1742 if (width <= 0 && (width < 0 || !zero_width_ok_p))
1743 width = 1;
1744
1745 if (width > 0 && it->line_wrap != TRUNCATE
1746 && it->current_x + width > it->last_visible_x)
1747 width = it->last_visible_x - it->current_x - 1;
1748
1749 if (width > 0 && it->glyph_row)
1750 {
1751 Lisp_Object o_object = it->object;
1752 Lisp_Object object = it->stack[it->sp - 1].string;
1753 int n = width;
1754
1755 if (!STRINGP (object))
1756 object = it->w->buffer;
1757 it->object = object;
1758 it->char_to_display = ' ';
1759 it->pixel_width = it->len = 1;
1760 while (n--)
1761 append_glyph (it);
1762 it->object = o_object;
1763 }
1764 it->pixel_width = width;
1765 it->nglyphs = width;
1766 }
1767
1768
1769 /* Append glyphs to IT's glyph_row for the composition IT->cmp_id.
1770 Called from produce_composite_glyph for terminal frames if
1771 IT->glyph_row != NULL. IT->face_id contains the character's
1772 face. */
1773
1774 static void
1775 append_composite_glyph (it)
1776 struct it *it;
1777 {
1778 struct glyph *glyph;
1779
1780 xassert (it->glyph_row);
1781 glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
1782 if (glyph < it->glyph_row->glyphs[1 + it->area])
1783 {
1784 glyph->type = COMPOSITE_GLYPH;
1785 glyph->pixel_width = it->pixel_width;
1786 glyph->u.cmp.id = it->cmp_it.id;
1787 if (it->cmp_it.ch < 0)
1788 {
1789 glyph->u.cmp.automatic = 0;
1790 glyph->u.cmp.id = it->cmp_it.id;
1791 }
1792 else
1793 {
1794 glyph->u.cmp.automatic = 1;
1795 glyph->u.cmp.id = it->cmp_it.id;
1796 glyph->u.cmp.from = it->cmp_it.from;
1797 glyph->u.cmp.to = it->cmp_it.to - 1;
1798 }
1799
1800 glyph->face_id = it->face_id;
1801 glyph->padding_p = 0;
1802 glyph->charpos = CHARPOS (it->position);
1803 glyph->object = it->object;
1804
1805 ++it->glyph_row->used[it->area];
1806 ++glyph;
1807 }
1808 }
1809
1810
1811 /* Produce a composite glyph for iterator IT. IT->cmp_id is the ID of
1812 the composition. We simply produces components of the composition
1813 assuming that the terminal has a capability to layout/render it
1814 correctly. */
1815
1816 static void
1817 produce_composite_glyph (it)
1818 struct it *it;
1819 {
1820 int c;
1821
1822 if (it->cmp_it.ch < 0)
1823 {
1824 struct composition *cmp = composition_table[it->cmp_it.id];
1825
1826 it->pixel_width = cmp->width;
1827 }
1828 else
1829 {
1830 Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id);
1831
1832 it->pixel_width = composition_gstring_width (gstring, it->cmp_it.from,
1833 it->cmp_it.to, NULL);
1834 }
1835 it->nglyphs = 1;
1836 if (it->glyph_row)
1837 append_composite_glyph (it);
1838 }
1839
1840
1841 /* Get information about special display element WHAT in an
1842 environment described by IT. WHAT is one of IT_TRUNCATION or
1843 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1844 non-null glyph_row member. This function ensures that fields like
1845 face_id, c, len of IT are left untouched. */
1846
1847 void
1848 produce_special_glyphs (it, what)
1849 struct it *it;
1850 enum display_element_type what;
1851 {
1852 struct it temp_it;
1853 Lisp_Object gc;
1854 GLYPH glyph;
1855
1856 temp_it = *it;
1857 temp_it.dp = NULL;
1858 temp_it.what = IT_CHARACTER;
1859 temp_it.len = 1;
1860 temp_it.object = make_number (0);
1861 bzero (&temp_it.current, sizeof temp_it.current);
1862
1863 if (what == IT_CONTINUATION)
1864 {
1865 /* Continuation glyph. */
1866 SET_GLYPH_FROM_CHAR (glyph, '\\');
1867 if (it->dp
1868 && (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc))
1869 && GLYPH_CODE_CHAR_VALID_P (gc))
1870 {
1871 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
1872 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
1873 }
1874 }
1875 else if (what == IT_TRUNCATION)
1876 {
1877 /* Truncation glyph. */
1878 SET_GLYPH_FROM_CHAR (glyph, '$');
1879 if (it->dp
1880 && (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc))
1881 && GLYPH_CODE_CHAR_VALID_P (gc))
1882 {
1883 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
1884 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
1885 }
1886 }
1887 else
1888 abort ();
1889
1890 temp_it.c = GLYPH_CHAR (glyph);
1891 temp_it.face_id = GLYPH_FACE (glyph);
1892 temp_it.len = CHAR_BYTES (temp_it.c);
1893
1894 produce_glyphs (&temp_it);
1895 it->pixel_width = temp_it.pixel_width;
1896 it->nglyphs = temp_it.pixel_width;
1897 }
1898
1899
1900 \f
1901 /***********************************************************************
1902 Faces
1903 ***********************************************************************/
1904
1905 /* Value is non-zero if attribute ATTR may be used. ATTR should be
1906 one of the enumerators from enum no_color_bit, or a bit set built
1907 from them. Some display attributes may not be used together with
1908 color; the termcap capability `NC' specifies which ones. */
1909
1910 #define MAY_USE_WITH_COLORS_P(tty, ATTR) \
1911 (tty->TN_max_colors > 0 \
1912 ? (tty->TN_no_color_video & (ATTR)) == 0 \
1913 : 1)
1914
1915 /* Turn appearances of face FACE_ID on tty frame F on.
1916 FACE_ID is a realized face ID number, in the face cache. */
1917
1918 static void
1919 turn_on_face (f, face_id)
1920 struct frame *f;
1921 int face_id;
1922 {
1923 struct face *face = FACE_FROM_ID (f, face_id);
1924 long fg = face->foreground;
1925 long bg = face->background;
1926 struct tty_display_info *tty = FRAME_TTY (f);
1927
1928 /* Do this first because TS_end_standout_mode may be the same
1929 as TS_exit_attribute_mode, which turns all appearances off. */
1930 if (MAY_USE_WITH_COLORS_P (tty, NC_REVERSE))
1931 {
1932 if (tty->TN_max_colors > 0)
1933 {
1934 if (fg >= 0 && bg >= 0)
1935 {
1936 /* If the terminal supports colors, we can set them
1937 below without using reverse video. The face's fg
1938 and bg colors are set as they should appear on
1939 the screen, i.e. they take the inverse-video'ness
1940 of the face already into account. */
1941 }
1942 else if (inverse_video)
1943 {
1944 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1945 || bg == FACE_TTY_DEFAULT_BG_COLOR)
1946 tty_toggle_highlight (tty);
1947 }
1948 else
1949 {
1950 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1951 || bg == FACE_TTY_DEFAULT_FG_COLOR)
1952 tty_toggle_highlight (tty);
1953 }
1954 }
1955 else
1956 {
1957 /* If we can't display colors, use reverse video
1958 if the face specifies that. */
1959 if (inverse_video)
1960 {
1961 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1962 || bg == FACE_TTY_DEFAULT_BG_COLOR)
1963 tty_toggle_highlight (tty);
1964 }
1965 else
1966 {
1967 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1968 || bg == FACE_TTY_DEFAULT_FG_COLOR)
1969 tty_toggle_highlight (tty);
1970 }
1971 }
1972 }
1973
1974 if (face->tty_bold_p && MAY_USE_WITH_COLORS_P (tty, NC_BOLD))
1975 OUTPUT1_IF (tty, tty->TS_enter_bold_mode);
1976
1977 if (face->tty_dim_p && MAY_USE_WITH_COLORS_P (tty, NC_DIM))
1978 OUTPUT1_IF (tty, tty->TS_enter_dim_mode);
1979
1980 /* Alternate charset and blinking not yet used. */
1981 if (face->tty_alt_charset_p
1982 && MAY_USE_WITH_COLORS_P (tty, NC_ALT_CHARSET))
1983 OUTPUT1_IF (tty, tty->TS_enter_alt_charset_mode);
1984
1985 if (face->tty_blinking_p
1986 && MAY_USE_WITH_COLORS_P (tty, NC_BLINK))
1987 OUTPUT1_IF (tty, tty->TS_enter_blink_mode);
1988
1989 if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (tty, NC_UNDERLINE))
1990 OUTPUT1_IF (tty, tty->TS_enter_underline_mode);
1991
1992 if (tty->TN_max_colors > 0)
1993 {
1994 char *ts, *p;
1995
1996 ts = tty->standout_mode ? tty->TS_set_background : tty->TS_set_foreground;
1997 if (fg >= 0 && ts)
1998 {
1999 p = tparam (ts, NULL, 0, (int) fg);
2000 OUTPUT (tty, p);
2001 xfree (p);
2002 }
2003
2004 ts = tty->standout_mode ? tty->TS_set_foreground : tty->TS_set_background;
2005 if (bg >= 0 && ts)
2006 {
2007 p = tparam (ts, NULL, 0, (int) bg);
2008 OUTPUT (tty, p);
2009 xfree (p);
2010 }
2011 }
2012 }
2013
2014
2015 /* Turn off appearances of face FACE_ID on tty frame F. */
2016
2017 static void
2018 turn_off_face (f, face_id)
2019 struct frame *f;
2020 int face_id;
2021 {
2022 struct face *face = FACE_FROM_ID (f, face_id);
2023 struct tty_display_info *tty = FRAME_TTY (f);
2024
2025 xassert (face != NULL);
2026
2027 if (tty->TS_exit_attribute_mode)
2028 {
2029 /* Capability "me" will turn off appearance modes double-bright,
2030 half-bright, reverse-video, standout, underline. It may or
2031 may not turn off alt-char-mode. */
2032 if (face->tty_bold_p
2033 || face->tty_dim_p
2034 || face->tty_reverse_p
2035 || face->tty_alt_charset_p
2036 || face->tty_blinking_p
2037 || face->tty_underline_p)
2038 {
2039 OUTPUT1_IF (tty, tty->TS_exit_attribute_mode);
2040 if (strcmp (tty->TS_exit_attribute_mode, tty->TS_end_standout_mode) == 0)
2041 tty->standout_mode = 0;
2042 }
2043
2044 if (face->tty_alt_charset_p)
2045 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
2046 }
2047 else
2048 {
2049 /* If we don't have "me" we can only have those appearances
2050 that have exit sequences defined. */
2051 if (face->tty_alt_charset_p)
2052 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
2053
2054 if (face->tty_underline_p)
2055 OUTPUT_IF (tty, tty->TS_exit_underline_mode);
2056 }
2057
2058 /* Switch back to default colors. */
2059 if (tty->TN_max_colors > 0
2060 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
2061 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
2062 || (face->background != FACE_TTY_DEFAULT_COLOR
2063 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
2064 OUTPUT1_IF (tty, tty->TS_orig_pair);
2065 }
2066
2067
2068 /* Return non-zero if the terminal on frame F supports all of the
2069 capabilities in CAPS simultaneously, with foreground and background
2070 colors FG and BG. */
2071
2072 int
2073 tty_capable_p (tty, caps, fg, bg)
2074 struct tty_display_info *tty;
2075 unsigned caps;
2076 unsigned long fg, bg;
2077 {
2078 #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
2079 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
2080 return 0;
2081
2082 TTY_CAPABLE_P_TRY (tty, TTY_CAP_INVERSE, tty->TS_standout_mode, NC_REVERSE);
2083 TTY_CAPABLE_P_TRY (tty, TTY_CAP_UNDERLINE, tty->TS_enter_underline_mode, NC_UNDERLINE);
2084 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BOLD, tty->TS_enter_bold_mode, NC_BOLD);
2085 TTY_CAPABLE_P_TRY (tty, TTY_CAP_DIM, tty->TS_enter_dim_mode, NC_DIM);
2086 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BLINK, tty->TS_enter_blink_mode, NC_BLINK);
2087 TTY_CAPABLE_P_TRY (tty, TTY_CAP_ALT_CHARSET, tty->TS_enter_alt_charset_mode, NC_ALT_CHARSET);
2088
2089 /* We can do it! */
2090 return 1;
2091 }
2092
2093 /* Return non-zero if the terminal is capable to display colors. */
2094
2095 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
2096 0, 1, 0,
2097 doc: /* Return non-nil if the tty device TERMINAL can display colors.
2098
2099 TERMINAL can be a terminal object, a frame, or nil (meaning the
2100 selected frame's terminal). This function always returns nil if
2101 TERMINAL does not refer to a text-only terminal. */)
2102 (terminal)
2103 Lisp_Object terminal;
2104 {
2105 struct terminal *t = get_tty_terminal (terminal, 0);
2106 if (!t)
2107 return Qnil;
2108 else
2109 return t->display_info.tty->TN_max_colors > 0 ? Qt : Qnil;
2110 }
2111
2112 /* Return the number of supported colors. */
2113 DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
2114 Stty_display_color_cells, 0, 1, 0,
2115 doc: /* Return the number of colors supported by the tty device TERMINAL.
2116
2117 TERMINAL can be a terminal object, a frame, or nil (meaning the
2118 selected frame's terminal). This function always returns 0 if
2119 TERMINAL does not refer to a text-only terminal. */)
2120 (terminal)
2121 Lisp_Object terminal;
2122 {
2123 struct terminal *t = get_tty_terminal (terminal, 0);
2124 if (!t)
2125 return make_number (0);
2126 else
2127 return make_number (t->display_info.tty->TN_max_colors);
2128 }
2129
2130 #ifndef DOS_NT
2131
2132 /* Declare here rather than in the function, as in the rest of Emacs,
2133 to work around an HPUX compiler bug (?). See
2134 http://lists.gnu.org/archive/html/emacs-devel/2007-08/msg00410.html */
2135 static int default_max_colors;
2136 static int default_max_pairs;
2137 static int default_no_color_video;
2138 static char *default_orig_pair;
2139 static char *default_set_foreground;
2140 static char *default_set_background;
2141
2142 /* Save or restore the default color-related capabilities of this
2143 terminal. */
2144 static void
2145 tty_default_color_capabilities (struct tty_display_info *tty, int save)
2146 {
2147
2148 if (save)
2149 {
2150 xfree (default_orig_pair);
2151 default_orig_pair = tty->TS_orig_pair ? xstrdup (tty->TS_orig_pair) : NULL;
2152
2153 xfree (default_set_foreground);
2154 default_set_foreground = tty->TS_set_foreground ? xstrdup (tty->TS_set_foreground)
2155 : NULL;
2156
2157 xfree (default_set_background);
2158 default_set_background = tty->TS_set_background ? xstrdup (tty->TS_set_background)
2159 : NULL;
2160
2161 default_max_colors = tty->TN_max_colors;
2162 default_max_pairs = tty->TN_max_pairs;
2163 default_no_color_video = tty->TN_no_color_video;
2164 }
2165 else
2166 {
2167 tty->TS_orig_pair = default_orig_pair;
2168 tty->TS_set_foreground = default_set_foreground;
2169 tty->TS_set_background = default_set_background;
2170 tty->TN_max_colors = default_max_colors;
2171 tty->TN_max_pairs = default_max_pairs;
2172 tty->TN_no_color_video = default_no_color_video;
2173 }
2174 }
2175
2176 /* Setup one of the standard tty color schemes according to MODE.
2177 MODE's value is generally the number of colors which we want to
2178 support; zero means set up for the default capabilities, the ones
2179 we saw at init_tty time; -1 means turn off color support. */
2180 static void
2181 tty_setup_colors (struct tty_display_info *tty, int mode)
2182 {
2183 /* Canonicalize all negative values of MODE. */
2184 if (mode < -1)
2185 mode = -1;
2186
2187 switch (mode)
2188 {
2189 case -1: /* no colors at all */
2190 tty->TN_max_colors = 0;
2191 tty->TN_max_pairs = 0;
2192 tty->TN_no_color_video = 0;
2193 tty->TS_set_foreground = tty->TS_set_background = tty->TS_orig_pair = NULL;
2194 break;
2195 case 0: /* default colors, if any */
2196 default:
2197 tty_default_color_capabilities (tty, 0);
2198 break;
2199 case 8: /* 8 standard ANSI colors */
2200 tty->TS_orig_pair = "\033[0m";
2201 #ifdef TERMINFO
2202 tty->TS_set_foreground = "\033[3%p1%dm";
2203 tty->TS_set_background = "\033[4%p1%dm";
2204 #else
2205 tty->TS_set_foreground = "\033[3%dm";
2206 tty->TS_set_background = "\033[4%dm";
2207 #endif
2208 tty->TN_max_colors = 8;
2209 tty->TN_max_pairs = 64;
2210 tty->TN_no_color_video = 0;
2211 break;
2212 }
2213 }
2214
2215 void
2216 set_tty_color_mode (tty, f)
2217 struct tty_display_info *tty;
2218 struct frame *f;
2219 {
2220 Lisp_Object tem, val, color_mode_spec;
2221 Lisp_Object color_mode;
2222 int mode;
2223 extern Lisp_Object Qtty_color_mode;
2224 Lisp_Object tty_color_mode_alist
2225 = Fintern_soft (build_string ("tty-color-mode-alist"), Qnil);
2226
2227 tem = assq_no_quit (Qtty_color_mode, f->param_alist);
2228 val = CONSP (tem) ? XCDR (tem) : Qnil;
2229
2230 if (INTEGERP (val))
2231 color_mode = val;
2232 else
2233 {
2234 tem = (NILP (tty_color_mode_alist) ? Qnil
2235 : Fassq (val, XSYMBOL (tty_color_mode_alist)->value));
2236 color_mode = CONSP (tem) ? XCDR (tem) : Qnil;
2237 }
2238
2239 mode = INTEGERP (color_mode) ? XINT (color_mode) : 0;
2240
2241 if (mode != tty->previous_color_mode)
2242 {
2243 Lisp_Object funsym = intern ("tty-set-up-initial-frame-faces");
2244 tty->previous_color_mode = mode;
2245 tty_setup_colors (tty , mode);
2246 /* This recomputes all the faces given the new color definitions. */
2247 safe_call (1, &funsym);
2248 }
2249 }
2250
2251 #endif /* !DOS_NT */
2252
2253 \f
2254
2255 /* Return the tty display object specified by TERMINAL. */
2256
2257 struct terminal *
2258 get_tty_terminal (Lisp_Object terminal, int throw)
2259 {
2260 struct terminal *t = get_terminal (terminal, throw);
2261
2262 if (t && t->type != output_termcap && t->type != output_msdos_raw)
2263 {
2264 if (throw)
2265 error ("Device %d is not a termcap terminal device", t->id);
2266 else
2267 return NULL;
2268 }
2269
2270 return t;
2271 }
2272
2273 /* Return an active termcap device that uses the tty device with the
2274 given name.
2275
2276 This function ignores suspended devices.
2277
2278 Returns NULL if the named terminal device is not opened. */
2279
2280 struct terminal *
2281 get_named_tty (name)
2282 char *name;
2283 {
2284 struct terminal *t;
2285
2286 if (!name)
2287 abort ();
2288
2289 for (t = terminal_list; t; t = t->next_terminal)
2290 {
2291 if ((t->type == output_termcap || t->type == output_msdos_raw)
2292 && !strcmp (t->display_info.tty->name, name)
2293 && TERMINAL_ACTIVE_P (t))
2294 return t;
2295 }
2296
2297 return 0;
2298 }
2299
2300 \f
2301 DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0,
2302 doc: /* Return the type of the tty device that TERMINAL uses.
2303 Returns nil if TERMINAL is not on a tty device.
2304
2305 TERMINAL can be a terminal object, a frame, or nil (meaning the
2306 selected frame's terminal). */)
2307 (terminal)
2308 Lisp_Object terminal;
2309 {
2310 struct terminal *t = get_terminal (terminal, 1);
2311
2312 if (t->type != output_termcap && t->type != output_msdos_raw)
2313 return Qnil;
2314
2315 if (t->display_info.tty->type)
2316 return build_string (t->display_info.tty->type);
2317 else
2318 return Qnil;
2319 }
2320
2321 DEFUN ("controlling-tty-p", Fcontrolling_tty_p, Scontrolling_tty_p, 0, 1, 0,
2322 doc: /* Return non-nil if TERMINAL is the controlling tty of the Emacs process.
2323
2324 TERMINAL can be a terminal object, a frame, or nil (meaning the
2325 selected frame's terminal). This function always returns nil if
2326 TERMINAL is not on a tty device. */)
2327 (terminal)
2328 Lisp_Object terminal;
2329 {
2330 struct terminal *t = get_terminal (terminal, 1);
2331
2332 if ((t->type != output_termcap && t->type != output_msdos_raw)
2333 || strcmp (t->display_info.tty->name, DEV_TTY) != 0)
2334 return Qnil;
2335 else
2336 return Qt;
2337 }
2338
2339 DEFUN ("tty-no-underline", Ftty_no_underline, Stty_no_underline, 0, 1, 0,
2340 doc: /* Declare that the tty used by TERMINAL does not handle underlining.
2341 This is used to override the terminfo data, for certain terminals that
2342 do not really do underlining, but say that they do. This function has
2343 no effect if used on a non-tty terminal.
2344
2345 TERMINAL can be a terminal object, a frame or nil (meaning the
2346 selected frame's terminal). This function always returns nil if
2347 TERMINAL does not refer to a text-only terminal. */)
2348 (terminal)
2349 Lisp_Object terminal;
2350 {
2351 struct terminal *t = get_terminal (terminal, 1);
2352
2353 if (t->type == output_termcap)
2354 t->display_info.tty->TS_enter_underline_mode = 0;
2355 return Qnil;
2356 }
2357
2358 \f
2359
2360 DEFUN ("suspend-tty", Fsuspend_tty, Ssuspend_tty, 0, 1, 0,
2361 doc: /* Suspend the terminal device TTY.
2362
2363 The device is restored to its default state, and Emacs ceases all
2364 access to the tty device. Frames that use the device are not deleted,
2365 but input is not read from them and if they change, their display is
2366 not updated.
2367
2368 TTY may be a terminal object, a frame, or nil for the terminal device
2369 of the currently selected frame.
2370
2371 This function runs `suspend-tty-functions' after suspending the
2372 device. The functions are run with one arg, the id of the suspended
2373 terminal device.
2374
2375 `suspend-tty' does nothing if it is called on a device that is already
2376 suspended.
2377
2378 A suspended tty may be resumed by calling `resume-tty' on it. */)
2379 (tty)
2380 Lisp_Object tty;
2381 {
2382 struct terminal *t = get_tty_terminal (tty, 1);
2383 FILE *f;
2384
2385 if (!t)
2386 error ("Unknown tty device");
2387
2388 f = t->display_info.tty->input;
2389
2390 if (f)
2391 {
2392 /* First run `suspend-tty-functions' and then clean up the tty
2393 state because `suspend-tty-functions' might need to change
2394 the tty state. */
2395 if (!NILP (Vrun_hooks))
2396 {
2397 Lisp_Object args[2];
2398 args[0] = intern ("suspend-tty-functions");
2399 XSETTERMINAL (args[1], t);
2400 Frun_hook_with_args (2, args);
2401 }
2402
2403 reset_sys_modes (t->display_info.tty);
2404
2405 #ifdef subprocesses
2406 delete_keyboard_wait_descriptor (fileno (f));
2407 #endif
2408
2409 #ifndef MSDOS
2410 fclose (f);
2411 if (f != t->display_info.tty->output)
2412 fclose (t->display_info.tty->output);
2413 #endif
2414
2415 t->display_info.tty->input = 0;
2416 t->display_info.tty->output = 0;
2417
2418 if (FRAMEP (t->display_info.tty->top_frame))
2419 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0);
2420
2421 }
2422
2423 /* Clear display hooks to prevent further output. */
2424 clear_tty_hooks (t);
2425
2426 return Qnil;
2427 }
2428
2429 DEFUN ("resume-tty", Fresume_tty, Sresume_tty, 0, 1, 0,
2430 doc: /* Resume the previously suspended terminal device TTY.
2431 The terminal is opened and reinitialized. Frames that are on the
2432 suspended terminal are revived.
2433
2434 It is an error to resume a terminal while another terminal is active
2435 on the same device.
2436
2437 This function runs `resume-tty-functions' after resuming the terminal.
2438 The functions are run with one arg, the id of the resumed terminal
2439 device.
2440
2441 `resume-tty' does nothing if it is called on a device that is not
2442 suspended.
2443
2444 TTY may be a terminal object, a frame, or nil (meaning the selected
2445 frame's terminal). */)
2446 (tty)
2447 Lisp_Object tty;
2448 {
2449 struct terminal *t = get_tty_terminal (tty, 1);
2450 int fd;
2451
2452 if (!t)
2453 error ("Unknown tty device");
2454
2455 if (!t->display_info.tty->input)
2456 {
2457 if (get_named_tty (t->display_info.tty->name))
2458 error ("Cannot resume display while another display is active on the same device");
2459
2460 #ifdef MSDOS
2461 t->display_info.tty->output = stdout;
2462 t->display_info.tty->input = stdin;
2463 #else /* !MSDOS */
2464 fd = emacs_open (t->display_info.tty->name, O_RDWR | O_NOCTTY, 0);
2465
2466 if (fd == -1)
2467 error ("Can not reopen tty device %s: %s", t->display_info.tty->name, strerror (errno));
2468
2469 if (strcmp (t->display_info.tty->name, DEV_TTY))
2470 dissociate_if_controlling_tty (fd);
2471
2472 t->display_info.tty->output = fdopen (fd, "w+");
2473 t->display_info.tty->input = t->display_info.tty->output;
2474 #endif
2475
2476 #ifdef subprocesses
2477 add_keyboard_wait_descriptor (fd);
2478 #endif
2479
2480 if (FRAMEP (t->display_info.tty->top_frame))
2481 {
2482 struct frame *f = XFRAME (t->display_info.tty->top_frame);
2483 int width, height;
2484 int old_height = FRAME_COLS (f);
2485 int old_width = FRAME_LINES (f);
2486
2487 /* Check if terminal/window size has changed while the frame
2488 was suspended. */
2489 get_tty_size (fileno (t->display_info.tty->input), &width, &height);
2490 if (width != old_width || height != old_height)
2491 change_frame_size (f, height, width, 0, 0, 0);
2492 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
2493 }
2494
2495 init_sys_modes (t->display_info.tty);
2496
2497 /* Run `resume-tty-functions'. */
2498 if (!NILP (Vrun_hooks))
2499 {
2500 Lisp_Object args[2];
2501 args[0] = intern ("resume-tty-functions");
2502 XSETTERMINAL (args[1], t);
2503 Frun_hook_with_args (2, args);
2504 }
2505 }
2506
2507 set_tty_hooks (t);
2508
2509 return Qnil;
2510 }
2511
2512 \f
2513 /***********************************************************************
2514 Mouse
2515 ***********************************************************************/
2516
2517 #ifdef HAVE_GPM
2518 void
2519 term_mouse_moveto (int x, int y)
2520 {
2521 /* TODO: how to set mouse position?
2522 const char *name;
2523 int fd;
2524 name = (const char *) ttyname (0);
2525 fd = open (name, O_WRONLY);
2526 SOME_FUNCTION (x, y, fd);
2527 close (fd);
2528 last_mouse_x = x;
2529 last_mouse_y = y; */
2530 }
2531
2532 static void
2533 term_show_mouse_face (enum draw_glyphs_face draw)
2534 {
2535 struct window *w = XWINDOW (mouse_face_window);
2536 int save_x, save_y;
2537 int i;
2538
2539 struct frame *f = XFRAME (w->frame);
2540 struct tty_display_info *tty = FRAME_TTY (f);
2541
2542 if (/* If window is in the process of being destroyed, don't bother
2543 to do anything. */
2544 w->current_matrix != NULL
2545 /* Recognize when we are called to operate on rows that don't exist
2546 anymore. This can happen when a window is split. */
2547 && mouse_face_end_row < w->current_matrix->nrows)
2548 {
2549 /* write_glyphs writes at cursor position, so we need to
2550 temporarily move cursor coordinates to the beginning of
2551 the highlight region. */
2552
2553 /* Save current cursor co-ordinates */
2554 save_y = curY (tty);
2555 save_x = curX (tty);
2556
2557 /* Note that mouse_face_beg_row etc. are window relative. */
2558 for (i = mouse_face_beg_row; i <= mouse_face_end_row; i++)
2559 {
2560 int start_hpos, end_hpos, nglyphs;
2561 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
2562
2563 /* Don't do anything if row doesn't have valid contents. */
2564 if (!row->enabled_p)
2565 continue;
2566
2567 /* For all but the first row, the highlight starts at column 0. */
2568 if (i == mouse_face_beg_row)
2569 start_hpos = mouse_face_beg_col;
2570 else
2571 start_hpos = 0;
2572
2573 if (i == mouse_face_end_row)
2574 end_hpos = mouse_face_end_col;
2575 else
2576 {
2577 end_hpos = row->used[TEXT_AREA];
2578 if (draw == DRAW_NORMAL_TEXT)
2579 row->fill_line_p = 1; /* Clear to end of line */
2580 }
2581
2582 if (end_hpos <= start_hpos)
2583 continue;
2584 /* Record that some glyphs of this row are displayed in
2585 mouse-face. */
2586 row->mouse_face_p = draw > 0;
2587
2588 nglyphs = end_hpos - start_hpos;
2589
2590 if (end_hpos >= row->used[TEXT_AREA])
2591 nglyphs = row->used[TEXT_AREA] - start_hpos;
2592
2593 pos_y = row->y + WINDOW_TOP_EDGE_Y (w);
2594 pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos
2595 + WINDOW_LEFT_EDGE_X (w);
2596
2597 cursor_to (f, pos_y, pos_x);
2598
2599 if (draw == DRAW_MOUSE_FACE)
2600 {
2601 tty_write_glyphs_with_face (f, row->glyphs[TEXT_AREA] + start_hpos,
2602 nglyphs, mouse_face_face_id);
2603 }
2604 else /* draw == DRAW_NORMAL_TEXT */
2605 write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
2606 }
2607 cursor_to (f, save_y, save_x);
2608 }
2609 }
2610
2611 static void
2612 term_clear_mouse_face ()
2613 {
2614 if (!NILP (mouse_face_window))
2615 term_show_mouse_face (DRAW_NORMAL_TEXT);
2616
2617 mouse_face_beg_row = mouse_face_beg_col = -1;
2618 mouse_face_end_row = mouse_face_end_col = -1;
2619 mouse_face_window = Qnil;
2620 }
2621
2622 /* Find the glyph matrix position of buffer position POS in window W.
2623 *HPOS and *VPOS are set to the positions found. W's current glyphs
2624 must be up to date. If POS is above window start return (0, 0).
2625 If POS is after end of W, return end of last line in W.
2626 - taken from msdos.c */
2627 static int
2628 fast_find_position (struct window *w, int pos, int *hpos, int *vpos)
2629 {
2630 int i, lastcol, line_start_position, maybe_next_line_p = 0;
2631 int yb = window_text_bottom_y (w);
2632 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0), *best_row = row;
2633
2634 while (row->y < yb)
2635 {
2636 if (row->used[TEXT_AREA])
2637 line_start_position = row->glyphs[TEXT_AREA]->charpos;
2638 else
2639 line_start_position = 0;
2640
2641 if (line_start_position > pos)
2642 break;
2643 /* If the position sought is the end of the buffer,
2644 don't include the blank lines at the bottom of the window. */
2645 else if (line_start_position == pos
2646 && pos == BUF_ZV (XBUFFER (w->buffer)))
2647 {
2648 maybe_next_line_p = 1;
2649 break;
2650 }
2651 else if (line_start_position > 0)
2652 best_row = row;
2653
2654 /* Don't overstep the last matrix row, lest we get into the
2655 never-never land... */
2656 if (row->y + 1 >= yb)
2657 break;
2658
2659 ++row;
2660 }
2661
2662 /* Find the right column within BEST_ROW. */
2663 lastcol = 0;
2664 row = best_row;
2665 for (i = 0; i < row->used[TEXT_AREA]; i++)
2666 {
2667 struct glyph *glyph = row->glyphs[TEXT_AREA] + i;
2668 int charpos;
2669
2670 charpos = glyph->charpos;
2671 if (charpos == pos)
2672 {
2673 *hpos = i;
2674 *vpos = row->y;
2675 return 1;
2676 }
2677 else if (charpos > pos)
2678 break;
2679 else if (charpos > 0)
2680 lastcol = i;
2681 }
2682
2683 /* If we're looking for the end of the buffer,
2684 and we didn't find it in the line we scanned,
2685 use the start of the following line. */
2686 if (maybe_next_line_p)
2687 {
2688 ++row;
2689 lastcol = 0;
2690 }
2691
2692 *vpos = row->y;
2693 *hpos = lastcol + 1;
2694 return 0;
2695 }
2696
2697 static void
2698 term_mouse_highlight (struct frame *f, int x, int y)
2699 {
2700 enum window_part part;
2701 Lisp_Object window;
2702 struct window *w;
2703 struct buffer *b;
2704
2705 if (NILP (Vmouse_highlight)
2706 || !f->glyphs_initialized_p)
2707 return;
2708
2709 /* Which window is that in? */
2710 window = window_from_coordinates (f, x, y, &part, &x, &y, 0);
2711
2712 /* Not on a window -> return. */
2713 if (!WINDOWP (window))
2714 return;
2715
2716 if (!EQ (window, mouse_face_window))
2717 term_clear_mouse_face ();
2718
2719 w = XWINDOW (window);
2720
2721 /* Are we in a window whose display is up to date?
2722 And verify the buffer's text has not changed. */
2723 b = XBUFFER (w->buffer);
2724 if (part == ON_TEXT
2725 && EQ (w->window_end_valid, w->buffer)
2726 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
2727 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
2728 {
2729 int pos, i, nrows = w->current_matrix->nrows;
2730 struct glyph_row *row;
2731 struct glyph *glyph;
2732
2733 /* Find the glyph under X/Y. */
2734 glyph = NULL;
2735 if (y >= 0 && y < nrows)
2736 {
2737 row = MATRIX_ROW (w->current_matrix, y);
2738 /* Give up if some row before the one we are looking for is
2739 not enabled. */
2740 for (i = 0; i <= y; i++)
2741 if (!MATRIX_ROW (w->current_matrix, i)->enabled_p)
2742 break;
2743 if (i > y /* all rows upto and including the one at Y are enabled */
2744 && row->displays_text_p
2745 && x < window_box_width (w, TEXT_AREA))
2746 {
2747 glyph = row->glyphs[TEXT_AREA];
2748 if (x >= row->used[TEXT_AREA])
2749 glyph = NULL;
2750 else
2751 {
2752 glyph += x;
2753 if (!BUFFERP (glyph->object))
2754 glyph = NULL;
2755 }
2756 }
2757 }
2758
2759 /* Clear mouse face if X/Y not over text. */
2760 if (glyph == NULL)
2761 {
2762 term_clear_mouse_face ();
2763 return;
2764 }
2765
2766 if (!BUFFERP (glyph->object))
2767 abort ();
2768 pos = glyph->charpos;
2769
2770 /* Check for mouse-face. */
2771 {
2772 extern Lisp_Object Qmouse_face;
2773 Lisp_Object mouse_face, overlay, position, *overlay_vec;
2774 int noverlays, obegv, ozv;
2775 struct buffer *obuf;
2776
2777 /* If we get an out-of-range value, return now; avoid an error. */
2778 if (pos > BUF_Z (b))
2779 return;
2780
2781 /* Make the window's buffer temporarily current for
2782 overlays_at and compute_char_face. */
2783 obuf = current_buffer;
2784 current_buffer = b;
2785 obegv = BEGV;
2786 ozv = ZV;
2787 BEGV = BEG;
2788 ZV = Z;
2789
2790 /* Is this char mouse-active? */
2791 XSETINT (position, pos);
2792
2793 /* Put all the overlays we want in a vector in overlay_vec. */
2794 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL, 0);
2795 /* Sort overlays into increasing priority order. */
2796 noverlays = sort_overlays (overlay_vec, noverlays, w);
2797
2798 /* Check mouse-face highlighting. */
2799 if (!(EQ (window, mouse_face_window)
2800 && y >= mouse_face_beg_row
2801 && y <= mouse_face_end_row
2802 && (y > mouse_face_beg_row
2803 || x >= mouse_face_beg_col)
2804 && (y < mouse_face_end_row
2805 || x < mouse_face_end_col
2806 || mouse_face_past_end)))
2807 {
2808 /* Clear the display of the old active region, if any. */
2809 term_clear_mouse_face ();
2810
2811 /* Find the highest priority overlay that has a mouse-face
2812 property. */
2813 overlay = Qnil;
2814 for (i = noverlays - 1; i >= 0; --i)
2815 {
2816 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
2817 if (!NILP (mouse_face))
2818 {
2819 overlay = overlay_vec[i];
2820 break;
2821 }
2822 }
2823
2824 /* If no overlay applies, get a text property. */
2825 if (NILP (overlay))
2826 mouse_face = Fget_text_property (position, Qmouse_face,
2827 w->buffer);
2828
2829 /* Handle the overlay case. */
2830 if (!NILP (overlay))
2831 {
2832 /* Find the range of text around this char that
2833 should be active. */
2834 Lisp_Object before, after;
2835 EMACS_INT ignore;
2836
2837
2838 before = Foverlay_start (overlay);
2839 after = Foverlay_end (overlay);
2840 /* Record this as the current active region. */
2841 fast_find_position (w, XFASTINT (before),
2842 &mouse_face_beg_col,
2843 &mouse_face_beg_row);
2844
2845 mouse_face_past_end
2846 = !fast_find_position (w, XFASTINT (after),
2847 &mouse_face_end_col,
2848 &mouse_face_end_row);
2849 mouse_face_window = window;
2850
2851 mouse_face_face_id
2852 = face_at_buffer_position (w, pos, 0, 0,
2853 &ignore, pos + 1, 1, -1);
2854
2855 /* Display it as active. */
2856 term_show_mouse_face (DRAW_MOUSE_FACE);
2857 }
2858 /* Handle the text property case. */
2859 else if (!NILP (mouse_face))
2860 {
2861 /* Find the range of text around this char that
2862 should be active. */
2863 Lisp_Object before, after, beginning, end;
2864 EMACS_INT ignore;
2865
2866 beginning = Fmarker_position (w->start);
2867 XSETINT (end, (BUF_Z (b) - XFASTINT (w->window_end_pos)));
2868 before
2869 = Fprevious_single_property_change (make_number (pos + 1),
2870 Qmouse_face,
2871 w->buffer, beginning);
2872 after
2873 = Fnext_single_property_change (position, Qmouse_face,
2874 w->buffer, end);
2875
2876 /* Record this as the current active region. */
2877 fast_find_position (w, XFASTINT (before),
2878 &mouse_face_beg_col,
2879 &mouse_face_beg_row);
2880 mouse_face_past_end
2881 = !fast_find_position (w, XFASTINT (after),
2882 &mouse_face_end_col,
2883 &mouse_face_end_row);
2884 mouse_face_window = window;
2885
2886 mouse_face_face_id
2887 = face_at_buffer_position (w, pos, 0, 0,
2888 &ignore, pos + 1, 1, -1);
2889
2890 /* Display it as active. */
2891 term_show_mouse_face (DRAW_MOUSE_FACE);
2892 }
2893 }
2894
2895 /* Look for a `help-echo' property. */
2896 {
2897 Lisp_Object help;
2898 extern Lisp_Object Qhelp_echo;
2899
2900 /* Check overlays first. */
2901 help = Qnil;
2902 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
2903 {
2904 overlay = overlay_vec[i];
2905 help = Foverlay_get (overlay, Qhelp_echo);
2906 }
2907
2908 if (!NILP (help))
2909 {
2910 help_echo_string = help;
2911 help_echo_window = window;
2912 help_echo_object = overlay;
2913 help_echo_pos = pos;
2914 }
2915 /* Try text properties. */
2916 else if (NILP (help)
2917 && ((STRINGP (glyph->object)
2918 && glyph->charpos >= 0
2919 && glyph->charpos < SCHARS (glyph->object))
2920 || (BUFFERP (glyph->object)
2921 && glyph->charpos >= BEGV
2922 && glyph->charpos < ZV)))
2923 {
2924 help = Fget_text_property (make_number (glyph->charpos),
2925 Qhelp_echo, glyph->object);
2926 if (!NILP (help))
2927 {
2928 help_echo_string = help;
2929 help_echo_window = window;
2930 help_echo_object = glyph->object;
2931 help_echo_pos = glyph->charpos;
2932 }
2933 }
2934 }
2935
2936 BEGV = obegv;
2937 ZV = ozv;
2938 current_buffer = obuf;
2939 }
2940 }
2941 }
2942
2943 static int
2944 term_mouse_movement (FRAME_PTR frame, Gpm_Event *event)
2945 {
2946 /* Has the mouse moved off the glyph it was on at the last sighting? */
2947 if (event->x != last_mouse_x || event->y != last_mouse_y)
2948 {
2949 frame->mouse_moved = 1;
2950 term_mouse_highlight (frame, event->x, event->y);
2951 /* Remember which glyph we're now on. */
2952 last_mouse_x = event->x;
2953 last_mouse_y = event->y;
2954 return 1;
2955 }
2956 return 0;
2957 }
2958
2959 /* Return the current position of the mouse.
2960
2961 Set *f to the frame the mouse is in, or zero if the mouse is in no
2962 Emacs frame. If it is set to zero, all the other arguments are
2963 garbage.
2964
2965 Set *bar_window to Qnil, and *x and *y to the column and
2966 row of the character cell the mouse is over.
2967
2968 Set *time to the time the mouse was at the returned position.
2969
2970 This clears mouse_moved until the next motion
2971 event arrives. */
2972 static void
2973 term_mouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
2974 enum scroll_bar_part *part, Lisp_Object *x,
2975 Lisp_Object *y, unsigned long *time)
2976 {
2977 struct timeval now;
2978
2979 *fp = SELECTED_FRAME ();
2980 (*fp)->mouse_moved = 0;
2981
2982 *bar_window = Qnil;
2983 *part = 0;
2984
2985 XSETINT (*x, last_mouse_x);
2986 XSETINT (*y, last_mouse_y);
2987 gettimeofday(&now, 0);
2988 *time = (now.tv_sec * 1000) + (now.tv_usec / 1000);
2989 }
2990
2991 /* Prepare a mouse-event in *RESULT for placement in the input queue.
2992
2993 If the event is a button press, then note that we have grabbed
2994 the mouse. */
2995
2996 static Lisp_Object
2997 term_mouse_click (struct input_event *result, Gpm_Event *event,
2998 struct frame *f)
2999 {
3000 struct timeval now;
3001 int i, j;
3002
3003 result->kind = GPM_CLICK_EVENT;
3004 for (i = 0, j = GPM_B_LEFT; i < 3; i++, j >>= 1 )
3005 {
3006 if (event->buttons & j) {
3007 result->code = i; /* button number */
3008 break;
3009 }
3010 }
3011 gettimeofday(&now, 0);
3012 result->timestamp = (now.tv_sec * 1000) + (now.tv_usec / 1000);
3013
3014 if (event->type & GPM_UP)
3015 result->modifiers = up_modifier;
3016 else if (event->type & GPM_DOWN)
3017 result->modifiers = down_modifier;
3018 else
3019 result->modifiers = 0;
3020
3021 if (event->type & GPM_SINGLE)
3022 result->modifiers |= click_modifier;
3023
3024 if (event->type & GPM_DOUBLE)
3025 result->modifiers |= double_modifier;
3026
3027 if (event->type & GPM_TRIPLE)
3028 result->modifiers |= triple_modifier;
3029
3030 if (event->type & GPM_DRAG)
3031 result->modifiers |= drag_modifier;
3032
3033 if (!(event->type & (GPM_MOVE | GPM_DRAG))) {
3034
3035 /* 1 << KG_SHIFT */
3036 if (event->modifiers & (1 << 0))
3037 result->modifiers |= shift_modifier;
3038
3039 /* 1 << KG_CTRL */
3040 if (event->modifiers & (1 << 2))
3041 result->modifiers |= ctrl_modifier;
3042
3043 /* 1 << KG_ALT || KG_ALTGR */
3044 if (event->modifiers & (1 << 3)
3045 || event->modifiers & (1 << 1))
3046 result->modifiers |= meta_modifier;
3047 }
3048
3049 XSETINT (result->x, event->x);
3050 XSETINT (result->y, event->y);
3051 XSETFRAME (result->frame_or_window, f);
3052 result->arg = Qnil;
3053 return Qnil;
3054 }
3055
3056 int
3057 handle_one_term_event (struct tty_display_info *tty, Gpm_Event *event, struct input_event* hold_quit)
3058 {
3059 struct frame *f = XFRAME (tty->top_frame);
3060 struct input_event ie;
3061 int do_help = 0;
3062 int count = 0;
3063
3064 EVENT_INIT (ie);
3065 ie.kind = NO_EVENT;
3066 ie.arg = Qnil;
3067
3068 if (event->type & (GPM_MOVE | GPM_DRAG)) {
3069 previous_help_echo_string = help_echo_string;
3070 help_echo_string = Qnil;
3071
3072 Gpm_DrawPointer (event->x, event->y, fileno (tty->output));
3073
3074 if (!term_mouse_movement (f, event))
3075 help_echo_string = previous_help_echo_string;
3076
3077 /* If the contents of the global variable help_echo_string
3078 has changed, generate a HELP_EVENT. */
3079 if (!NILP (help_echo_string)
3080 || !NILP (previous_help_echo_string))
3081 do_help = 1;
3082
3083 goto done;
3084 }
3085 else {
3086 f->mouse_moved = 0;
3087 term_mouse_click (&ie, event, f);
3088 }
3089
3090 done:
3091 if (ie.kind != NO_EVENT)
3092 {
3093 kbd_buffer_store_event_hold (&ie, hold_quit);
3094 count++;
3095 }
3096
3097 if (do_help
3098 && !(hold_quit && hold_quit->kind != NO_EVENT))
3099 {
3100 Lisp_Object frame;
3101
3102 if (f)
3103 XSETFRAME (frame, f);
3104 else
3105 frame = Qnil;
3106
3107 gen_help_event (help_echo_string, frame, help_echo_window,
3108 help_echo_object, help_echo_pos);
3109 count++;
3110 }
3111
3112 return count;
3113 }
3114
3115 DEFUN ("gpm-mouse-start", Fgpm_mouse_start, Sgpm_mouse_start,
3116 0, 0, 0,
3117 doc: /* Open a connection to Gpm.
3118 Gpm-mouse can only be activated for one tty at a time. */)
3119 ()
3120 {
3121 struct frame *f = SELECTED_FRAME ();
3122 struct tty_display_info *tty
3123 = ((f)->output_method == output_termcap
3124 ? (f)->terminal->display_info.tty : NULL);
3125 Gpm_Connect connection;
3126
3127 if (!tty)
3128 error ("Gpm-mouse only works in the GNU/Linux console");
3129 if (gpm_tty == tty)
3130 return Qnil; /* Already activated, nothing to do. */
3131 if (gpm_tty)
3132 error ("Gpm-mouse can only be activated for one tty at a time");
3133
3134 connection.eventMask = ~0;
3135 connection.defaultMask = ~GPM_HARD;
3136 connection.maxMod = ~0;
3137 connection.minMod = 0;
3138 gpm_zerobased = 1;
3139
3140 if (Gpm_Open (&connection, 0) < 0)
3141 error ("Gpm-mouse failed to connect to the gpm daemon");
3142 else
3143 {
3144 gpm_tty = tty;
3145 /* `init_sys_modes' arranges for mouse movements sent through gpm_fd
3146 to generate SIGIOs. Apparently we need to call reset_sys_modes
3147 before calling init_sys_modes. */
3148 reset_sys_modes (tty);
3149 init_sys_modes (tty);
3150 add_gpm_wait_descriptor (gpm_fd);
3151 return Qnil;
3152 }
3153 }
3154
3155 void
3156 close_gpm (int fd)
3157 {
3158 if (fd >= 0)
3159 delete_gpm_wait_descriptor (fd);
3160 while (Gpm_Close()); /* close all the stack */
3161 gpm_tty = NULL;
3162 }
3163
3164 DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop, Sgpm_mouse_stop,
3165 0, 0, 0,
3166 doc: /* Close a connection to Gpm. */)
3167 ()
3168 {
3169 struct frame *f = SELECTED_FRAME ();
3170 struct tty_display_info *tty
3171 = ((f)->output_method == output_termcap
3172 ? (f)->terminal->display_info.tty : NULL);
3173
3174 if (!tty || gpm_tty != tty)
3175 return Qnil; /* Not activated on this terminal, nothing to do. */
3176
3177 close_gpm (gpm_fd);
3178 return Qnil;
3179 }
3180 #endif /* HAVE_GPM */
3181
3182 \f
3183 #ifndef MSDOS
3184 /***********************************************************************
3185 Initialization
3186 ***********************************************************************/
3187
3188 /* Initialize the tty-dependent part of frame F. The frame must
3189 already have its device initialized. */
3190
3191 void
3192 create_tty_output (struct frame *f)
3193 {
3194 struct tty_output *t;
3195
3196 if (! FRAME_TERMCAP_P (f))
3197 abort ();
3198
3199 t = xmalloc (sizeof (struct tty_output));
3200 bzero (t, sizeof (struct tty_output));
3201
3202 t->display_info = FRAME_TERMINAL (f)->display_info.tty;
3203
3204 f->output_data.tty = t;
3205 }
3206
3207 /* Delete frame F's face cache, and its tty-dependent part. */
3208
3209 static void
3210 tty_free_frame_resources (struct frame *f)
3211 {
3212 if (! FRAME_TERMCAP_P (f))
3213 abort ();
3214
3215 if (FRAME_FACE_CACHE (f))
3216 free_frame_faces (f);
3217
3218 xfree (f->output_data.tty);
3219 }
3220
3221 #else /* MSDOS */
3222
3223 /* Delete frame F's face cache. */
3224
3225 static void
3226 tty_free_frame_resources (struct frame *f)
3227 {
3228 if (! FRAME_TERMCAP_P (f) && ! FRAME_MSDOS_P (f))
3229 abort ();
3230
3231 if (FRAME_FACE_CACHE (f))
3232 free_frame_faces (f);
3233 }
3234 #endif /* MSDOS */
3235 \f
3236 /* Reset the hooks in TERMINAL. */
3237
3238 static void
3239 clear_tty_hooks (struct terminal *terminal)
3240 {
3241 terminal->rif = 0;
3242 terminal->cursor_to_hook = 0;
3243 terminal->raw_cursor_to_hook = 0;
3244 terminal->clear_to_end_hook = 0;
3245 terminal->clear_frame_hook = 0;
3246 terminal->clear_end_of_line_hook = 0;
3247 terminal->ins_del_lines_hook = 0;
3248 terminal->insert_glyphs_hook = 0;
3249 terminal->write_glyphs_hook = 0;
3250 terminal->delete_glyphs_hook = 0;
3251 terminal->ring_bell_hook = 0;
3252 terminal->reset_terminal_modes_hook = 0;
3253 terminal->set_terminal_modes_hook = 0;
3254 terminal->update_begin_hook = 0;
3255 terminal->update_end_hook = 0;
3256 terminal->set_terminal_window_hook = 0;
3257 terminal->mouse_position_hook = 0;
3258 terminal->frame_rehighlight_hook = 0;
3259 terminal->frame_raise_lower_hook = 0;
3260 terminal->fullscreen_hook = 0;
3261 terminal->set_vertical_scroll_bar_hook = 0;
3262 terminal->condemn_scroll_bars_hook = 0;
3263 terminal->redeem_scroll_bar_hook = 0;
3264 terminal->judge_scroll_bars_hook = 0;
3265 terminal->read_socket_hook = 0;
3266 terminal->frame_up_to_date_hook = 0;
3267
3268 /* Leave these two set, or suspended frames are not deleted
3269 correctly. */
3270 terminal->delete_frame_hook = &tty_free_frame_resources;
3271 terminal->delete_terminal_hook = &delete_tty;
3272 }
3273
3274 /* Initialize hooks in TERMINAL with the values needed for a tty. */
3275
3276 static void
3277 set_tty_hooks (struct terminal *terminal)
3278 {
3279 terminal->rif = 0; /* ttys don't support window-based redisplay. */
3280
3281 terminal->cursor_to_hook = &tty_cursor_to;
3282 terminal->raw_cursor_to_hook = &tty_raw_cursor_to;
3283
3284 terminal->clear_to_end_hook = &tty_clear_to_end;
3285 terminal->clear_frame_hook = &tty_clear_frame;
3286 terminal->clear_end_of_line_hook = &tty_clear_end_of_line;
3287
3288 terminal->ins_del_lines_hook = &tty_ins_del_lines;
3289
3290 terminal->insert_glyphs_hook = &tty_insert_glyphs;
3291 terminal->write_glyphs_hook = &tty_write_glyphs;
3292 terminal->delete_glyphs_hook = &tty_delete_glyphs;
3293
3294 terminal->ring_bell_hook = &tty_ring_bell;
3295
3296 terminal->reset_terminal_modes_hook = &tty_reset_terminal_modes;
3297 terminal->set_terminal_modes_hook = &tty_set_terminal_modes;
3298 terminal->update_begin_hook = 0; /* Not needed. */
3299 terminal->update_end_hook = &tty_update_end;
3300 terminal->set_terminal_window_hook = &tty_set_terminal_window;
3301
3302 terminal->mouse_position_hook = 0; /* Not needed. */
3303 terminal->frame_rehighlight_hook = 0; /* Not needed. */
3304 terminal->frame_raise_lower_hook = 0; /* Not needed. */
3305
3306 terminal->set_vertical_scroll_bar_hook = 0; /* Not needed. */
3307 terminal->condemn_scroll_bars_hook = 0; /* Not needed. */
3308 terminal->redeem_scroll_bar_hook = 0; /* Not needed. */
3309 terminal->judge_scroll_bars_hook = 0; /* Not needed. */
3310
3311 terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */
3312 terminal->frame_up_to_date_hook = 0; /* Not needed. */
3313
3314 terminal->delete_frame_hook = &tty_free_frame_resources;
3315 terminal->delete_terminal_hook = &delete_tty;
3316 }
3317
3318 /* Drop the controlling terminal if fd is the same device. */
3319 static void
3320 dissociate_if_controlling_tty (int fd)
3321 {
3322 #ifndef DOS_NT
3323 int pgid;
3324 EMACS_GET_TTY_PGRP (fd, &pgid); /* If tcgetpgrp succeeds, fd is the ctty. */
3325 if (pgid != -1)
3326 {
3327 #if defined (USG) && !defined (BSD_PGRPS)
3328 setpgrp ();
3329 no_controlling_tty = 1;
3330 #elif defined (CYGWIN)
3331 setsid ();
3332 no_controlling_tty = 1;
3333 #else
3334 #ifdef TIOCNOTTY /* Try BSD ioctls. */
3335 sigblock (sigmask (SIGTTOU));
3336 fd = emacs_open (DEV_TTY, O_RDWR, 0);
3337 if (fd != -1 && ioctl (fd, TIOCNOTTY, 0) != -1)
3338 {
3339 no_controlling_tty = 1;
3340 }
3341 if (fd != -1)
3342 emacs_close (fd);
3343 sigunblock (sigmask (SIGTTOU));
3344 #else
3345 /* Unknown system. */
3346 croak ();
3347 #endif /* ! TIOCNOTTY */
3348 #endif /* ! USG */
3349 }
3350 #endif /* !DOS_NT */
3351 }
3352
3353 static void maybe_fatal();
3354
3355 /* Create a termcap display on the tty device with the given name and
3356 type.
3357
3358 If NAME is NULL, then use the controlling tty, i.e., "/dev/tty".
3359 Otherwise NAME should be a path to the tty device file,
3360 e.g. "/dev/pts/7".
3361
3362 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
3363
3364 If MUST_SUCCEED is true, then all errors are fatal. */
3365
3366 struct terminal *
3367 init_tty (char *name, char *terminal_type, int must_succeed)
3368 {
3369 char *area = NULL;
3370 char **address = &area;
3371 int buffer_size = 4096;
3372 register char *p = NULL;
3373 int status;
3374 struct tty_display_info *tty = NULL;
3375 struct terminal *terminal = NULL;
3376 int ctty = 0; /* 1 if asked to open controlling tty. */
3377
3378 if (!terminal_type)
3379 maybe_fatal (must_succeed, 0,
3380 "Unknown terminal type",
3381 "Unknown terminal type");
3382
3383 if (name == NULL)
3384 name = DEV_TTY;
3385 if (!strcmp (name, DEV_TTY))
3386 ctty = 1;
3387
3388 /* If we already have a terminal on the given device, use that. If
3389 all such terminals are suspended, create a new one instead. */
3390 /* XXX Perhaps this should be made explicit by having init_tty
3391 always create a new terminal and separating terminal and frame
3392 creation on Lisp level. */
3393 terminal = get_named_tty (name);
3394 if (terminal)
3395 return terminal;
3396
3397 terminal = create_terminal ();
3398 #ifdef MSDOS
3399 if (been_here > 0)
3400 maybe_fatal (1, 0, "Attempt to create another terminal %s", "",
3401 name, "");
3402 been_here = 1;
3403 tty = &the_only_display_info;
3404 #else
3405 tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info));
3406 #endif
3407 bzero (tty, sizeof (struct tty_display_info));
3408 tty->next = tty_list;
3409 tty_list = tty;
3410
3411 terminal->type = output_termcap;
3412 terminal->display_info.tty = tty;
3413 tty->terminal = terminal;
3414
3415 tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
3416 Wcm_clear (tty);
3417
3418 #ifndef DOS_NT
3419 set_tty_hooks (terminal);
3420
3421 {
3422 int fd;
3423 FILE *file;
3424
3425 #ifdef O_IGNORE_CTTY
3426 if (!ctty)
3427 /* Open the terminal device. Don't recognize it as our
3428 controlling terminal, and don't make it the controlling tty
3429 if we don't have one at the moment. */
3430 fd = emacs_open (name, O_RDWR | O_IGNORE_CTTY | O_NOCTTY, 0);
3431 else
3432 #else
3433 /* Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
3434 defined on Hurd. On other systems, we need to explicitly
3435 dissociate ourselves from the controlling tty when we want to
3436 open a frame on the same terminal. */
3437 fd = emacs_open (name, O_RDWR | O_NOCTTY, 0);
3438 #endif /* O_IGNORE_CTTY */
3439
3440 tty->name = xstrdup (name);
3441 terminal->name = xstrdup (name);
3442
3443 if (fd < 0)
3444 maybe_fatal (must_succeed, terminal,
3445 "Could not open file: %s",
3446 "Could not open file: %s",
3447 name);
3448 if (!isatty (fd))
3449 {
3450 close (fd);
3451 maybe_fatal (must_succeed, terminal,
3452 "Not a tty device: %s",
3453 "Not a tty device: %s",
3454 name);
3455 }
3456
3457 #ifndef O_IGNORE_CTTY
3458 if (!ctty)
3459 dissociate_if_controlling_tty (fd);
3460 #endif
3461
3462 file = fdopen (fd, "w+");
3463 tty->input = file;
3464 tty->output = file;
3465 }
3466
3467 tty->type = xstrdup (terminal_type);
3468
3469 add_keyboard_wait_descriptor (fileno (tty->input));
3470
3471 #endif /* !DOS_NT */
3472
3473 encode_terminal_src_size = 0;
3474 encode_terminal_dst_size = 0;
3475
3476 #ifdef HAVE_GPM
3477 terminal->mouse_position_hook = term_mouse_position;
3478 mouse_face_window = Qnil;
3479 #endif
3480
3481 #ifdef DOS_NT
3482 #ifdef WINDOWSNT
3483 initialize_w32_display (terminal);
3484 #else /* MSDOS */
3485 if (strcmp (terminal_type, "internal") == 0)
3486 terminal->type = output_msdos_raw;
3487 initialize_msdos_display (terminal);
3488 #endif /* MSDOS */
3489 tty->output = stdout;
3490 tty->input = stdin;
3491 /* The following two are inaccessible from w32console.c. */
3492 terminal->delete_frame_hook = &tty_free_frame_resources;
3493 terminal->delete_terminal_hook = &delete_tty;
3494
3495 tty->name = xstrdup (name);
3496 terminal->name = xstrdup (name);
3497 tty->type = xstrdup (terminal_type);
3498
3499 #ifdef subprocesses
3500 add_keyboard_wait_descriptor (0);
3501 #endif
3502
3503 Wcm_clear (tty);
3504
3505 #ifdef WINDOWSNT
3506 {
3507 struct frame *f = XFRAME (selected_frame);
3508
3509 FrameRows (tty) = FRAME_LINES (f);
3510 FrameCols (tty) = FRAME_COLS (f);
3511 tty->specified_window = FRAME_LINES (f);
3512
3513 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
3514 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
3515 }
3516 #else /* MSDOS */
3517 {
3518 int height, width;
3519 get_tty_size (fileno (tty->input), &width, &height);
3520 FrameCols (tty) = width;
3521 FrameRows (tty) = height;
3522 }
3523 #endif /* MSDOS */
3524 tty->delete_in_insert_mode = 1;
3525
3526 UseTabs (tty) = 0;
3527 terminal->scroll_region_ok = 0;
3528
3529 /* Seems to insert lines when it's not supposed to, messing up the
3530 display. In doing a trace, it didn't seem to be called much, so I
3531 don't think we're losing anything by turning it off. */
3532 terminal->line_ins_del_ok = 0;
3533 #ifdef WINDOWSNT
3534 terminal->char_ins_del_ok = 1;
3535 baud_rate = 19200;
3536 #else /* MSDOS */
3537 terminal->char_ins_del_ok = 0;
3538 init_baud_rate (fileno (tty->input));
3539 #endif /* MSDOS */
3540
3541 tty->TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
3542
3543 #else /* not DOS_NT */
3544
3545 Wcm_clear (tty);
3546
3547 tty->termcap_term_buffer = (char *) xmalloc (buffer_size);
3548
3549 /* On some systems, tgetent tries to access the controlling
3550 terminal. */
3551 sigblock (sigmask (SIGTTOU));
3552 status = tgetent (tty->termcap_term_buffer, terminal_type);
3553 sigunblock (sigmask (SIGTTOU));
3554
3555 if (status < 0)
3556 {
3557 #ifdef TERMINFO
3558 maybe_fatal (must_succeed, terminal,
3559 "Cannot open terminfo database file",
3560 "Cannot open terminfo database file");
3561 #else
3562 maybe_fatal (must_succeed, terminal,
3563 "Cannot open termcap database file",
3564 "Cannot open termcap database file");
3565 #endif
3566 }
3567 if (status == 0)
3568 {
3569 #ifdef TERMINFO
3570 maybe_fatal (must_succeed, terminal,
3571 "Terminal type %s is not defined",
3572 "Terminal type %s is not defined.\n\
3573 If that is not the actual type of terminal you have,\n\
3574 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3575 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3576 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3577 terminal_type);
3578 #else
3579 maybe_fatal (must_succeed, terminal,
3580 "Terminal type %s is not defined",
3581 "Terminal type %s is not defined.\n\
3582 If that is not the actual type of terminal you have,\n\
3583 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3584 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3585 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3586 terminal_type);
3587 #endif
3588 }
3589
3590 #ifndef TERMINFO
3591 if (strlen (tty->termcap_term_buffer) >= buffer_size)
3592 abort ();
3593 buffer_size = strlen (tty->termcap_term_buffer);
3594 #endif
3595 tty->termcap_strings_buffer = area = (char *) xmalloc (buffer_size);
3596 tty->TS_ins_line = tgetstr ("al", address);
3597 tty->TS_ins_multi_lines = tgetstr ("AL", address);
3598 tty->TS_bell = tgetstr ("bl", address);
3599 BackTab (tty) = tgetstr ("bt", address);
3600 tty->TS_clr_to_bottom = tgetstr ("cd", address);
3601 tty->TS_clr_line = tgetstr ("ce", address);
3602 tty->TS_clr_frame = tgetstr ("cl", address);
3603 ColPosition (tty) = NULL; /* tgetstr ("ch", address); */
3604 AbsPosition (tty) = tgetstr ("cm", address);
3605 CR (tty) = tgetstr ("cr", address);
3606 tty->TS_set_scroll_region = tgetstr ("cs", address);
3607 tty->TS_set_scroll_region_1 = tgetstr ("cS", address);
3608 RowPosition (tty) = tgetstr ("cv", address);
3609 tty->TS_del_char = tgetstr ("dc", address);
3610 tty->TS_del_multi_chars = tgetstr ("DC", address);
3611 tty->TS_del_line = tgetstr ("dl", address);
3612 tty->TS_del_multi_lines = tgetstr ("DL", address);
3613 tty->TS_delete_mode = tgetstr ("dm", address);
3614 tty->TS_end_delete_mode = tgetstr ("ed", address);
3615 tty->TS_end_insert_mode = tgetstr ("ei", address);
3616 Home (tty) = tgetstr ("ho", address);
3617 tty->TS_ins_char = tgetstr ("ic", address);
3618 tty->TS_ins_multi_chars = tgetstr ("IC", address);
3619 tty->TS_insert_mode = tgetstr ("im", address);
3620 tty->TS_pad_inserted_char = tgetstr ("ip", address);
3621 tty->TS_end_keypad_mode = tgetstr ("ke", address);
3622 tty->TS_keypad_mode = tgetstr ("ks", address);
3623 LastLine (tty) = tgetstr ("ll", address);
3624 Right (tty) = tgetstr ("nd", address);
3625 Down (tty) = tgetstr ("do", address);
3626 if (!Down (tty))
3627 Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do" */
3628 if (tgetflag ("bs"))
3629 Left (tty) = "\b"; /* can't possibly be longer! */
3630 else /* (Actually, "bs" is obsolete...) */
3631 Left (tty) = tgetstr ("le", address);
3632 if (!Left (tty))
3633 Left (tty) = tgetstr ("bc", address); /* Obsolete name for "le" */
3634 tty->TS_pad_char = tgetstr ("pc", address);
3635 tty->TS_repeat = tgetstr ("rp", address);
3636 tty->TS_end_standout_mode = tgetstr ("se", address);
3637 tty->TS_fwd_scroll = tgetstr ("sf", address);
3638 tty->TS_standout_mode = tgetstr ("so", address);
3639 tty->TS_rev_scroll = tgetstr ("sr", address);
3640 tty->Wcm->cm_tab = tgetstr ("ta", address);
3641 tty->TS_end_termcap_modes = tgetstr ("te", address);
3642 tty->TS_termcap_modes = tgetstr ("ti", address);
3643 Up (tty) = tgetstr ("up", address);
3644 tty->TS_visible_bell = tgetstr ("vb", address);
3645 tty->TS_cursor_normal = tgetstr ("ve", address);
3646 tty->TS_cursor_visible = tgetstr ("vs", address);
3647 tty->TS_cursor_invisible = tgetstr ("vi", address);
3648 tty->TS_set_window = tgetstr ("wi", address);
3649
3650 tty->TS_enter_underline_mode = tgetstr ("us", address);
3651 tty->TS_exit_underline_mode = tgetstr ("ue", address);
3652 tty->TS_enter_bold_mode = tgetstr ("md", address);
3653 tty->TS_enter_dim_mode = tgetstr ("mh", address);
3654 tty->TS_enter_blink_mode = tgetstr ("mb", address);
3655 tty->TS_enter_reverse_mode = tgetstr ("mr", address);
3656 tty->TS_enter_alt_charset_mode = tgetstr ("as", address);
3657 tty->TS_exit_alt_charset_mode = tgetstr ("ae", address);
3658 tty->TS_exit_attribute_mode = tgetstr ("me", address);
3659
3660 MultiUp (tty) = tgetstr ("UP", address);
3661 MultiDown (tty) = tgetstr ("DO", address);
3662 MultiLeft (tty) = tgetstr ("LE", address);
3663 MultiRight (tty) = tgetstr ("RI", address);
3664
3665 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
3666 color because we can't switch back to the default foreground and
3667 background. */
3668 tty->TS_orig_pair = tgetstr ("op", address);
3669 if (tty->TS_orig_pair)
3670 {
3671 tty->TS_set_foreground = tgetstr ("AF", address);
3672 tty->TS_set_background = tgetstr ("AB", address);
3673 if (!tty->TS_set_foreground)
3674 {
3675 /* SVr4. */
3676 tty->TS_set_foreground = tgetstr ("Sf", address);
3677 tty->TS_set_background = tgetstr ("Sb", address);
3678 }
3679
3680 tty->TN_max_colors = tgetnum ("Co");
3681 tty->TN_max_pairs = tgetnum ("pa");
3682
3683 tty->TN_no_color_video = tgetnum ("NC");
3684 if (tty->TN_no_color_video == -1)
3685 tty->TN_no_color_video = 0;
3686 }
3687
3688 tty_default_color_capabilities (tty, 1);
3689
3690 MagicWrap (tty) = tgetflag ("xn");
3691 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
3692 the former flag imply the latter. */
3693 AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
3694 terminal->memory_below_frame = tgetflag ("db");
3695 tty->TF_hazeltine = tgetflag ("hz");
3696 terminal->must_write_spaces = tgetflag ("in");
3697 tty->meta_key = tgetflag ("km") || tgetflag ("MT");
3698 tty->TF_insmode_motion = tgetflag ("mi");
3699 tty->TF_standout_motion = tgetflag ("ms");
3700 tty->TF_underscore = tgetflag ("ul");
3701 tty->TF_teleray = tgetflag ("xt");
3702
3703 #endif /* !DOS_NT */
3704 terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
3705 init_kboard (terminal->kboard);
3706 terminal->kboard->Vwindow_system = Qnil;
3707 terminal->kboard->next_kboard = all_kboards;
3708 all_kboards = terminal->kboard;
3709 terminal->kboard->reference_count++;
3710 /* Don't let the initial kboard remain current longer than necessary.
3711 That would cause problems if a file loaded on startup tries to
3712 prompt in the mini-buffer. */
3713 if (current_kboard == initial_kboard)
3714 current_kboard = terminal->kboard;
3715 #ifndef DOS_NT
3716 term_get_fkeys (address, terminal->kboard);
3717
3718 /* Get frame size from system, or else from termcap. */
3719 {
3720 int height, width;
3721 get_tty_size (fileno (tty->input), &width, &height);
3722 FrameCols (tty) = width;
3723 FrameRows (tty) = height;
3724 }
3725
3726 if (FrameCols (tty) <= 0)
3727 FrameCols (tty) = tgetnum ("co");
3728 if (FrameRows (tty) <= 0)
3729 FrameRows (tty) = tgetnum ("li");
3730
3731 if (FrameRows (tty) < 3 || FrameCols (tty) < 3)
3732 maybe_fatal (must_succeed, terminal,
3733 "Screen size %dx%d is too small"
3734 "Screen size %dx%d is too small",
3735 FrameCols (tty), FrameRows (tty));
3736
3737 TabWidth (tty) = tgetnum ("tw");
3738
3739 if (!tty->TS_bell)
3740 tty->TS_bell = "\07";
3741
3742 if (!tty->TS_fwd_scroll)
3743 tty->TS_fwd_scroll = Down (tty);
3744
3745 PC = tty->TS_pad_char ? *tty->TS_pad_char : 0;
3746
3747 if (TabWidth (tty) < 0)
3748 TabWidth (tty) = 8;
3749
3750 /* Turned off since /etc/termcap seems to have :ta= for most terminals
3751 and newer termcap doc does not seem to say there is a default.
3752 if (!tty->Wcm->cm_tab)
3753 tty->Wcm->cm_tab = "\t";
3754 */
3755
3756 /* We don't support standout modes that use `magic cookies', so
3757 turn off any that do. */
3758 if (tty->TS_standout_mode && tgetnum ("sg") >= 0)
3759 {
3760 tty->TS_standout_mode = 0;
3761 tty->TS_end_standout_mode = 0;
3762 }
3763 if (tty->TS_enter_underline_mode && tgetnum ("ug") >= 0)
3764 {
3765 tty->TS_enter_underline_mode = 0;
3766 tty->TS_exit_underline_mode = 0;
3767 }
3768
3769 /* If there's no standout mode, try to use underlining instead. */
3770 if (tty->TS_standout_mode == 0)
3771 {
3772 tty->TS_standout_mode = tty->TS_enter_underline_mode;
3773 tty->TS_end_standout_mode = tty->TS_exit_underline_mode;
3774 }
3775
3776 /* If no `se' string, try using a `me' string instead.
3777 If that fails, we can't use standout mode at all. */
3778 if (tty->TS_end_standout_mode == 0)
3779 {
3780 char *s = tgetstr ("me", address);
3781 if (s != 0)
3782 tty->TS_end_standout_mode = s;
3783 else
3784 tty->TS_standout_mode = 0;
3785 }
3786
3787 if (tty->TF_teleray)
3788 {
3789 tty->Wcm->cm_tab = 0;
3790 /* We can't support standout mode, because it uses magic cookies. */
3791 tty->TS_standout_mode = 0;
3792 /* But that means we cannot rely on ^M to go to column zero! */
3793 CR (tty) = 0;
3794 /* LF can't be trusted either -- can alter hpos */
3795 /* if move at column 0 thru a line with TS_standout_mode */
3796 Down (tty) = 0;
3797 }
3798
3799 /* Special handling for certain terminal types known to need it */
3800
3801 if (!strcmp (terminal_type, "supdup"))
3802 {
3803 terminal->memory_below_frame = 1;
3804 tty->Wcm->cm_losewrap = 1;
3805 }
3806 if (!strncmp (terminal_type, "c10", 3)
3807 || !strcmp (terminal_type, "perq"))
3808 {
3809 /* Supply a makeshift :wi string.
3810 This string is not valid in general since it works only
3811 for windows starting at the upper left corner;
3812 but that is all Emacs uses.
3813
3814 This string works only if the frame is using
3815 the top of the video memory, because addressing is memory-relative.
3816 So first check the :ti string to see if that is true.
3817
3818 It would be simpler if the :wi string could go in the termcap
3819 entry, but it can't because it is not fully valid.
3820 If it were in the termcap entry, it would confuse other programs. */
3821 if (!tty->TS_set_window)
3822 {
3823 p = tty->TS_termcap_modes;
3824 while (*p && strcmp (p, "\033v "))
3825 p++;
3826 if (*p)
3827 tty->TS_set_window = "\033v%C %C %C %C ";
3828 }
3829 /* Termcap entry often fails to have :in: flag */
3830 terminal->must_write_spaces = 1;
3831 /* :ti string typically fails to have \E^G! in it */
3832 /* This limits scope of insert-char to one line. */
3833 strcpy (area, tty->TS_termcap_modes);
3834 strcat (area, "\033\007!");
3835 tty->TS_termcap_modes = area;
3836 area += strlen (area) + 1;
3837 p = AbsPosition (tty);
3838 /* Change all %+ parameters to %C, to handle
3839 values above 96 correctly for the C100. */
3840 while (*p)
3841 {
3842 if (p[0] == '%' && p[1] == '+')
3843 p[1] = 'C';
3844 p++;
3845 }
3846 }
3847
3848 tty->specified_window = FrameRows (tty);
3849
3850 if (Wcm_init (tty) == -1) /* can't do cursor motion */
3851 {
3852 maybe_fatal (must_succeed, terminal,
3853 "Terminal type \"%s\" is not powerful enough to run Emacs",
3854 # ifdef TERMINFO
3855 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3856 It lacks the ability to position the cursor.\n\
3857 If that is not the actual type of terminal you have,\n\
3858 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3859 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3860 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3861 # else /* TERMCAP */
3862 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3863 It lacks the ability to position the cursor.\n\
3864 If that is not the actual type of terminal you have,\n\
3865 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3866 `setenv TERM ...') to specify the correct type. It may be necessary\n\
3867 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3868 # endif /* TERMINFO */
3869 terminal_type);
3870 }
3871
3872 if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
3873 maybe_fatal (must_succeed, terminal,
3874 "Could not determine the frame size",
3875 "Could not determine the frame size");
3876
3877 tty->delete_in_insert_mode
3878 = tty->TS_delete_mode && tty->TS_insert_mode
3879 && !strcmp (tty->TS_delete_mode, tty->TS_insert_mode);
3880
3881 tty->se_is_so = (tty->TS_standout_mode
3882 && tty->TS_end_standout_mode
3883 && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode));
3884
3885 UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8;
3886
3887 terminal->scroll_region_ok
3888 = (tty->Wcm->cm_abs
3889 && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
3890
3891 terminal->line_ins_del_ok
3892 = (((tty->TS_ins_line || tty->TS_ins_multi_lines)
3893 && (tty->TS_del_line || tty->TS_del_multi_lines))
3894 || (terminal->scroll_region_ok
3895 && tty->TS_fwd_scroll && tty->TS_rev_scroll));
3896
3897 terminal->char_ins_del_ok
3898 = ((tty->TS_ins_char || tty->TS_insert_mode
3899 || tty->TS_pad_inserted_char || tty->TS_ins_multi_chars)
3900 && (tty->TS_del_char || tty->TS_del_multi_chars));
3901
3902 terminal->fast_clear_end_of_line = tty->TS_clr_line != 0;
3903
3904 init_baud_rate (fileno (tty->input));
3905
3906 #endif /* not DOS_NT */
3907
3908 /* Init system terminal modes (RAW or CBREAK, etc.). */
3909 init_sys_modes (tty);
3910
3911 return terminal;
3912 }
3913
3914 /* Auxiliary error-handling function for init_tty.
3915 Delete TERMINAL, then call error or fatal with str1 or str2,
3916 respectively, according to MUST_SUCCEED. */
3917
3918 static void
3919 maybe_fatal (must_succeed, terminal, str1, str2, arg1, arg2)
3920 int must_succeed;
3921 struct terminal *terminal;
3922 char *str1, *str2, *arg1, *arg2;
3923 {
3924 if (terminal)
3925 delete_tty (terminal);
3926
3927 if (must_succeed)
3928 fatal (str2, arg1, arg2);
3929 else
3930 error (str1, arg1, arg2);
3931
3932 abort ();
3933 }
3934
3935 void
3936 fatal (const char *str, ...)
3937 {
3938 va_list ap;
3939 va_start (ap, str);
3940 fprintf (stderr, "emacs: ");
3941 vfprintf (stderr, str, ap);
3942 if (!(strlen (str) > 0 && str[strlen (str) - 1] == '\n'))
3943 fprintf (stderr, "\n");
3944 va_end (ap);
3945 fflush (stderr);
3946 exit (1);
3947 }
3948
3949 \f
3950
3951 /* Delete the given tty terminal, closing all frames on it. */
3952
3953 static void
3954 delete_tty (struct terminal *terminal)
3955 {
3956 struct tty_display_info *tty;
3957
3958 /* Protect against recursive calls. delete_frame in
3959 delete_terminal calls us back when it deletes our last frame. */
3960 if (!terminal->name)
3961 return;
3962
3963 if (terminal->type != output_termcap)
3964 abort ();
3965
3966 tty = terminal->display_info.tty;
3967
3968 if (tty == tty_list)
3969 tty_list = tty->next;
3970 else
3971 {
3972 struct tty_display_info *p;
3973 for (p = tty_list; p && p->next != tty; p = p->next)
3974 ;
3975
3976 if (! p)
3977 /* This should not happen. */
3978 abort ();
3979
3980 p->next = tty->next;
3981 tty->next = 0;
3982 }
3983
3984 /* reset_sys_modes needs a valid device, so this call needs to be
3985 before delete_terminal. */
3986 reset_sys_modes (tty);
3987
3988 delete_terminal (terminal);
3989
3990 xfree (tty->name);
3991 xfree (tty->type);
3992
3993 if (tty->input)
3994 {
3995 #ifdef subprocesses
3996 delete_keyboard_wait_descriptor (fileno (tty->input));
3997 #endif
3998 if (tty->input != stdin)
3999 fclose (tty->input);
4000 }
4001 if (tty->output && tty->output != stdout && tty->output != tty->input)
4002 fclose (tty->output);
4003 if (tty->termscript)
4004 fclose (tty->termscript);
4005
4006 xfree (tty->old_tty);
4007 xfree (tty->Wcm);
4008 xfree (tty->termcap_strings_buffer);
4009 xfree (tty->termcap_term_buffer);
4010
4011 bzero (tty, sizeof (struct tty_display_info));
4012 xfree (tty);
4013 }
4014
4015 \f
4016
4017 /* Mark the pointers in the tty_display_info objects.
4018 Called by the Fgarbage_collector. */
4019
4020 void
4021 mark_ttys (void)
4022 {
4023 struct tty_display_info *tty;
4024
4025 for (tty = tty_list; tty; tty = tty->next)
4026 mark_object (tty->top_frame);
4027 }
4028
4029 \f
4030
4031 void
4032 syms_of_term ()
4033 {
4034 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
4035 doc: /* Non-nil means the system uses terminfo rather than termcap.
4036 This variable can be used by terminal emulator packages. */);
4037 #ifdef TERMINFO
4038 system_uses_terminfo = 1;
4039 #else
4040 system_uses_terminfo = 0;
4041 #endif
4042
4043 DEFVAR_LISP ("suspend-tty-functions", &Vsuspend_tty_functions,
4044 doc: /* Functions to be run after suspending a tty.
4045 The functions are run with one argument, the terminal object to be suspended.
4046 See `suspend-tty'. */);
4047 Vsuspend_tty_functions = Qnil;
4048
4049
4050 DEFVAR_LISP ("resume-tty-functions", &Vresume_tty_functions,
4051 doc: /* Functions to be run after resuming a tty.
4052 The functions are run with one argument, the terminal object that was revived.
4053 See `resume-tty'. */);
4054 Vresume_tty_functions = Qnil;
4055
4056 DEFVAR_BOOL ("visible-cursor", &visible_cursor,
4057 doc: /* Non-nil means to make the cursor very visible.
4058 This only has an effect when running in a text terminal.
4059 What means \"very visible\" is up to your terminal. It may make the cursor
4060 bigger, or it may make it blink, or it may do nothing at all. */);
4061 visible_cursor = 1;
4062
4063 defsubr (&Stty_display_color_p);
4064 defsubr (&Stty_display_color_cells);
4065 defsubr (&Stty_no_underline);
4066 defsubr (&Stty_type);
4067 defsubr (&Scontrolling_tty_p);
4068 defsubr (&Ssuspend_tty);
4069 defsubr (&Sresume_tty);
4070 #ifdef HAVE_GPM
4071 defsubr (&Sgpm_mouse_start);
4072 defsubr (&Sgpm_mouse_stop);
4073
4074 staticpro (&mouse_face_window);
4075 #endif /* HAVE_GPM */
4076
4077 #ifndef DOS_NT
4078 default_orig_pair = NULL;
4079 default_set_foreground = NULL;
4080 default_set_background = NULL;
4081 #endif /* !DOS_NT */
4082
4083 encode_terminal_src = NULL;
4084 encode_terminal_dst = NULL;
4085 }
4086
4087
4088
4089 /* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193
4090 (do not change this comment) */