(defcustom): Doc fix.
[emacs.git] / src / term.c
blob6cdfa8d43551c67069bddb138730de0508ed2bc1
1 /* Terminal control module for terminals described by TERMCAP
2 Copyright (C) 1985, 86, 87, 93, 94, 95, 98, 2000, 2001
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>
28 #include "termchar.h"
29 #include "termopts.h"
30 #include "lisp.h"
31 #include "charset.h"
32 #include "coding.h"
33 #include "keyboard.h"
34 #include "frame.h"
35 #include "disptab.h"
36 #include "termhooks.h"
37 #include "dispextern.h"
38 #include "window.h"
40 /* For now, don't try to include termcap.h. On some systems,
41 configure finds a non-standard termcap.h that the main build
42 won't find. */
44 #if defined HAVE_TERMCAP_H && 0
45 #include <termcap.h>
46 #else
47 extern void tputs P_ ((const char *, int, int (*)(int)));
48 extern int tgetent P_ ((char *, const char *));
49 extern int tgetflag P_ ((char *id));
50 extern int tgetnum P_ ((char *id));
51 #endif
53 #include "cm.h"
54 #ifdef HAVE_X_WINDOWS
55 #include "xterm.h"
56 #endif
57 #ifdef macintosh
58 #include "macterm.h"
59 #endif
61 static void turn_on_face P_ ((struct frame *, int face_id));
62 static void turn_off_face P_ ((struct frame *, int face_id));
63 static void tty_show_cursor P_ ((void));
64 static void tty_hide_cursor P_ ((void));
66 #define max(a, b) ((a) > (b) ? (a) : (b))
67 #define min(a, b) ((a) < (b) ? (a) : (b))
69 #define OUTPUT(a) \
70 tputs (a, (int) (FRAME_HEIGHT (XFRAME (selected_frame)) - curY), cmputc)
71 #define OUTPUT1(a) tputs (a, 1, cmputc)
72 #define OUTPUTL(a, lines) tputs (a, lines, cmputc)
74 #define OUTPUT_IF(a) \
75 do { \
76 if (a) \
77 tputs (a, (int) (FRAME_HEIGHT (XFRAME (selected_frame)) \
78 - curY), cmputc); \
79 } while (0)
81 #define OUTPUT1_IF(a) do { if (a) tputs (a, 1, cmputc); } while (0)
83 /* Function to use to ring the bell. */
85 Lisp_Object Vring_bell_function;
87 /* Terminal characteristics that higher levels want to look at.
88 These are all extern'd in termchar.h */
90 int must_write_spaces; /* Nonzero means spaces in the text
91 must actually be output; can't just skip
92 over some columns to leave them blank. */
93 int min_padding_speed; /* Speed below which no padding necessary */
95 int line_ins_del_ok; /* Terminal can insert and delete lines */
96 int char_ins_del_ok; /* Terminal can insert and delete chars */
97 int scroll_region_ok; /* Terminal supports setting the
98 scroll window */
99 int scroll_region_cost; /* Cost of setting a scroll window,
100 measured in characters */
101 int memory_below_frame; /* Terminal remembers lines
102 scrolled off bottom */
103 int fast_clear_end_of_line; /* Terminal has a `ce' string */
105 /* Nonzero means no need to redraw the entire frame on resuming
106 a suspended Emacs. This is useful on terminals with multiple pages,
107 where one page is used for Emacs and another for all else. */
109 int no_redraw_on_reenter;
111 /* Hook functions that you can set to snap out the functions in this file.
112 These are all extern'd in termhooks.h */
114 void (*cursor_to_hook) P_ ((int, int));
115 void (*raw_cursor_to_hook) P_ ((int, int));
116 void (*clear_to_end_hook) P_ ((void));
117 void (*clear_frame_hook) P_ ((void));
118 void (*clear_end_of_line_hook) P_ ((int));
120 void (*ins_del_lines_hook) P_ ((int, int));
122 void (*change_line_highlight_hook) P_ ((int, int, int, int));
123 void (*reassert_line_highlight_hook) P_ ((int, int));
125 void (*delete_glyphs_hook) P_ ((int));
127 void (*ring_bell_hook) P_ ((void));
129 void (*reset_terminal_modes_hook) P_ ((void));
130 void (*set_terminal_modes_hook) P_ ((void));
131 void (*update_begin_hook) P_ ((struct frame *));
132 void (*update_end_hook) P_ ((struct frame *));
133 void (*set_terminal_window_hook) P_ ((int));
134 void (*insert_glyphs_hook) P_ ((struct glyph *, int));
135 void (*write_glyphs_hook) P_ ((struct glyph *, int));
136 void (*delete_glyphs_hook) P_ ((int));
138 int (*read_socket_hook) P_ ((int, struct input_event *, int, int));
140 void (*frame_up_to_date_hook) P_ ((struct frame *));
142 /* Return the current position of the mouse.
144 Set *f to the frame the mouse is in, or zero if the mouse is in no
145 Emacs frame. If it is set to zero, all the other arguments are
146 garbage.
148 If the motion started in a scroll bar, set *bar_window to the
149 scroll bar's window, *part to the part the mouse is currently over,
150 *x to the position of the mouse along the scroll bar, and *y to the
151 overall length of the scroll bar.
153 Otherwise, set *bar_window to Qnil, and *x and *y to the column and
154 row of the character cell the mouse is over.
156 Set *time to the time the mouse was at the returned position.
158 This should clear mouse_moved until the next motion
159 event arrives. */
161 void (*mouse_position_hook) P_ ((FRAME_PTR *f, int insist,
162 Lisp_Object *bar_window,
163 enum scroll_bar_part *part,
164 Lisp_Object *x,
165 Lisp_Object *y,
166 unsigned long *time));
168 /* When reading from a minibuffer in a different frame, Emacs wants
169 to shift the highlight from the selected frame to the mini-buffer's
170 frame; under X, this means it lies about where the focus is.
171 This hook tells the window system code to re-decide where to put
172 the highlight. */
174 void (*frame_rehighlight_hook) P_ ((FRAME_PTR f));
176 /* If we're displaying frames using a window system that can stack
177 frames on top of each other, this hook allows you to bring a frame
178 to the front, or bury it behind all the other windows. If this
179 hook is zero, that means the device we're displaying on doesn't
180 support overlapping frames, so there's no need to raise or lower
181 anything.
183 If RAISE is non-zero, F is brought to the front, before all other
184 windows. If RAISE is zero, F is sent to the back, behind all other
185 windows. */
187 void (*frame_raise_lower_hook) P_ ((FRAME_PTR f, int raise));
189 /* Set the vertical scroll bar for WINDOW to have its upper left corner
190 at (TOP, LEFT), and be LENGTH rows high. Set its handle to
191 indicate that we are displaying PORTION characters out of a total
192 of WHOLE characters, starting at POSITION. If WINDOW doesn't yet
193 have a scroll bar, create one for it. */
195 void (*set_vertical_scroll_bar_hook)
196 P_ ((struct window *window,
197 int portion, int whole, int position));
200 /* The following three hooks are used when we're doing a thorough
201 redisplay of the frame. We don't explicitly know which scroll bars
202 are going to be deleted, because keeping track of when windows go
203 away is a real pain - can you say set-window-configuration?
204 Instead, we just assert at the beginning of redisplay that *all*
205 scroll bars are to be removed, and then save scroll bars from the
206 fiery pit when we actually redisplay their window. */
208 /* Arrange for all scroll bars on FRAME to be removed at the next call
209 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
210 `*redeem_scroll_bar_hook' is applied to its window before the judgment.
212 This should be applied to each frame each time its window tree is
213 redisplayed, even if it is not displaying scroll bars at the moment;
214 if the HAS_SCROLL_BARS flag has just been turned off, only calling
215 this and the judge_scroll_bars_hook will get rid of them.
217 If non-zero, this hook should be safe to apply to any frame,
218 whether or not it can support scroll bars, and whether or not it is
219 currently displaying them. */
221 void (*condemn_scroll_bars_hook) P_ ((FRAME_PTR frame));
223 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
224 Note that it's okay to redeem a scroll bar that is not condemned. */
226 void (*redeem_scroll_bar_hook) P_ ((struct window *window));
228 /* Remove all scroll bars on FRAME that haven't been saved since the
229 last call to `*condemn_scroll_bars_hook'.
231 This should be applied to each frame after each time its window
232 tree is redisplayed, even if it is not displaying scroll bars at the
233 moment; if the HAS_SCROLL_BARS flag has just been turned off, only
234 calling this and condemn_scroll_bars_hook will get rid of them.
236 If non-zero, this hook should be safe to apply to any frame,
237 whether or not it can support scroll bars, and whether or not it is
238 currently displaying them. */
240 void (*judge_scroll_bars_hook) P_ ((FRAME_PTR FRAME));
242 /* Hook to call in estimate_mode_line_height, if any. */
244 int (* estimate_mode_line_height_hook) P_ ((struct frame *f, enum face_id));
247 /* Strings, numbers and flags taken from the termcap entry. */
249 char *TS_ins_line; /* "al" */
250 char *TS_ins_multi_lines; /* "AL" (one parameter, # lines to insert) */
251 char *TS_bell; /* "bl" */
252 char *TS_clr_to_bottom; /* "cd" */
253 char *TS_clr_line; /* "ce", clear to end of line */
254 char *TS_clr_frame; /* "cl" */
255 char *TS_set_scroll_region; /* "cs" (2 params, first line and last line) */
256 char *TS_set_scroll_region_1; /* "cS" (4 params: total lines,
257 lines above scroll region, lines below it,
258 total lines again) */
259 char *TS_del_char; /* "dc" */
260 char *TS_del_multi_chars; /* "DC" (one parameter, # chars to delete) */
261 char *TS_del_line; /* "dl" */
262 char *TS_del_multi_lines; /* "DL" (one parameter, # lines to delete) */
263 char *TS_delete_mode; /* "dm", enter character-delete mode */
264 char *TS_end_delete_mode; /* "ed", leave character-delete mode */
265 char *TS_end_insert_mode; /* "ei", leave character-insert mode */
266 char *TS_ins_char; /* "ic" */
267 char *TS_ins_multi_chars; /* "IC" (one parameter, # chars to insert) */
268 char *TS_insert_mode; /* "im", enter character-insert mode */
269 char *TS_pad_inserted_char; /* "ip". Just padding, no commands. */
270 char *TS_end_keypad_mode; /* "ke" */
271 char *TS_keypad_mode; /* "ks" */
272 char *TS_pad_char; /* "pc", char to use as padding */
273 char *TS_repeat; /* "rp" (2 params, # times to repeat
274 and character to be repeated) */
275 char *TS_end_standout_mode; /* "se" */
276 char *TS_fwd_scroll; /* "sf" */
277 char *TS_standout_mode; /* "so" */
278 char *TS_rev_scroll; /* "sr" */
279 char *TS_end_termcap_modes; /* "te" */
280 char *TS_termcap_modes; /* "ti" */
281 char *TS_visible_bell; /* "vb" */
282 char *TS_cursor_normal; /* "ve" */
283 char *TS_cursor_visible; /* "vs" */
284 char *TS_cursor_invisible; /* "vi" */
285 char *TS_set_window; /* "wi" (4 params, start and end of window,
286 each as vpos and hpos) */
288 /* Value of the "NC" (no_color_video) capability, or 0 if not
289 present. */
291 static int TN_no_color_video;
293 /* Meaning of bits in no_color_video. Each bit set means that the
294 corresponding attribute cannot be combined with colors. */
296 enum no_color_bit
298 NC_STANDOUT = 1 << 0,
299 NC_UNDERLINE = 1 << 1,
300 NC_REVERSE = 1 << 2,
301 NC_BLINK = 1 << 3,
302 NC_DIM = 1 << 4,
303 NC_BOLD = 1 << 5,
304 NC_INVIS = 1 << 6,
305 NC_PROTECT = 1 << 7,
306 NC_ALT_CHARSET = 1 << 8
309 /* "md" -- turn on bold (extra bright mode). */
311 char *TS_enter_bold_mode;
313 /* "mh" -- turn on half-bright mode. */
315 char *TS_enter_dim_mode;
317 /* "mb" -- enter blinking mode. */
319 char *TS_enter_blink_mode;
321 /* "mr" -- enter reverse video mode. */
323 char *TS_enter_reverse_mode;
325 /* "us"/"ue" -- start/end underlining. */
327 char *TS_exit_underline_mode, *TS_enter_underline_mode;
329 /* "ug" -- number of blanks left by underline. */
331 int TN_magic_cookie_glitch_ul;
333 /* "as"/"ae" -- start/end alternate character set. Not really
334 supported, yet. */
336 char *TS_enter_alt_charset_mode, *TS_exit_alt_charset_mode;
338 /* "me" -- switch appearances off. */
340 char *TS_exit_attribute_mode;
342 /* "Co" -- number of colors. */
344 int TN_max_colors;
346 /* "pa" -- max. number of color pairs on screen. Not handled yet.
347 Could be a problem if not equal to TN_max_colors * TN_max_colors. */
349 int TN_max_pairs;
351 /* "op" -- SVr4 set default pair to its original value. */
353 char *TS_orig_pair;
355 /* "AF"/"AB" or "Sf"/"Sb"-- set ANSI or SVr4 foreground/background color.
356 1 param, the color index. */
358 char *TS_set_foreground, *TS_set_background;
360 int TF_hazeltine; /* termcap hz flag. */
361 int TF_insmode_motion; /* termcap mi flag: can move while in insert mode. */
362 int TF_standout_motion; /* termcap mi flag: can move while in standout mode. */
363 int TF_underscore; /* termcap ul flag: _ underlines if over-struck on
364 non-blank position. Must clear before writing _. */
365 int TF_teleray; /* termcap xt flag: many weird consequences.
366 For t1061. */
368 int TF_xs; /* Nonzero for "xs". If set together with
369 TN_standout_width == 0, it means don't bother
370 to write any end-standout cookies. */
372 int TN_standout_width; /* termcap sg number: width occupied by standout
373 markers */
375 static int RPov; /* # chars to start a TS_repeat */
377 static int delete_in_insert_mode; /* delete mode == insert mode */
379 static int se_is_so; /* 1 if same string both enters and leaves
380 standout mode */
382 /* internal state */
384 /* The largest frame width in any call to calculate_costs. */
386 int max_frame_width;
388 /* The largest frame height in any call to calculate_costs. */
390 int max_frame_height;
392 /* Number of chars of space used for standout marker at beginning of line,
393 or'd with 0100. Zero if no standout marker at all.
394 The length of these vectors is max_frame_height.
396 Used IFF TN_standout_width >= 0. */
398 static char *chars_wasted;
399 static char *copybuf;
401 /* nonzero means supposed to write text in standout mode. */
403 int standout_requested;
405 int insert_mode; /* Nonzero when in insert mode. */
406 int standout_mode; /* Nonzero when in standout mode. */
408 /* Size of window specified by higher levels.
409 This is the number of lines, from the top of frame downwards,
410 which can participate in insert-line/delete-line operations.
412 Effectively it excludes the bottom frame_height - specified_window_size
413 lines from those operations. */
415 int specified_window;
417 /* Frame currently being redisplayed; 0 if not currently redisplaying.
418 (Direct output does not count). */
420 FRAME_PTR updating_frame;
422 /* Provided for lisp packages. */
424 static int system_uses_terminfo;
426 /* Flag used in tty_show/hide_cursor. */
428 static int tty_cursor_hidden;
430 char *tparam ();
432 extern char *tgetstr ();
435 #ifdef WINDOWSNT
436 /* We aren't X windows, but we aren't termcap either. This makes me
437 uncertain as to what value to use for frame.output_method. For
438 this file, we'll define FRAME_TERMCAP_P to be zero so that our
439 output hooks get called instead of the termcap functions. Probably
440 the best long-term solution is to define an output_windows_nt... */
442 #undef FRAME_TERMCAP_P
443 #define FRAME_TERMCAP_P(_f_) 0
444 #endif /* WINDOWSNT */
446 void
447 ring_bell ()
449 if (!NILP (Vring_bell_function))
451 Lisp_Object function;
453 /* Temporarily set the global variable to nil
454 so that if we get an error, it stays nil
455 and we don't call it over and over.
457 We don't specbind it, because that would carefully
458 restore the bad value if there's an error
459 and make the loop of errors happen anyway. */
461 function = Vring_bell_function;
462 Vring_bell_function = Qnil;
464 call0 (function);
466 Vring_bell_function = function;
468 else if (!FRAME_TERMCAP_P (XFRAME (selected_frame)))
469 (*ring_bell_hook) ();
470 else
471 OUTPUT (TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell);
474 void
475 set_terminal_modes ()
477 if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
479 OUTPUT_IF (TS_termcap_modes);
480 OUTPUT_IF (TS_cursor_visible);
481 OUTPUT_IF (TS_keypad_mode);
482 losecursor ();
484 else
485 (*set_terminal_modes_hook) ();
488 void
489 reset_terminal_modes ()
491 if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
493 if (TN_standout_width < 0)
494 turn_off_highlight ();
495 turn_off_insert ();
496 OUTPUT_IF (TS_end_keypad_mode);
497 OUTPUT_IF (TS_cursor_normal);
498 OUTPUT_IF (TS_end_termcap_modes);
499 OUTPUT_IF (TS_orig_pair);
500 /* Output raw CR so kernel can track the cursor hpos. */
501 /* But on magic-cookie terminals this can erase an end-standout
502 marker and cause the rest of the frame to be in standout, so
503 move down first. */
504 if (TN_standout_width >= 0)
505 cmputc ('\n');
506 cmputc ('\r');
508 else if (reset_terminal_modes_hook)
509 (*reset_terminal_modes_hook) ();
512 void
513 update_begin (f)
514 struct frame *f;
516 updating_frame = f;
517 if (!FRAME_TERMCAP_P (f))
518 update_begin_hook (f);
521 void
522 update_end (f)
523 struct frame *f;
525 if (FRAME_TERMCAP_P (f))
527 if (!XWINDOW (selected_window)->cursor_off_p)
528 tty_show_cursor ();
529 turn_off_insert ();
530 background_highlight ();
531 standout_requested = 0;
533 else
534 update_end_hook (f);
536 updating_frame = NULL;
539 void
540 set_terminal_window (size)
541 int size;
543 if (FRAME_TERMCAP_P (updating_frame))
545 specified_window = size ? size : FRAME_HEIGHT (updating_frame);
546 if (scroll_region_ok)
547 set_scroll_region (0, specified_window);
549 else
550 set_terminal_window_hook (size);
553 void
554 set_scroll_region (start, stop)
555 int start, stop;
557 char *buf;
558 struct frame *sf = XFRAME (selected_frame);
560 if (TS_set_scroll_region)
561 buf = tparam (TS_set_scroll_region, 0, 0, start, stop - 1);
562 else if (TS_set_scroll_region_1)
563 buf = tparam (TS_set_scroll_region_1, 0, 0,
564 FRAME_HEIGHT (sf), start,
565 FRAME_HEIGHT (sf) - stop,
566 FRAME_HEIGHT (sf));
567 else
568 buf = tparam (TS_set_window, 0, 0, start, 0, stop, FRAME_WIDTH (sf));
570 OUTPUT (buf);
571 xfree (buf);
572 losecursor ();
576 static void
577 turn_on_insert ()
579 if (!insert_mode)
580 OUTPUT (TS_insert_mode);
581 insert_mode = 1;
584 void
585 turn_off_insert ()
587 if (insert_mode)
588 OUTPUT (TS_end_insert_mode);
589 insert_mode = 0;
592 /* Handle highlighting when TN_standout_width (termcap sg) is not specified.
593 In these terminals, output is affected by the value of standout
594 mode when the output is written.
596 These functions are called on all terminals, but do nothing
597 on terminals whose standout mode does not work that way. */
599 void
600 turn_off_highlight ()
602 if (TN_standout_width < 0)
604 if (standout_mode)
605 OUTPUT_IF (TS_end_standout_mode);
606 standout_mode = 0;
610 static void
611 turn_on_highlight ()
613 if (TN_standout_width < 0)
615 if (!standout_mode)
616 OUTPUT_IF (TS_standout_mode);
617 standout_mode = 1;
621 static void
622 toggle_highlight ()
624 if (standout_mode)
625 turn_off_highlight ();
626 else
627 turn_on_highlight ();
631 /* Make cursor invisible. */
633 static void
634 tty_hide_cursor ()
636 if (tty_cursor_hidden == 0)
638 tty_cursor_hidden = 1;
639 OUTPUT_IF (TS_cursor_invisible);
644 /* Ensure that cursor is visible. */
646 static void
647 tty_show_cursor ()
649 if (tty_cursor_hidden)
651 tty_cursor_hidden = 0;
652 OUTPUT_IF (TS_cursor_normal);
653 OUTPUT_IF (TS_cursor_visible);
658 /* Set standout mode to the state it should be in for
659 empty space inside windows. What this is,
660 depends on the user option inverse-video. */
662 void
663 background_highlight ()
665 if (TN_standout_width >= 0)
666 return;
667 if (inverse_video)
668 turn_on_highlight ();
669 else
670 turn_off_highlight ();
673 /* Set standout mode to the mode specified for the text to be output. */
675 static void
676 highlight_if_desired ()
678 if (TN_standout_width >= 0)
679 return;
680 if (!inverse_video == !standout_requested)
681 turn_off_highlight ();
682 else
683 turn_on_highlight ();
686 /* Handle standout mode for terminals in which TN_standout_width >= 0.
687 On these terminals, standout is controlled by markers that
688 live inside the terminal's memory. TN_standout_width is the width
689 that the marker occupies in memory. Standout runs from the marker
690 to the end of the line on some terminals, or to the next
691 turn-off-standout marker (TS_end_standout_mode) string
692 on other terminals. */
694 /* Write a standout marker or end-standout marker at the front of the line
695 at vertical position vpos. */
697 static void
698 write_standout_marker (flag, vpos)
699 int flag, vpos;
701 if (flag
702 || (TS_end_standout_mode && !TF_teleray && !se_is_so
703 && !(TF_xs && TN_standout_width == 0)))
705 cmgoto (vpos, 0);
706 cmplus (TN_standout_width);
707 OUTPUT (flag ? TS_standout_mode : TS_end_standout_mode);
708 chars_wasted[curY] = TN_standout_width | 0100;
712 /* External interface to control of standout mode.
713 Call this when about to modify line at position VPOS
714 and not change whether it is highlighted. */
716 void
717 reassert_line_highlight (highlight, vpos)
718 int highlight;
719 int vpos;
721 struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
722 if (! FRAME_TERMCAP_P (f))
724 (*reassert_line_highlight_hook) (highlight, vpos);
725 return;
727 if (TN_standout_width < 0)
728 /* Handle terminals where standout takes affect at output time */
729 standout_requested = highlight;
730 else if (chars_wasted && chars_wasted[vpos] == 0)
731 /* For terminals with standout markers, write one on this line
732 if there isn't one already. */
733 write_standout_marker (inverse_video ? !highlight : highlight, vpos);
736 /* Call this when about to modify line at position VPOS
737 and change whether it is highlighted. */
739 void
740 change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
741 int new_highlight, vpos, y, first_unused_hpos;
743 standout_requested = new_highlight;
744 if (! FRAME_TERMCAP_P (updating_frame))
746 (*change_line_highlight_hook) (new_highlight, vpos, y, first_unused_hpos);
747 return;
750 cursor_to (vpos, 0);
752 if (TN_standout_width < 0)
753 background_highlight ();
754 /* If line starts with a marker, delete the marker */
755 else if (TS_clr_line && chars_wasted[curY])
757 turn_off_insert ();
758 /* On Teleray, make sure to erase the SO marker. */
759 if (TF_teleray)
761 cmgoto (curY - 1, FRAME_WIDTH (XFRAME (selected_frame)) - 4);
762 OUTPUT ("\033S");
763 curY++; /* ESC S moves to next line where the TS_standout_mode was */
764 curX = 0;
766 else
767 cmgoto (curY, 0); /* reposition to kill standout marker */
769 clear_end_of_line_raw (first_unused_hpos);
770 reassert_line_highlight (new_highlight, curY);
774 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
775 frame-relative coordinates. */
777 void
778 cursor_to (vpos, hpos)
779 int vpos, hpos;
781 struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
783 if (! FRAME_TERMCAP_P (f) && cursor_to_hook)
785 (*cursor_to_hook) (vpos, hpos);
786 return;
789 /* Detect the case where we are called from reset_sys_modes
790 and the costs have never been calculated. Do nothing. */
791 if (chars_wasted == 0)
792 return;
794 hpos += chars_wasted[vpos] & 077;
795 if (curY == vpos && curX == hpos)
796 return;
797 if (!TF_standout_motion)
798 background_highlight ();
799 if (!TF_insmode_motion)
800 turn_off_insert ();
801 cmgoto (vpos, hpos);
804 /* Similar but don't take any account of the wasted characters. */
806 void
807 raw_cursor_to (row, col)
808 int row, col;
810 struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
811 if (! FRAME_TERMCAP_P (f))
813 (*raw_cursor_to_hook) (row, col);
814 return;
816 if (curY == row && curX == col)
817 return;
818 if (!TF_standout_motion)
819 background_highlight ();
820 if (!TF_insmode_motion)
821 turn_off_insert ();
822 cmgoto (row, col);
825 /* Erase operations */
827 /* clear from cursor to end of frame */
828 void
829 clear_to_end ()
831 register int i;
833 if (clear_to_end_hook && ! FRAME_TERMCAP_P (updating_frame))
835 (*clear_to_end_hook) ();
836 return;
838 if (TS_clr_to_bottom)
840 background_highlight ();
841 OUTPUT (TS_clr_to_bottom);
842 bzero (chars_wasted + curY,
843 FRAME_HEIGHT (XFRAME (selected_frame)) - curY);
845 else
847 for (i = curY; i < FRAME_HEIGHT (XFRAME (selected_frame)); i++)
849 cursor_to (i, 0);
850 clear_end_of_line_raw (FRAME_WIDTH (XFRAME (selected_frame)));
855 /* Clear entire frame */
857 void
858 clear_frame ()
860 struct frame *sf = XFRAME (selected_frame);
862 if (clear_frame_hook
863 && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : sf)))
865 (*clear_frame_hook) ();
866 return;
868 if (TS_clr_frame)
870 background_highlight ();
871 OUTPUT (TS_clr_frame);
872 bzero (chars_wasted, FRAME_HEIGHT (sf));
873 cmat (0, 0);
875 else
877 cursor_to (0, 0);
878 clear_to_end ();
882 /* Clear to end of line, but do not clear any standout marker.
883 Assumes that the cursor is positioned at a character of real text,
884 which implies it cannot be before a standout marker
885 unless the marker has zero width.
887 Note that the cursor may be moved. */
889 void
890 clear_end_of_line (first_unused_hpos)
891 int first_unused_hpos;
893 if (FRAME_TERMCAP_P (XFRAME (selected_frame))
894 && chars_wasted != 0
895 && TN_standout_width == 0 && curX == 0 && chars_wasted[curY] != 0)
896 write_glyphs (&space_glyph, 1);
897 clear_end_of_line_raw (first_unused_hpos);
900 /* Clear from cursor to end of line.
901 Assume that the line is already clear starting at column first_unused_hpos.
902 If the cursor is at a standout marker, erase the marker.
904 Note that the cursor may be moved, on terminals lacking a `ce' string. */
906 void
907 clear_end_of_line_raw (first_unused_hpos)
908 int first_unused_hpos;
910 register int i;
912 if (clear_end_of_line_hook
913 && ! FRAME_TERMCAP_P ((updating_frame
914 ? updating_frame
915 : XFRAME (selected_frame))))
917 (*clear_end_of_line_hook) (first_unused_hpos);
918 return;
921 /* Detect the case where we are called from reset_sys_modes
922 and the costs have never been calculated. Do nothing. */
923 if (chars_wasted == 0)
924 return;
926 first_unused_hpos += chars_wasted[curY] & 077;
927 if (curX >= first_unused_hpos)
928 return;
929 /* Notice if we are erasing a magic cookie */
930 if (curX == 0)
931 chars_wasted[curY] = 0;
932 background_highlight ();
933 if (TS_clr_line)
935 OUTPUT1 (TS_clr_line);
937 else
938 { /* have to do it the hard way */
939 struct frame *sf = XFRAME (selected_frame);
940 turn_off_insert ();
942 /* Do not write in last row last col with Auto-wrap on. */
943 if (AutoWrap && curY == FRAME_HEIGHT (sf) - 1
944 && first_unused_hpos == FRAME_WIDTH (sf))
945 first_unused_hpos--;
947 for (i = curX; i < first_unused_hpos; i++)
949 if (termscript)
950 fputc (' ', termscript);
951 putchar (' ');
953 cmplus (first_unused_hpos - curX);
957 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes and
958 store them at DST. Do not write more than DST_LEN bytes. That may
959 require stopping before all SRC_LEN input glyphs have been
960 converted.
962 We store the number of glyphs actually converted in *CONSUMED. The
963 return value is the number of bytes store in DST. */
966 encode_terminal_code (src, dst, src_len, dst_len, consumed)
967 struct glyph *src;
968 int src_len;
969 unsigned char *dst;
970 int dst_len, *consumed;
972 struct glyph *src_start = src, *src_end = src + src_len;
973 unsigned char *dst_start = dst, *dst_end = dst + dst_len;
974 register GLYPH g;
975 unsigned char workbuf[MAX_MULTIBYTE_LENGTH], *buf;
976 int len;
977 register int tlen = GLYPH_TABLE_LENGTH;
978 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
979 int result;
980 struct coding_system *coding;
982 /* If terminal_coding does any conversion, use it, otherwise use
983 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
984 because it always return 1 if the member src_multibyte is 1. */
985 coding = (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK
986 ? &terminal_coding
987 : &safe_terminal_coding);
989 while (src < src_end)
991 /* We must skip glyphs to be padded for a wide character. */
992 if (! CHAR_GLYPH_PADDING_P (*src))
994 g = GLYPH_FROM_CHAR_GLYPH (src[0]);
996 if (g < 0 || g >= tlen)
998 /* This glyph doesn't has an entry in Vglyph_table. */
999 if (! CHAR_VALID_P (src->u.ch, 0))
1001 len = 1;
1002 buf = " ";
1003 coding->src_multibyte = 0;
1005 else
1007 len = CHAR_STRING (src->u.ch, workbuf);
1008 buf = workbuf;
1009 coding->src_multibyte = 1;
1012 else
1014 /* This glyph has an entry in Vglyph_table,
1015 so process any alias before testing for simpleness. */
1016 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
1018 if (GLYPH_SIMPLE_P (tbase, tlen, g))
1020 /* We set the multi-byte form of a character in G
1021 (that should be an ASCII character) at
1022 WORKBUF. */
1023 workbuf[0] = FAST_GLYPH_CHAR (g);
1024 len = 1;
1025 buf = workbuf;
1026 coding->src_multibyte = 0;
1028 else
1030 /* We have a string in Vglyph_table. */
1031 len = GLYPH_LENGTH (tbase, g);
1032 buf = GLYPH_STRING (tbase, g);
1033 coding->src_multibyte = STRING_MULTIBYTE (tbase[g]);
1037 result = encode_coding (coding, buf, dst, len, dst_end - dst);
1038 len -= coding->consumed;
1039 dst += coding->produced;
1040 if (result == CODING_FINISH_INSUFFICIENT_DST
1041 || (result == CODING_FINISH_INSUFFICIENT_SRC
1042 && len > dst_end - dst))
1043 /* The remaining output buffer is too short. We must
1044 break the loop here without increasing SRC so that the
1045 next call of this function starts from the same glyph. */
1046 break;
1048 if (len > 0)
1050 /* This is the case that a code of the range 0200..0237
1051 exists in buf. We must just write out such a code. */
1052 buf += coding->consumed;
1053 while (len--)
1054 *dst++ = *buf++;
1057 src++;
1060 *consumed = src - src_start;
1061 return (dst - dst_start);
1065 void
1066 write_glyphs (string, len)
1067 register struct glyph *string;
1068 register int len;
1070 int produced, consumed;
1071 struct frame *sf = XFRAME (selected_frame);
1072 struct frame *f = updating_frame ? updating_frame : sf;
1073 unsigned char conversion_buffer[1024];
1074 int conversion_buffer_size = sizeof conversion_buffer;
1076 if (write_glyphs_hook
1077 && ! FRAME_TERMCAP_P (f))
1079 (*write_glyphs_hook) (string, len);
1080 return;
1083 turn_off_insert ();
1084 tty_hide_cursor ();
1086 /* Don't dare write in last column of bottom line, if Auto-Wrap,
1087 since that would scroll the whole frame on some terminals. */
1089 if (AutoWrap
1090 && curY + 1 == FRAME_HEIGHT (sf)
1091 && (curX + len - (chars_wasted[curY] & 077) == FRAME_WIDTH (sf)))
1092 len --;
1093 if (len <= 0)
1094 return;
1096 cmplus (len);
1098 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
1099 the tail. */
1100 terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
1102 while (len > 0)
1104 /* Identify a run of glyphs with the same face. */
1105 int face_id = string->face_id;
1106 int n;
1108 for (n = 1; n < len; ++n)
1109 if (string[n].face_id != face_id)
1110 break;
1112 /* Turn appearance modes of the face of the run on. */
1113 highlight_if_desired ();
1114 turn_on_face (f, face_id);
1116 while (n > 0)
1118 /* We use a fixed size (1024 bytes) of conversion buffer.
1119 Usually it is sufficient, but if not, we just repeat the
1120 loop. */
1121 produced = encode_terminal_code (string, conversion_buffer,
1122 n, conversion_buffer_size,
1123 &consumed);
1124 if (produced > 0)
1126 fwrite (conversion_buffer, 1, produced, stdout);
1127 if (ferror (stdout))
1128 clearerr (stdout);
1129 if (termscript)
1130 fwrite (conversion_buffer, 1, produced, termscript);
1132 len -= consumed;
1133 n -= consumed;
1134 string += consumed;
1137 /* Turn appearance modes off. */
1138 turn_off_face (f, face_id);
1139 turn_off_highlight ();
1142 /* We may have to output some codes to terminate the writing. */
1143 if (CODING_REQUIRE_FLUSHING (&terminal_coding))
1145 terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
1146 encode_coding (&terminal_coding, "", conversion_buffer,
1147 0, conversion_buffer_size);
1148 if (terminal_coding.produced > 0)
1150 fwrite (conversion_buffer, 1, terminal_coding.produced, stdout);
1151 if (ferror (stdout))
1152 clearerr (stdout);
1153 if (termscript)
1154 fwrite (conversion_buffer, 1, terminal_coding.produced,
1155 termscript);
1159 cmcheckmagic ();
1162 /* If start is zero, insert blanks instead of a string at start */
1164 void
1165 insert_glyphs (start, len)
1166 register struct glyph *start;
1167 register int len;
1169 char *buf;
1170 struct glyph *glyph = NULL;
1171 struct frame *f, *sf;
1173 if (len <= 0)
1174 return;
1176 if (insert_glyphs_hook)
1178 (*insert_glyphs_hook) (start, len);
1179 return;
1182 sf = XFRAME (selected_frame);
1183 f = updating_frame ? updating_frame : sf;
1185 if (TS_ins_multi_chars)
1187 buf = tparam (TS_ins_multi_chars, 0, 0, len);
1188 OUTPUT1 (buf);
1189 xfree (buf);
1190 if (start)
1191 write_glyphs (start, len);
1192 return;
1195 turn_on_insert ();
1196 cmplus (len);
1197 /* The bit CODING_MODE_LAST_BLOCK should be set to 1 only at the tail. */
1198 terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
1199 while (len-- > 0)
1201 int produced, consumed;
1202 unsigned char conversion_buffer[1024];
1203 int conversion_buffer_size = sizeof conversion_buffer;
1205 OUTPUT1_IF (TS_ins_char);
1206 if (!start)
1208 conversion_buffer[0] = SPACEGLYPH;
1209 produced = 1;
1211 else
1213 highlight_if_desired ();
1214 turn_on_face (f, start->face_id);
1215 glyph = start;
1216 ++start;
1217 /* We must open sufficient space for a character which
1218 occupies more than one column. */
1219 while (len && CHAR_GLYPH_PADDING_P (*start))
1221 OUTPUT1_IF (TS_ins_char);
1222 start++, len--;
1225 if (len <= 0)
1226 /* This is the last glyph. */
1227 terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
1229 /* The size of conversion buffer (1024 bytes) is surely
1230 sufficient for just one glyph. */
1231 produced = encode_terminal_code (glyph, conversion_buffer, 1,
1232 conversion_buffer_size, &consumed);
1235 if (produced > 0)
1237 fwrite (conversion_buffer, 1, produced, stdout);
1238 if (ferror (stdout))
1239 clearerr (stdout);
1240 if (termscript)
1241 fwrite (conversion_buffer, 1, produced, termscript);
1244 OUTPUT1_IF (TS_pad_inserted_char);
1245 if (start)
1247 turn_off_face (f, glyph->face_id);
1248 turn_off_highlight ();
1252 cmcheckmagic ();
1255 void
1256 delete_glyphs (n)
1257 register int n;
1259 char *buf;
1260 register int i;
1262 if (delete_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame))
1264 (*delete_glyphs_hook) (n);
1265 return;
1268 if (delete_in_insert_mode)
1270 turn_on_insert ();
1272 else
1274 turn_off_insert ();
1275 OUTPUT_IF (TS_delete_mode);
1278 if (TS_del_multi_chars)
1280 buf = tparam (TS_del_multi_chars, 0, 0, n);
1281 OUTPUT1 (buf);
1282 xfree (buf);
1284 else
1285 for (i = 0; i < n; i++)
1286 OUTPUT1 (TS_del_char);
1287 if (!delete_in_insert_mode)
1288 OUTPUT_IF (TS_end_delete_mode);
1291 /* Insert N lines at vpos VPOS. If N is negative, delete -N lines. */
1293 void
1294 ins_del_lines (vpos, n)
1295 int vpos, n;
1297 char *multi = n > 0 ? TS_ins_multi_lines : TS_del_multi_lines;
1298 char *single = n > 0 ? TS_ins_line : TS_del_line;
1299 char *scroll = n > 0 ? TS_rev_scroll : TS_fwd_scroll;
1300 struct frame *sf;
1302 register int i = n > 0 ? n : -n;
1303 register char *buf;
1305 if (ins_del_lines_hook && ! FRAME_TERMCAP_P (updating_frame))
1307 (*ins_del_lines_hook) (vpos, n);
1308 return;
1311 sf = XFRAME (selected_frame);
1313 /* If the lines below the insertion are being pushed
1314 into the end of the window, this is the same as clearing;
1315 and we know the lines are already clear, since the matching
1316 deletion has already been done. So can ignore this. */
1317 /* If the lines below the deletion are blank lines coming
1318 out of the end of the window, don't bother,
1319 as there will be a matching inslines later that will flush them. */
1320 if (scroll_region_ok && vpos + i >= specified_window)
1321 return;
1322 if (!memory_below_frame && vpos + i >= FRAME_HEIGHT (sf))
1323 return;
1325 if (multi)
1327 raw_cursor_to (vpos, 0);
1328 background_highlight ();
1329 buf = tparam (multi, 0, 0, i);
1330 OUTPUT (buf);
1331 xfree (buf);
1333 else if (single)
1335 raw_cursor_to (vpos, 0);
1336 background_highlight ();
1337 while (--i >= 0)
1338 OUTPUT (single);
1339 if (TF_teleray)
1340 curX = 0;
1342 else
1344 set_scroll_region (vpos, specified_window);
1345 if (n < 0)
1346 raw_cursor_to (specified_window - 1, 0);
1347 else
1348 raw_cursor_to (vpos, 0);
1349 background_highlight ();
1350 while (--i >= 0)
1351 OUTPUTL (scroll, specified_window - vpos);
1352 set_scroll_region (0, specified_window);
1355 if (TN_standout_width >= 0)
1357 register int lower_limit
1358 = (scroll_region_ok
1359 ? specified_window
1360 : FRAME_HEIGHT (sf));
1362 if (n < 0)
1364 bcopy (&chars_wasted[vpos - n], &chars_wasted[vpos],
1365 lower_limit - vpos + n);
1366 bzero (&chars_wasted[lower_limit + n], - n);
1368 else
1370 bcopy (&chars_wasted[vpos], &copybuf[vpos], lower_limit - vpos - n);
1371 bcopy (&copybuf[vpos], &chars_wasted[vpos + n],
1372 lower_limit - vpos - n);
1373 bzero (&chars_wasted[vpos], n);
1376 if (!scroll_region_ok && memory_below_frame && n < 0)
1378 cursor_to (FRAME_HEIGHT (sf) + n, 0);
1379 clear_to_end ();
1383 /* Compute cost of sending "str", in characters,
1384 not counting any line-dependent padding. */
1387 string_cost (str)
1388 char *str;
1390 cost = 0;
1391 if (str)
1392 tputs (str, 0, evalcost);
1393 return cost;
1396 /* Compute cost of sending "str", in characters,
1397 counting any line-dependent padding at one line. */
1399 static int
1400 string_cost_one_line (str)
1401 char *str;
1403 cost = 0;
1404 if (str)
1405 tputs (str, 1, evalcost);
1406 return cost;
1409 /* Compute per line amount of line-dependent padding,
1410 in tenths of characters. */
1413 per_line_cost (str)
1414 register char *str;
1416 cost = 0;
1417 if (str)
1418 tputs (str, 0, evalcost);
1419 cost = - cost;
1420 if (str)
1421 tputs (str, 10, evalcost);
1422 return cost;
1425 #ifndef old
1426 /* char_ins_del_cost[n] is cost of inserting N characters.
1427 char_ins_del_cost[-n] is cost of deleting N characters.
1428 The length of this vector is based on max_frame_width. */
1430 int *char_ins_del_vector;
1432 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WIDTH ((f))])
1433 #endif
1435 /* ARGSUSED */
1436 static void
1437 calculate_ins_del_char_costs (frame)
1438 FRAME_PTR frame;
1440 int ins_startup_cost, del_startup_cost;
1441 int ins_cost_per_char, del_cost_per_char;
1442 register int i;
1443 register int *p;
1445 if (TS_ins_multi_chars)
1447 ins_cost_per_char = 0;
1448 ins_startup_cost = string_cost_one_line (TS_ins_multi_chars);
1450 else if (TS_ins_char || TS_pad_inserted_char
1451 || (TS_insert_mode && TS_end_insert_mode))
1453 ins_startup_cost = (30 * (string_cost (TS_insert_mode)
1454 + string_cost (TS_end_insert_mode))) / 100;
1455 ins_cost_per_char = (string_cost_one_line (TS_ins_char)
1456 + string_cost_one_line (TS_pad_inserted_char));
1458 else
1460 ins_startup_cost = 9999;
1461 ins_cost_per_char = 0;
1464 if (TS_del_multi_chars)
1466 del_cost_per_char = 0;
1467 del_startup_cost = string_cost_one_line (TS_del_multi_chars);
1469 else if (TS_del_char)
1471 del_startup_cost = (string_cost (TS_delete_mode)
1472 + string_cost (TS_end_delete_mode));
1473 if (delete_in_insert_mode)
1474 del_startup_cost /= 2;
1475 del_cost_per_char = string_cost_one_line (TS_del_char);
1477 else
1479 del_startup_cost = 9999;
1480 del_cost_per_char = 0;
1483 /* Delete costs are at negative offsets */
1484 p = &char_ins_del_cost (frame)[0];
1485 for (i = FRAME_WIDTH (frame); --i >= 0;)
1486 *--p = (del_startup_cost += del_cost_per_char);
1488 /* Doing nothing is free */
1489 p = &char_ins_del_cost (frame)[0];
1490 *p++ = 0;
1492 /* Insert costs are at positive offsets */
1493 for (i = FRAME_WIDTH (frame); --i >= 0;)
1494 *p++ = (ins_startup_cost += ins_cost_per_char);
1497 void
1498 calculate_costs (frame)
1499 FRAME_PTR frame;
1501 register char *f = (TS_set_scroll_region
1502 ? TS_set_scroll_region
1503 : TS_set_scroll_region_1);
1505 FRAME_COST_BAUD_RATE (frame) = baud_rate;
1507 scroll_region_cost = string_cost (f);
1509 /* These variables are only used for terminal stuff. They are allocated
1510 once for the terminal frame of X-windows emacs, but not used afterwards.
1512 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1513 X turns off char_ins_del_ok.
1515 chars_wasted and copybuf are only used here in term.c in cases where
1516 the term hook isn't called. */
1518 max_frame_height = max (max_frame_height, FRAME_HEIGHT (frame));
1519 max_frame_width = max (max_frame_width, FRAME_WIDTH (frame));
1521 if (chars_wasted != 0)
1522 chars_wasted = (char *) xrealloc (chars_wasted, max_frame_height);
1523 else
1524 chars_wasted = (char *) xmalloc (max_frame_height);
1526 if (copybuf != 0)
1527 copybuf = (char *) xrealloc (copybuf, max_frame_height);
1528 else
1529 copybuf = (char *) xmalloc (max_frame_height);
1531 if (char_ins_del_vector != 0)
1532 char_ins_del_vector
1533 = (int *) xrealloc (char_ins_del_vector,
1534 (sizeof (int)
1535 + 2 * max_frame_width * sizeof (int)));
1536 else
1537 char_ins_del_vector
1538 = (int *) xmalloc (sizeof (int)
1539 + 2 * max_frame_width * sizeof (int));
1541 bzero (chars_wasted, max_frame_height);
1542 bzero (copybuf, max_frame_height);
1543 bzero (char_ins_del_vector, (sizeof (int)
1544 + 2 * max_frame_width * sizeof (int)));
1546 if (f && (!TS_ins_line && !TS_del_line))
1547 do_line_insertion_deletion_costs (frame,
1548 TS_rev_scroll, TS_ins_multi_lines,
1549 TS_fwd_scroll, TS_del_multi_lines,
1550 f, f, 1);
1551 else
1552 do_line_insertion_deletion_costs (frame,
1553 TS_ins_line, TS_ins_multi_lines,
1554 TS_del_line, TS_del_multi_lines,
1555 0, 0, 1);
1557 calculate_ins_del_char_costs (frame);
1559 /* Don't use TS_repeat if its padding is worse than sending the chars */
1560 if (TS_repeat && per_line_cost (TS_repeat) * baud_rate < 9000)
1561 RPov = string_cost (TS_repeat);
1562 else
1563 RPov = FRAME_WIDTH (frame) * 2;
1565 cmcostinit (); /* set up cursor motion costs */
1568 struct fkey_table {
1569 char *cap, *name;
1572 /* Termcap capability names that correspond directly to X keysyms.
1573 Some of these (marked "terminfo") aren't supplied by old-style
1574 (Berkeley) termcap entries. They're listed in X keysym order;
1575 except we put the keypad keys first, so that if they clash with
1576 other keys (as on the IBM PC keyboard) they get overridden.
1579 static struct fkey_table keys[] =
1581 "kh", "home", /* termcap */
1582 "kl", "left", /* termcap */
1583 "ku", "up", /* termcap */
1584 "kr", "right", /* termcap */
1585 "kd", "down", /* termcap */
1586 "%8", "prior", /* terminfo */
1587 "%5", "next", /* terminfo */
1588 "@7", "end", /* terminfo */
1589 "@1", "begin", /* terminfo */
1590 "*6", "select", /* terminfo */
1591 "%9", "print", /* terminfo */
1592 "@4", "execute", /* terminfo --- actually the `command' key */
1594 * "insert" --- see below
1596 "&8", "undo", /* terminfo */
1597 "%0", "redo", /* terminfo */
1598 "%7", "menu", /* terminfo --- actually the `options' key */
1599 "@0", "find", /* terminfo */
1600 "@2", "cancel", /* terminfo */
1601 "%1", "help", /* terminfo */
1603 * "break" goes here, but can't be reliably intercepted with termcap
1605 "&4", "reset", /* terminfo --- actually `restart' */
1607 * "system" and "user" --- no termcaps
1609 "kE", "clearline", /* terminfo */
1610 "kA", "insertline", /* terminfo */
1611 "kL", "deleteline", /* terminfo */
1612 "kI", "insertchar", /* terminfo */
1613 "kD", "deletechar", /* terminfo */
1614 "kB", "backtab", /* terminfo */
1616 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1618 "@8", "kp-enter", /* terminfo */
1620 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1621 * "kp-multiply", "kp-add", "kp-separator",
1622 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1623 * --- no termcaps for any of these.
1625 "K4", "kp-1", /* terminfo */
1627 * "kp-2" --- no termcap
1629 "K5", "kp-3", /* terminfo */
1631 * "kp-4" --- no termcap
1633 "K2", "kp-5", /* terminfo */
1635 * "kp-6" --- no termcap
1637 "K1", "kp-7", /* terminfo */
1639 * "kp-8" --- no termcap
1641 "K3", "kp-9", /* terminfo */
1643 * "kp-equal" --- no termcap
1645 "k1", "f1",
1646 "k2", "f2",
1647 "k3", "f3",
1648 "k4", "f4",
1649 "k5", "f5",
1650 "k6", "f6",
1651 "k7", "f7",
1652 "k8", "f8",
1653 "k9", "f9",
1656 static char **term_get_fkeys_arg;
1657 static Lisp_Object term_get_fkeys_1 ();
1659 /* Find the escape codes sent by the function keys for Vfunction_key_map.
1660 This function scans the termcap function key sequence entries, and
1661 adds entries to Vfunction_key_map for each function key it finds. */
1663 void
1664 term_get_fkeys (address)
1665 char **address;
1667 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1668 errors during the call. The only errors should be from Fdefine_key
1669 when given a key sequence containing an invalid prefix key. If the
1670 termcap defines function keys which use a prefix that is already bound
1671 to a command by the default bindings, we should silently ignore that
1672 function key specification, rather than giving the user an error and
1673 refusing to run at all on such a terminal. */
1675 extern Lisp_Object Fidentity ();
1676 term_get_fkeys_arg = address;
1677 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1680 static Lisp_Object
1681 term_get_fkeys_1 ()
1683 int i;
1685 char **address = term_get_fkeys_arg;
1687 /* This can happen if CANNOT_DUMP or with strange options. */
1688 if (!initialized)
1689 Vfunction_key_map = Fmake_sparse_keymap (Qnil);
1691 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1693 char *sequence = tgetstr (keys[i].cap, address);
1694 if (sequence)
1695 Fdefine_key (Vfunction_key_map, build_string (sequence),
1696 Fmake_vector (make_number (1),
1697 intern (keys[i].name)));
1700 /* The uses of the "k0" capability are inconsistent; sometimes it
1701 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1702 We will attempt to politely accommodate both systems by testing for
1703 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1706 char *k_semi = tgetstr ("k;", address);
1707 char *k0 = tgetstr ("k0", address);
1708 char *k0_name = "f10";
1710 if (k_semi)
1712 Fdefine_key (Vfunction_key_map, build_string (k_semi),
1713 Fmake_vector (make_number (1), intern ("f10")));
1714 k0_name = "f0";
1717 if (k0)
1718 Fdefine_key (Vfunction_key_map, build_string (k0),
1719 Fmake_vector (make_number (1), intern (k0_name)));
1722 /* Set up cookies for numbered function keys above f10. */
1724 char fcap[3], fkey[4];
1726 fcap[0] = 'F'; fcap[2] = '\0';
1727 for (i = 11; i < 64; i++)
1729 if (i <= 19)
1730 fcap[1] = '1' + i - 11;
1731 else if (i <= 45)
1732 fcap[1] = 'A' + i - 20;
1733 else
1734 fcap[1] = 'a' + i - 46;
1737 char *sequence = tgetstr (fcap, address);
1738 if (sequence)
1740 sprintf (fkey, "f%d", i);
1741 Fdefine_key (Vfunction_key_map, build_string (sequence),
1742 Fmake_vector (make_number (1),
1743 intern (fkey)));
1750 * Various mappings to try and get a better fit.
1753 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1754 if (!tgetstr (cap1, address)) \
1756 char *sequence = tgetstr (cap2, address); \
1757 if (sequence) \
1758 Fdefine_key (Vfunction_key_map, build_string (sequence), \
1759 Fmake_vector (make_number (1), \
1760 intern (sym))); \
1763 /* if there's no key_next keycap, map key_npage to `next' keysym */
1764 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1765 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1766 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1767 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1768 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1769 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1770 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1772 /* IBM has their own non-standard dialect of terminfo.
1773 If the standard name isn't found, try the IBM name. */
1774 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1775 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1776 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1777 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1778 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1779 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1780 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1781 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1782 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1783 #undef CONDITIONAL_REASSIGN
1786 return Qnil;
1790 /***********************************************************************
1791 Character Display Information
1792 ***********************************************************************/
1794 static void append_glyph P_ ((struct it *));
1797 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1798 terminal frames if IT->glyph_row != NULL. IT->c is the character
1799 for which to produce glyphs; IT->face_id contains the character's
1800 face. Padding glyphs are appended if IT->c has a IT->pixel_width >
1801 1. */
1803 static void
1804 append_glyph (it)
1805 struct it *it;
1807 struct glyph *glyph, *end;
1808 int i;
1810 xassert (it->glyph_row);
1811 glyph = (it->glyph_row->glyphs[it->area]
1812 + it->glyph_row->used[it->area]);
1813 end = it->glyph_row->glyphs[1 + it->area];
1815 for (i = 0;
1816 i < it->pixel_width && glyph < end;
1817 ++i)
1819 glyph->type = CHAR_GLYPH;
1820 glyph->pixel_width = 1;
1821 glyph->u.ch = it->c;
1822 glyph->face_id = it->face_id;
1823 glyph->padding_p = i > 0;
1824 glyph->charpos = CHARPOS (it->position);
1825 glyph->object = it->object;
1827 ++it->glyph_row->used[it->area];
1828 ++glyph;
1833 /* Produce glyphs for the display element described by IT. The
1834 function fills output fields of IT with pixel information like the
1835 pixel width and height of a character, and maybe produces glyphs at
1836 the same time if IT->glyph_row is non-null. See the explanation of
1837 struct display_iterator in dispextern.h for an overview. */
1839 void
1840 produce_glyphs (it)
1841 struct it *it;
1843 /* If a hook is installed, let it do the work. */
1844 xassert (it->what == IT_CHARACTER
1845 || it->what == IT_COMPOSITION
1846 || it->what == IT_IMAGE
1847 || it->what == IT_STRETCH);
1849 /* Nothing but characters are supported on terminal frames. For a
1850 composition sequence, it->c is the first character of the
1851 sequence. */
1852 xassert (it->what == IT_CHARACTER
1853 || it->what == IT_COMPOSITION);
1855 if (it->c >= 040 && it->c < 0177)
1857 it->pixel_width = it->nglyphs = 1;
1858 if (it->glyph_row)
1859 append_glyph (it);
1861 else if (it->c == '\n')
1862 it->pixel_width = it->nglyphs = 0;
1863 else if (it->c == '\t')
1865 int absolute_x = (it->current_x
1866 + it->continuation_lines_width);
1867 int next_tab_x
1868 = (((1 + absolute_x + it->tab_width - 1)
1869 / it->tab_width)
1870 * it->tab_width);
1871 int nspaces;
1873 /* If part of the TAB has been displayed on the previous line
1874 which is continued now, continuation_lines_width will have
1875 been incremented already by the part that fitted on the
1876 continued line. So, we will get the right number of spaces
1877 here. */
1878 nspaces = next_tab_x - absolute_x;
1880 if (it->glyph_row)
1882 int n = nspaces;
1884 it->c = ' ';
1885 it->pixel_width = it->len = 1;
1887 while (n--)
1888 append_glyph (it);
1890 it->c = '\t';
1893 it->pixel_width = nspaces;
1894 it->nglyphs = nspaces;
1896 else if (SINGLE_BYTE_CHAR_P (it->c))
1898 /* Coming here means that it->c is from display table, thus we
1899 must send the code as is to the terminal. Although there's
1900 no way to know how many columns it occupies on a screen, it
1901 is a good assumption that a single byte code has 1-column
1902 width. */
1903 it->pixel_width = it->nglyphs = 1;
1904 if (it->glyph_row)
1905 append_glyph (it);
1907 else
1909 /* A multi-byte character. The display width is fixed for all
1910 characters of the set. Some of the glyphs may have to be
1911 ignored because they are already displayed in a continued
1912 line. */
1913 int charset = CHAR_CHARSET (it->c);
1915 it->pixel_width = CHARSET_WIDTH (charset);
1916 it->nglyphs = it->pixel_width;
1918 if (it->glyph_row)
1919 append_glyph (it);
1922 /* Advance current_x by the pixel width as a convenience for
1923 the caller. */
1924 if (it->area == TEXT_AREA)
1925 it->current_x += it->pixel_width;
1926 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1927 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
1931 /* Get information about special display element WHAT in an
1932 environment described by IT. WHAT is one of IT_TRUNCATION or
1933 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1934 non-null glyph_row member. This function ensures that fields like
1935 face_id, c, len of IT are left untouched. */
1937 void
1938 produce_special_glyphs (it, what)
1939 struct it *it;
1940 enum display_element_type what;
1942 struct it temp_it;
1944 temp_it = *it;
1945 temp_it.dp = NULL;
1946 temp_it.what = IT_CHARACTER;
1947 temp_it.len = 1;
1948 temp_it.object = make_number (0);
1949 bzero (&temp_it.current, sizeof temp_it.current);
1951 if (what == IT_CONTINUATION)
1953 /* Continuation glyph. */
1954 if (it->dp
1955 && INTEGERP (DISP_CONTINUE_GLYPH (it->dp))
1956 && GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (it->dp))))
1958 temp_it.c = FAST_GLYPH_CHAR (XINT (DISP_CONTINUE_GLYPH (it->dp)));
1959 temp_it.len = CHAR_BYTES (temp_it.c);
1961 else
1962 temp_it.c = '\\';
1964 produce_glyphs (&temp_it);
1965 it->pixel_width = temp_it.pixel_width;
1966 it->nglyphs = temp_it.pixel_width;
1968 else if (what == IT_TRUNCATION)
1970 /* Truncation glyph. */
1971 if (it->dp
1972 && INTEGERP (DISP_TRUNC_GLYPH (it->dp))
1973 && GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (it->dp))))
1975 temp_it.c = FAST_GLYPH_CHAR (XINT (DISP_TRUNC_GLYPH (it->dp)));
1976 temp_it.len = CHAR_BYTES (temp_it.c);
1978 else
1979 temp_it.c = '$';
1981 produce_glyphs (&temp_it);
1982 it->pixel_width = temp_it.pixel_width;
1983 it->nglyphs = temp_it.pixel_width;
1985 else
1986 abort ();
1990 /* Return an estimation of the pixel height of mode or top lines on
1991 frame F. FACE_ID specifies what line's height to estimate. */
1994 estimate_mode_line_height (f, face_id)
1995 struct frame *f;
1996 enum face_id face_id;
1998 if (estimate_mode_line_height_hook)
1999 return estimate_mode_line_height_hook (f, face_id);
2000 else
2001 return 1;
2006 /***********************************************************************
2007 Faces
2008 ***********************************************************************/
2010 /* Value is non-zero if attribute ATTR may be used. ATTR should be
2011 one of the enumerators from enum no_color_bit, or a bit set built
2012 from them. Some display attributes may not be used together with
2013 color; the termcap capability `NC' specifies which ones. */
2015 #define MAY_USE_WITH_COLORS_P(ATTR) \
2016 (TN_max_colors > 0 \
2017 ? (TN_no_color_video & (ATTR)) == 0 \
2018 : 1)
2020 /* Turn appearances of face FACE_ID on tty frame F on. */
2022 static void
2023 turn_on_face (f, face_id)
2024 struct frame *f;
2025 int face_id;
2027 struct face *face = FACE_FROM_ID (f, face_id);
2028 long fg = face->foreground;
2029 long bg = face->background;
2031 /* Do this first because TS_end_standout_mode may be the same
2032 as TS_exit_attribute_mode, which turns all appearances off. */
2033 if (MAY_USE_WITH_COLORS_P (NC_REVERSE))
2035 if (TN_max_colors > 0)
2037 if (fg >= 0 && bg >= 0)
2039 /* If the terminal supports colors, we can set them
2040 below without using reverse video. The face's fg
2041 and bg colors are set as they should appear on
2042 the screen, i.e. they take the inverse-video'ness
2043 of the face already into account. */
2045 else if (inverse_video)
2047 if (fg == FACE_TTY_DEFAULT_FG_COLOR
2048 || bg == FACE_TTY_DEFAULT_BG_COLOR)
2049 toggle_highlight ();
2051 else
2053 if (fg == FACE_TTY_DEFAULT_BG_COLOR
2054 || bg == FACE_TTY_DEFAULT_FG_COLOR)
2055 toggle_highlight ();
2058 else
2060 /* If we can't display colors, use reverse video
2061 if the face specifies that. */
2062 if (inverse_video)
2064 if (fg == FACE_TTY_DEFAULT_FG_COLOR
2065 || bg == FACE_TTY_DEFAULT_BG_COLOR)
2066 toggle_highlight ();
2068 else
2070 if (fg == FACE_TTY_DEFAULT_BG_COLOR
2071 || bg == FACE_TTY_DEFAULT_FG_COLOR)
2072 toggle_highlight ();
2077 if (face->tty_bold_p)
2079 if (MAY_USE_WITH_COLORS_P (NC_BOLD))
2080 OUTPUT1_IF (TS_enter_bold_mode);
2082 else if (face->tty_dim_p)
2083 if (MAY_USE_WITH_COLORS_P (NC_DIM))
2084 OUTPUT1_IF (TS_enter_dim_mode);
2086 /* Alternate charset and blinking not yet used. */
2087 if (face->tty_alt_charset_p
2088 && MAY_USE_WITH_COLORS_P (NC_ALT_CHARSET))
2089 OUTPUT1_IF (TS_enter_alt_charset_mode);
2091 if (face->tty_blinking_p
2092 && MAY_USE_WITH_COLORS_P (NC_BLINK))
2093 OUTPUT1_IF (TS_enter_blink_mode);
2095 if (face->tty_underline_p
2096 /* Don't underline if that's difficult. */
2097 && TN_magic_cookie_glitch_ul <= 0
2098 && MAY_USE_WITH_COLORS_P (NC_UNDERLINE))
2099 OUTPUT1_IF (TS_enter_underline_mode);
2101 if (TN_max_colors > 0)
2103 char *p;
2105 if (fg >= 0 && TS_set_foreground)
2107 p = tparam (TS_set_foreground, NULL, 0, (int) fg);
2108 OUTPUT (p);
2109 xfree (p);
2112 if (bg >= 0 && TS_set_background)
2114 p = tparam (TS_set_background, NULL, 0, (int) bg);
2115 OUTPUT (p);
2116 xfree (p);
2122 /* Turn off appearances of face FACE_ID on tty frame F. */
2124 static void
2125 turn_off_face (f, face_id)
2126 struct frame *f;
2127 int face_id;
2129 struct face *face = FACE_FROM_ID (f, face_id);
2131 xassert (face != NULL);
2133 if (TS_exit_attribute_mode)
2135 /* Capability "me" will turn off appearance modes double-bright,
2136 half-bright, reverse-video, standout, underline. It may or
2137 may not turn off alt-char-mode. */
2138 if (face->tty_bold_p
2139 || face->tty_dim_p
2140 || face->tty_reverse_p
2141 || face->tty_alt_charset_p
2142 || face->tty_blinking_p
2143 || face->tty_underline_p)
2145 OUTPUT1_IF (TS_exit_attribute_mode);
2146 if (strcmp (TS_exit_attribute_mode, TS_end_standout_mode) == 0)
2147 standout_mode = 0;
2150 if (face->tty_alt_charset_p)
2151 OUTPUT_IF (TS_exit_alt_charset_mode);
2153 else
2155 /* If we don't have "me" we can only have those appearances
2156 that have exit sequences defined. */
2157 if (face->tty_alt_charset_p)
2158 OUTPUT_IF (TS_exit_alt_charset_mode);
2160 if (face->tty_underline_p
2161 /* We don't underline if that's difficult. */
2162 && TN_magic_cookie_glitch_ul <= 0)
2163 OUTPUT_IF (TS_exit_underline_mode);
2166 /* Switch back to default colors. */
2167 if (TN_max_colors > 0
2168 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
2169 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
2170 || (face->background != FACE_TTY_DEFAULT_COLOR
2171 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
2172 OUTPUT1_IF (TS_orig_pair);
2176 /* Return non-zero if the terminal is capable to display colors. */
2178 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
2179 0, 1, 0,
2180 "Return non-nil if TTY can display colors on FRAME.")
2181 (frame)
2182 Lisp_Object frame;
2184 return TN_max_colors > 0 ? Qt : Qnil;
2190 /***********************************************************************
2191 Initialization
2192 ***********************************************************************/
2194 void
2195 term_init (terminal_type)
2196 char *terminal_type;
2198 char *area;
2199 char **address = &area;
2200 char buffer[2044];
2201 register char *p;
2202 int status;
2203 struct frame *sf = XFRAME (selected_frame);
2205 #ifdef WINDOWSNT
2206 initialize_w32_display ();
2208 Wcm_clear ();
2210 area = (char *) xmalloc (2044);
2212 if (area == 0)
2213 abort ();
2215 FrameRows = FRAME_HEIGHT (sf);
2216 FrameCols = FRAME_WIDTH (sf);
2217 specified_window = FRAME_HEIGHT (sf);
2219 delete_in_insert_mode = 1;
2221 UseTabs = 0;
2222 scroll_region_ok = 0;
2224 /* Seems to insert lines when it's not supposed to, messing
2225 up the display. In doing a trace, it didn't seem to be
2226 called much, so I don't think we're losing anything by
2227 turning it off. */
2229 line_ins_del_ok = 0;
2230 char_ins_del_ok = 1;
2232 baud_rate = 19200;
2234 FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0;
2235 FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none;
2236 TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
2238 return;
2239 #else /* not WINDOWSNT */
2241 Wcm_clear ();
2243 status = tgetent (buffer, terminal_type);
2244 if (status < 0)
2246 #ifdef TERMINFO
2247 fatal ("Cannot open terminfo database file");
2248 #else
2249 fatal ("Cannot open termcap database file");
2250 #endif
2252 if (status == 0)
2254 #ifdef TERMINFO
2255 fatal ("Terminal type %s is not defined.\n\
2256 If that is not the actual type of terminal you have,\n\
2257 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2258 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2259 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
2260 terminal_type);
2261 #else
2262 fatal ("Terminal type %s is not defined.\n\
2263 If that is not the actual type of terminal you have,\n\
2264 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2265 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2266 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
2267 terminal_type);
2268 #endif
2270 #ifdef TERMINFO
2271 area = (char *) xmalloc (2044);
2272 #else
2273 area = (char *) xmalloc (strlen (buffer));
2274 #endif /* not TERMINFO */
2275 if (area == 0)
2276 abort ();
2278 TS_ins_line = tgetstr ("al", address);
2279 TS_ins_multi_lines = tgetstr ("AL", address);
2280 TS_bell = tgetstr ("bl", address);
2281 BackTab = tgetstr ("bt", address);
2282 TS_clr_to_bottom = tgetstr ("cd", address);
2283 TS_clr_line = tgetstr ("ce", address);
2284 TS_clr_frame = tgetstr ("cl", address);
2285 ColPosition = NULL; /* tgetstr ("ch", address); */
2286 AbsPosition = tgetstr ("cm", address);
2287 CR = tgetstr ("cr", address);
2288 TS_set_scroll_region = tgetstr ("cs", address);
2289 TS_set_scroll_region_1 = tgetstr ("cS", address);
2290 RowPosition = tgetstr ("cv", address);
2291 TS_del_char = tgetstr ("dc", address);
2292 TS_del_multi_chars = tgetstr ("DC", address);
2293 TS_del_line = tgetstr ("dl", address);
2294 TS_del_multi_lines = tgetstr ("DL", address);
2295 TS_delete_mode = tgetstr ("dm", address);
2296 TS_end_delete_mode = tgetstr ("ed", address);
2297 TS_end_insert_mode = tgetstr ("ei", address);
2298 Home = tgetstr ("ho", address);
2299 TS_ins_char = tgetstr ("ic", address);
2300 TS_ins_multi_chars = tgetstr ("IC", address);
2301 TS_insert_mode = tgetstr ("im", address);
2302 TS_pad_inserted_char = tgetstr ("ip", address);
2303 TS_end_keypad_mode = tgetstr ("ke", address);
2304 TS_keypad_mode = tgetstr ("ks", address);
2305 LastLine = tgetstr ("ll", address);
2306 Right = tgetstr ("nd", address);
2307 Down = tgetstr ("do", address);
2308 if (!Down)
2309 Down = tgetstr ("nl", address); /* Obsolete name for "do" */
2310 #ifdef VMS
2311 /* VMS puts a carriage return before each linefeed,
2312 so it is not safe to use linefeeds. */
2313 if (Down && Down[0] == '\n' && Down[1] == '\0')
2314 Down = 0;
2315 #endif /* VMS */
2316 if (tgetflag ("bs"))
2317 Left = "\b"; /* can't possibly be longer! */
2318 else /* (Actually, "bs" is obsolete...) */
2319 Left = tgetstr ("le", address);
2320 if (!Left)
2321 Left = tgetstr ("bc", address); /* Obsolete name for "le" */
2322 TS_pad_char = tgetstr ("pc", address);
2323 TS_repeat = tgetstr ("rp", address);
2324 TS_end_standout_mode = tgetstr ("se", address);
2325 TS_fwd_scroll = tgetstr ("sf", address);
2326 TS_standout_mode = tgetstr ("so", address);
2327 TS_rev_scroll = tgetstr ("sr", address);
2328 Wcm.cm_tab = tgetstr ("ta", address);
2329 TS_end_termcap_modes = tgetstr ("te", address);
2330 TS_termcap_modes = tgetstr ("ti", address);
2331 Up = tgetstr ("up", address);
2332 TS_visible_bell = tgetstr ("vb", address);
2333 TS_cursor_normal = tgetstr ("ve", address);
2334 TS_cursor_visible = tgetstr ("vs", address);
2335 TS_cursor_invisible = tgetstr ("vi", address);
2336 TS_set_window = tgetstr ("wi", address);
2338 TS_enter_underline_mode = tgetstr ("us", address);
2339 TS_exit_underline_mode = tgetstr ("ue", address);
2340 TN_magic_cookie_glitch_ul = tgetnum ("ug");
2341 TS_enter_bold_mode = tgetstr ("md", address);
2342 TS_enter_dim_mode = tgetstr ("mh", address);
2343 TS_enter_blink_mode = tgetstr ("mb", address);
2344 TS_enter_reverse_mode = tgetstr ("mr", address);
2345 TS_enter_alt_charset_mode = tgetstr ("as", address);
2346 TS_exit_alt_charset_mode = tgetstr ("ae", address);
2347 TS_exit_attribute_mode = tgetstr ("me", address);
2349 MultiUp = tgetstr ("UP", address);
2350 MultiDown = tgetstr ("DO", address);
2351 MultiLeft = tgetstr ("LE", address);
2352 MultiRight = tgetstr ("RI", address);
2354 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
2355 color because we can't switch back to the default foreground and
2356 background. */
2357 TS_orig_pair = tgetstr ("op", address);
2358 if (TS_orig_pair)
2360 TS_set_foreground = tgetstr ("AF", address);
2361 TS_set_background = tgetstr ("AB", address);
2362 if (!TS_set_foreground)
2364 /* SVr4. */
2365 TS_set_foreground = tgetstr ("Sf", address);
2366 TS_set_background = tgetstr ("Sb", address);
2369 TN_max_colors = tgetnum ("Co");
2370 TN_max_pairs = tgetnum ("pa");
2372 TN_no_color_video = tgetnum ("NC");
2373 if (TN_no_color_video == -1)
2374 TN_no_color_video = 0;
2377 MagicWrap = tgetflag ("xn");
2378 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
2379 the former flag imply the latter. */
2380 AutoWrap = MagicWrap || tgetflag ("am");
2381 memory_below_frame = tgetflag ("db");
2382 TF_hazeltine = tgetflag ("hz");
2383 must_write_spaces = tgetflag ("in");
2384 meta_key = tgetflag ("km") || tgetflag ("MT");
2385 TF_insmode_motion = tgetflag ("mi");
2386 TF_standout_motion = tgetflag ("ms");
2387 TF_underscore = tgetflag ("ul");
2388 TF_xs = tgetflag ("xs");
2389 TF_teleray = tgetflag ("xt");
2391 term_get_fkeys (address);
2393 /* Get frame size from system, or else from termcap. */
2395 int height, width;
2396 get_frame_size (&width, &height);
2397 FRAME_WIDTH (sf) = width;
2398 FRAME_HEIGHT (sf) = height;
2401 if (FRAME_WIDTH (sf) <= 0)
2402 SET_FRAME_WIDTH (sf, tgetnum ("co"));
2403 else
2404 /* Keep width and external_width consistent */
2405 SET_FRAME_WIDTH (sf, FRAME_WIDTH (sf));
2406 if (FRAME_HEIGHT (sf) <= 0)
2407 FRAME_HEIGHT (sf) = tgetnum ("li");
2409 if (FRAME_HEIGHT (sf) < 3 || FRAME_WIDTH (sf) < 3)
2410 fatal ("Screen size %dx%d is too small",
2411 FRAME_HEIGHT (sf), FRAME_WIDTH (sf));
2413 min_padding_speed = tgetnum ("pb");
2414 TN_standout_width = tgetnum ("sg");
2415 TabWidth = tgetnum ("tw");
2417 #ifdef VMS
2418 /* These capabilities commonly use ^J.
2419 I don't know why, but sending them on VMS does not work;
2420 it causes following spaces to be lost, sometimes.
2421 For now, the simplest fix is to avoid using these capabilities ever. */
2422 if (Down && Down[0] == '\n')
2423 Down = 0;
2424 #endif /* VMS */
2426 if (!TS_bell)
2427 TS_bell = "\07";
2429 if (!TS_fwd_scroll)
2430 TS_fwd_scroll = Down;
2432 PC = TS_pad_char ? *TS_pad_char : 0;
2434 if (TabWidth < 0)
2435 TabWidth = 8;
2437 /* Turned off since /etc/termcap seems to have :ta= for most terminals
2438 and newer termcap doc does not seem to say there is a default.
2439 if (!Wcm.cm_tab)
2440 Wcm.cm_tab = "\t";
2443 if (TS_standout_mode == 0)
2445 TN_standout_width = tgetnum ("ug");
2446 TS_end_standout_mode = tgetstr ("ue", address);
2447 TS_standout_mode = tgetstr ("us", address);
2450 /* If no `se' string, try using a `me' string instead.
2451 If that fails, we can't use standout mode at all. */
2452 if (TS_end_standout_mode == 0)
2454 char *s = tgetstr ("me", address);
2455 if (s != 0)
2456 TS_end_standout_mode = s;
2457 else
2458 TS_standout_mode = 0;
2461 if (TF_teleray)
2463 Wcm.cm_tab = 0;
2464 /* Teleray: most programs want a space in front of TS_standout_mode,
2465 but Emacs can do without it (and give one extra column). */
2466 TS_standout_mode = "\033RD";
2467 TN_standout_width = 1;
2468 /* But that means we cannot rely on ^M to go to column zero! */
2469 CR = 0;
2470 /* LF can't be trusted either -- can alter hpos */
2471 /* if move at column 0 thru a line with TS_standout_mode */
2472 Down = 0;
2475 /* Special handling for certain terminal types known to need it */
2477 if (!strcmp (terminal_type, "supdup"))
2479 memory_below_frame = 1;
2480 Wcm.cm_losewrap = 1;
2482 if (!strncmp (terminal_type, "c10", 3)
2483 || !strcmp (terminal_type, "perq"))
2485 /* Supply a makeshift :wi string.
2486 This string is not valid in general since it works only
2487 for windows starting at the upper left corner;
2488 but that is all Emacs uses.
2490 This string works only if the frame is using
2491 the top of the video memory, because addressing is memory-relative.
2492 So first check the :ti string to see if that is true.
2494 It would be simpler if the :wi string could go in the termcap
2495 entry, but it can't because it is not fully valid.
2496 If it were in the termcap entry, it would confuse other programs. */
2497 if (!TS_set_window)
2499 p = TS_termcap_modes;
2500 while (*p && strcmp (p, "\033v "))
2501 p++;
2502 if (*p)
2503 TS_set_window = "\033v%C %C %C %C ";
2505 /* Termcap entry often fails to have :in: flag */
2506 must_write_spaces = 1;
2507 /* :ti string typically fails to have \E^G! in it */
2508 /* This limits scope of insert-char to one line. */
2509 strcpy (area, TS_termcap_modes);
2510 strcat (area, "\033\007!");
2511 TS_termcap_modes = area;
2512 area += strlen (area) + 1;
2513 p = AbsPosition;
2514 /* Change all %+ parameters to %C, to handle
2515 values above 96 correctly for the C100. */
2516 while (*p)
2518 if (p[0] == '%' && p[1] == '+')
2519 p[1] = 'C';
2520 p++;
2524 FrameRows = FRAME_HEIGHT (sf);
2525 FrameCols = FRAME_WIDTH (sf);
2526 specified_window = FRAME_HEIGHT (sf);
2528 if (Wcm_init () == -1) /* can't do cursor motion */
2529 #ifdef VMS
2530 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2531 It lacks the ability to position the cursor.\n\
2532 If that is not the actual type of terminal you have, use either the\n\
2533 DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
2534 or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
2535 terminal_type);
2536 #else /* not VMS */
2537 # ifdef TERMINFO
2538 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2539 It lacks the ability to position the cursor.\n\
2540 If that is not the actual type of terminal you have,\n\
2541 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2542 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2543 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
2544 terminal_type);
2545 # else /* TERMCAP */
2546 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2547 It lacks the ability to position the cursor.\n\
2548 If that is not the actual type of terminal you have,\n\
2549 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2550 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2551 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
2552 terminal_type);
2553 # endif /* TERMINFO */
2554 #endif /*VMS */
2555 if (FRAME_HEIGHT (sf) <= 0
2556 || FRAME_WIDTH (sf) <= 0)
2557 fatal ("The frame size has not been specified");
2559 delete_in_insert_mode
2560 = TS_delete_mode && TS_insert_mode
2561 && !strcmp (TS_delete_mode, TS_insert_mode);
2563 se_is_so = (TS_standout_mode
2564 && TS_end_standout_mode
2565 && !strcmp (TS_standout_mode, TS_end_standout_mode));
2567 /* Remove width of standout marker from usable width of line */
2568 if (TN_standout_width > 0)
2569 SET_FRAME_WIDTH (sf, FRAME_WIDTH (sf) - TN_standout_width);
2571 UseTabs = tabs_safe_p () && TabWidth == 8;
2573 scroll_region_ok
2574 = (Wcm.cm_abs
2575 && (TS_set_window || TS_set_scroll_region || TS_set_scroll_region_1));
2577 line_ins_del_ok = (((TS_ins_line || TS_ins_multi_lines)
2578 && (TS_del_line || TS_del_multi_lines))
2579 || (scroll_region_ok && TS_fwd_scroll && TS_rev_scroll));
2581 char_ins_del_ok = ((TS_ins_char || TS_insert_mode
2582 || TS_pad_inserted_char || TS_ins_multi_chars)
2583 && (TS_del_char || TS_del_multi_chars));
2585 fast_clear_end_of_line = TS_clr_line != 0;
2587 init_baud_rate ();
2588 if (read_socket_hook) /* Baudrate is somewhat */
2589 /* meaningless in this case */
2590 baud_rate = 9600;
2592 FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0;
2593 FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none;
2594 #endif /* WINDOWSNT */
2597 /* VARARGS 1 */
2598 void
2599 fatal (str, arg1, arg2)
2600 char *str, *arg1, *arg2;
2602 fprintf (stderr, "emacs: ");
2603 fprintf (stderr, str, arg1, arg2);
2604 fprintf (stderr, "\n");
2605 fflush (stderr);
2606 exit (1);
2609 void
2610 syms_of_term ()
2612 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
2613 "Non-nil means the system uses terminfo rather than termcap.\n\
2614 This variable can be used by terminal emulator packages.");
2615 #ifdef TERMINFO
2616 system_uses_terminfo = 1;
2617 #else
2618 system_uses_terminfo = 0;
2619 #endif
2621 DEFVAR_LISP ("ring-bell-function", &Vring_bell_function,
2622 "Non-nil means call this function to ring the bell.\n\
2623 The function should accept no arguments.");
2624 Vring_bell_function = Qnil;
2626 defsubr (&Stty_display_color_p);