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