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