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