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