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