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