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