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