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