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