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