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