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