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