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