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