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