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