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