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