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