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