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