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