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