Full support for multiple terminal I/O (with some rough edges).
[emacs.git] / src / term.c
blob80e5e437e4365b5cc4edbceeb2b4f065c45f654a
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.
5 This file is part of GNU Emacs.
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.
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.
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. */
22 /* New redisplay, TTY faces by Gerd Moellmann <gerd@gnu.org>. */
24 #include <config.h>
25 #include <stdio.h>
26 #include <ctype.h>
27 #include <string.h>
29 #include <sys/file.h>
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"
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. */
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
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
66 #ifndef O_RDWR
67 #define O_RDWR 2
68 #endif
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_ ((void));
73 static void tty_hide_cursor P_ ((void));
75 #define OUTPUT(tty, a) \
76 emacs_tputs ((tty), a, \
77 (int) (FRAME_LINES (XFRAME (selected_frame)) \
78 - curY (tty)), \
79 cmputc)
81 #define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
82 #define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
84 #define OUTPUT_IF(tty, a) \
85 do { \
86 if (a) \
87 emacs_tputs ((tty), a, \
88 (int) (FRAME_LINES (XFRAME (selected_frame)) \
89 - curY (tty) ), \
90 cmputc); \
91 } while (0)
93 #define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
95 /* Function to use to ring the bell. */
97 Lisp_Object Vring_bell_function;
99 /* Terminal characteristics that higher levels want to look at. */
101 struct tty_output *tty_list;
103 /* Nonzero means no need to redraw the entire frame on resuming
104 a suspended Emacs. This is useful on terminals with multiple pages,
105 where one page is used for Emacs and another for all else. */
106 int no_redraw_on_reenter;
108 /* Hook functions that you can set to snap out the functions in this file.
109 These are all extern'd in termhooks.h */
111 void (*cursor_to_hook) P_ ((int, int));
112 void (*raw_cursor_to_hook) P_ ((int, int));
113 void (*clear_to_end_hook) P_ ((void));
114 void (*clear_frame_hook) P_ ((void));
115 void (*clear_end_of_line_hook) P_ ((int));
117 void (*ins_del_lines_hook) P_ ((int, int));
119 void (*delete_glyphs_hook) P_ ((int));
121 void (*ring_bell_hook) P_ ((void));
123 void (*reset_terminal_modes_hook) P_ ((void));
124 void (*set_terminal_modes_hook) P_ ((void));
125 void (*update_begin_hook) P_ ((struct frame *));
126 void (*update_end_hook) P_ ((struct frame *));
127 void (*set_terminal_window_hook) P_ ((int));
128 void (*insert_glyphs_hook) P_ ((struct glyph *, int));
129 void (*write_glyphs_hook) P_ ((struct glyph *, int));
130 void (*delete_glyphs_hook) P_ ((int));
132 int (*read_socket_hook) P_ ((struct input_event *, int, int));
134 void (*frame_up_to_date_hook) P_ ((struct frame *));
136 /* Return the current position of the mouse.
138 Set *f to the frame the mouse is in, or zero if the mouse is in no
139 Emacs frame. If it is set to zero, all the other arguments are
140 garbage.
142 If the motion started in a scroll bar, set *bar_window to the
143 scroll bar's window, *part to the part the mouse is currently over,
144 *x to the position of the mouse along the scroll bar, and *y to the
145 overall length of the scroll bar.
147 Otherwise, set *bar_window to Qnil, and *x and *y to the column and
148 row of the character cell the mouse is over.
150 Set *time to the time the mouse was at the returned position.
152 This should clear mouse_moved until the next motion
153 event arrives. */
155 void (*mouse_position_hook) P_ ((FRAME_PTR *f, int insist,
156 Lisp_Object *bar_window,
157 enum scroll_bar_part *part,
158 Lisp_Object *x,
159 Lisp_Object *y,
160 unsigned long *time));
162 /* When reading from a minibuffer in a different frame, Emacs wants
163 to shift the highlight from the selected frame to the mini-buffer's
164 frame; under X, this means it lies about where the focus is.
165 This hook tells the window system code to re-decide where to put
166 the highlight. */
168 void (*frame_rehighlight_hook) P_ ((FRAME_PTR f));
170 /* If we're displaying frames using a window system that can stack
171 frames on top of each other, this hook allows you to bring a frame
172 to the front, or bury it behind all the other windows. If this
173 hook is zero, that means the device we're displaying on doesn't
174 support overlapping frames, so there's no need to raise or lower
175 anything.
177 If RAISE is non-zero, F is brought to the front, before all other
178 windows. If RAISE is zero, F is sent to the back, behind all other
179 windows. */
181 void (*frame_raise_lower_hook) P_ ((FRAME_PTR f, int raise));
183 /* Set the vertical scroll bar for WINDOW to have its upper left corner
184 at (TOP, LEFT), and be LENGTH rows high. Set its handle to
185 indicate that we are displaying PORTION characters out of a total
186 of WHOLE characters, starting at POSITION. If WINDOW doesn't yet
187 have a scroll bar, create one for it. */
189 void (*set_vertical_scroll_bar_hook)
190 P_ ((struct window *window,
191 int portion, int whole, int position));
194 /* The following three hooks are used when we're doing a thorough
195 redisplay of the frame. We don't explicitly know which scroll bars
196 are going to be deleted, because keeping track of when windows go
197 away is a real pain - can you say set-window-configuration?
198 Instead, we just assert at the beginning of redisplay that *all*
199 scroll bars are to be removed, and then save scroll bars from the
200 fiery pit when we actually redisplay their window. */
202 /* Arrange for all scroll bars on FRAME to be removed at the next call
203 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
204 `*redeem_scroll_bar_hook' is applied to its window before the judgment.
206 This should be applied to each frame each time its window tree is
207 redisplayed, even if it is not displaying scroll bars at the moment;
208 if the HAS_SCROLL_BARS flag has just been turned off, only calling
209 this and the judge_scroll_bars_hook will get rid of them.
211 If non-zero, this hook should be safe to apply to any frame,
212 whether or not it can support scroll bars, and whether or not it is
213 currently displaying them. */
215 void (*condemn_scroll_bars_hook) P_ ((FRAME_PTR frame));
217 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
218 Note that it's okay to redeem a scroll bar that is not condemned. */
220 void (*redeem_scroll_bar_hook) P_ ((struct window *window));
222 /* Remove all scroll bars on FRAME that haven't been saved since the
223 last call to `*condemn_scroll_bars_hook'.
225 This should be applied to each frame after each time its window
226 tree is redisplayed, even if it is not displaying scroll bars at the
227 moment; if the HAS_SCROLL_BARS flag has just been turned off, only
228 calling this and condemn_scroll_bars_hook will get rid of them.
230 If non-zero, this hook should be safe to apply to any frame,
231 whether or not it can support scroll bars, and whether or not it is
232 currently displaying them. */
234 void (*judge_scroll_bars_hook) P_ ((FRAME_PTR FRAME));
236 /* Strings, numbers and flags taken from the termcap entry. */
238 char *TS_ins_line; /* "al" */
239 char *TS_ins_multi_lines; /* "AL" (one parameter, # lines to insert) */
240 char *TS_bell; /* "bl" */
241 char *TS_clr_to_bottom; /* "cd" */
242 char *TS_clr_line; /* "ce", clear to end of line */
243 char *TS_clr_frame; /* "cl" */
244 char *TS_set_scroll_region; /* "cs" (2 params, first line and last line) */
245 char *TS_set_scroll_region_1; /* "cS" (4 params: total lines,
246 lines above scroll region, lines below it,
247 total lines again) */
248 char *TS_del_char; /* "dc" */
249 char *TS_del_multi_chars; /* "DC" (one parameter, # chars to delete) */
250 char *TS_del_line; /* "dl" */
251 char *TS_del_multi_lines; /* "DL" (one parameter, # lines to delete) */
252 char *TS_delete_mode; /* "dm", enter character-delete mode */
253 char *TS_end_delete_mode; /* "ed", leave character-delete mode */
254 char *TS_end_insert_mode; /* "ei", leave character-insert mode */
255 char *TS_ins_char; /* "ic" */
256 char *TS_ins_multi_chars; /* "IC" (one parameter, # chars to insert) */
257 char *TS_insert_mode; /* "im", enter character-insert mode */
258 char *TS_pad_inserted_char; /* "ip". Just padding, no commands. */
259 char *TS_end_keypad_mode; /* "ke" */
260 char *TS_keypad_mode; /* "ks" */
261 char *TS_pad_char; /* "pc", char to use as padding */
262 char *TS_repeat; /* "rp" (2 params, # times to repeat
263 and character to be repeated) */
264 char *TS_end_standout_mode; /* "se" */
265 char *TS_fwd_scroll; /* "sf" */
266 char *TS_standout_mode; /* "so" */
267 char *TS_rev_scroll; /* "sr" */
268 char *TS_end_termcap_modes; /* "te" */
269 char *TS_termcap_modes; /* "ti" */
270 char *TS_visible_bell; /* "vb" */
271 char *TS_cursor_normal; /* "ve" */
272 char *TS_cursor_visible; /* "vs" */
273 char *TS_cursor_invisible; /* "vi" */
274 char *TS_set_window; /* "wi" (4 params, start and end of window,
275 each as vpos and hpos) */
277 /* Value of the "NC" (no_color_video) capability, or 0 if not
278 present. */
280 static int TN_no_color_video;
282 /* Meaning of bits in no_color_video. Each bit set means that the
283 corresponding attribute cannot be combined with colors. */
285 enum no_color_bit
287 NC_STANDOUT = 1 << 0,
288 NC_UNDERLINE = 1 << 1,
289 NC_REVERSE = 1 << 2,
290 NC_BLINK = 1 << 3,
291 NC_DIM = 1 << 4,
292 NC_BOLD = 1 << 5,
293 NC_INVIS = 1 << 6,
294 NC_PROTECT = 1 << 7,
295 NC_ALT_CHARSET = 1 << 8
298 /* "md" -- turn on bold (extra bright mode). */
300 char *TS_enter_bold_mode;
302 /* "mh" -- turn on half-bright mode. */
304 char *TS_enter_dim_mode;
306 /* "mb" -- enter blinking mode. */
308 char *TS_enter_blink_mode;
310 /* "mr" -- enter reverse video mode. */
312 char *TS_enter_reverse_mode;
314 /* "us"/"ue" -- start/end underlining. */
316 char *TS_exit_underline_mode, *TS_enter_underline_mode;
318 /* "as"/"ae" -- start/end alternate character set. Not really
319 supported, yet. */
321 char *TS_enter_alt_charset_mode, *TS_exit_alt_charset_mode;
323 /* "me" -- switch appearances off. */
325 char *TS_exit_attribute_mode;
327 /* "Co" -- number of colors. */
329 int TN_max_colors;
331 /* "pa" -- max. number of color pairs on screen. Not handled yet.
332 Could be a problem if not equal to TN_max_colors * TN_max_colors. */
334 int TN_max_pairs;
336 /* "op" -- SVr4 set default pair to its original value. */
338 char *TS_orig_pair;
340 /* "AF"/"AB" or "Sf"/"Sb"-- set ANSI or SVr4 foreground/background color.
341 1 param, the color index. */
343 char *TS_set_foreground, *TS_set_background;
345 int TF_hazeltine; /* termcap hz flag. */
346 int TF_insmode_motion; /* termcap mi flag: can move while in insert mode. */
347 int TF_standout_motion; /* termcap mi flag: can move while in standout mode. */
348 int TF_underscore; /* termcap ul flag: _ underlines if over-struck on
349 non-blank position. Must clear before writing _. */
350 int TF_teleray; /* termcap xt flag: many weird consequences.
351 For t1061. */
353 static int RPov; /* # chars to start a TS_repeat */
355 static int delete_in_insert_mode; /* delete mode == insert mode */
357 static int se_is_so; /* 1 if same string both enters and leaves
358 standout mode */
360 /* internal state */
362 /* The largest frame width in any call to calculate_costs. */
364 int max_frame_cols;
366 /* The largest frame height in any call to calculate_costs. */
368 int max_frame_lines;
370 static int costs_set; /* Nonzero if costs have been calculated. */
372 int insert_mode; /* Nonzero when in insert mode. */
373 int standout_mode; /* Nonzero when in standout mode. */
375 /* Size of window specified by higher levels.
376 This is the number of lines, from the top of frame downwards,
377 which can participate in insert-line/delete-line operations.
379 Effectively it excludes the bottom frame_lines - specified_window_size
380 lines from those operations. */
382 int specified_window;
384 /* Frame currently being redisplayed; 0 if not currently redisplaying.
385 (Direct output does not count). */
387 FRAME_PTR updating_frame;
389 /* Provided for lisp packages. */
391 static int system_uses_terminfo;
393 /* Flag used in tty_show/hide_cursor. */
395 static int tty_cursor_hidden;
397 char *tparam ();
399 extern char *tgetstr ();
402 #ifdef WINDOWSNT
403 /* We aren't X windows, but we aren't termcap either. This makes me
404 uncertain as to what value to use for frame.output_method. For
405 this file, we'll define FRAME_TERMCAP_P to be zero so that our
406 output hooks get called instead of the termcap functions. Probably
407 the best long-term solution is to define an output_windows_nt... */
409 #undef FRAME_TERMCAP_P
410 #define FRAME_TERMCAP_P(_f_) 0
411 #endif /* WINDOWSNT */
413 void
414 ring_bell ()
416 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
418 if (!NILP (Vring_bell_function))
420 Lisp_Object function;
422 /* Temporarily set the global variable to nil
423 so that if we get an error, it stays nil
424 and we don't call it over and over.
426 We don't specbind it, because that would carefully
427 restore the bad value if there's an error
428 and make the loop of errors happen anyway. */
430 function = Vring_bell_function;
431 Vring_bell_function = Qnil;
433 call0 (function);
435 Vring_bell_function = function;
437 else if (!FRAME_TERMCAP_P (f))
438 (*ring_bell_hook) ();
439 else {
440 struct tty_output *tty = FRAME_TTY (f);
441 OUTPUT (tty, TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell);
445 void
446 set_terminal_modes ()
448 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
449 if (FRAME_TERMCAP_P (f))
451 struct tty_output *tty = FRAME_TTY (f);
452 OUTPUT_IF (tty, TS_termcap_modes);
453 OUTPUT_IF (tty, TS_cursor_visible);
454 OUTPUT_IF (tty, TS_keypad_mode);
455 losecursor (tty);
457 else
458 (*set_terminal_modes_hook) ();
461 void
462 reset_terminal_modes ()
464 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
465 if (FRAME_TERMCAP_P (f))
467 struct tty_output *tty = FRAME_TTY (f);
468 turn_off_highlight ();
469 turn_off_insert ();
470 OUTPUT_IF (tty, TS_end_keypad_mode);
471 OUTPUT_IF (tty, TS_cursor_normal);
472 OUTPUT_IF (tty, TS_end_termcap_modes);
473 OUTPUT_IF (tty, TS_orig_pair);
474 /* Output raw CR so kernel can track the cursor hpos. */
475 current_tty = tty;
476 cmputc ('\r');
478 else if (reset_terminal_modes_hook)
479 (*reset_terminal_modes_hook) ();
482 void
483 update_begin (f)
484 struct frame *f;
486 updating_frame = f;
487 if (!FRAME_TERMCAP_P (f))
488 update_begin_hook (f);
491 void
492 update_end (f)
493 struct frame *f;
495 if (FRAME_TERMCAP_P (f))
497 if (!XWINDOW (selected_window)->cursor_off_p)
498 tty_show_cursor ();
499 turn_off_insert ();
500 background_highlight ();
502 else
503 update_end_hook (f);
505 updating_frame = NULL;
508 void
509 set_terminal_window (size)
510 int size;
512 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
513 if (FRAME_TERMCAP_P (f))
515 struct tty_output *tty = FRAME_TTY (f);
516 specified_window = size ? size : FRAME_LINES (f);
517 if (TTY_SCROLL_REGION_OK (tty))
518 set_scroll_region (0, specified_window);
520 else
521 set_terminal_window_hook (size);
524 void
525 set_scroll_region (start, stop)
526 int start, stop;
528 char *buf;
529 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
530 struct tty_output *tty = FRAME_TTY (f);
532 if (TS_set_scroll_region)
533 buf = tparam (TS_set_scroll_region, 0, 0, start, stop - 1);
534 else if (TS_set_scroll_region_1)
535 buf = tparam (TS_set_scroll_region_1, 0, 0,
536 FRAME_LINES (f), start,
537 FRAME_LINES (f) - stop,
538 FRAME_LINES (f));
539 else
540 buf = tparam (TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (f));
542 OUTPUT (tty, buf);
543 xfree (buf);
544 losecursor (tty);
548 static void
549 turn_on_insert ()
551 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
552 struct tty_output *tty = FRAME_TTY (f);
553 if (!insert_mode)
554 OUTPUT (tty, TS_insert_mode);
555 insert_mode = 1;
558 void
559 turn_off_insert ()
561 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
562 struct tty_output *tty = FRAME_TTY (f);
563 if (insert_mode)
564 OUTPUT (tty, TS_end_insert_mode);
565 insert_mode = 0;
568 /* Handle highlighting. */
570 void
571 turn_off_highlight ()
573 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
574 struct tty_output *tty = FRAME_TTY (f);
575 if (standout_mode)
576 OUTPUT_IF (tty, TS_end_standout_mode);
577 standout_mode = 0;
580 static void
581 turn_on_highlight ()
583 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
584 struct tty_output *tty = FRAME_TTY (f);
585 if (!standout_mode)
586 OUTPUT_IF (tty, TS_standout_mode);
587 standout_mode = 1;
590 static void
591 toggle_highlight ()
593 if (standout_mode)
594 turn_off_highlight ();
595 else
596 turn_on_highlight ();
600 /* Make cursor invisible. */
602 static void
603 tty_hide_cursor ()
605 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
606 struct tty_output *tty = FRAME_TTY (f);
607 if (tty_cursor_hidden == 0)
609 tty_cursor_hidden = 1;
610 OUTPUT_IF (tty, TS_cursor_invisible);
615 /* Ensure that cursor is visible. */
617 static void
618 tty_show_cursor ()
620 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
621 struct tty_output *tty = FRAME_TTY (f);
623 if (tty_cursor_hidden)
625 tty_cursor_hidden = 0;
626 OUTPUT_IF (tty, TS_cursor_normal);
627 OUTPUT_IF (tty, TS_cursor_visible);
632 /* Set standout mode to the state it should be in for
633 empty space inside windows. What this is,
634 depends on the user option inverse-video. */
636 void
637 background_highlight ()
639 if (inverse_video)
640 turn_on_highlight ();
641 else
642 turn_off_highlight ();
645 /* Set standout mode to the mode specified for the text to be output. */
647 static void
648 highlight_if_desired ()
650 if (inverse_video)
651 turn_on_highlight ();
652 else
653 turn_off_highlight ();
657 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
658 frame-relative coordinates. */
660 void
661 cursor_to (vpos, hpos)
662 int vpos, hpos;
664 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
666 if (! FRAME_TERMCAP_P (f) && cursor_to_hook)
668 (*cursor_to_hook) (vpos, hpos);
669 return;
672 struct tty_output *tty = FRAME_TTY (f);
674 /* Detect the case where we are called from reset_sys_modes
675 and the costs have never been calculated. Do nothing. */
676 if (! costs_set)
677 return;
679 if (curY (tty) == vpos
680 && curX (tty) == hpos)
681 return;
682 if (!TF_standout_motion)
683 background_highlight ();
684 if (!TF_insmode_motion)
685 turn_off_insert ();
686 cmgoto (tty, vpos, hpos);
689 /* Similar but don't take any account of the wasted characters. */
691 void
692 raw_cursor_to (row, col)
693 int row, col;
695 struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
696 if (! FRAME_TERMCAP_P (f))
698 (*raw_cursor_to_hook) (row, col);
699 return;
701 struct tty_output *tty = FRAME_TTY (f);
702 if (curY (tty) == row
703 && curX (tty) == col)
704 return;
705 if (!TF_standout_motion)
706 background_highlight ();
707 if (!TF_insmode_motion)
708 turn_off_insert ();
709 cmgoto (tty, row, col);
712 /* Erase operations */
714 /* clear from cursor to end of frame */
715 void
716 clear_to_end ()
718 register int i;
720 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
722 if (clear_to_end_hook && ! FRAME_TERMCAP_P (f))
724 (*clear_to_end_hook) ();
725 return;
727 struct tty_output *tty = FRAME_TTY (f);
728 if (TS_clr_to_bottom)
730 background_highlight ();
731 OUTPUT (tty, TS_clr_to_bottom);
733 else
735 for (i = curY (tty); i < FRAME_LINES (f); i++)
737 cursor_to (i, 0);
738 clear_end_of_line (FRAME_COLS (f));
743 /* Clear entire frame */
745 void
746 clear_frame ()
748 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
750 if (clear_frame_hook && ! FRAME_TERMCAP_P (f))
752 (*clear_frame_hook) ();
753 return;
755 struct tty_output *tty = FRAME_TTY (f);
756 if (TS_clr_frame)
758 background_highlight ();
759 OUTPUT (tty, TS_clr_frame);
760 cmat (tty, 0, 0);
762 else
764 cursor_to (0, 0);
765 clear_to_end ();
769 /* Clear from cursor to end of line.
770 Assume that the line is already clear starting at column first_unused_hpos.
772 Note that the cursor may be moved, on terminals lacking a `ce' string. */
774 void
775 clear_end_of_line (first_unused_hpos)
776 int first_unused_hpos;
778 register int i;
780 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
782 if (clear_end_of_line_hook
783 && ! FRAME_TERMCAP_P (f))
785 (*clear_end_of_line_hook) (first_unused_hpos);
786 return;
789 struct tty_output *tty = FRAME_TTY (f);
791 /* Detect the case where we are called from reset_sys_modes
792 and the costs have never been calculated. Do nothing. */
793 if (! costs_set)
794 return;
796 if (curX (tty) >= first_unused_hpos)
797 return;
798 background_highlight ();
799 if (TS_clr_line)
801 OUTPUT1 (tty, TS_clr_line);
803 else
804 { /* have to do it the hard way */
805 turn_off_insert ();
807 /* Do not write in last row last col with Auto-wrap on. */
808 if (AutoWrap (tty)
809 && curY (tty) == FRAME_LINES (f) - 1
810 && first_unused_hpos == FRAME_COLS (f))
811 first_unused_hpos--;
813 for (i = curX (tty); i < first_unused_hpos; i++)
815 if (TTY_TERMSCRIPT (tty))
816 fputc (' ', TTY_TERMSCRIPT (tty));
817 fputc (' ', TTY_OUTPUT (tty));
819 cmplus (tty, first_unused_hpos - curX (tty));
823 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes and
824 store them at DST. Do not write more than DST_LEN bytes. That may
825 require stopping before all SRC_LEN input glyphs have been
826 converted.
828 We store the number of glyphs actually converted in *CONSUMED. The
829 return value is the number of bytes store in DST. */
832 encode_terminal_code (src, dst, src_len, dst_len, consumed)
833 struct glyph *src;
834 int src_len;
835 unsigned char *dst;
836 int dst_len, *consumed;
838 struct glyph *src_start = src, *src_end = src + src_len;
839 unsigned char *dst_start = dst, *dst_end = dst + dst_len;
840 register GLYPH g;
841 unsigned char workbuf[MAX_MULTIBYTE_LENGTH];
842 const unsigned char *buf;
843 int len;
844 register int tlen = GLYPH_TABLE_LENGTH;
845 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
846 int result;
847 struct coding_system *coding;
849 /* If terminal_coding does any conversion, use it, otherwise use
850 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
851 because it always return 1 if the member src_multibyte is 1. */
852 coding = (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK
853 ? &terminal_coding
854 : &safe_terminal_coding);
856 while (src < src_end)
858 /* We must skip glyphs to be padded for a wide character. */
859 if (! CHAR_GLYPH_PADDING_P (*src))
861 g = GLYPH_FROM_CHAR_GLYPH (src[0]);
863 if (g < 0 || g >= tlen)
865 /* This glyph doesn't has an entry in Vglyph_table. */
866 if (! CHAR_VALID_P (src->u.ch, 0))
868 len = 1;
869 buf = " ";
870 coding->src_multibyte = 0;
872 else
874 len = CHAR_STRING (src->u.ch, workbuf);
875 buf = workbuf;
876 coding->src_multibyte = 1;
879 else
881 /* This glyph has an entry in Vglyph_table,
882 so process any alias before testing for simpleness. */
883 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
885 if (GLYPH_SIMPLE_P (tbase, tlen, g))
887 /* We set the multi-byte form of a character in G
888 (that should be an ASCII character) at
889 WORKBUF. */
890 workbuf[0] = FAST_GLYPH_CHAR (g);
891 len = 1;
892 buf = workbuf;
893 coding->src_multibyte = 0;
895 else
897 /* We have a string in Vglyph_table. */
898 len = GLYPH_LENGTH (tbase, g);
899 buf = GLYPH_STRING (tbase, g);
900 coding->src_multibyte = STRING_MULTIBYTE (tbase[g]);
904 result = encode_coding (coding, buf, dst, len, dst_end - dst);
905 len -= coding->consumed;
906 dst += coding->produced;
907 if (result == CODING_FINISH_INSUFFICIENT_DST
908 || (result == CODING_FINISH_INSUFFICIENT_SRC
909 && len > dst_end - dst))
910 /* The remaining output buffer is too short. We must
911 break the loop here without increasing SRC so that the
912 next call of this function starts from the same glyph. */
913 break;
915 if (len > 0)
917 /* This is the case that a code of the range 0200..0237
918 exists in buf. We must just write out such a code. */
919 buf += coding->consumed;
920 while (len--)
921 *dst++ = *buf++;
924 src++;
927 *consumed = src - src_start;
928 return (dst - dst_start);
932 void
933 write_glyphs (string, len)
934 register struct glyph *string;
935 register int len;
937 int produced, consumed;
938 struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
939 unsigned char conversion_buffer[1024];
940 int conversion_buffer_size = sizeof conversion_buffer;
942 if (write_glyphs_hook
943 && ! FRAME_TERMCAP_P (f))
945 (*write_glyphs_hook) (string, len);
946 return;
949 struct tty_output *tty = FRAME_TTY (f);
951 turn_off_insert ();
952 tty_hide_cursor ();
954 /* Don't dare write in last column of bottom line, if Auto-Wrap,
955 since that would scroll the whole frame on some terminals. */
957 if (AutoWrap (tty)
958 && curY (tty) + 1 == FRAME_LINES (f)
959 && (curX (tty) + len) == FRAME_COLS (f))
960 len --;
961 if (len <= 0)
962 return;
964 cmplus (tty, len);
966 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
967 the tail. */
968 terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
970 while (len > 0)
972 /* Identify a run of glyphs with the same face. */
973 int face_id = string->face_id;
974 int n;
976 for (n = 1; n < len; ++n)
977 if (string[n].face_id != face_id)
978 break;
980 /* Turn appearance modes of the face of the run on. */
981 highlight_if_desired ();
982 turn_on_face (f, face_id);
984 while (n > 0)
986 /* We use a fixed size (1024 bytes) of conversion buffer.
987 Usually it is sufficient, but if not, we just repeat the
988 loop. */
989 produced = encode_terminal_code (string, conversion_buffer,
990 n, conversion_buffer_size,
991 &consumed);
992 if (produced > 0)
994 fwrite (conversion_buffer, 1, produced,
995 TTY_OUTPUT (tty));
996 if (ferror (TTY_OUTPUT (tty)))
997 clearerr (TTY_OUTPUT (tty));
998 if (TTY_TERMSCRIPT (tty))
999 fwrite (conversion_buffer, 1, produced,
1000 TTY_TERMSCRIPT (tty));
1002 len -= consumed;
1003 n -= consumed;
1004 string += consumed;
1007 /* Turn appearance modes off. */
1008 turn_off_face (f, face_id);
1009 turn_off_highlight ();
1012 /* We may have to output some codes to terminate the writing. */
1013 if (CODING_REQUIRE_FLUSHING (&terminal_coding))
1015 terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
1016 encode_coding (&terminal_coding, "", conversion_buffer,
1017 0, conversion_buffer_size);
1018 if (terminal_coding.produced > 0)
1020 fwrite (conversion_buffer, 1, terminal_coding.produced,
1021 TTY_OUTPUT (tty));
1022 if (ferror (TTY_OUTPUT (tty)))
1023 clearerr (TTY_OUTPUT (tty));
1024 if (TTY_TERMSCRIPT (tty))
1025 fwrite (conversion_buffer, 1, terminal_coding.produced,
1026 TTY_TERMSCRIPT (tty));
1030 cmcheckmagic (tty);
1033 /* If start is zero, insert blanks instead of a string at start */
1035 void
1036 insert_glyphs (start, len)
1037 register struct glyph *start;
1038 register int len;
1040 char *buf;
1041 struct glyph *glyph = NULL;
1042 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
1044 if (len <= 0)
1045 return;
1047 if (insert_glyphs_hook && ! FRAME_TERMCAP_P (f))
1049 (*insert_glyphs_hook) (start, len);
1050 return;
1053 struct tty_output *tty = FRAME_TTY (f);
1055 if (TS_ins_multi_chars)
1057 buf = tparam (TS_ins_multi_chars, 0, 0, len);
1058 OUTPUT1 (tty, buf);
1059 xfree (buf);
1060 if (start)
1061 write_glyphs (start, len);
1062 return;
1065 turn_on_insert ();
1066 cmplus (tty, len);
1067 /* The bit CODING_MODE_LAST_BLOCK should be set to 1 only at the tail. */
1068 terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
1069 while (len-- > 0)
1071 int produced, consumed;
1072 unsigned char conversion_buffer[1024];
1073 int conversion_buffer_size = sizeof conversion_buffer;
1075 OUTPUT1_IF (tty, TS_ins_char);
1076 if (!start)
1078 conversion_buffer[0] = SPACEGLYPH;
1079 produced = 1;
1081 else
1083 highlight_if_desired ();
1084 turn_on_face (f, start->face_id);
1085 glyph = start;
1086 ++start;
1087 /* We must open sufficient space for a character which
1088 occupies more than one column. */
1089 while (len && CHAR_GLYPH_PADDING_P (*start))
1091 OUTPUT1_IF (tty, TS_ins_char);
1092 start++, len--;
1095 if (len <= 0)
1096 /* This is the last glyph. */
1097 terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
1099 /* The size of conversion buffer (1024 bytes) is surely
1100 sufficient for just one glyph. */
1101 produced = encode_terminal_code (glyph, conversion_buffer, 1,
1102 conversion_buffer_size, &consumed);
1105 if (produced > 0)
1107 fwrite (conversion_buffer, 1, produced,
1108 TTY_OUTPUT (tty));
1109 if (ferror (TTY_OUTPUT (tty)))
1110 clearerr (TTY_OUTPUT (tty));
1111 if (TTY_TERMSCRIPT (tty))
1112 fwrite (conversion_buffer, 1, produced,
1113 TTY_TERMSCRIPT (tty));
1116 OUTPUT1_IF (tty, TS_pad_inserted_char);
1117 if (start)
1119 turn_off_face (f, glyph->face_id);
1120 turn_off_highlight ();
1124 cmcheckmagic (tty);
1127 void
1128 delete_glyphs (n)
1129 register int n;
1131 char *buf;
1132 register int i;
1133 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
1134 struct tty_output *tty = FRAME_TTY (f);
1136 if (delete_glyphs_hook && ! FRAME_TERMCAP_P (f))
1138 (*delete_glyphs_hook) (n);
1139 return;
1143 if (delete_in_insert_mode)
1145 turn_on_insert ();
1147 else
1149 turn_off_insert ();
1150 OUTPUT_IF (tty, TS_delete_mode);
1153 if (TS_del_multi_chars)
1155 buf = tparam (TS_del_multi_chars, 0, 0, n);
1156 OUTPUT1 (tty, buf);
1157 xfree (buf);
1159 else
1160 for (i = 0; i < n; i++)
1161 OUTPUT1 (tty, TS_del_char);
1162 if (!delete_in_insert_mode)
1163 OUTPUT_IF (tty, TS_end_delete_mode);
1166 /* Insert N lines at vpos VPOS. If N is negative, delete -N lines. */
1168 void
1169 ins_del_lines (vpos, n)
1170 int vpos, n;
1172 char *multi = n > 0 ? TS_ins_multi_lines : TS_del_multi_lines;
1173 char *single = n > 0 ? TS_ins_line : TS_del_line;
1174 char *scroll = n > 0 ? TS_rev_scroll : TS_fwd_scroll;
1175 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
1177 register int i = n > 0 ? n : -n;
1178 register char *buf;
1180 if (ins_del_lines_hook && ! FRAME_TERMCAP_P (f))
1182 (*ins_del_lines_hook) (vpos, n);
1183 return;
1186 struct tty_output *tty = FRAME_TTY (f);
1188 /* If the lines below the insertion are being pushed
1189 into the end of the window, this is the same as clearing;
1190 and we know the lines are already clear, since the matching
1191 deletion has already been done. So can ignore this. */
1192 /* If the lines below the deletion are blank lines coming
1193 out of the end of the window, don't bother,
1194 as there will be a matching inslines later that will flush them. */
1195 if (TTY_SCROLL_REGION_OK (tty)
1196 && vpos + i >= specified_window)
1197 return;
1198 if (!TTY_MEMORY_BELOW_FRAME (tty)
1199 && vpos + i >= FRAME_LINES (f))
1200 return;
1202 if (multi)
1204 raw_cursor_to (vpos, 0);
1205 background_highlight ();
1206 buf = tparam (multi, 0, 0, i);
1207 OUTPUT (tty, buf);
1208 xfree (buf);
1210 else if (single)
1212 raw_cursor_to (vpos, 0);
1213 background_highlight ();
1214 while (--i >= 0)
1215 OUTPUT (tty, single);
1216 if (TF_teleray)
1217 curX (tty) = 0;
1219 else
1221 set_scroll_region (vpos, specified_window);
1222 if (n < 0)
1223 raw_cursor_to (specified_window - 1, 0);
1224 else
1225 raw_cursor_to (vpos, 0);
1226 background_highlight ();
1227 while (--i >= 0)
1228 OUTPUTL (tty, scroll, specified_window - vpos);
1229 set_scroll_region (0, specified_window);
1232 if (!TTY_SCROLL_REGION_OK (tty)
1233 && TTY_MEMORY_BELOW_FRAME (tty)
1234 && n < 0)
1236 cursor_to (FRAME_LINES (f) + n, 0);
1237 clear_to_end ();
1241 /* Compute cost of sending "str", in characters,
1242 not counting any line-dependent padding. */
1245 string_cost (str)
1246 char *str;
1248 cost = 0;
1249 if (str)
1250 tputs (str, 0, evalcost);
1251 return cost;
1254 /* Compute cost of sending "str", in characters,
1255 counting any line-dependent padding at one line. */
1257 static int
1258 string_cost_one_line (str)
1259 char *str;
1261 cost = 0;
1262 if (str)
1263 tputs (str, 1, evalcost);
1264 return cost;
1267 /* Compute per line amount of line-dependent padding,
1268 in tenths of characters. */
1271 per_line_cost (str)
1272 register char *str;
1274 cost = 0;
1275 if (str)
1276 tputs (str, 0, evalcost);
1277 cost = - cost;
1278 if (str)
1279 tputs (str, 10, evalcost);
1280 return cost;
1283 #ifndef old
1284 /* char_ins_del_cost[n] is cost of inserting N characters.
1285 char_ins_del_cost[-n] is cost of deleting N characters.
1286 The length of this vector is based on max_frame_cols. */
1288 int *char_ins_del_vector;
1290 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
1291 #endif
1293 /* ARGSUSED */
1294 static void
1295 calculate_ins_del_char_costs (frame)
1296 FRAME_PTR frame;
1298 int ins_startup_cost, del_startup_cost;
1299 int ins_cost_per_char, del_cost_per_char;
1300 register int i;
1301 register int *p;
1303 if (TS_ins_multi_chars)
1305 ins_cost_per_char = 0;
1306 ins_startup_cost = string_cost_one_line (TS_ins_multi_chars);
1308 else if (TS_ins_char || TS_pad_inserted_char
1309 || (TS_insert_mode && TS_end_insert_mode))
1311 ins_startup_cost = (30 * (string_cost (TS_insert_mode)
1312 + string_cost (TS_end_insert_mode))) / 100;
1313 ins_cost_per_char = (string_cost_one_line (TS_ins_char)
1314 + string_cost_one_line (TS_pad_inserted_char));
1316 else
1318 ins_startup_cost = 9999;
1319 ins_cost_per_char = 0;
1322 if (TS_del_multi_chars)
1324 del_cost_per_char = 0;
1325 del_startup_cost = string_cost_one_line (TS_del_multi_chars);
1327 else if (TS_del_char)
1329 del_startup_cost = (string_cost (TS_delete_mode)
1330 + string_cost (TS_end_delete_mode));
1331 if (delete_in_insert_mode)
1332 del_startup_cost /= 2;
1333 del_cost_per_char = string_cost_one_line (TS_del_char);
1335 else
1337 del_startup_cost = 9999;
1338 del_cost_per_char = 0;
1341 /* Delete costs are at negative offsets */
1342 p = &char_ins_del_cost (frame)[0];
1343 for (i = FRAME_COLS (frame); --i >= 0;)
1344 *--p = (del_startup_cost += del_cost_per_char);
1346 /* Doing nothing is free */
1347 p = &char_ins_del_cost (frame)[0];
1348 *p++ = 0;
1350 /* Insert costs are at positive offsets */
1351 for (i = FRAME_COLS (frame); --i >= 0;)
1352 *p++ = (ins_startup_cost += ins_cost_per_char);
1355 void
1356 calculate_costs (frame)
1357 FRAME_PTR frame;
1359 register char *f = (TS_set_scroll_region
1360 ? TS_set_scroll_region
1361 : TS_set_scroll_region_1);
1363 FRAME_COST_BAUD_RATE (frame) = baud_rate;
1365 if (FRAME_TERMCAP_P (frame))
1366 TTY_SCROLL_REGION_COST (frame->output_data.tty) = string_cost (f);
1368 /* These variables are only used for terminal stuff. They are allocated
1369 once for the terminal frame of X-windows emacs, but not used afterwards.
1371 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1372 X turns off char_ins_del_ok. */
1374 max_frame_lines = max (max_frame_lines, FRAME_LINES (frame));
1375 max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
1377 costs_set = 1;
1379 if (char_ins_del_vector != 0)
1380 char_ins_del_vector
1381 = (int *) xrealloc (char_ins_del_vector,
1382 (sizeof (int)
1383 + 2 * max_frame_cols * sizeof (int)));
1384 else
1385 char_ins_del_vector
1386 = (int *) xmalloc (sizeof (int)
1387 + 2 * max_frame_cols * sizeof (int));
1389 bzero (char_ins_del_vector, (sizeof (int)
1390 + 2 * max_frame_cols * sizeof (int)));
1392 if (f && (!TS_ins_line && !TS_del_line))
1393 do_line_insertion_deletion_costs (frame,
1394 TS_rev_scroll, TS_ins_multi_lines,
1395 TS_fwd_scroll, TS_del_multi_lines,
1396 f, f, 1);
1397 else
1398 do_line_insertion_deletion_costs (frame,
1399 TS_ins_line, TS_ins_multi_lines,
1400 TS_del_line, TS_del_multi_lines,
1401 0, 0, 1);
1403 calculate_ins_del_char_costs (frame);
1405 /* Don't use TS_repeat if its padding is worse than sending the chars */
1406 if (TS_repeat && per_line_cost (TS_repeat) * baud_rate < 9000)
1407 RPov = string_cost (TS_repeat);
1408 else
1409 RPov = FRAME_COLS (frame) * 2;
1411 cmcostinit (FRAME_TTY (frame)); /* set up cursor motion costs */
1414 struct fkey_table {
1415 char *cap, *name;
1418 /* Termcap capability names that correspond directly to X keysyms.
1419 Some of these (marked "terminfo") aren't supplied by old-style
1420 (Berkeley) termcap entries. They're listed in X keysym order;
1421 except we put the keypad keys first, so that if they clash with
1422 other keys (as on the IBM PC keyboard) they get overridden.
1425 static struct fkey_table keys[] =
1427 {"kh", "home"}, /* termcap */
1428 {"kl", "left"}, /* termcap */
1429 {"ku", "up"}, /* termcap */
1430 {"kr", "right"}, /* termcap */
1431 {"kd", "down"}, /* termcap */
1432 {"%8", "prior"}, /* terminfo */
1433 {"%5", "next"}, /* terminfo */
1434 {"@7", "end"}, /* terminfo */
1435 {"@1", "begin"}, /* terminfo */
1436 {"*6", "select"}, /* terminfo */
1437 {"%9", "print"}, /* terminfo */
1438 {"@4", "execute"}, /* terminfo --- actually the `command' key */
1440 * "insert" --- see below
1442 {"&8", "undo"}, /* terminfo */
1443 {"%0", "redo"}, /* terminfo */
1444 {"%7", "menu"}, /* terminfo --- actually the `options' key */
1445 {"@0", "find"}, /* terminfo */
1446 {"@2", "cancel"}, /* terminfo */
1447 {"%1", "help"}, /* terminfo */
1449 * "break" goes here, but can't be reliably intercepted with termcap
1451 {"&4", "reset"}, /* terminfo --- actually `restart' */
1453 * "system" and "user" --- no termcaps
1455 {"kE", "clearline"}, /* terminfo */
1456 {"kA", "insertline"}, /* terminfo */
1457 {"kL", "deleteline"}, /* terminfo */
1458 {"kI", "insertchar"}, /* terminfo */
1459 {"kD", "deletechar"}, /* terminfo */
1460 {"kB", "backtab"}, /* terminfo */
1462 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1464 {"@8", "kp-enter"}, /* terminfo */
1466 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1467 * "kp-multiply", "kp-add", "kp-separator",
1468 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1469 * --- no termcaps for any of these.
1471 {"K4", "kp-1"}, /* terminfo */
1473 * "kp-2" --- no termcap
1475 {"K5", "kp-3"}, /* terminfo */
1477 * "kp-4" --- no termcap
1479 {"K2", "kp-5"}, /* terminfo */
1481 * "kp-6" --- no termcap
1483 {"K1", "kp-7"}, /* terminfo */
1485 * "kp-8" --- no termcap
1487 {"K3", "kp-9"}, /* terminfo */
1489 * "kp-equal" --- no termcap
1491 {"k1", "f1"},
1492 {"k2", "f2"},
1493 {"k3", "f3"},
1494 {"k4", "f4"},
1495 {"k5", "f5"},
1496 {"k6", "f6"},
1497 {"k7", "f7"},
1498 {"k8", "f8"},
1499 {"k9", "f9"}
1502 static char **term_get_fkeys_arg;
1503 static Lisp_Object term_get_fkeys_1 ();
1505 /* Find the escape codes sent by the function keys for Vfunction_key_map.
1506 This function scans the termcap function key sequence entries, and
1507 adds entries to Vfunction_key_map for each function key it finds. */
1509 void
1510 term_get_fkeys (address)
1511 char **address;
1513 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1514 errors during the call. The only errors should be from Fdefine_key
1515 when given a key sequence containing an invalid prefix key. If the
1516 termcap defines function keys which use a prefix that is already bound
1517 to a command by the default bindings, we should silently ignore that
1518 function key specification, rather than giving the user an error and
1519 refusing to run at all on such a terminal. */
1521 extern Lisp_Object Fidentity ();
1522 term_get_fkeys_arg = address;
1523 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1526 static Lisp_Object
1527 term_get_fkeys_1 ()
1529 int i;
1531 char **address = term_get_fkeys_arg;
1533 /* This can happen if CANNOT_DUMP or with strange options. */
1534 if (!initialized)
1535 Vfunction_key_map = Fmake_sparse_keymap (Qnil);
1537 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1539 char *sequence = tgetstr (keys[i].cap, address);
1540 if (sequence)
1541 Fdefine_key (Vfunction_key_map, build_string (sequence),
1542 Fmake_vector (make_number (1),
1543 intern (keys[i].name)));
1546 /* The uses of the "k0" capability are inconsistent; sometimes it
1547 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1548 We will attempt to politely accommodate both systems by testing for
1549 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1552 char *k_semi = tgetstr ("k;", address);
1553 char *k0 = tgetstr ("k0", address);
1554 char *k0_name = "f10";
1556 if (k_semi)
1558 if (k0)
1559 /* Define f0 first, so that f10 takes precedence in case the
1560 key sequences happens to be the same. */
1561 Fdefine_key (Vfunction_key_map, build_string (k0),
1562 Fmake_vector (make_number (1), intern ("f0")));
1563 Fdefine_key (Vfunction_key_map, build_string (k_semi),
1564 Fmake_vector (make_number (1), intern ("f10")));
1566 else if (k0)
1567 Fdefine_key (Vfunction_key_map, build_string (k0),
1568 Fmake_vector (make_number (1), intern (k0_name)));
1571 /* Set up cookies for numbered function keys above f10. */
1573 char fcap[3], fkey[4];
1575 fcap[0] = 'F'; fcap[2] = '\0';
1576 for (i = 11; i < 64; i++)
1578 if (i <= 19)
1579 fcap[1] = '1' + i - 11;
1580 else if (i <= 45)
1581 fcap[1] = 'A' + i - 20;
1582 else
1583 fcap[1] = 'a' + i - 46;
1586 char *sequence = tgetstr (fcap, address);
1587 if (sequence)
1589 sprintf (fkey, "f%d", i);
1590 Fdefine_key (Vfunction_key_map, build_string (sequence),
1591 Fmake_vector (make_number (1),
1592 intern (fkey)));
1599 * Various mappings to try and get a better fit.
1602 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1603 if (!tgetstr (cap1, address)) \
1605 char *sequence = tgetstr (cap2, address); \
1606 if (sequence) \
1607 Fdefine_key (Vfunction_key_map, build_string (sequence), \
1608 Fmake_vector (make_number (1), \
1609 intern (sym))); \
1612 /* if there's no key_next keycap, map key_npage to `next' keysym */
1613 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1614 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1615 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1616 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1617 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1618 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1619 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1621 /* IBM has their own non-standard dialect of terminfo.
1622 If the standard name isn't found, try the IBM name. */
1623 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1624 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1625 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1626 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1627 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1628 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1629 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1630 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1631 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1632 #undef CONDITIONAL_REASSIGN
1635 return Qnil;
1639 /***********************************************************************
1640 Character Display Information
1641 ***********************************************************************/
1643 static void append_glyph P_ ((struct it *));
1646 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1647 terminal frames if IT->glyph_row != NULL. IT->c is the character
1648 for which to produce glyphs; IT->face_id contains the character's
1649 face. Padding glyphs are appended if IT->c has a IT->pixel_width >
1650 1. */
1652 static void
1653 append_glyph (it)
1654 struct it *it;
1656 struct glyph *glyph, *end;
1657 int i;
1659 xassert (it->glyph_row);
1660 glyph = (it->glyph_row->glyphs[it->area]
1661 + it->glyph_row->used[it->area]);
1662 end = it->glyph_row->glyphs[1 + it->area];
1664 for (i = 0;
1665 i < it->pixel_width && glyph < end;
1666 ++i)
1668 glyph->type = CHAR_GLYPH;
1669 glyph->pixel_width = 1;
1670 glyph->u.ch = it->c;
1671 glyph->face_id = it->face_id;
1672 glyph->padding_p = i > 0;
1673 glyph->charpos = CHARPOS (it->position);
1674 glyph->object = it->object;
1676 ++it->glyph_row->used[it->area];
1677 ++glyph;
1682 /* Produce glyphs for the display element described by IT. *IT
1683 specifies what we want to produce a glyph for (character, image, ...),
1684 and where in the glyph matrix we currently are (glyph row and hpos).
1685 produce_glyphs fills in output fields of *IT with information such as the
1686 pixel width and height of a character, and maybe output actual glyphs at
1687 the same time if IT->glyph_row is non-null. See the explanation of
1688 struct display_iterator in dispextern.h for an overview.
1690 produce_glyphs also stores the result of glyph width, ascent
1691 etc. computations in *IT.
1693 IT->glyph_row may be null, in which case produce_glyphs does not
1694 actually fill in the glyphs. This is used in the move_* functions
1695 in xdisp.c for text width and height computations.
1697 Callers usually don't call produce_glyphs directly;
1698 instead they use the macro PRODUCE_GLYPHS. */
1700 void
1701 produce_glyphs (it)
1702 struct it *it;
1704 /* If a hook is installed, let it do the work. */
1705 xassert (it->what == IT_CHARACTER
1706 || it->what == IT_COMPOSITION
1707 || it->what == IT_IMAGE
1708 || it->what == IT_STRETCH);
1710 /* Nothing but characters are supported on terminal frames. For a
1711 composition sequence, it->c is the first character of the
1712 sequence. */
1713 xassert (it->what == IT_CHARACTER
1714 || it->what == IT_COMPOSITION);
1716 if (it->c >= 040 && it->c < 0177)
1718 it->pixel_width = it->nglyphs = 1;
1719 if (it->glyph_row)
1720 append_glyph (it);
1722 else if (it->c == '\n')
1723 it->pixel_width = it->nglyphs = 0;
1724 else if (it->c == '\t')
1726 int absolute_x = (it->current_x
1727 + it->continuation_lines_width);
1728 int next_tab_x
1729 = (((1 + absolute_x + it->tab_width - 1)
1730 / it->tab_width)
1731 * it->tab_width);
1732 int nspaces;
1734 /* If part of the TAB has been displayed on the previous line
1735 which is continued now, continuation_lines_width will have
1736 been incremented already by the part that fitted on the
1737 continued line. So, we will get the right number of spaces
1738 here. */
1739 nspaces = next_tab_x - absolute_x;
1741 if (it->glyph_row)
1743 int n = nspaces;
1745 it->c = ' ';
1746 it->pixel_width = it->len = 1;
1748 while (n--)
1749 append_glyph (it);
1751 it->c = '\t';
1754 it->pixel_width = nspaces;
1755 it->nglyphs = nspaces;
1757 else if (SINGLE_BYTE_CHAR_P (it->c))
1759 /* Coming here means that it->c is from display table, thus we
1760 must send the code as is to the terminal. Although there's
1761 no way to know how many columns it occupies on a screen, it
1762 is a good assumption that a single byte code has 1-column
1763 width. */
1764 it->pixel_width = it->nglyphs = 1;
1765 if (it->glyph_row)
1766 append_glyph (it);
1768 else
1770 /* A multi-byte character. The display width is fixed for all
1771 characters of the set. Some of the glyphs may have to be
1772 ignored because they are already displayed in a continued
1773 line. */
1774 int charset = CHAR_CHARSET (it->c);
1776 it->pixel_width = CHARSET_WIDTH (charset);
1777 it->nglyphs = it->pixel_width;
1779 if (it->glyph_row)
1780 append_glyph (it);
1783 /* Advance current_x by the pixel width as a convenience for
1784 the caller. */
1785 if (it->area == TEXT_AREA)
1786 it->current_x += it->pixel_width;
1787 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1788 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
1792 /* Get information about special display element WHAT in an
1793 environment described by IT. WHAT is one of IT_TRUNCATION or
1794 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1795 non-null glyph_row member. This function ensures that fields like
1796 face_id, c, len of IT are left untouched. */
1798 void
1799 produce_special_glyphs (it, what)
1800 struct it *it;
1801 enum display_element_type what;
1803 struct it temp_it;
1805 temp_it = *it;
1806 temp_it.dp = NULL;
1807 temp_it.what = IT_CHARACTER;
1808 temp_it.len = 1;
1809 temp_it.object = make_number (0);
1810 bzero (&temp_it.current, sizeof temp_it.current);
1812 if (what == IT_CONTINUATION)
1814 /* Continuation glyph. */
1815 if (it->dp
1816 && INTEGERP (DISP_CONTINUE_GLYPH (it->dp))
1817 && GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (it->dp))))
1819 temp_it.c = FAST_GLYPH_CHAR (XINT (DISP_CONTINUE_GLYPH (it->dp)));
1820 temp_it.len = CHAR_BYTES (temp_it.c);
1822 else
1823 temp_it.c = '\\';
1825 produce_glyphs (&temp_it);
1826 it->pixel_width = temp_it.pixel_width;
1827 it->nglyphs = temp_it.pixel_width;
1829 else if (what == IT_TRUNCATION)
1831 /* Truncation glyph. */
1832 if (it->dp
1833 && INTEGERP (DISP_TRUNC_GLYPH (it->dp))
1834 && GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (it->dp))))
1836 temp_it.c = FAST_GLYPH_CHAR (XINT (DISP_TRUNC_GLYPH (it->dp)));
1837 temp_it.len = CHAR_BYTES (temp_it.c);
1839 else
1840 temp_it.c = '$';
1842 produce_glyphs (&temp_it);
1843 it->pixel_width = temp_it.pixel_width;
1844 it->nglyphs = temp_it.pixel_width;
1846 else
1847 abort ();
1852 /***********************************************************************
1853 Faces
1854 ***********************************************************************/
1856 /* Value is non-zero if attribute ATTR may be used. ATTR should be
1857 one of the enumerators from enum no_color_bit, or a bit set built
1858 from them. Some display attributes may not be used together with
1859 color; the termcap capability `NC' specifies which ones. */
1861 #define MAY_USE_WITH_COLORS_P(ATTR) \
1862 (TN_max_colors > 0 \
1863 ? (TN_no_color_video & (ATTR)) == 0 \
1864 : 1)
1866 /* Turn appearances of face FACE_ID on tty frame F on. */
1868 static void
1869 turn_on_face (f, face_id)
1870 struct frame *f;
1871 int face_id;
1873 struct face *face = FACE_FROM_ID (f, face_id);
1874 long fg = face->foreground;
1875 long bg = face->background;
1876 struct tty_output *tty = FRAME_TTY (f);
1878 /* Do this first because TS_end_standout_mode may be the same
1879 as TS_exit_attribute_mode, which turns all appearances off. */
1880 if (MAY_USE_WITH_COLORS_P (NC_REVERSE))
1882 if (TN_max_colors > 0)
1884 if (fg >= 0 && bg >= 0)
1886 /* If the terminal supports colors, we can set them
1887 below without using reverse video. The face's fg
1888 and bg colors are set as they should appear on
1889 the screen, i.e. they take the inverse-video'ness
1890 of the face already into account. */
1892 else if (inverse_video)
1894 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1895 || bg == FACE_TTY_DEFAULT_BG_COLOR)
1896 toggle_highlight ();
1898 else
1900 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1901 || bg == FACE_TTY_DEFAULT_FG_COLOR)
1902 toggle_highlight ();
1905 else
1907 /* If we can't display colors, use reverse video
1908 if the face specifies that. */
1909 if (inverse_video)
1911 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1912 || bg == FACE_TTY_DEFAULT_BG_COLOR)
1913 toggle_highlight ();
1915 else
1917 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1918 || bg == FACE_TTY_DEFAULT_FG_COLOR)
1919 toggle_highlight ();
1924 if (face->tty_bold_p)
1926 if (MAY_USE_WITH_COLORS_P (NC_BOLD))
1927 OUTPUT1_IF (tty, TS_enter_bold_mode);
1929 else if (face->tty_dim_p)
1930 if (MAY_USE_WITH_COLORS_P (NC_DIM))
1931 OUTPUT1_IF (tty, TS_enter_dim_mode);
1933 /* Alternate charset and blinking not yet used. */
1934 if (face->tty_alt_charset_p
1935 && MAY_USE_WITH_COLORS_P (NC_ALT_CHARSET))
1936 OUTPUT1_IF (tty, TS_enter_alt_charset_mode);
1938 if (face->tty_blinking_p
1939 && MAY_USE_WITH_COLORS_P (NC_BLINK))
1940 OUTPUT1_IF (tty, TS_enter_blink_mode);
1942 if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (NC_UNDERLINE))
1943 OUTPUT1_IF (tty, TS_enter_underline_mode);
1945 if (TN_max_colors > 0)
1947 char *p;
1949 if (fg >= 0 && TS_set_foreground)
1951 p = tparam (TS_set_foreground, NULL, 0, (int) fg);
1952 OUTPUT (tty, p);
1953 xfree (p);
1956 if (bg >= 0 && TS_set_background)
1958 p = tparam (TS_set_background, NULL, 0, (int) bg);
1959 OUTPUT (tty, p);
1960 xfree (p);
1966 /* Turn off appearances of face FACE_ID on tty frame F. */
1968 static void
1969 turn_off_face (f, face_id)
1970 struct frame *f;
1971 int face_id;
1973 struct face *face = FACE_FROM_ID (f, face_id);
1974 struct tty_output *tty = FRAME_TTY (f);
1976 xassert (face != NULL);
1978 if (TS_exit_attribute_mode)
1980 /* Capability "me" will turn off appearance modes double-bright,
1981 half-bright, reverse-video, standout, underline. It may or
1982 may not turn off alt-char-mode. */
1983 if (face->tty_bold_p
1984 || face->tty_dim_p
1985 || face->tty_reverse_p
1986 || face->tty_alt_charset_p
1987 || face->tty_blinking_p
1988 || face->tty_underline_p)
1990 OUTPUT1_IF (tty, TS_exit_attribute_mode);
1991 if (strcmp (TS_exit_attribute_mode, TS_end_standout_mode) == 0)
1992 standout_mode = 0;
1995 if (face->tty_alt_charset_p)
1996 OUTPUT_IF (tty, TS_exit_alt_charset_mode);
1998 else
2000 /* If we don't have "me" we can only have those appearances
2001 that have exit sequences defined. */
2002 if (face->tty_alt_charset_p)
2003 OUTPUT_IF (tty, TS_exit_alt_charset_mode);
2005 if (face->tty_underline_p)
2006 OUTPUT_IF (tty, TS_exit_underline_mode);
2009 /* Switch back to default colors. */
2010 if (TN_max_colors > 0
2011 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
2012 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
2013 || (face->background != FACE_TTY_DEFAULT_COLOR
2014 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
2015 OUTPUT1_IF (tty, TS_orig_pair);
2019 /* Return non-zero if the terminal on frame F supports all of the
2020 capabilities in CAPS simultaneously, with foreground and background
2021 colors FG and BG. */
2024 tty_capable_p (f, caps, fg, bg)
2025 struct frame *f;
2026 unsigned caps;
2027 unsigned long fg, bg;
2029 #define TTY_CAPABLE_P_TRY(cap, TS, NC_bit) \
2030 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(NC_bit))) \
2031 return 0;
2033 TTY_CAPABLE_P_TRY (TTY_CAP_INVERSE, TS_standout_mode, NC_REVERSE);
2034 TTY_CAPABLE_P_TRY (TTY_CAP_UNDERLINE, TS_enter_underline_mode, NC_UNDERLINE);
2035 TTY_CAPABLE_P_TRY (TTY_CAP_BOLD, TS_enter_bold_mode, NC_BOLD);
2036 TTY_CAPABLE_P_TRY (TTY_CAP_DIM, TS_enter_dim_mode, NC_DIM);
2037 TTY_CAPABLE_P_TRY (TTY_CAP_BLINK, TS_enter_blink_mode, NC_BLINK);
2038 TTY_CAPABLE_P_TRY (TTY_CAP_ALT_CHARSET, TS_enter_alt_charset_mode, NC_ALT_CHARSET);
2040 /* We can do it! */
2041 return 1;
2045 /* Return non-zero if the terminal is capable to display colors. */
2047 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
2048 0, 1, 0,
2049 doc: /* Return non-nil if TTY can display colors on DISPLAY. */)
2050 (display)
2051 Lisp_Object display;
2053 return TN_max_colors > 0 ? Qt : Qnil;
2056 /* Return the number of supported colors. */
2057 DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
2058 Stty_display_color_cells, 0, 1, 0,
2059 doc: /* Return the number of colors supported by TTY on DISPLAY. */)
2060 (display)
2061 Lisp_Object display;
2063 return make_number (TN_max_colors);
2066 #ifndef WINDOWSNT
2068 /* Save or restore the default color-related capabilities of this
2069 terminal. */
2070 static void
2071 tty_default_color_capabilities (save)
2072 int save;
2074 static char
2075 *default_orig_pair, *default_set_foreground, *default_set_background;
2076 static int default_max_colors, default_max_pairs, default_no_color_video;
2078 if (save)
2080 if (default_orig_pair)
2081 xfree (default_orig_pair);
2082 default_orig_pair = TS_orig_pair ? xstrdup (TS_orig_pair) : NULL;
2084 if (default_set_foreground)
2085 xfree (default_set_foreground);
2086 default_set_foreground = TS_set_foreground ? xstrdup (TS_set_foreground)
2087 : NULL;
2089 if (default_set_background)
2090 xfree (default_set_background);
2091 default_set_background = TS_set_background ? xstrdup (TS_set_background)
2092 : NULL;
2094 default_max_colors = TN_max_colors;
2095 default_max_pairs = TN_max_pairs;
2096 default_no_color_video = TN_no_color_video;
2098 else
2100 TS_orig_pair = default_orig_pair;
2101 TS_set_foreground = default_set_foreground;
2102 TS_set_background = default_set_background;
2103 TN_max_colors = default_max_colors;
2104 TN_max_pairs = default_max_pairs;
2105 TN_no_color_video = default_no_color_video;
2109 /* Setup one of the standard tty color schemes according to MODE.
2110 MODE's value is generally the number of colors which we want to
2111 support; zero means set up for the default capabilities, the ones
2112 we saw at term_init time; -1 means turn off color support. */
2113 void
2114 tty_setup_colors (mode)
2115 int mode;
2117 /* Canonicalize all negative values of MODE. */
2118 if (mode < -1)
2119 mode = -1;
2121 switch (mode)
2123 case -1: /* no colors at all */
2124 TN_max_colors = 0;
2125 TN_max_pairs = 0;
2126 TN_no_color_video = 0;
2127 TS_set_foreground = TS_set_background = TS_orig_pair = NULL;
2128 break;
2129 case 0: /* default colors, if any */
2130 default:
2131 tty_default_color_capabilities (0);
2132 break;
2133 case 8: /* 8 standard ANSI colors */
2134 TS_orig_pair = "\033[0m";
2135 #ifdef TERMINFO
2136 TS_set_foreground = "\033[3%p1%dm";
2137 TS_set_background = "\033[4%p1%dm";
2138 #else
2139 TS_set_foreground = "\033[3%dm";
2140 TS_set_background = "\033[4%dm";
2141 #endif
2142 TN_max_colors = 8;
2143 TN_max_pairs = 64;
2144 TN_no_color_video = 0;
2145 break;
2149 void
2150 set_tty_color_mode (f, val)
2151 struct frame *f;
2152 Lisp_Object val;
2154 Lisp_Object color_mode_spec, current_mode_spec;
2155 Lisp_Object color_mode, current_mode;
2156 int mode, old_mode;
2157 extern Lisp_Object Qtty_color_mode;
2158 Lisp_Object tty_color_mode_alist;
2160 tty_color_mode_alist = Fintern_soft (build_string ("tty-color-mode-alist"),
2161 Qnil);
2163 if (INTEGERP (val))
2164 color_mode = val;
2165 else
2167 if (NILP (tty_color_mode_alist))
2168 color_mode_spec = Qnil;
2169 else
2170 color_mode_spec = Fassq (val, XSYMBOL (tty_color_mode_alist)->value);
2172 if (CONSP (color_mode_spec))
2173 color_mode = XCDR (color_mode_spec);
2174 else
2175 color_mode = Qnil;
2178 current_mode_spec = assq_no_quit (Qtty_color_mode, f->param_alist);
2180 if (CONSP (current_mode_spec))
2181 current_mode = XCDR (current_mode_spec);
2182 else
2183 current_mode = Qnil;
2184 if (INTEGERP (color_mode))
2185 mode = XINT (color_mode);
2186 else
2187 mode = 0; /* meaning default */
2188 if (INTEGERP (current_mode))
2189 old_mode = XINT (current_mode);
2190 else
2191 old_mode = 0;
2193 if (mode != old_mode)
2195 tty_setup_colors (mode);
2196 /* This recomputes all the faces given the new color
2197 definitions. */
2198 call0 (intern ("tty-set-up-initial-frame-faces"));
2199 redraw_frame (f);
2203 #endif /* !WINDOWSNT */
2207 struct tty_output *
2208 get_named_tty (name)
2209 char *name;
2211 struct tty_output *tty = tty_list;
2213 while (tty) {
2214 if ((tty->name == 0 && name == 0)
2215 || (name && tty->name && !strcmp (tty->name, name)))
2216 return tty;
2217 tty = tty->next;
2220 return 0;
2224 /***********************************************************************
2225 Initialization
2226 ***********************************************************************/
2228 struct tty_output *
2229 term_dummy_init (void)
2231 if (initialized || tty_list)
2232 error ("tty already initialized");
2234 tty_list = xmalloc (sizeof (struct tty_output));
2235 bzero (tty_list, sizeof (struct tty_output));
2236 TTY_NAME (tty_list) = 0;
2237 TTY_INPUT (tty_list) = stdin;
2238 TTY_OUTPUT (tty_list) = stdout;
2239 return tty_list;
2243 struct tty_output *
2244 term_init (name, terminal_type)
2245 char *name;
2246 char *terminal_type;
2248 char *area;
2249 char **address = &area;
2250 char *buffer = NULL;
2251 int buffer_size = 4096;
2252 register char *p;
2253 int status;
2254 struct frame *sf = XFRAME (selected_frame);
2256 struct tty_output *tty;
2258 tty = get_named_tty (name);
2259 if (tty)
2261 /* Return the previously initialized terminal, except if it is the dummy
2262 terminal created for the initial frame. */
2263 if (tty->type)
2264 return tty;
2266 else
2268 if (!terminal_type)
2269 error ("Unknown terminal type");
2271 tty = (struct tty_output *) xmalloc (sizeof (struct tty_output));
2272 bzero (tty, sizeof (struct tty_output));
2273 tty->next = tty_list;
2274 tty_list = tty;
2277 if (tty->Wcm)
2278 xfree (tty->Wcm);
2279 tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
2281 if (name)
2283 int fd;
2284 FILE *f;
2285 fd = emacs_open (name, O_RDWR, 0);
2286 if (fd < 0)
2288 tty_list = tty->next;
2289 xfree (tty);
2290 error ("could not open file: %s", name);
2292 f = fdopen (fd, "w+");
2293 TTY_NAME (tty) = xstrdup (name);
2294 TTY_INPUT (tty) = f;
2295 TTY_OUTPUT (tty) = f;
2297 else
2299 TTY_NAME (tty) = 0;
2300 TTY_INPUT (tty) = stdin;
2301 TTY_OUTPUT (tty) = stdout;
2304 init_sys_modes (tty);
2306 #ifdef WINDOWSNT
2307 initialize_w32_display ();
2309 Wcm_clear ();
2311 area = (char *) xmalloc (2044);
2313 FrameRows = FRAME_LINES (sf);
2314 FrameCols = FRAME_COLS (sf);
2315 specified_window = FRAME_LINES (sf);
2317 delete_in_insert_mode = 1;
2319 UseTabs = 0;
2320 TTY_SCROLL_REGION_OK (tty) = 0;
2322 /* Seems to insert lines when it's not supposed to, messing
2323 up the display. In doing a trace, it didn't seem to be
2324 called much, so I don't think we're losing anything by
2325 turning it off. */
2326 TTY_LINE_INS_DEL_OK (tty) = 0;
2328 TTY_CHAR_INS_DEL_OK (tty) = 1;
2330 baud_rate = 19200;
2332 FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0;
2333 FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none;
2334 TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
2336 return tty;
2337 #else /* not WINDOWSNT */
2339 Wcm_clear (tty);
2341 TTY_TYPE (tty) = xstrdup (terminal_type);
2343 buffer = (char *) xmalloc (buffer_size);
2344 status = tgetent (buffer, terminal_type);
2345 if (status < 0)
2347 #ifdef TERMINFO
2348 fatal ("Cannot open terminfo database file");
2349 #else
2350 fatal ("Cannot open termcap database file");
2351 #endif
2353 if (status == 0)
2355 #ifdef TERMINFO
2356 fatal ("Terminal type %s is not defined.\n\
2357 If that is not the actual type of terminal you have,\n\
2358 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2359 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2360 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
2361 terminal_type);
2362 #else
2363 fatal ("Terminal type %s is not defined.\n\
2364 If that is not the actual type of terminal you have,\n\
2365 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2366 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2367 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
2368 terminal_type);
2369 #endif
2372 #ifndef TERMINFO
2373 if (strlen (buffer) >= buffer_size)
2374 abort ();
2375 buffer_size = strlen (buffer);
2376 #endif
2377 area = (char *) xmalloc (buffer_size);
2379 TS_ins_line = tgetstr ("al", address);
2380 TS_ins_multi_lines = tgetstr ("AL", address);
2381 TS_bell = tgetstr ("bl", address);
2382 BackTab (tty) = tgetstr ("bt", address);
2383 TS_clr_to_bottom = tgetstr ("cd", address);
2384 TS_clr_line = tgetstr ("ce", address);
2385 TS_clr_frame = tgetstr ("cl", address);
2386 ColPosition (tty) = NULL; /* tgetstr ("ch", address); */
2387 AbsPosition (tty) = tgetstr ("cm", address);
2388 CR (tty) = tgetstr ("cr", address);
2389 TS_set_scroll_region = tgetstr ("cs", address);
2390 TS_set_scroll_region_1 = tgetstr ("cS", address);
2391 RowPosition (tty) = tgetstr ("cv", address);
2392 TS_del_char = tgetstr ("dc", address);
2393 TS_del_multi_chars = tgetstr ("DC", address);
2394 TS_del_line = tgetstr ("dl", address);
2395 TS_del_multi_lines = tgetstr ("DL", address);
2396 TS_delete_mode = tgetstr ("dm", address);
2397 TS_end_delete_mode = tgetstr ("ed", address);
2398 TS_end_insert_mode = tgetstr ("ei", address);
2399 Home (tty) = tgetstr ("ho", address);
2400 TS_ins_char = tgetstr ("ic", address);
2401 TS_ins_multi_chars = tgetstr ("IC", address);
2402 TS_insert_mode = tgetstr ("im", address);
2403 TS_pad_inserted_char = tgetstr ("ip", address);
2404 TS_end_keypad_mode = tgetstr ("ke", address);
2405 TS_keypad_mode = tgetstr ("ks", address);
2406 LastLine (tty) = tgetstr ("ll", address);
2407 Right (tty) = tgetstr ("nd", address);
2408 Down (tty) = tgetstr ("do", address);
2409 if (!Down (tty))
2410 Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do" */
2411 #ifdef VMS
2412 /* VMS puts a carriage return before each linefeed,
2413 so it is not safe to use linefeeds. */
2414 if (Down (tty) && Down (tty)[0] == '\n' && Down (tty)[1] == '\0')
2415 Down (tty) = 0;
2416 #endif /* VMS */
2417 if (tgetflag ("bs"))
2418 Left (tty) = "\b"; /* can't possibly be longer! */
2419 else /* (Actually, "bs" is obsolete...) */
2420 Left (tty) = tgetstr ("le", address);
2421 if (!Left (tty))
2422 Left (tty) = tgetstr ("bc", address); /* Obsolete name for "le" */
2423 TS_pad_char = tgetstr ("pc", address);
2424 TS_repeat = tgetstr ("rp", address);
2425 TS_end_standout_mode = tgetstr ("se", address);
2426 TS_fwd_scroll = tgetstr ("sf", address);
2427 TS_standout_mode = tgetstr ("so", address);
2428 TS_rev_scroll = tgetstr ("sr", address);
2429 tty->Wcm->cm_tab = tgetstr ("ta", address);
2430 TS_end_termcap_modes = tgetstr ("te", address);
2431 TS_termcap_modes = tgetstr ("ti", address);
2432 Up (tty) = tgetstr ("up", address);
2433 TS_visible_bell = tgetstr ("vb", address);
2434 TS_cursor_normal = tgetstr ("ve", address);
2435 TS_cursor_visible = tgetstr ("vs", address);
2436 TS_cursor_invisible = tgetstr ("vi", address);
2437 TS_set_window = tgetstr ("wi", address);
2439 TS_enter_underline_mode = tgetstr ("us", address);
2440 TS_exit_underline_mode = tgetstr ("ue", address);
2441 TS_enter_bold_mode = tgetstr ("md", address);
2442 TS_enter_dim_mode = tgetstr ("mh", address);
2443 TS_enter_blink_mode = tgetstr ("mb", address);
2444 TS_enter_reverse_mode = tgetstr ("mr", address);
2445 TS_enter_alt_charset_mode = tgetstr ("as", address);
2446 TS_exit_alt_charset_mode = tgetstr ("ae", address);
2447 TS_exit_attribute_mode = tgetstr ("me", address);
2449 MultiUp (tty) = tgetstr ("UP", address);
2450 MultiDown (tty) = tgetstr ("DO", address);
2451 MultiLeft (tty) = tgetstr ("LE", address);
2452 MultiRight (tty) = tgetstr ("RI", address);
2454 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
2455 color because we can't switch back to the default foreground and
2456 background. */
2457 TS_orig_pair = tgetstr ("op", address);
2458 if (TS_orig_pair)
2460 TS_set_foreground = tgetstr ("AF", address);
2461 TS_set_background = tgetstr ("AB", address);
2462 if (!TS_set_foreground)
2464 /* SVr4. */
2465 TS_set_foreground = tgetstr ("Sf", address);
2466 TS_set_background = tgetstr ("Sb", address);
2469 TN_max_colors = tgetnum ("Co");
2470 TN_max_pairs = tgetnum ("pa");
2472 TN_no_color_video = tgetnum ("NC");
2473 if (TN_no_color_video == -1)
2474 TN_no_color_video = 0;
2477 tty_default_color_capabilities (1);
2479 MagicWrap (tty) = tgetflag ("xn");
2480 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
2481 the former flag imply the latter. */
2482 AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
2483 TTY_MEMORY_BELOW_FRAME (tty) = tgetflag ("db");
2484 TF_hazeltine = tgetflag ("hz");
2485 TTY_MUST_WRITE_SPACES (tty) = tgetflag ("in");
2486 meta_key = tgetflag ("km") || tgetflag ("MT");
2487 TF_insmode_motion = tgetflag ("mi");
2488 TF_standout_motion = tgetflag ("ms");
2489 TF_underscore = tgetflag ("ul");
2490 TF_teleray = tgetflag ("xt");
2492 term_get_fkeys (address);
2494 /* Get frame size from system, or else from termcap. */
2496 int height, width;
2497 get_tty_size (tty, &width, &height);
2498 FRAME_COLS (sf) = width;
2499 FRAME_LINES (sf) = height;
2502 if (FRAME_COLS (sf) <= 0)
2503 SET_FRAME_COLS (sf, tgetnum ("co"));
2504 else
2505 /* Keep width and external_width consistent */
2506 SET_FRAME_COLS (sf, FRAME_COLS (sf));
2507 if (FRAME_LINES (sf) <= 0)
2508 FRAME_LINES (sf) = tgetnum ("li");
2510 if (FRAME_LINES (sf) < 3 || FRAME_COLS (sf) < 3)
2511 fatal ("Screen size %dx%d is too small",
2512 FRAME_LINES (sf), FRAME_COLS (sf));
2514 #if 0 /* This is not used anywhere. */
2515 TTY_MIN_PADDING_SPEED (tty) = tgetnum ("pb");
2516 #endif
2518 TabWidth (tty) = tgetnum ("tw");
2520 #ifdef VMS
2521 /* These capabilities commonly use ^J.
2522 I don't know why, but sending them on VMS does not work;
2523 it causes following spaces to be lost, sometimes.
2524 For now, the simplest fix is to avoid using these capabilities ever. */
2525 if (Down (tty) && Down (tty)[0] == '\n')
2526 Down (tty) = 0;
2527 #endif /* VMS */
2529 if (!TS_bell)
2530 TS_bell = "\07";
2532 if (!TS_fwd_scroll)
2533 TS_fwd_scroll = Down (tty);
2535 PC = TS_pad_char ? *TS_pad_char : 0;
2537 if (TabWidth (tty) < 0)
2538 TabWidth (tty) = 8;
2540 /* Turned off since /etc/termcap seems to have :ta= for most terminals
2541 and newer termcap doc does not seem to say there is a default.
2542 if (!tty->Wcm->cm_tab)
2543 tty->Wcm->cm_tab = "\t";
2546 /* We don't support standout modes that use `magic cookies', so
2547 turn off any that do. */
2548 if (TS_standout_mode && tgetnum ("sg") >= 0)
2550 TS_standout_mode = 0;
2551 TS_end_standout_mode = 0;
2553 if (TS_enter_underline_mode && tgetnum ("ug") >= 0)
2555 TS_enter_underline_mode = 0;
2556 TS_exit_underline_mode = 0;
2559 /* If there's no standout mode, try to use underlining instead. */
2560 if (TS_standout_mode == 0)
2562 TS_standout_mode = TS_enter_underline_mode;
2563 TS_end_standout_mode = TS_exit_underline_mode;
2566 /* If no `se' string, try using a `me' string instead.
2567 If that fails, we can't use standout mode at all. */
2568 if (TS_end_standout_mode == 0)
2570 char *s = tgetstr ("me", address);
2571 if (s != 0)
2572 TS_end_standout_mode = s;
2573 else
2574 TS_standout_mode = 0;
2577 if (TF_teleray)
2579 tty->Wcm->cm_tab = 0;
2580 /* We can't support standout mode, because it uses magic cookies. */
2581 TS_standout_mode = 0;
2582 /* But that means we cannot rely on ^M to go to column zero! */
2583 CR (tty) = 0;
2584 /* LF can't be trusted either -- can alter hpos */
2585 /* if move at column 0 thru a line with TS_standout_mode */
2586 Down (tty) = 0;
2589 /* Special handling for certain terminal types known to need it */
2591 if (!strcmp (terminal_type, "supdup"))
2593 TTY_MEMORY_BELOW_FRAME (tty) = 1;
2594 tty->Wcm->cm_losewrap = 1;
2596 if (!strncmp (terminal_type, "c10", 3)
2597 || !strcmp (terminal_type, "perq"))
2599 /* Supply a makeshift :wi string.
2600 This string is not valid in general since it works only
2601 for windows starting at the upper left corner;
2602 but that is all Emacs uses.
2604 This string works only if the frame is using
2605 the top of the video memory, because addressing is memory-relative.
2606 So first check the :ti string to see if that is true.
2608 It would be simpler if the :wi string could go in the termcap
2609 entry, but it can't because it is not fully valid.
2610 If it were in the termcap entry, it would confuse other programs. */
2611 if (!TS_set_window)
2613 p = TS_termcap_modes;
2614 while (*p && strcmp (p, "\033v "))
2615 p++;
2616 if (*p)
2617 TS_set_window = "\033v%C %C %C %C ";
2619 /* Termcap entry often fails to have :in: flag */
2620 TTY_MUST_WRITE_SPACES (tty) = 1;
2621 /* :ti string typically fails to have \E^G! in it */
2622 /* This limits scope of insert-char to one line. */
2623 strcpy (area, TS_termcap_modes);
2624 strcat (area, "\033\007!");
2625 TS_termcap_modes = area;
2626 area += strlen (area) + 1;
2627 p = AbsPosition (tty);
2628 /* Change all %+ parameters to %C, to handle
2629 values above 96 correctly for the C100. */
2630 while (*p)
2632 if (p[0] == '%' && p[1] == '+')
2633 p[1] = 'C';
2634 p++;
2638 FrameRows (tty) = FRAME_LINES (sf);
2639 FrameCols (tty) = FRAME_COLS (sf);
2640 specified_window = FRAME_LINES (sf);
2642 if (Wcm_init (tty) == -1) /* can't do cursor motion */
2643 #ifdef VMS
2644 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2645 It lacks the ability to position the cursor.\n\
2646 If that is not the actual type of terminal you have, use either the\n\
2647 DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
2648 or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
2649 terminal_type);
2650 #else /* not VMS */
2651 # ifdef TERMINFO
2652 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2653 It lacks the ability to position the cursor.\n\
2654 If that is not the actual type of terminal you have,\n\
2655 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2656 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2657 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
2658 terminal_type);
2659 # else /* TERMCAP */
2660 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2661 It lacks the ability to position the cursor.\n\
2662 If that is not the actual type of terminal you have,\n\
2663 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2664 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2665 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
2666 terminal_type);
2667 # endif /* TERMINFO */
2668 #endif /*VMS */
2669 if (FRAME_LINES (sf) <= 0
2670 || FRAME_COLS (sf) <= 0)
2671 fatal ("The frame size has not been specified");
2673 delete_in_insert_mode
2674 = TS_delete_mode && TS_insert_mode
2675 && !strcmp (TS_delete_mode, TS_insert_mode);
2677 se_is_so = (TS_standout_mode
2678 && TS_end_standout_mode
2679 && !strcmp (TS_standout_mode, TS_end_standout_mode));
2681 UseTabs (tty) = tabs_safe_p (tty) && TabWidth (tty) == 8;
2683 TTY_SCROLL_REGION_OK (tty)
2684 = (tty->Wcm->cm_abs
2685 && (TS_set_window || TS_set_scroll_region || TS_set_scroll_region_1));
2687 TTY_LINE_INS_DEL_OK (tty)
2688 = (((TS_ins_line || TS_ins_multi_lines)
2689 && (TS_del_line || TS_del_multi_lines))
2690 || (TTY_SCROLL_REGION_OK (tty)
2691 && TS_fwd_scroll && TS_rev_scroll));
2693 TTY_CHAR_INS_DEL_OK (tty)
2694 = ((TS_ins_char || TS_insert_mode
2695 || TS_pad_inserted_char || TS_ins_multi_chars)
2696 && (TS_del_char || TS_del_multi_chars));
2698 TTY_FAST_CLEAR_END_OF_LINE (tty) = TS_clr_line != 0;
2700 init_baud_rate ();
2701 if (read_socket_hook) /* Baudrate is somewhat
2702 meaningless in this case */
2703 baud_rate = 9600;
2705 FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0;
2706 FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none;
2707 #endif /* WINDOWSNT */
2709 xfree (buffer);
2711 return tty;
2714 /* VARARGS 1 */
2715 void
2716 fatal (str, arg1, arg2)
2717 char *str, *arg1, *arg2;
2719 fprintf (stderr, "emacs: ");
2720 fprintf (stderr, str, arg1, arg2);
2721 fprintf (stderr, "\n");
2722 fflush (stderr);
2723 exit (1);
2726 void
2727 syms_of_term ()
2729 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
2730 doc: /* Non-nil means the system uses terminfo rather than termcap.
2731 This variable can be used by terminal emulator packages. */);
2732 #ifdef TERMINFO
2733 system_uses_terminfo = 1;
2734 #else
2735 system_uses_terminfo = 0;
2736 #endif
2738 DEFVAR_LISP ("ring-bell-function", &Vring_bell_function,
2739 doc: /* Non-nil means call this function to ring the bell.
2740 The function should accept no arguments. */);
2741 Vring_bell_function = Qnil;
2743 defsubr (&Stty_display_color_p);
2744 defsubr (&Stty_display_color_cells);
2746 Fprovide (intern ("multi-tty"), Qnil);
2749 struct tty_output *
2750 get_current_tty ()
2752 return CURTTY();
2756 /* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193
2757 (do not change this comment) */