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