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