(consume_chars): If coding->src_object is nil, don't check annotation.
[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
a4decb7f
KH
792/* Encode SRC_LEN glyphs starting at SRC to terminal output codes and
793 store them at DST. Do not write more than DST_LEN bytes. That may
794 require stopping before all SRC_LEN input glyphs have been
795 converted.
796
797 We store the number of glyphs actually converted in *CONSUMED. The
798 return value is the number of bytes store in DST. */
799
800int
801encode_terminal_code (src, dst, src_len, dst_len, consumed)
a168702a 802 struct glyph *src;
a4decb7f
KH
803 int src_len;
804 unsigned char *dst;
805 int dst_len, *consumed;
806{
a168702a 807 struct glyph *src_start = src, *src_end = src + src_len;
a4decb7f 808 unsigned char *dst_start = dst, *dst_end = dst + dst_len;
085d5908 809 register GLYPH g;
405ea71c
KR
810 unsigned char workbuf[MAX_MULTIBYTE_LENGTH];
811 const unsigned char *buf;
6589fd67 812 int len;
a4decb7f
KH
813 register int tlen = GLYPH_TABLE_LENGTH;
814 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
6589fd67
KH
815 struct coding_system *coding;
816
1ac0700a
KH
817 /* If terminal_coding does any conversion, use it, otherwise use
818 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
819 because it always return 1 if the member src_multibyte is 1. */
820 coding = (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK
6589fd67
KH
821 ? &terminal_coding
822 : &safe_terminal_coding);
a4decb7f
KH
823
824 while (src < src_end)
825 {
a4decb7f 826 /* We must skip glyphs to be padded for a wide character. */
a168702a 827 if (! CHAR_GLYPH_PADDING_P (*src))
a4decb7f 828 {
32de38e4
KH
829 g = GLYPH_FROM_CHAR_GLYPH (src[0]);
830
831 if (g < 0 || g >= tlen)
085d5908 832 {
9542cb1f 833 /* This glyph doesn't have an entry in Vglyph_table. */
32de38e4
KH
834 if (! CHAR_VALID_P (src->u.ch, 0))
835 {
836 len = 1;
837 buf = " ";
f2ba40be 838 coding->src_multibyte = 0;
32de38e4
KH
839 }
840 else
841 {
842 len = CHAR_STRING (src->u.ch, workbuf);
843 buf = workbuf;
f2ba40be 844 coding->src_multibyte = 1;
32de38e4 845 }
085d5908 846 }
32de38e4 847 else
a4decb7f 848 {
32de38e4 849 /* This glyph has an entry in Vglyph_table,
a4decb7f
KH
850 so process any alias before testing for simpleness. */
851 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
32de38e4
KH
852
853 if (GLYPH_SIMPLE_P (tbase, tlen, g))
854 {
c989b7be
KH
855 /* We set the multi-byte form of a character in G
856 (that should be an ASCII character) at
857 WORKBUF. */
858 workbuf[0] = FAST_GLYPH_CHAR (g);
859 len = 1;
32de38e4 860 buf = workbuf;
f2ba40be 861 coding->src_multibyte = 0;
32de38e4
KH
862 }
863 else
864 {
865 /* We have a string in Vglyph_table. */
866 len = GLYPH_LENGTH (tbase, g);
867 buf = GLYPH_STRING (tbase, g);
f2ba40be 868 coding->src_multibyte = STRING_MULTIBYTE (tbase[g]);
32de38e4 869 }
171d7f24 870 }
177c0ea7 871
9332ea03
KH
872 coding->source = buf;
873 coding->destination = dst;
874 coding->dst_bytes = dst_end - dst;
875 encode_coding_object (coding, Qnil, 0, 0, 1, len, Qnil);
c42869c4 876 len -= coding->consumed;
6589fd67 877 dst += coding->produced;
9332ea03 878 if (coding->result == CODING_RESULT_INSUFFICIENT_DST)
f3ac545f
KH
879 /* The remaining output buffer is too short. We must
880 break the loop here without increasing SRC so that the
881 next call of this function starts from the same glyph. */
882 break;
883
c42869c4
KH
884 if (len > 0)
885 {
f3ac545f
KH
886 /* This is the case that a code of the range 0200..0237
887 exists in buf. We must just write out such a code. */
888 buf += coding->consumed;
889 while (len--)
890 *dst++ = *buf++;
c42869c4 891 }
a4decb7f
KH
892 }
893 src++;
894 }
177c0ea7 895
a4decb7f
KH
896 *consumed = src - src_start;
897 return (dst - dst_start);
898}
899
08a24c47 900
dfcf069d 901void
08a24c47 902write_glyphs (string, len)
a168702a 903 register struct glyph *string;
08a24c47
JB
904 register int len;
905{
a4decb7f 906 int produced, consumed;
e52f4e08
GM
907 struct frame *sf = XFRAME (selected_frame);
908 struct frame *f = updating_frame ? updating_frame : sf;
d2fdb076
KH
909 unsigned char conversion_buffer[1024];
910 int conversion_buffer_size = sizeof conversion_buffer;
08a24c47
JB
911
912 if (write_glyphs_hook
a168702a 913 && ! FRAME_TERMCAP_P (f))
08a24c47
JB
914 {
915 (*write_glyphs_hook) (string, len);
916 return;
917 }
918
08a24c47 919 turn_off_insert ();
d284f58f 920 tty_hide_cursor ();
08a24c47 921
a168702a 922 /* Don't dare write in last column of bottom line, if Auto-Wrap,
ff11dfa1 923 since that would scroll the whole frame on some terminals. */
08a24c47
JB
924
925 if (AutoWrap
9882535b
KS
926 && curY + 1 == FRAME_LINES (sf)
927 && (curX + len) == FRAME_COLS (sf))
08a24c47 928 len --;
a4decb7f
KH
929 if (len <= 0)
930 return;
08a24c47
JB
931
932 cmplus (len);
177c0ea7 933
6589fd67
KH
934 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
935 the tail. */
936 terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
177c0ea7 937
a4decb7f 938 while (len > 0)
08a24c47 939 {
a168702a 940 /* Identify a run of glyphs with the same face. */
32de38e4 941 int face_id = string->face_id;
a168702a 942 int n;
177c0ea7 943
a168702a 944 for (n = 1; n < len; ++n)
32de38e4 945 if (string[n].face_id != face_id)
a168702a
GM
946 break;
947
948 /* Turn appearance modes of the face of the run on. */
2535aa8c 949 highlight_if_desired ();
a168702a
GM
950 turn_on_face (f, face_id);
951
952 while (n > 0)
08a24c47 953 {
d2fdb076
KH
954 /* We use a fixed size (1024 bytes) of conversion buffer.
955 Usually it is sufficient, but if not, we just repeat the
956 loop. */
a168702a
GM
957 produced = encode_terminal_code (string, conversion_buffer,
958 n, conversion_buffer_size,
959 &consumed);
960 if (produced > 0)
961 {
962 fwrite (conversion_buffer, 1, produced, stdout);
963 if (ferror (stdout))
964 clearerr (stdout);
965 if (termscript)
966 fwrite (conversion_buffer, 1, produced, termscript);
967 }
968 len -= consumed;
969 n -= consumed;
970 string += consumed;
08a24c47 971 }
a168702a
GM
972
973 /* Turn appearance modes off. */
974 turn_off_face (f, face_id);
65aa5e85 975 turn_off_highlight ();
a4decb7f 976 }
177c0ea7 977
a4decb7f 978 /* We may have to output some codes to terminate the writing. */
ca1e6a13 979 if (CODING_REQUIRE_FLUSHING (&terminal_coding))
a4decb7f 980 {
6589fd67 981 terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
9332ea03
KH
982 terminal_coding.source = (unsigned char *) "";
983 terminal_coding.destination = conversion_buffer;
984 terminal_coding.dst_bytes = conversion_buffer_size;
985 encode_coding_object (&terminal_coding, Qnil, 0, 0, 0, 0, Qnil);
6589fd67 986 if (terminal_coding.produced > 0)
df8bf431 987 {
6589fd67 988 fwrite (conversion_buffer, 1, terminal_coding.produced, stdout);
df8bf431
KH
989 if (ferror (stdout))
990 clearerr (stdout);
991 if (termscript)
6589fd67
KH
992 fwrite (conversion_buffer, 1, terminal_coding.produced,
993 termscript);
df8bf431 994 }
08a24c47 995 }
177c0ea7 996
9a6b6f92 997 cmcheckmagic ();
08a24c47
JB
998}
999
1000/* If start is zero, insert blanks instead of a string at start */
177c0ea7 1001
dfcf069d 1002void
08a24c47 1003insert_glyphs (start, len)
a168702a 1004 register struct glyph *start;
08a24c47
JB
1005 register int len;
1006{
1007 char *buf;
6bbd7a29 1008 struct glyph *glyph = NULL;
e52f4e08 1009 struct frame *f, *sf;
08a24c47 1010
a4decb7f
KH
1011 if (len <= 0)
1012 return;
1013
a168702a 1014 if (insert_glyphs_hook)
08a24c47
JB
1015 {
1016 (*insert_glyphs_hook) (start, len);
1017 return;
1018 }
a168702a 1019
e52f4e08
GM
1020 sf = XFRAME (selected_frame);
1021 f = updating_frame ? updating_frame : sf;
08a24c47
JB
1022
1023 if (TS_ins_multi_chars)
1024 {
1025 buf = tparam (TS_ins_multi_chars, 0, 0, len);
1026 OUTPUT1 (buf);
9ac0d9e0 1027 xfree (buf);
08a24c47
JB
1028 if (start)
1029 write_glyphs (start, len);
1030 return;
1031 }
1032
1033 turn_on_insert ();
1034 cmplus (len);
6589fd67
KH
1035 /* The bit CODING_MODE_LAST_BLOCK should be set to 1 only at the tail. */
1036 terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
07109bf9 1037 while (len-- > 0)
08a24c47 1038 {
a4decb7f 1039 int produced, consumed;
d2fdb076
KH
1040 unsigned char conversion_buffer[1024];
1041 int conversion_buffer_size = sizeof conversion_buffer;
a4decb7f 1042
08a24c47
JB
1043 OUTPUT1_IF (TS_ins_char);
1044 if (!start)
32de38e4
KH
1045 {
1046 conversion_buffer[0] = SPACEGLYPH;
1047 produced = 1;
1048 }
08a24c47 1049 else
08a24c47 1050 {
65aa5e85 1051 highlight_if_desired ();
32de38e4 1052 turn_on_face (f, start->face_id);
816be8b8 1053 glyph = start;
a168702a 1054 ++start;
a4decb7f
KH
1055 /* We must open sufficient space for a character which
1056 occupies more than one column. */
a168702a 1057 while (len && CHAR_GLYPH_PADDING_P (*start))
a4decb7f
KH
1058 {
1059 OUTPUT1_IF (TS_ins_char);
1060 start++, len--;
1061 }
a4decb7f 1062
32de38e4
KH
1063 if (len <= 0)
1064 /* This is the last glyph. */
1065 terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
1066
d2fdb076
KH
1067 /* The size of conversion buffer (1024 bytes) is surely
1068 sufficient for just one glyph. */
816be8b8 1069 produced = encode_terminal_code (glyph, conversion_buffer, 1,
32de38e4
KH
1070 conversion_buffer_size, &consumed);
1071 }
a4decb7f 1072
a4decb7f 1073 if (produced > 0)
08a24c47 1074 {
a4decb7f 1075 fwrite (conversion_buffer, 1, produced, stdout);
08a24c47
JB
1076 if (ferror (stdout))
1077 clearerr (stdout);
1078 if (termscript)
a4decb7f 1079 fwrite (conversion_buffer, 1, produced, termscript);
08a24c47
JB
1080 }
1081
9a6b6f92 1082 OUTPUT1_IF (TS_pad_inserted_char);
32de38e4 1083 if (start)
65aa5e85
GM
1084 {
1085 turn_off_face (f, glyph->face_id);
1086 turn_off_highlight ();
1087 }
9a6b6f92 1088 }
177c0ea7 1089
9a6b6f92 1090 cmcheckmagic ();
08a24c47
JB
1091}
1092
dfcf069d 1093void
08a24c47
JB
1094delete_glyphs (n)
1095 register int n;
1096{
1097 char *buf;
1098 register int i;
1099
1820044b 1100 if (delete_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame))
08a24c47
JB
1101 {
1102 (*delete_glyphs_hook) (n);
1103 return;
1104 }
1105
1106 if (delete_in_insert_mode)
1107 {
1108 turn_on_insert ();
1109 }
1110 else
1111 {
1112 turn_off_insert ();
1113 OUTPUT_IF (TS_delete_mode);
1114 }
1115
1116 if (TS_del_multi_chars)
1117 {
1118 buf = tparam (TS_del_multi_chars, 0, 0, n);
1119 OUTPUT1 (buf);
9ac0d9e0 1120 xfree (buf);
08a24c47
JB
1121 }
1122 else
1123 for (i = 0; i < n; i++)
1124 OUTPUT1 (TS_del_char);
1125 if (!delete_in_insert_mode)
1126 OUTPUT_IF (TS_end_delete_mode);
1127}
1128\f
1129/* Insert N lines at vpos VPOS. If N is negative, delete -N lines. */
1130
dfcf069d 1131void
08a24c47
JB
1132ins_del_lines (vpos, n)
1133 int vpos, n;
1134{
1135 char *multi = n > 0 ? TS_ins_multi_lines : TS_del_multi_lines;
1136 char *single = n > 0 ? TS_ins_line : TS_del_line;
1137 char *scroll = n > 0 ? TS_rev_scroll : TS_fwd_scroll;
e52f4e08 1138 struct frame *sf;
08a24c47
JB
1139
1140 register int i = n > 0 ? n : -n;
1141 register char *buf;
1142
1820044b 1143 if (ins_del_lines_hook && ! FRAME_TERMCAP_P (updating_frame))
08a24c47
JB
1144 {
1145 (*ins_del_lines_hook) (vpos, n);
1146 return;
1147 }
1148
e52f4e08 1149 sf = XFRAME (selected_frame);
177c0ea7 1150
08a24c47
JB
1151 /* If the lines below the insertion are being pushed
1152 into the end of the window, this is the same as clearing;
1153 and we know the lines are already clear, since the matching
1154 deletion has already been done. So can ignore this. */
1155 /* If the lines below the deletion are blank lines coming
1156 out of the end of the window, don't bother,
1157 as there will be a matching inslines later that will flush them. */
1158 if (scroll_region_ok && vpos + i >= specified_window)
1159 return;
9882535b 1160 if (!memory_below_frame && vpos + i >= FRAME_LINES (sf))
08a24c47
JB
1161 return;
1162
1163 if (multi)
1164 {
1165 raw_cursor_to (vpos, 0);
1166 background_highlight ();
1167 buf = tparam (multi, 0, 0, i);
1168 OUTPUT (buf);
9ac0d9e0 1169 xfree (buf);
08a24c47
JB
1170 }
1171 else if (single)
1172 {
1173 raw_cursor_to (vpos, 0);
1174 background_highlight ();
1175 while (--i >= 0)
1176 OUTPUT (single);
1177 if (TF_teleray)
1178 curX = 0;
1179 }
1180 else
1181 {
1182 set_scroll_region (vpos, specified_window);
1183 if (n < 0)
1184 raw_cursor_to (specified_window - 1, 0);
1185 else
1186 raw_cursor_to (vpos, 0);
1187 background_highlight ();
1188 while (--i >= 0)
1189 OUTPUTL (scroll, specified_window - vpos);
1190 set_scroll_region (0, specified_window);
1191 }
1192
ff11dfa1 1193 if (!scroll_region_ok && memory_below_frame && n < 0)
08a24c47 1194 {
9882535b 1195 cursor_to (FRAME_LINES (sf) + n, 0);
08a24c47
JB
1196 clear_to_end ();
1197 }
1198}
1199\f
1200/* Compute cost of sending "str", in characters,
1201 not counting any line-dependent padding. */
1202
1203int
1204string_cost (str)
1205 char *str;
1206{
1207 cost = 0;
1208 if (str)
1209 tputs (str, 0, evalcost);
1210 return cost;
1211}
1212
1213/* Compute cost of sending "str", in characters,
1214 counting any line-dependent padding at one line. */
1215
1216static int
1217string_cost_one_line (str)
1218 char *str;
1219{
1220 cost = 0;
1221 if (str)
1222 tputs (str, 1, evalcost);
1223 return cost;
1224}
1225
1226/* Compute per line amount of line-dependent padding,
1227 in tenths of characters. */
1228
1229int
1230per_line_cost (str)
1231 register char *str;
1232{
1233 cost = 0;
1234 if (str)
1235 tputs (str, 0, evalcost);
1236 cost = - cost;
1237 if (str)
1238 tputs (str, 10, evalcost);
1239 return cost;
1240}
1241
1242#ifndef old
1243/* char_ins_del_cost[n] is cost of inserting N characters.
8dd0c7cb 1244 char_ins_del_cost[-n] is cost of deleting N characters.
9882535b 1245 The length of this vector is based on max_frame_cols. */
08a24c47
JB
1246
1247int *char_ins_del_vector;
1248
9882535b 1249#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
08a24c47
JB
1250#endif
1251
1252/* ARGSUSED */
1253static void
ff11dfa1
JB
1254calculate_ins_del_char_costs (frame)
1255 FRAME_PTR frame;
08a24c47
JB
1256{
1257 int ins_startup_cost, del_startup_cost;
1258 int ins_cost_per_char, del_cost_per_char;
1259 register int i;
1260 register int *p;
1261
1262 if (TS_ins_multi_chars)
1263 {
1264 ins_cost_per_char = 0;
1265 ins_startup_cost = string_cost_one_line (TS_ins_multi_chars);
1266 }
1267 else if (TS_ins_char || TS_pad_inserted_char
1268 || (TS_insert_mode && TS_end_insert_mode))
1269 {
1270 ins_startup_cost = (30 * (string_cost (TS_insert_mode)
1271 + string_cost (TS_end_insert_mode))) / 100;
1272 ins_cost_per_char = (string_cost_one_line (TS_ins_char)
1273 + string_cost_one_line (TS_pad_inserted_char));
1274 }
1275 else
1276 {
1277 ins_startup_cost = 9999;
1278 ins_cost_per_char = 0;
1279 }
1280
1281 if (TS_del_multi_chars)
1282 {
1283 del_cost_per_char = 0;
1284 del_startup_cost = string_cost_one_line (TS_del_multi_chars);
1285 }
1286 else if (TS_del_char)
1287 {
1288 del_startup_cost = (string_cost (TS_delete_mode)
1289 + string_cost (TS_end_delete_mode));
1290 if (delete_in_insert_mode)
1291 del_startup_cost /= 2;
1292 del_cost_per_char = string_cost_one_line (TS_del_char);
1293 }
1294 else
1295 {
1296 del_startup_cost = 9999;
1297 del_cost_per_char = 0;
1298 }
1299
1300 /* Delete costs are at negative offsets */
ff11dfa1 1301 p = &char_ins_del_cost (frame)[0];
9882535b 1302 for (i = FRAME_COLS (frame); --i >= 0;)
08a24c47
JB
1303 *--p = (del_startup_cost += del_cost_per_char);
1304
1305 /* Doing nothing is free */
ff11dfa1 1306 p = &char_ins_del_cost (frame)[0];
08a24c47
JB
1307 *p++ = 0;
1308
1309 /* Insert costs are at positive offsets */
9882535b 1310 for (i = FRAME_COLS (frame); --i >= 0;)
08a24c47
JB
1311 *p++ = (ins_startup_cost += ins_cost_per_char);
1312}
1313
dfcf069d 1314void
ff11dfa1
JB
1315calculate_costs (frame)
1316 FRAME_PTR frame;
08a24c47 1317{
9f732a77
RS
1318 register char *f = (TS_set_scroll_region
1319 ? TS_set_scroll_region
1320 : TS_set_scroll_region_1);
08a24c47 1321
9f732a77 1322 FRAME_COST_BAUD_RATE (frame) = baud_rate;
08a24c47 1323
be7cd44f 1324 scroll_region_cost = string_cost (f);
08a24c47
JB
1325
1326 /* These variables are only used for terminal stuff. They are allocated
ff11dfa1 1327 once for the terminal frame of X-windows emacs, but not used afterwards.
08a24c47
JB
1328
1329 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
8ede64a5 1330 X turns off char_ins_del_ok. */
08a24c47 1331
9882535b
KS
1332 max_frame_lines = max (max_frame_lines, FRAME_LINES (frame));
1333 max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
8dd0c7cb 1334
8ede64a5 1335 costs_set = 1;
08a24c47
JB
1336
1337 if (char_ins_del_vector != 0)
1338 char_ins_del_vector
1339 = (int *) xrealloc (char_ins_del_vector,
1340 (sizeof (int)
9882535b 1341 + 2 * max_frame_cols * sizeof (int)));
08a24c47
JB
1342 else
1343 char_ins_del_vector
1344 = (int *) xmalloc (sizeof (int)
9882535b 1345 + 2 * max_frame_cols * sizeof (int));
08a24c47 1346
08a24c47 1347 bzero (char_ins_del_vector, (sizeof (int)
9882535b 1348 + 2 * max_frame_cols * sizeof (int)));
08a24c47 1349
ff11dfa1
JB
1350 if (f && (!TS_ins_line && !TS_del_line))
1351 do_line_insertion_deletion_costs (frame,
08a24c47
JB
1352 TS_rev_scroll, TS_ins_multi_lines,
1353 TS_fwd_scroll, TS_del_multi_lines,
ff11dfa1 1354 f, f, 1);
08a24c47 1355 else
ff11dfa1 1356 do_line_insertion_deletion_costs (frame,
08a24c47
JB
1357 TS_ins_line, TS_ins_multi_lines,
1358 TS_del_line, TS_del_multi_lines,
1359 0, 0, 1);
1360
ff11dfa1 1361 calculate_ins_del_char_costs (frame);
08a24c47
JB
1362
1363 /* Don't use TS_repeat if its padding is worse than sending the chars */
1364 if (TS_repeat && per_line_cost (TS_repeat) * baud_rate < 9000)
1365 RPov = string_cost (TS_repeat);
1366 else
9882535b 1367 RPov = FRAME_COLS (frame) * 2;
08a24c47
JB
1368
1369 cmcostinit (); /* set up cursor motion costs */
1370}
1371\f
a796ac82
JB
1372struct fkey_table {
1373 char *cap, *name;
1374};
1375
01d8deb0
ER
1376 /* Termcap capability names that correspond directly to X keysyms.
1377 Some of these (marked "terminfo") aren't supplied by old-style
1378 (Berkeley) termcap entries. They're listed in X keysym order;
1379 except we put the keypad keys first, so that if they clash with
1380 other keys (as on the IBM PC keyboard) they get overridden.
1381 */
1382
a168702a
GM
1383static struct fkey_table keys[] =
1384{
8103ad1a
PJ
1385 {"kh", "home"}, /* termcap */
1386 {"kl", "left"}, /* termcap */
1387 {"ku", "up"}, /* termcap */
1388 {"kr", "right"}, /* termcap */
1389 {"kd", "down"}, /* termcap */
1390 {"%8", "prior"}, /* terminfo */
1391 {"%5", "next"}, /* terminfo */
1392 {"@7", "end"}, /* terminfo */
1393 {"@1", "begin"}, /* terminfo */
1394 {"*6", "select"}, /* terminfo */
1395 {"%9", "print"}, /* terminfo */
1396 {"@4", "execute"}, /* terminfo --- actually the `command' key */
01d8deb0
ER
1397 /*
1398 * "insert" --- see below
1399 */
8103ad1a
PJ
1400 {"&8", "undo"}, /* terminfo */
1401 {"%0", "redo"}, /* terminfo */
1402 {"%7", "menu"}, /* terminfo --- actually the `options' key */
1403 {"@0", "find"}, /* terminfo */
1404 {"@2", "cancel"}, /* terminfo */
1405 {"%1", "help"}, /* terminfo */
01d8deb0
ER
1406 /*
1407 * "break" goes here, but can't be reliably intercepted with termcap
1408 */
8103ad1a 1409 {"&4", "reset"}, /* terminfo --- actually `restart' */
01d8deb0
ER
1410 /*
1411 * "system" and "user" --- no termcaps
1412 */
8103ad1a
PJ
1413 {"kE", "clearline"}, /* terminfo */
1414 {"kA", "insertline"}, /* terminfo */
1415 {"kL", "deleteline"}, /* terminfo */
1416 {"kI", "insertchar"}, /* terminfo */
1417 {"kD", "deletechar"}, /* terminfo */
1418 {"kB", "backtab"}, /* terminfo */
01d8deb0
ER
1419 /*
1420 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1421 */
8103ad1a 1422 {"@8", "kp-enter"}, /* terminfo */
01d8deb0
ER
1423 /*
1424 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1425 * "kp-multiply", "kp-add", "kp-separator",
1426 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1427 * --- no termcaps for any of these.
1428 */
8103ad1a 1429 {"K4", "kp-1"}, /* terminfo */
01d8deb0
ER
1430 /*
1431 * "kp-2" --- no termcap
1432 */
8103ad1a 1433 {"K5", "kp-3"}, /* terminfo */
01d8deb0
ER
1434 /*
1435 * "kp-4" --- no termcap
1436 */
8103ad1a 1437 {"K2", "kp-5"}, /* terminfo */
01d8deb0
ER
1438 /*
1439 * "kp-6" --- no termcap
1440 */
8103ad1a 1441 {"K1", "kp-7"}, /* terminfo */
01d8deb0
ER
1442 /*
1443 * "kp-8" --- no termcap
1444 */
8103ad1a 1445 {"K3", "kp-9"}, /* terminfo */
01d8deb0
ER
1446 /*
1447 * "kp-equal" --- no termcap
1448 */
8103ad1a
PJ
1449 {"k1", "f1"},
1450 {"k2", "f2"},
1451 {"k3", "f3"},
1452 {"k4", "f4"},
1453 {"k5", "f5"},
1454 {"k6", "f6"},
1455 {"k7", "f7"},
1456 {"k8", "f8"},
1457 {"k9", "f9"}
a796ac82
JB
1458 };
1459
f2a00342
RM
1460static char **term_get_fkeys_arg;
1461static Lisp_Object term_get_fkeys_1 ();
465db27b 1462
01d8deb0 1463/* Find the escape codes sent by the function keys for Vfunction_key_map.
177c0ea7 1464 This function scans the termcap function key sequence entries, and
01d8deb0
ER
1465 adds entries to Vfunction_key_map for each function key it finds. */
1466
5c2c7893
JB
1467void
1468term_get_fkeys (address)
1469 char **address;
f2a00342
RM
1470{
1471 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1472 errors during the call. The only errors should be from Fdefine_key
1473 when given a key sequence containing an invalid prefix key. If the
1474 termcap defines function keys which use a prefix that is already bound
1475 to a command by the default bindings, we should silently ignore that
1476 function key specification, rather than giving the user an error and
1477 refusing to run at all on such a terminal. */
1478
1479 extern Lisp_Object Fidentity ();
f2a00342
RM
1480 term_get_fkeys_arg = address;
1481 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1482}
1483
1484static Lisp_Object
1485term_get_fkeys_1 ()
5c2c7893 1486{
5c2c7893
JB
1487 int i;
1488
37085233 1489 char **address = term_get_fkeys_arg;
f778aff2 1490
3e65092f
RS
1491 /* This can happen if CANNOT_DUMP or with strange options. */
1492 if (!initialized)
1493 Vfunction_key_map = Fmake_sparse_keymap (Qnil);
1494
5c2c7893
JB
1495 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1496 {
1497 char *sequence = tgetstr (keys[i].cap, address);
1498 if (sequence)
f2a00342
RM
1499 Fdefine_key (Vfunction_key_map, build_string (sequence),
1500 Fmake_vector (make_number (1),
1501 intern (keys[i].name)));
5c2c7893 1502 }
a796ac82
JB
1503
1504 /* The uses of the "k0" capability are inconsistent; sometimes it
1505 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
eb8c3be9 1506 We will attempt to politely accommodate both systems by testing for
a796ac82
JB
1507 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1508 */
1509 {
1510 char *k_semi = tgetstr ("k;", address);
1511 char *k0 = tgetstr ("k0", address);
1512 char *k0_name = "f10";
1513
1514 if (k_semi)
1515 {
95c11956
SM
1516 if (k0)
1517 /* Define f0 first, so that f10 takes precedence in case the
1518 key sequences happens to be the same. */
1519 Fdefine_key (Vfunction_key_map, build_string (k0),
1520 Fmake_vector (make_number (1), intern ("f0")));
f2a00342
RM
1521 Fdefine_key (Vfunction_key_map, build_string (k_semi),
1522 Fmake_vector (make_number (1), intern ("f10")));
a796ac82 1523 }
95c11956 1524 else if (k0)
f2a00342
RM
1525 Fdefine_key (Vfunction_key_map, build_string (k0),
1526 Fmake_vector (make_number (1), intern (k0_name)));
a796ac82 1527 }
01d8deb0
ER
1528
1529 /* Set up cookies for numbered function keys above f10. */
1530 {
1531 char fcap[3], fkey[4];
1532
fc4f24da 1533 fcap[0] = 'F'; fcap[2] = '\0';
01d8deb0
ER
1534 for (i = 11; i < 64; i++)
1535 {
1536 if (i <= 19)
1537 fcap[1] = '1' + i - 11;
1538 else if (i <= 45)
b59ab95c 1539 fcap[1] = 'A' + i - 20;
01d8deb0 1540 else
b59ab95c 1541 fcap[1] = 'a' + i - 46;
01d8deb0 1542
fc4f24da
RS
1543 {
1544 char *sequence = tgetstr (fcap, address);
1545 if (sequence)
1546 {
465db27b 1547 sprintf (fkey, "f%d", i);
f2a00342
RM
1548 Fdefine_key (Vfunction_key_map, build_string (sequence),
1549 Fmake_vector (make_number (1),
1550 intern (fkey)));
fc4f24da
RS
1551 }
1552 }
01d8deb0
ER
1553 }
1554 }
1555
1556 /*
1557 * Various mappings to try and get a better fit.
1558 */
1559 {
fc4f24da
RS
1560#define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1561 if (!tgetstr (cap1, address)) \
1562 { \
1563 char *sequence = tgetstr (cap2, address); \
1564 if (sequence) \
f2a00342
RM
1565 Fdefine_key (Vfunction_key_map, build_string (sequence), \
1566 Fmake_vector (make_number (1), \
1567 intern (sym))); \
fc4f24da 1568 }
177c0ea7 1569
01d8deb0 1570 /* if there's no key_next keycap, map key_npage to `next' keysym */
27b61785 1571 CONDITIONAL_REASSIGN ("%5", "kN", "next");
01d8deb0 1572 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
381d11a1 1573 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
01d8deb0 1574 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
27b61785 1575 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
403c995b
RS
1576 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1577 CONDITIONAL_REASSIGN ("@7", "kH", "end");
0a7f697a
KH
1578
1579 /* IBM has their own non-standard dialect of terminfo.
1580 If the standard name isn't found, try the IBM name. */
1581 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1582 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1583 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1584 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1585 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1586 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1587 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1588 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1589 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1dd40212 1590#undef CONDITIONAL_REASSIGN
01d8deb0 1591 }
a168702a
GM
1592
1593 return Qnil;
5c2c7893
JB
1594}
1595
1596\f
a168702a
GM
1597/***********************************************************************
1598 Character Display Information
1599 ***********************************************************************/
1600
1601static void append_glyph P_ ((struct it *));
1602
1603
1604/* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1605 terminal frames if IT->glyph_row != NULL. IT->c is the character
1606 for which to produce glyphs; IT->face_id contains the character's
1607 face. Padding glyphs are appended if IT->c has a IT->pixel_width >
1608 1. */
177c0ea7 1609
a168702a
GM
1610static void
1611append_glyph (it)
1612 struct it *it;
1613{
1614 struct glyph *glyph, *end;
1615 int i;
1616
1617 xassert (it->glyph_row);
1618 glyph = (it->glyph_row->glyphs[it->area]
1619 + it->glyph_row->used[it->area]);
1620 end = it->glyph_row->glyphs[1 + it->area];
1621
177c0ea7
JB
1622 for (i = 0;
1623 i < it->pixel_width && glyph < end;
a168702a
GM
1624 ++i)
1625 {
1626 glyph->type = CHAR_GLYPH;
d13f3e2e 1627 glyph->pixel_width = 1;
32de38e4
KH
1628 glyph->u.ch = it->c;
1629 glyph->face_id = it->face_id;
1630 glyph->padding_p = i > 0;
a168702a
GM
1631 glyph->charpos = CHARPOS (it->position);
1632 glyph->object = it->object;
177c0ea7 1633
a168702a
GM
1634 ++it->glyph_row->used[it->area];
1635 ++glyph;
1636 }
1637}
1638
1639
b50fe468
RS
1640/* Produce glyphs for the display element described by IT. *IT
1641 specifies what we want to produce a glyph for (character, image, ...),
1642 and where in the glyph matrix we currently are (glyph row and hpos).
1643 produce_glyphs fills in output fields of *IT with information such as the
1644 pixel width and height of a character, and maybe output actual glyphs at
a168702a 1645 the same time if IT->glyph_row is non-null. See the explanation of
b50fe468
RS
1646 struct display_iterator in dispextern.h for an overview.
1647
1648 produce_glyphs also stores the result of glyph width, ascent
1649 etc. computations in *IT.
1650
1651 IT->glyph_row may be null, in which case produce_glyphs does not
1652 actually fill in the glyphs. This is used in the move_* functions
1653 in xdisp.c for text width and height computations.
1654
1655 Callers usually don't call produce_glyphs directly;
1656 instead they use the macro PRODUCE_GLYPHS. */
a168702a 1657
177c0ea7 1658void
a168702a
GM
1659produce_glyphs (it)
1660 struct it *it;
1661{
1662 /* If a hook is installed, let it do the work. */
1663 xassert (it->what == IT_CHARACTER
c7cba11d 1664 || it->what == IT_COMPOSITION
a168702a
GM
1665 || it->what == IT_IMAGE
1666 || it->what == IT_STRETCH);
177c0ea7 1667
c7cba11d
KH
1668 /* Nothing but characters are supported on terminal frames. For a
1669 composition sequence, it->c is the first character of the
1670 sequence. */
1671 xassert (it->what == IT_CHARACTER
1672 || it->what == IT_COMPOSITION);
a168702a
GM
1673
1674 if (it->c >= 040 && it->c < 0177)
1675 {
1676 it->pixel_width = it->nglyphs = 1;
1677 if (it->glyph_row)
1678 append_glyph (it);
1679 }
1680 else if (it->c == '\n')
1681 it->pixel_width = it->nglyphs = 0;
1682 else if (it->c == '\t')
1683 {
2efdbcdd 1684 int absolute_x = (it->current_x
a168702a 1685 + it->continuation_lines_width);
177c0ea7
JB
1686 int next_tab_x
1687 = (((1 + absolute_x + it->tab_width - 1)
a168702a
GM
1688 / it->tab_width)
1689 * it->tab_width);
1690 int nspaces;
1691
1692 /* If part of the TAB has been displayed on the previous line
1693 which is continued now, continuation_lines_width will have
1694 been incremented already by the part that fitted on the
1695 continued line. So, we will get the right number of spaces
1696 here. */
1697 nspaces = next_tab_x - absolute_x;
177c0ea7 1698
a168702a
GM
1699 if (it->glyph_row)
1700 {
1701 int n = nspaces;
177c0ea7 1702
a168702a
GM
1703 it->c = ' ';
1704 it->pixel_width = it->len = 1;
177c0ea7 1705
a168702a
GM
1706 while (n--)
1707 append_glyph (it);
177c0ea7 1708
a168702a
GM
1709 it->c = '\t';
1710 }
1711
1712 it->pixel_width = nspaces;
1713 it->nglyphs = nspaces;
1714 }
add44890
EZ
1715 else if (SINGLE_BYTE_CHAR_P (it->c))
1716 {
cf872af5 1717 /* Coming here means that it->c is from display table, thus we
add44890
EZ
1718 must send the code as is to the terminal. Although there's
1719 no way to know how many columns it occupies on a screen, it
1720 is a good assumption that a single byte code has 1-column
1721 width. */
1722 it->pixel_width = it->nglyphs = 1;
1723 if (it->glyph_row)
1724 append_glyph (it);
1725 }
a168702a
GM
1726 else
1727 {
9332ea03 1728 it->pixel_width = CHAR_WIDTH (it->c);
a168702a 1729 it->nglyphs = it->pixel_width;
177c0ea7 1730
a168702a
GM
1731 if (it->glyph_row)
1732 append_glyph (it);
1733 }
1734
177c0ea7 1735 /* Advance current_x by the pixel width as a convenience for
a168702a
GM
1736 the caller. */
1737 if (it->area == TEXT_AREA)
1738 it->current_x += it->pixel_width;
cfe8a05e
GM
1739 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1740 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
a168702a
GM
1741}
1742
1743
1744/* Get information about special display element WHAT in an
1745 environment described by IT. WHAT is one of IT_TRUNCATION or
1746 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1747 non-null glyph_row member. This function ensures that fields like
1748 face_id, c, len of IT are left untouched. */
1749
1750void
1751produce_special_glyphs (it, what)
1752 struct it *it;
1753 enum display_element_type what;
1754{
1755 struct it temp_it;
177c0ea7 1756
a168702a
GM
1757 temp_it = *it;
1758 temp_it.dp = NULL;
1759 temp_it.what = IT_CHARACTER;
1760 temp_it.len = 1;
7c752c80 1761 temp_it.object = make_number (0);
a168702a
GM
1762 bzero (&temp_it.current, sizeof temp_it.current);
1763
1764 if (what == IT_CONTINUATION)
1765 {
1766 /* Continuation glyph. */
1767 if (it->dp
1768 && INTEGERP (DISP_CONTINUE_GLYPH (it->dp))
1769 && GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (it->dp))))
1770 {
1771 temp_it.c = FAST_GLYPH_CHAR (XINT (DISP_CONTINUE_GLYPH (it->dp)));
68526af5 1772 temp_it.len = CHAR_BYTES (temp_it.c);
a168702a
GM
1773 }
1774 else
1775 temp_it.c = '\\';
177c0ea7 1776
a168702a
GM
1777 produce_glyphs (&temp_it);
1778 it->pixel_width = temp_it.pixel_width;
1779 it->nglyphs = temp_it.pixel_width;
1780 }
1781 else if (what == IT_TRUNCATION)
1782 {
1783 /* Truncation glyph. */
1784 if (it->dp
1785 && INTEGERP (DISP_TRUNC_GLYPH (it->dp))
1786 && GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (it->dp))))
1787 {
1788 temp_it.c = FAST_GLYPH_CHAR (XINT (DISP_TRUNC_GLYPH (it->dp)));
68526af5 1789 temp_it.len = CHAR_BYTES (temp_it.c);
a168702a
GM
1790 }
1791 else
1792 temp_it.c = '$';
177c0ea7 1793
a168702a
GM
1794 produce_glyphs (&temp_it);
1795 it->pixel_width = temp_it.pixel_width;
1796 it->nglyphs = temp_it.pixel_width;
1797 }
1798 else
1799 abort ();
1800}
1801
1802
a168702a
GM
1803\f
1804/***********************************************************************
1805 Faces
1806 ***********************************************************************/
1807
4e6ba4a4
GM
1808/* Value is non-zero if attribute ATTR may be used. ATTR should be
1809 one of the enumerators from enum no_color_bit, or a bit set built
1810 from them. Some display attributes may not be used together with
1811 color; the termcap capability `NC' specifies which ones. */
1812
1813#define MAY_USE_WITH_COLORS_P(ATTR) \
1814 (TN_max_colors > 0 \
1815 ? (TN_no_color_video & (ATTR)) == 0 \
1816 : 1)
a168702a
GM
1817
1818/* Turn appearances of face FACE_ID on tty frame F on. */
1819
1820static void
1821turn_on_face (f, face_id)
1822 struct frame *f;
1823 int face_id;
1824{
1825 struct face *face = FACE_FROM_ID (f, face_id);
86a7d192
GM
1826 long fg = face->foreground;
1827 long bg = face->background;
a168702a 1828
86a7d192
GM
1829 /* Do this first because TS_end_standout_mode may be the same
1830 as TS_exit_attribute_mode, which turns all appearances off. */
1831 if (MAY_USE_WITH_COLORS_P (NC_REVERSE))
1832 {
1833 if (TN_max_colors > 0)
1834 {
1835 if (fg >= 0 && bg >= 0)
1836 {
1837 /* If the terminal supports colors, we can set them
1838 below without using reverse video. The face's fg
1839 and bg colors are set as they should appear on
1840 the screen, i.e. they take the inverse-video'ness
1841 of the face already into account. */
1842 }
1843 else if (inverse_video)
1844 {
1845 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1846 || bg == FACE_TTY_DEFAULT_BG_COLOR)
1847 toggle_highlight ();
1848 }
1849 else
1850 {
1851 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1852 || bg == FACE_TTY_DEFAULT_FG_COLOR)
1853 toggle_highlight ();
1854 }
1855 }
1856 else
1857 {
1858 /* If we can't display colors, use reverse video
1859 if the face specifies that. */
37526b42
GM
1860 if (inverse_video)
1861 {
1862 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1863 || bg == FACE_TTY_DEFAULT_BG_COLOR)
1864 toggle_highlight ();
1865 }
1866 else
1867 {
1868 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1869 || bg == FACE_TTY_DEFAULT_FG_COLOR)
1870 toggle_highlight ();
1871 }
86a7d192
GM
1872 }
1873 }
a168702a
GM
1874
1875 if (face->tty_bold_p)
4e6ba4a4
GM
1876 {
1877 if (MAY_USE_WITH_COLORS_P (NC_BOLD))
1878 OUTPUT1_IF (TS_enter_bold_mode);
1879 }
a168702a 1880 else if (face->tty_dim_p)
4e6ba4a4
GM
1881 if (MAY_USE_WITH_COLORS_P (NC_DIM))
1882 OUTPUT1_IF (TS_enter_dim_mode);
a168702a
GM
1883
1884 /* Alternate charset and blinking not yet used. */
4e6ba4a4
GM
1885 if (face->tty_alt_charset_p
1886 && MAY_USE_WITH_COLORS_P (NC_ALT_CHARSET))
a168702a
GM
1887 OUTPUT1_IF (TS_enter_alt_charset_mode);
1888
4e6ba4a4
GM
1889 if (face->tty_blinking_p
1890 && MAY_USE_WITH_COLORS_P (NC_BLINK))
a168702a
GM
1891 OUTPUT1_IF (TS_enter_blink_mode);
1892
54800acb 1893 if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (NC_UNDERLINE))
a168702a
GM
1894 OUTPUT1_IF (TS_enter_underline_mode);
1895
a168702a
GM
1896 if (TN_max_colors > 0)
1897 {
1898 char *p;
177c0ea7 1899
86a7d192 1900 if (fg >= 0 && TS_set_foreground)
a168702a 1901 {
86a7d192 1902 p = tparam (TS_set_foreground, NULL, 0, (int) fg);
a168702a
GM
1903 OUTPUT (p);
1904 xfree (p);
1905 }
1906
86a7d192 1907 if (bg >= 0 && TS_set_background)
a168702a 1908 {
86a7d192 1909 p = tparam (TS_set_background, NULL, 0, (int) bg);
a168702a
GM
1910 OUTPUT (p);
1911 xfree (p);
1912 }
1913 }
1914}
177c0ea7 1915
a168702a
GM
1916
1917/* Turn off appearances of face FACE_ID on tty frame F. */
1918
1919static void
1920turn_off_face (f, face_id)
1921 struct frame *f;
1922 int face_id;
1923{
1924 struct face *face = FACE_FROM_ID (f, face_id);
a168702a
GM
1925
1926 xassert (face != NULL);
1927
1928 if (TS_exit_attribute_mode)
1929 {
1930 /* Capability "me" will turn off appearance modes double-bright,
1931 half-bright, reverse-video, standout, underline. It may or
1932 may not turn off alt-char-mode. */
1933 if (face->tty_bold_p
1934 || face->tty_dim_p
1935 || face->tty_reverse_p
1936 || face->tty_alt_charset_p
1937 || face->tty_blinking_p
1938 || face->tty_underline_p)
65aa5e85
GM
1939 {
1940 OUTPUT1_IF (TS_exit_attribute_mode);
1941 if (strcmp (TS_exit_attribute_mode, TS_end_standout_mode) == 0)
1942 standout_mode = 0;
1943 }
a168702a
GM
1944
1945 if (face->tty_alt_charset_p)
1946 OUTPUT_IF (TS_exit_alt_charset_mode);
1947 }
1948 else
1949 {
1950 /* If we don't have "me" we can only have those appearances
1951 that have exit sequences defined. */
1952 if (face->tty_alt_charset_p)
1953 OUTPUT_IF (TS_exit_alt_charset_mode);
1954
54800acb 1955 if (face->tty_underline_p)
a168702a
GM
1956 OUTPUT_IF (TS_exit_underline_mode);
1957 }
1958
1959 /* Switch back to default colors. */
1960 if (TN_max_colors > 0
f9d2fdc4
EZ
1961 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
1962 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
1963 || (face->background != FACE_TTY_DEFAULT_COLOR
1964 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
a168702a
GM
1965 OUTPUT1_IF (TS_orig_pair);
1966}
177c0ea7
JB
1967
1968
b63a55ac
MB
1969/* Return non-zero if the terminal on frame F supports all of the
1970 capabilities in CAPS simultaneously, with foreground and background
1971 colors FG and BG. */
1972
4a8130f2
MB
1973int
1974tty_capable_p (f, caps, fg, bg)
b63a55ac
MB
1975 struct frame *f;
1976 unsigned caps;
1977 unsigned long fg, bg;
1978{
1979#define TTY_CAPABLE_P_TRY(cap, TS, NC_bit) \
1980 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(NC_bit))) \
1981 return 0;
1982
1983 TTY_CAPABLE_P_TRY (TTY_CAP_INVERSE, TS_standout_mode, NC_REVERSE);
1984 TTY_CAPABLE_P_TRY (TTY_CAP_UNDERLINE, TS_enter_underline_mode, NC_UNDERLINE);
1985 TTY_CAPABLE_P_TRY (TTY_CAP_BOLD, TS_enter_bold_mode, NC_BOLD);
1986 TTY_CAPABLE_P_TRY (TTY_CAP_DIM, TS_enter_dim_mode, NC_DIM);
1987 TTY_CAPABLE_P_TRY (TTY_CAP_BLINK, TS_enter_blink_mode, NC_BLINK);
1988 TTY_CAPABLE_P_TRY (TTY_CAP_ALT_CHARSET, TS_enter_alt_charset_mode, NC_ALT_CHARSET);
1989
1990 /* We can do it! */
1991 return 1;
1992}
1993
1994
a168702a
GM
1995/* Return non-zero if the terminal is capable to display colors. */
1996
1997DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
981e4297 1998 0, 1, 0,
99fdd6bc
EZ
1999 doc: /* Return non-nil if TTY can display colors on DISPLAY. */)
2000 (display)
2001 Lisp_Object display;
a168702a
GM
2002{
2003 return TN_max_colors > 0 ? Qt : Qnil;
2004}
2005
bfa62f96
EZ
2006/* Return the number of supported colors. */
2007DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
2008 Stty_display_color_cells, 0, 1, 0,
99fdd6bc
EZ
2009 doc: /* Return the number of colors supported by TTY on DISPLAY. */)
2010 (display)
2011 Lisp_Object display;
bfa62f96
EZ
2012{
2013 return make_number (TN_max_colors);
2014}
2015
ace28297 2016#ifndef WINDOWSNT
a168702a 2017
ace28297
EZ
2018/* Save or restore the default color-related capabilities of this
2019 terminal. */
2020static void
2021tty_default_color_capabilities (save)
2022 int save;
2023{
2024 static char
2025 *default_orig_pair, *default_set_foreground, *default_set_background;
2026 static int default_max_colors, default_max_pairs, default_no_color_video;
2027
2028 if (save)
2029 {
2030 if (default_orig_pair)
2031 xfree (default_orig_pair);
2032 default_orig_pair = TS_orig_pair ? xstrdup (TS_orig_pair) : NULL;
2033
2034 if (default_set_foreground)
2035 xfree (default_set_foreground);
2036 default_set_foreground = TS_set_foreground ? xstrdup (TS_set_foreground)
2037 : NULL;
2038
2039 if (default_set_background)
2040 xfree (default_set_background);
2041 default_set_background = TS_set_background ? xstrdup (TS_set_background)
2042 : NULL;
2043
2044 default_max_colors = TN_max_colors;
2045 default_max_pairs = TN_max_pairs;
2046 default_no_color_video = TN_no_color_video;
2047 }
2048 else
2049 {
2050 TS_orig_pair = default_orig_pair;
2051 TS_set_foreground = default_set_foreground;
2052 TS_set_background = default_set_background;
2053 TN_max_colors = default_max_colors;
2054 TN_max_pairs = default_max_pairs;
2055 TN_no_color_video = default_no_color_video;
2056 }
2057}
2058
2059/* Setup one of the standard tty color schemes according to MODE.
2060 MODE's value is generally the number of colors which we want to
2061 support; zero means set up for the default capabilities, the ones
2062 we saw at term_init time; -1 means turn off color support. */
2063void
2064tty_setup_colors (mode)
2065 int mode;
2066{
2067 switch (mode)
2068 {
2069 case -1: /* no colors at all */
2070 TN_max_colors = 0;
2071 TN_max_pairs = 0;
2072 TN_no_color_video = 0;
2073 TS_set_foreground = TS_set_background = TS_orig_pair = NULL;
2074 break;
2075 case 0: /* default colors, if any */
2076 default:
2077 tty_default_color_capabilities (0);
2078 break;
2079 case 8: /* 8 standard ANSI colors */
2080 TS_orig_pair = "\033[0m";
2081#ifdef TERMINFO
2082 TS_set_foreground = "\033[3%p1%dm";
2083 TS_set_background = "\033[4%p1%dm";
2084#else
2085 TS_set_foreground = "\033[3%dm";
2086 TS_set_background = "\033[4%dm";
2087#endif
2088 TN_max_colors = 8;
2089 TN_max_pairs = 64;
2090 TN_no_color_video = 0;
2091 break;
2092 }
2093}
2094
2095void
2096set_tty_color_mode (f, val)
2097 struct frame *f;
2098 Lisp_Object val;
2099{
dfc7a077 2100 Lisp_Object color_mode_spec, current_mode_spec;
ace28297
EZ
2101 Lisp_Object color_mode, current_mode;
2102 int mode, old_mode;
2103 extern Lisp_Object Qtty_color_mode;
2104 Lisp_Object tty_color_mode_alist;
2105
2106 tty_color_mode_alist = Fintern_soft (build_string ("tty-color-mode-alist"),
2107 Qnil);
2108
2109 if (NATNUMP (val))
2110 color_mode = val;
2111 else
2112 {
2113 if (NILP (tty_color_mode_alist))
2114 color_mode_spec = Qnil;
2115 else
2116 color_mode_spec = Fassq (val, XSYMBOL (tty_color_mode_alist)->value);
2117 current_mode_spec = assq_no_quit (Qtty_color_mode, f->param_alist);
2118
2119 if (CONSP (color_mode_spec))
2120 color_mode = XCDR (color_mode_spec);
2121 else
2122 color_mode = Qnil;
2123 }
2124 if (CONSP (current_mode_spec))
2125 current_mode = XCDR (current_mode_spec);
2126 else
2127 current_mode = Qnil;
2128 if (NATNUMP (color_mode))
2129 mode = XINT (color_mode);
2130 else
2131 mode = 0; /* meaning default */
2132 if (NATNUMP (current_mode))
2133 old_mode = XINT (current_mode);
2134 else
2135 old_mode = 0;
2136
2137 if (mode != old_mode)
2138 {
2139 tty_setup_colors (mode);
2140 /* This recomputes all the faces given the new color
2141 definitions. */
2142 call0 (intern ("tty-set-up-initial-frame-faces"));
2143 redraw_frame (f);
2144 }
2145}
2146
2147#endif /* !WINDOWSNT */
a168702a
GM
2148
2149\f
2150/***********************************************************************
2151 Initialization
2152 ***********************************************************************/
2153
dfcf069d 2154void
08a24c47
JB
2155term_init (terminal_type)
2156 char *terminal_type;
2157{
2158 char *area;
2159 char **address = &area;
463f5630 2160 char buffer[2044];
08a24c47
JB
2161 register char *p;
2162 int status;
e52f4e08 2163 struct frame *sf = XFRAME (selected_frame);
08a24c47 2164
cb28b9c2 2165#ifdef WINDOWSNT
29f27c39 2166 initialize_w32_display ();
cb28b9c2
RS
2167
2168 Wcm_clear ();
cb28b9c2 2169
a678d9ff 2170 area = (char *) xmalloc (2044);
cb28b9c2 2171
463f5630
KH
2172 if (area == 0)
2173 abort ();
2174
9882535b
KS
2175 FrameRows = FRAME_LINES (sf);
2176 FrameCols = FRAME_COLS (sf);
2177 specified_window = FRAME_LINES (sf);
cb28b9c2
RS
2178
2179 delete_in_insert_mode = 1;
2180
2181 UseTabs = 0;
2182 scroll_region_ok = 0;
2183
2184 /* Seems to insert lines when it's not supposed to, messing
2185 up the display. In doing a trace, it didn't seem to be
2186 called much, so I don't think we're losing anything by
2187 turning it off. */
2188
2189 line_ins_del_ok = 0;
2190 char_ins_del_ok = 1;
2191
2192 baud_rate = 19200;
2193
e52f4e08
GM
2194 FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0;
2195 FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none;
acfcd5cd 2196 TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
cb28b9c2
RS
2197
2198 return;
eccec691 2199#else /* not WINDOWSNT */
cb28b9c2 2200
08a24c47 2201 Wcm_clear ();
08a24c47
JB
2202
2203 status = tgetent (buffer, terminal_type);
2204 if (status < 0)
b0347178
KH
2205 {
2206#ifdef TERMINFO
e12c1054 2207 fatal ("Cannot open terminfo database file");
b0347178 2208#else
e12c1054 2209 fatal ("Cannot open termcap database file");
b0347178
KH
2210#endif
2211 }
08a24c47 2212 if (status == 0)
b0347178
KH
2213 {
2214#ifdef TERMINFO
2215 fatal ("Terminal type %s is not defined.\n\
2216If that is not the actual type of terminal you have,\n\
2217use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2218`setenv TERM ...') to specify the correct type. It may be necessary\n\
e12c1054 2219to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
b0347178
KH
2220 terminal_type);
2221#else
2222 fatal ("Terminal type %s is not defined.\n\
c5a9c3e6
RS
2223If that is not the actual type of terminal you have,\n\
2224use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2225`setenv TERM ...') to specify the correct type. It may be necessary\n\
e12c1054 2226to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
b0347178
KH
2227 terminal_type);
2228#endif
2229 }
463f5630
KH
2230#ifdef TERMINFO
2231 area = (char *) xmalloc (2044);
2232#else
2233 area = (char *) xmalloc (strlen (buffer));
2234#endif /* not TERMINFO */
2235 if (area == 0)
08a24c47
JB
2236 abort ();
2237
2238 TS_ins_line = tgetstr ("al", address);
2239 TS_ins_multi_lines = tgetstr ("AL", address);
2240 TS_bell = tgetstr ("bl", address);
2241 BackTab = tgetstr ("bt", address);
2242 TS_clr_to_bottom = tgetstr ("cd", address);
2243 TS_clr_line = tgetstr ("ce", address);
ff11dfa1 2244 TS_clr_frame = tgetstr ("cl", address);
2efdbcdd 2245 ColPosition = NULL; /* tgetstr ("ch", address); */
08a24c47
JB
2246 AbsPosition = tgetstr ("cm", address);
2247 CR = tgetstr ("cr", address);
2248 TS_set_scroll_region = tgetstr ("cs", address);
2249 TS_set_scroll_region_1 = tgetstr ("cS", address);
2250 RowPosition = tgetstr ("cv", address);
2251 TS_del_char = tgetstr ("dc", address);
2252 TS_del_multi_chars = tgetstr ("DC", address);
2253 TS_del_line = tgetstr ("dl", address);
2254 TS_del_multi_lines = tgetstr ("DL", address);
2255 TS_delete_mode = tgetstr ("dm", address);
2256 TS_end_delete_mode = tgetstr ("ed", address);
2257 TS_end_insert_mode = tgetstr ("ei", address);
2258 Home = tgetstr ("ho", address);
2259 TS_ins_char = tgetstr ("ic", address);
2260 TS_ins_multi_chars = tgetstr ("IC", address);
2261 TS_insert_mode = tgetstr ("im", address);
2262 TS_pad_inserted_char = tgetstr ("ip", address);
2263 TS_end_keypad_mode = tgetstr ("ke", address);
2264 TS_keypad_mode = tgetstr ("ks", address);
2265 LastLine = tgetstr ("ll", address);
2266 Right = tgetstr ("nd", address);
2267 Down = tgetstr ("do", address);
2268 if (!Down)
2269 Down = tgetstr ("nl", address); /* Obsolete name for "do" */
2270#ifdef VMS
2271 /* VMS puts a carriage return before each linefeed,
2272 so it is not safe to use linefeeds. */
2273 if (Down && Down[0] == '\n' && Down[1] == '\0')
2274 Down = 0;
2275#endif /* VMS */
2276 if (tgetflag ("bs"))
2277 Left = "\b"; /* can't possibly be longer! */
2278 else /* (Actually, "bs" is obsolete...) */
2279 Left = tgetstr ("le", address);
2280 if (!Left)
2281 Left = tgetstr ("bc", address); /* Obsolete name for "le" */
2282 TS_pad_char = tgetstr ("pc", address);
2283 TS_repeat = tgetstr ("rp", address);
2284 TS_end_standout_mode = tgetstr ("se", address);
2285 TS_fwd_scroll = tgetstr ("sf", address);
2286 TS_standout_mode = tgetstr ("so", address);
2287 TS_rev_scroll = tgetstr ("sr", address);
2288 Wcm.cm_tab = tgetstr ("ta", address);
2289 TS_end_termcap_modes = tgetstr ("te", address);
2290 TS_termcap_modes = tgetstr ("ti", address);
2291 Up = tgetstr ("up", address);
2292 TS_visible_bell = tgetstr ("vb", address);
a168702a
GM
2293 TS_cursor_normal = tgetstr ("ve", address);
2294 TS_cursor_visible = tgetstr ("vs", address);
2295 TS_cursor_invisible = tgetstr ("vi", address);
08a24c47 2296 TS_set_window = tgetstr ("wi", address);
177c0ea7 2297
a168702a
GM
2298 TS_enter_underline_mode = tgetstr ("us", address);
2299 TS_exit_underline_mode = tgetstr ("ue", address);
a168702a
GM
2300 TS_enter_bold_mode = tgetstr ("md", address);
2301 TS_enter_dim_mode = tgetstr ("mh", address);
2302 TS_enter_blink_mode = tgetstr ("mb", address);
2303 TS_enter_reverse_mode = tgetstr ("mr", address);
2304 TS_enter_alt_charset_mode = tgetstr ("as", address);
2305 TS_exit_alt_charset_mode = tgetstr ("ae", address);
2306 TS_exit_attribute_mode = tgetstr ("me", address);
177c0ea7 2307
08a24c47
JB
2308 MultiUp = tgetstr ("UP", address);
2309 MultiDown = tgetstr ("DO", address);
2310 MultiLeft = tgetstr ("LE", address);
2311 MultiRight = tgetstr ("RI", address);
2312
e7f90eab
GM
2313 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
2314 color because we can't switch back to the default foreground and
2315 background. */
a168702a 2316 TS_orig_pair = tgetstr ("op", address);
e7f90eab 2317 if (TS_orig_pair)
a168702a 2318 {
e7f90eab
GM
2319 TS_set_foreground = tgetstr ("AF", address);
2320 TS_set_background = tgetstr ("AB", address);
2321 if (!TS_set_foreground)
2322 {
2323 /* SVr4. */
2324 TS_set_foreground = tgetstr ("Sf", address);
2325 TS_set_background = tgetstr ("Sb", address);
2326 }
177c0ea7 2327
e7f90eab
GM
2328 TN_max_colors = tgetnum ("Co");
2329 TN_max_pairs = tgetnum ("pa");
177c0ea7 2330
4e6ba4a4
GM
2331 TN_no_color_video = tgetnum ("NC");
2332 if (TN_no_color_video == -1)
2333 TN_no_color_video = 0;
a168702a 2334 }
a168702a 2335
ace28297
EZ
2336 tty_default_color_capabilities (1);
2337
e4058338
KH
2338 MagicWrap = tgetflag ("xn");
2339 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
2340 the former flag imply the latter. */
2341 AutoWrap = MagicWrap || tgetflag ("am");
ff11dfa1 2342 memory_below_frame = tgetflag ("db");
08a24c47
JB
2343 TF_hazeltine = tgetflag ("hz");
2344 must_write_spaces = tgetflag ("in");
2345 meta_key = tgetflag ("km") || tgetflag ("MT");
2346 TF_insmode_motion = tgetflag ("mi");
2347 TF_standout_motion = tgetflag ("ms");
2348 TF_underscore = tgetflag ("ul");
08a24c47
JB
2349 TF_teleray = tgetflag ("xt");
2350
5c2c7893
JB
2351 term_get_fkeys (address);
2352
ff11dfa1 2353 /* Get frame size from system, or else from termcap. */
3b12ce12
RS
2354 {
2355 int height, width;
2356 get_frame_size (&width, &height);
9882535b
KS
2357 FRAME_COLS (sf) = width;
2358 FRAME_LINES (sf) = height;
3b12ce12
RS
2359 }
2360
9882535b
KS
2361 if (FRAME_COLS (sf) <= 0)
2362 SET_FRAME_COLS (sf, tgetnum ("co"));
1efd8636
RS
2363 else
2364 /* Keep width and external_width consistent */
9882535b
KS
2365 SET_FRAME_COLS (sf, FRAME_COLS (sf));
2366 if (FRAME_LINES (sf) <= 0)
2367 FRAME_LINES (sf) = tgetnum ("li");
177c0ea7 2368
9882535b 2369 if (FRAME_LINES (sf) < 3 || FRAME_COLS (sf) < 3)
e12c1054 2370 fatal ("Screen size %dx%d is too small",
9882535b 2371 FRAME_LINES (sf), FRAME_COLS (sf));
ee7a2de4 2372
08a24c47 2373 min_padding_speed = tgetnum ("pb");
08a24c47
JB
2374 TabWidth = tgetnum ("tw");
2375
2376#ifdef VMS
2377 /* These capabilities commonly use ^J.
2378 I don't know why, but sending them on VMS does not work;
2379 it causes following spaces to be lost, sometimes.
2380 For now, the simplest fix is to avoid using these capabilities ever. */
2381 if (Down && Down[0] == '\n')
2382 Down = 0;
2383#endif /* VMS */
2384
2385 if (!TS_bell)
2386 TS_bell = "\07";
2387
2388 if (!TS_fwd_scroll)
2389 TS_fwd_scroll = Down;
2390
2391 PC = TS_pad_char ? *TS_pad_char : 0;
2392
2393 if (TabWidth < 0)
2394 TabWidth = 8;
177c0ea7 2395
08a24c47
JB
2396/* Turned off since /etc/termcap seems to have :ta= for most terminals
2397 and newer termcap doc does not seem to say there is a default.
2398 if (!Wcm.cm_tab)
2399 Wcm.cm_tab = "\t";
2400*/
2401
54800acb
MB
2402 /* We don't support standout modes that use `magic cookies', so
2403 turn off any that do. */
2404 if (TS_standout_mode && tgetnum ("sg") >= 0)
2405 {
2406 TS_standout_mode = 0;
2407 TS_end_standout_mode = 0;
2408 }
2409 if (TS_enter_underline_mode && tgetnum ("ug") >= 0)
2410 {
2411 TS_enter_underline_mode = 0;
2412 TS_exit_underline_mode = 0;
2413 }
2414
2415 /* If there's no standout mode, try to use underlining instead. */
08a24c47
JB
2416 if (TS_standout_mode == 0)
2417 {
54800acb
MB
2418 TS_standout_mode = TS_enter_underline_mode;
2419 TS_end_standout_mode = TS_exit_underline_mode;
08a24c47
JB
2420 }
2421
afd359c4
RS
2422 /* If no `se' string, try using a `me' string instead.
2423 If that fails, we can't use standout mode at all. */
2424 if (TS_end_standout_mode == 0)
2425 {
e4bfb3b6 2426 char *s = tgetstr ("me", address);
afd359c4
RS
2427 if (s != 0)
2428 TS_end_standout_mode = s;
2429 else
2430 TS_standout_mode = 0;
2431 }
2432
08a24c47
JB
2433 if (TF_teleray)
2434 {
2435 Wcm.cm_tab = 0;
54800acb
MB
2436 /* We can't support standout mode, because it uses magic cookies. */
2437 TS_standout_mode = 0;
08a24c47
JB
2438 /* But that means we cannot rely on ^M to go to column zero! */
2439 CR = 0;
2440 /* LF can't be trusted either -- can alter hpos */
2441 /* if move at column 0 thru a line with TS_standout_mode */
2442 Down = 0;
2443 }
2444
2445 /* Special handling for certain terminal types known to need it */
2446
2447 if (!strcmp (terminal_type, "supdup"))
2448 {
ff11dfa1 2449 memory_below_frame = 1;
08a24c47
JB
2450 Wcm.cm_losewrap = 1;
2451 }
2452 if (!strncmp (terminal_type, "c10", 3)
2453 || !strcmp (terminal_type, "perq"))
2454 {
2455 /* Supply a makeshift :wi string.
2456 This string is not valid in general since it works only
2457 for windows starting at the upper left corner;
2458 but that is all Emacs uses.
2459
ff11dfa1 2460 This string works only if the frame is using
08a24c47
JB
2461 the top of the video memory, because addressing is memory-relative.
2462 So first check the :ti string to see if that is true.
2463
2464 It would be simpler if the :wi string could go in the termcap
2465 entry, but it can't because it is not fully valid.
2466 If it were in the termcap entry, it would confuse other programs. */
2467 if (!TS_set_window)
2468 {
2469 p = TS_termcap_modes;
2470 while (*p && strcmp (p, "\033v "))
2471 p++;
2472 if (*p)
2473 TS_set_window = "\033v%C %C %C %C ";
2474 }
2475 /* Termcap entry often fails to have :in: flag */
2476 must_write_spaces = 1;
2477 /* :ti string typically fails to have \E^G! in it */
2478 /* This limits scope of insert-char to one line. */
2479 strcpy (area, TS_termcap_modes);
2480 strcat (area, "\033\007!");
2481 TS_termcap_modes = area;
2482 area += strlen (area) + 1;
2483 p = AbsPosition;
2484 /* Change all %+ parameters to %C, to handle
2485 values above 96 correctly for the C100. */
2486 while (*p)
2487 {
2488 if (p[0] == '%' && p[1] == '+')
2489 p[1] = 'C';
2490 p++;
2491 }
2492 }
2493
9882535b
KS
2494 FrameRows = FRAME_LINES (sf);
2495 FrameCols = FRAME_COLS (sf);
2496 specified_window = FRAME_LINES (sf);
08a24c47
JB
2497
2498 if (Wcm_init () == -1) /* can't do cursor motion */
2499#ifdef VMS
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, use either the\n\
2503DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
e12c1054 2504or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
08a24c47 2505 terminal_type);
37dad45a
RS
2506#else /* not VMS */
2507# ifdef TERMINFO
2508 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2509It lacks the ability to position the cursor.\n\
2510If that is not the actual type of terminal you have,\n\
2511use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2512`setenv TERM ...') to specify the correct type. It may be necessary\n\
e12c1054 2513to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
37dad45a
RS
2514 terminal_type);
2515# else /* TERMCAP */
08a24c47
JB
2516 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2517It lacks the ability to position the cursor.\n\
2518If that is not the actual type of terminal you have,\n\
c5a9c3e6
RS
2519use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2520`setenv TERM ...') to specify the correct type. It may be necessary\n\
e12c1054 2521to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
08a24c47 2522 terminal_type);
37dad45a
RS
2523# endif /* TERMINFO */
2524#endif /*VMS */
9882535b
KS
2525 if (FRAME_LINES (sf) <= 0
2526 || FRAME_COLS (sf) <= 0)
e12c1054 2527 fatal ("The frame size has not been specified");
08a24c47
JB
2528
2529 delete_in_insert_mode
2530 = TS_delete_mode && TS_insert_mode
2531 && !strcmp (TS_delete_mode, TS_insert_mode);
2532
2533 se_is_so = (TS_standout_mode
2534 && TS_end_standout_mode
2535 && !strcmp (TS_standout_mode, TS_end_standout_mode));
2536
08a24c47
JB
2537 UseTabs = tabs_safe_p () && TabWidth == 8;
2538
2539 scroll_region_ok
2540 = (Wcm.cm_abs
2541 && (TS_set_window || TS_set_scroll_region || TS_set_scroll_region_1));
2542
2543 line_ins_del_ok = (((TS_ins_line || TS_ins_multi_lines)
2544 && (TS_del_line || TS_del_multi_lines))
2545 || (scroll_region_ok && TS_fwd_scroll && TS_rev_scroll));
2546
2547 char_ins_del_ok = ((TS_ins_char || TS_insert_mode
2548 || TS_pad_inserted_char || TS_ins_multi_chars)
2549 && (TS_del_char || TS_del_multi_chars));
2550
2551 fast_clear_end_of_line = TS_clr_line != 0;
2552
2553 init_baud_rate ();
2554 if (read_socket_hook) /* Baudrate is somewhat */
2555 /* meaningless in this case */
2556 baud_rate = 9600;
20a558dc 2557
e52f4e08
GM
2558 FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0;
2559 FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none;
eccec691 2560#endif /* WINDOWSNT */
08a24c47
JB
2561}
2562
2563/* VARARGS 1 */
dfcf069d 2564void
08a24c47 2565fatal (str, arg1, arg2)
4746118a 2566 char *str, *arg1, *arg2;
08a24c47
JB
2567{
2568 fprintf (stderr, "emacs: ");
2569 fprintf (stderr, str, arg1, arg2);
e12c1054 2570 fprintf (stderr, "\n");
08a24c47
JB
2571 fflush (stderr);
2572 exit (1);
2573}
07c57952 2574
dfcf069d 2575void
07c57952
KH
2576syms_of_term ()
2577{
7ee72033
MB
2578 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
2579 doc: /* Non-nil means the system uses terminfo rather than termcap.
228299fa 2580This variable can be used by terminal emulator packages. */);
07c57952
KH
2581#ifdef TERMINFO
2582 system_uses_terminfo = 1;
2583#else
2584 system_uses_terminfo = 0;
2585#endif
c291d9ef 2586
7ee72033
MB
2587 DEFVAR_LISP ("ring-bell-function", &Vring_bell_function,
2588 doc: /* Non-nil means call this function to ring the bell.
228299fa 2589The function should accept no arguments. */);
c291d9ef 2590 Vring_bell_function = Qnil;
a168702a
GM
2591
2592 defsubr (&Stty_display_color_p);
bfa62f96 2593 defsubr (&Stty_display_color_cells);
07c57952 2594}
a168702a 2595