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