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