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