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