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