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