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