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