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