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