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