Overhaul and simplify single_kboard API. Allow calls to `recursive-edit' in process...
[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));
6ed8eeff 90static void delete_tty P_ ((struct terminal *));
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
6ed8eeff 201tty_set_terminal_modes (struct terminal *terminal)
fca177d4 202{
6ed8eeff 203 struct tty_display_info *tty = terminal->display_info.tty;
3224dac1 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
6ed8eeff 230tty_reset_terminal_modes (struct terminal *terminal)
fca177d4 231{
6ed8eeff 232 struct tty_display_info *tty = terminal->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
6ed8eeff 249/* Flag the end of a display update on a termcap terminal. */
da8e1115 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,
6ed8eeff
KL
1812 doc: /* Return non-nil if the tty device TERMINAL can display colors.
1813
1814TERMINAL can be a terminal id, a frame or nil (meaning the selected
1815frame's terminal). This function always returns nil if TERMINAL
1816is not on a tty device. */)
1817 (terminal)
1818 Lisp_Object terminal;
a168702a 1819{
6ed8eeff
KL
1820 struct terminal *t = get_tty_terminal (terminal);
1821 if (!t)
428a555e 1822 return Qnil;
3224dac1 1823 else
6ed8eeff 1824 return t->display_info.tty->TN_max_colors > 0 ? Qt : Qnil;
a168702a
GM
1825}
1826
bfa62f96
EZ
1827/* Return the number of supported colors. */
1828DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
1829 Stty_display_color_cells, 0, 1, 0,
6ed8eeff
KL
1830 doc: /* Return the number of colors supported by the tty device TERMINAL.
1831
1832TERMINAL can be a terminal id, a frame or nil (meaning the selected
1833frame's terminal). This function always returns nil if TERMINAL
1834is not on a tty device. */)
1835 (terminal)
1836 Lisp_Object terminal;
bfa62f96 1837{
6ed8eeff
KL
1838 struct terminal *t = get_tty_terminal (terminal);
1839 if (!t)
8c8d5f35 1840 return make_number (0);
3224dac1 1841 else
6ed8eeff 1842 return make_number (t->display_info.tty->TN_max_colors);
bfa62f96
EZ
1843}
1844
ace28297 1845#ifndef WINDOWSNT
a168702a 1846
ace28297
EZ
1847/* Save or restore the default color-related capabilities of this
1848 terminal. */
1849static void
28d7d09f 1850tty_default_color_capabilities (struct tty_display_info *tty, int save)
ace28297
EZ
1851{
1852 static char
1853 *default_orig_pair, *default_set_foreground, *default_set_background;
1854 static int default_max_colors, default_max_pairs, default_no_color_video;
1855
1856 if (save)
1857 {
1858 if (default_orig_pair)
1859 xfree (default_orig_pair);
fca177d4 1860 default_orig_pair = tty->TS_orig_pair ? xstrdup (tty->TS_orig_pair) : NULL;
ace28297
EZ
1861
1862 if (default_set_foreground)
1863 xfree (default_set_foreground);
fca177d4 1864 default_set_foreground = tty->TS_set_foreground ? xstrdup (tty->TS_set_foreground)
ace28297
EZ
1865 : NULL;
1866
1867 if (default_set_background)
1868 xfree (default_set_background);
fca177d4 1869 default_set_background = tty->TS_set_background ? xstrdup (tty->TS_set_background)
ace28297
EZ
1870 : NULL;
1871
fca177d4
KL
1872 default_max_colors = tty->TN_max_colors;
1873 default_max_pairs = tty->TN_max_pairs;
1874 default_no_color_video = tty->TN_no_color_video;
ace28297
EZ
1875 }
1876 else
1877 {
fca177d4
KL
1878 tty->TS_orig_pair = default_orig_pair;
1879 tty->TS_set_foreground = default_set_foreground;
1880 tty->TS_set_background = default_set_background;
1881 tty->TN_max_colors = default_max_colors;
1882 tty->TN_max_pairs = default_max_pairs;
1883 tty->TN_no_color_video = default_no_color_video;
ace28297
EZ
1884 }
1885}
1886
1887/* Setup one of the standard tty color schemes according to MODE.
1888 MODE's value is generally the number of colors which we want to
1889 support; zero means set up for the default capabilities, the ones
a4c6993d 1890 we saw at init_tty time; -1 means turn off color support. */
ed8dad6b 1891static void
28d7d09f 1892tty_setup_colors (struct tty_display_info *tty, int mode)
ace28297 1893{
40409f05
EZ
1894 /* Canonicalize all negative values of MODE. */
1895 if (mode < -1)
1896 mode = -1;
1897
ace28297
EZ
1898 switch (mode)
1899 {
1900 case -1: /* no colors at all */
fca177d4
KL
1901 tty->TN_max_colors = 0;
1902 tty->TN_max_pairs = 0;
1903 tty->TN_no_color_video = 0;
1904 tty->TS_set_foreground = tty->TS_set_background = tty->TS_orig_pair = NULL;
ace28297
EZ
1905 break;
1906 case 0: /* default colors, if any */
1907 default:
fca177d4 1908 tty_default_color_capabilities (tty, 0);
ace28297
EZ
1909 break;
1910 case 8: /* 8 standard ANSI colors */
fca177d4 1911 tty->TS_orig_pair = "\033[0m";
ace28297 1912#ifdef TERMINFO
fca177d4
KL
1913 tty->TS_set_foreground = "\033[3%p1%dm";
1914 tty->TS_set_background = "\033[4%p1%dm";
ace28297 1915#else
fca177d4
KL
1916 tty->TS_set_foreground = "\033[3%dm";
1917 tty->TS_set_background = "\033[4%dm";
ace28297 1918#endif
fca177d4
KL
1919 tty->TN_max_colors = 8;
1920 tty->TN_max_pairs = 64;
1921 tty->TN_no_color_video = 0;
ace28297
EZ
1922 break;
1923 }
1924}
1925
1926void
1927set_tty_color_mode (f, val)
1928 struct frame *f;
1929 Lisp_Object val;
1930{
dfc7a077 1931 Lisp_Object color_mode_spec, current_mode_spec;
ace28297
EZ
1932 Lisp_Object color_mode, current_mode;
1933 int mode, old_mode;
1934 extern Lisp_Object Qtty_color_mode;
1935 Lisp_Object tty_color_mode_alist;
1936
1937 tty_color_mode_alist = Fintern_soft (build_string ("tty-color-mode-alist"),
1938 Qnil);
1939
9ac61a89 1940 if (INTEGERP (val))
ace28297
EZ
1941 color_mode = val;
1942 else
1943 {
1944 if (NILP (tty_color_mode_alist))
1945 color_mode_spec = Qnil;
1946 else
1947 color_mode_spec = Fassq (val, XSYMBOL (tty_color_mode_alist)->value);
ace28297
EZ
1948
1949 if (CONSP (color_mode_spec))
1950 color_mode = XCDR (color_mode_spec);
1951 else
1952 color_mode = Qnil;
1953 }
545d91d5
RS
1954
1955 current_mode_spec = assq_no_quit (Qtty_color_mode, f->param_alist);
1956
ace28297
EZ
1957 if (CONSP (current_mode_spec))
1958 current_mode = XCDR (current_mode_spec);
1959 else
1960 current_mode = Qnil;
9ac61a89 1961 if (INTEGERP (color_mode))
ace28297
EZ
1962 mode = XINT (color_mode);
1963 else
1964 mode = 0; /* meaning default */
9ac61a89 1965 if (INTEGERP (current_mode))
ace28297
EZ
1966 old_mode = XINT (current_mode);
1967 else
1968 old_mode = 0;
1969
1970 if (mode != old_mode)
1971 {
fca177d4 1972 tty_setup_colors (FRAME_TTY (f), mode);
ace28297
EZ
1973 /* This recomputes all the faces given the new color
1974 definitions. */
1975 call0 (intern ("tty-set-up-initial-frame-faces"));
1976 redraw_frame (f);
1977 }
1978}
1979
1980#endif /* !WINDOWSNT */
a168702a
GM
1981
1982\f
28d440ab 1983
6ed8eeff 1984/* Return the tty display object specified by TERMINAL. */
b6660415 1985
6ed8eeff
KL
1986struct terminal *
1987get_tty_terminal (Lisp_Object terminal)
b6660415 1988{
6ed8eeff 1989 struct terminal *t = get_terminal (terminal, 0);
62af879c 1990
6ed8eeff
KL
1991 if (t && t->type == output_initial)
1992 t = NULL;
d7e4838f 1993
6ed8eeff
KL
1994 if (t && t->type != output_termcap)
1995 error ("Device %d is not a termcap terminal device", t->id);
b6660415 1996
6ed8eeff 1997 return t;
b6660415
KL
1998}
1999
7e59217d
KL
2000/* Return the active termcap device that uses the tty device with the
2001 given name. If NAME is NULL, return the device corresponding to
b6660415
KL
2002 our controlling terminal.
2003
7e59217d 2004 This function ignores suspended devices.
da8e1115
KL
2005
2006 Returns NULL if the named terminal device is not opened. */
2007
6ed8eeff 2008struct terminal *
7e59217d 2009get_named_tty (name)
28d440ab
KL
2010 char *name;
2011{
6ed8eeff
KL
2012 struct terminal *t;
2013
2014 for (t = terminal_list; t; t = t->next_terminal) {
2015 if (t->type == output_termcap
2016 && ((t->display_info.tty->name == 0 && name == 0)
2017 || (name && t->display_info.tty->name
2018 && !strcmp (t->display_info.tty->name, name)))
2019 && TERMINAL_ACTIVE_P (t))
2020 return t;
28d440ab
KL
2021 };
2022
2023 return 0;
2024}
2025
2026\f
6ed8eeff
KL
2027DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0,
2028 doc: /* Return the type of the tty device that TERMINAL uses.
a3fbb897 2029
6ed8eeff
KL
2030TERMINAL can be a terminal id, a frame or nil (meaning the selected
2031frame's terminal). */)
2032 (terminal)
2033 Lisp_Object terminal;
b6660415 2034{
6ed8eeff 2035 struct terminal *t = get_terminal (terminal, 1);
819b8f00 2036
6ed8eeff
KL
2037 if (t->type != output_termcap)
2038 error ("Terminal %d is not a termcap terminal", t->id);
b6660415 2039
6ed8eeff
KL
2040 if (t->display_info.tty->type)
2041 return build_string (t->display_info.tty->type);
819b8f00
KL
2042 else
2043 return Qnil;
2044}
2045
6ed8eeff
KL
2046DEFUN ("controlling-tty-p", Fcontrolling_tty_p, Scontrolling_tty_p, 0, 1, 0,
2047 doc: /* Return non-nil if TERMINAL is on the controlling tty of the Emacs process.
a3fbb897 2048
6ed8eeff
KL
2049TERMINAL can be a terminal id, a frame or nil (meaning the selected
2050frame's terminal). This function always returns nil if TERMINAL
2051is not on a tty device. */)
2052 (terminal)
2053 Lisp_Object terminal;
4a933ef8 2054{
6ed8eeff 2055 struct terminal *t = get_terminal (terminal, 1);
4a933ef8 2056
6ed8eeff 2057 if (t->type != output_termcap || t->display_info.tty->name)
4a933ef8
KL
2058 return Qnil;
2059 else
2060 return Qt;
2061}
2062
a3fbb897 2063DEFUN ("tty-no-underline", Ftty_no_underline, Stty_no_underline, 0, 1, 0,
6ed8eeff 2064 doc: /* Declare that the tty used by TERMINAL does not handle underlining.
a3fbb897
KL
2065This is used to override the terminfo data, for certain terminals that
2066do not really do underlining, but say that they do. This function has
6ed8eeff 2067no effect if used on a non-tty terminal.
a3fbb897 2068
6ed8eeff
KL
2069TERMINAL can be a terminal id, a frame or nil (meaning the selected
2070frame's terminal). This function always returns nil if TERMINAL
2071is not on a tty device. */)
2072 (terminal)
2073 Lisp_Object terminal;
a3fbb897 2074{
6ed8eeff 2075 struct terminal *t = get_terminal (terminal, 1);
a3fbb897 2076
6ed8eeff
KL
2077 if (t->type == output_termcap)
2078 t->display_info.tty->TS_enter_underline_mode = 0;
a3fbb897
KL
2079 return Qnil;
2080}
2081
ed8dad6b
KL
2082\f
2083
2084DEFUN ("suspend-tty", Fsuspend_tty, Ssuspend_tty, 0, 1, 0,
2085 doc: /* Suspend the terminal device TTY.
2086
2087The device is restored to its default state, and Emacs ceases all
2088access to the tty device. Frames that use the device are not deleted,
2089but input is not read from them and if they change, their display is
2090not updated.
2091
2092TTY may be a terminal id, a frame, or nil for the terminal device of
2093the currently selected frame.
2094
2095This function runs `suspend-tty-functions' after suspending the
2096device. The functions are run with one arg, the id of the suspended
2097terminal device.
2098
2099`suspend-tty' does nothing if it is called on a device that is already
2100suspended.
2101
2102A suspended tty may be resumed by calling `resume-tty' on it. */)
2103 (tty)
2104 Lisp_Object tty;
2105{
6ed8eeff 2106 struct terminal *t = get_tty_terminal (tty);
ed8dad6b
KL
2107 FILE *f;
2108
6ed8eeff 2109 if (!t)
ed8dad6b
KL
2110 error ("Unknown tty device");
2111
6ed8eeff 2112 f = t->display_info.tty->input;
ed8dad6b
KL
2113
2114 if (f)
2115 {
6ed8eeff 2116 reset_sys_modes (t->display_info.tty);
ed8dad6b
KL
2117
2118 delete_keyboard_wait_descriptor (fileno (f));
2119
2120 fclose (f);
6ed8eeff
KL
2121 if (f != t->display_info.tty->output)
2122 fclose (t->display_info.tty->output);
ed8dad6b 2123
6ed8eeff
KL
2124 t->display_info.tty->input = 0;
2125 t->display_info.tty->output = 0;
ed8dad6b 2126
6ed8eeff
KL
2127 if (FRAMEP (t->display_info.tty->top_frame))
2128 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0);
ed8dad6b
KL
2129
2130 /* Run `suspend-tty-functions'. */
2131 if (!NILP (Vrun_hooks))
2132 {
2133 Lisp_Object args[2];
2134 args[0] = intern ("suspend-tty-functions");
6ed8eeff 2135 args[1] = make_number (t->id);
ed8dad6b
KL
2136 Frun_hook_with_args (2, args);
2137 }
2138 }
2139
2140 return Qnil;
2141}
2142
2143DEFUN ("resume-tty", Fresume_tty, Sresume_tty, 0, 1, 0,
2144 doc: /* Resume the previously suspended terminal device TTY.
2145The terminal is opened and reinitialized. Frames that are on the
6ed8eeff 2146suspended terminal are revived.
ed8dad6b 2147
6ed8eeff
KL
2148It is an error to resume a terminal while another terminal is active
2149on the same device.
ed8dad6b 2150
6ed8eeff
KL
2151This function runs `resume-tty-functions' after resuming the terminal.
2152The functions are run with one arg, the id of the resumed terminal
ed8dad6b
KL
2153device.
2154
2155`resume-tty' does nothing if it is called on a device that is not
2156suspended.
2157
6ed8eeff
KL
2158TTY may be a terminal id, a frame, or nil for the terminal device of
2159the currently selected frame. */)
ed8dad6b
KL
2160 (tty)
2161 Lisp_Object tty;
2162{
6ed8eeff 2163 struct terminal *t = get_tty_terminal (tty);
ed8dad6b
KL
2164 int fd;
2165
6ed8eeff 2166 if (!t)
ed8dad6b
KL
2167 error ("Unknown tty device");
2168
6ed8eeff 2169 if (!t->display_info.tty->input)
ed8dad6b 2170 {
6ed8eeff 2171 if (get_named_tty (t->display_info.tty->name))
ed8dad6b
KL
2172 error ("Cannot resume display while another display is active on the same device");
2173
6ed8eeff 2174 fd = emacs_open (t->display_info.tty->name, O_RDWR | O_NOCTTY, 0);
ed8dad6b
KL
2175
2176 /* XXX What if open fails? */
2177
2178 dissociate_if_controlling_tty (fd);
2179
6ed8eeff
KL
2180 t->display_info.tty->output = fdopen (fd, "w+");
2181 t->display_info.tty->input = t->display_info.tty->output;
ed8dad6b
KL
2182
2183 add_keyboard_wait_descriptor (fd);
2184
6ed8eeff
KL
2185 if (FRAMEP (t->display_info.tty->top_frame))
2186 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
ed8dad6b 2187
6ed8eeff 2188 init_sys_modes (t->display_info.tty);
ed8dad6b
KL
2189
2190 /* Run `suspend-tty-functions'. */
2191 if (!NILP (Vrun_hooks))
2192 {
2193 Lisp_Object args[2];
2194 args[0] = intern ("resume-tty-functions");
6ed8eeff 2195 args[1] = make_number (t->id);
ed8dad6b
KL
2196 Frun_hook_with_args (2, args);
2197 }
2198 }
2199
2200 return Qnil;
2201}
a3fbb897 2202
819b8f00 2203\f
a168702a
GM
2204/***********************************************************************
2205 Initialization
2206 ***********************************************************************/
2207
ed8dad6b
KL
2208/* Initialize the tty-dependent part of frame F. The frame must
2209 already have its device initialized. */
3224dac1 2210
ed8dad6b
KL
2211void
2212create_tty_output (struct frame *f)
28d440ab 2213{
ed8dad6b
KL
2214 struct tty_output *t;
2215
2216 if (! FRAME_TERMCAP_P (f))
428a555e
KL
2217 abort ();
2218
ed8dad6b
KL
2219 t = xmalloc (sizeof (struct tty_output));
2220 bzero (t, sizeof (struct tty_output));
b6660415 2221
6ed8eeff 2222 t->display_info = FRAME_TERMINAL (f)->display_info.tty;
bedb9c0e 2223
ed8dad6b 2224 f->output_data.tty = t;
3224dac1
KL
2225}
2226
ed8dad6b 2227/* Delete the tty-dependent part of frame F. */
da8e1115 2228
ed8dad6b
KL
2229static void
2230delete_tty_output (struct frame *f)
3224dac1 2231{
ed8dad6b 2232 if (! FRAME_TERMCAP_P (f))
3224dac1
KL
2233 abort ();
2234
ed8dad6b 2235 xfree (f->output_data.tty);
28d440ab
KL
2236}
2237
ed8dad6b
KL
2238\f
2239
03a1d6bd 2240/* Drop the controlling terminal if fd is the same device. */
ed8dad6b 2241static void
03a1d6bd
KL
2242dissociate_if_controlling_tty (int fd)
2243{
03a1d6bd 2244 int pgid;
8516815b 2245 EMACS_GET_TTY_PGRP (fd, &pgid); /* If tcgetpgrp succeeds, fd is the ctty. */
03a1d6bd
KL
2246 if (pgid != -1)
2247 {
8516815b 2248#if defined (USG) && !defined (BSD_PGRPS)
03a1d6bd
KL
2249 setpgrp ();
2250 no_controlling_tty = 1;
03a1d6bd
KL
2251#else
2252#ifdef TIOCNOTTY /* Try BSD ioctls. */
8516815b
KL
2253 sigblock (sigmask (SIGTTOU));
2254 fd = emacs_open ("/dev/tty", O_RDWR, 0);
2255 if (fd != -1 && ioctl (fd, TIOCNOTTY, 0) != -1)
2256 {
2257 no_controlling_tty = 1;
2258 }
2259 if (fd != -1)
2260 emacs_close (fd);
2261 sigunblock (sigmask (SIGTTOU));
03a1d6bd 2262#else
8516815b
KL
2263 /* Unknown system. */
2264 croak ();
03a1d6bd
KL
2265#endif /* ! TIOCNOTTY */
2266#endif /* ! USG */
71a96040 2267 }
03a1d6bd
KL
2268}
2269
520c4dfd
KL
2270static void maybe_fatal();
2271
3224dac1
KL
2272/* Create a termcap display on the tty device with the given name and
2273 type.
2274
2275 If NAME is NULL, then use the controlling tty, i.e., stdin/stdout.
2276 Otherwise NAME should be a path to the tty device file,
2277 e.g. "/dev/pts/7".
28d440ab 2278
3224dac1
KL
2279 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
2280
2281 If MUST_SUCCEED is true, then all errors are fatal. */
da8e1115 2282
6ed8eeff 2283struct terminal *
a4c6993d 2284init_tty (char *name, char *terminal_type, int must_succeed)
08a24c47
JB
2285{
2286 char *area;
2287 char **address = &area;
3a06a6d9 2288 char *buffer = NULL;
5846981b 2289 int buffer_size = 4096;
08a24c47
JB
2290 register char *p;
2291 int status;
28d7d09f 2292 struct tty_display_info *tty;
6ed8eeff 2293 struct terminal *terminal;
28d440ab 2294
3224dac1
KL
2295 if (!terminal_type)
2296 maybe_fatal (must_succeed, 0, 0,
2297 "Unknown terminal type",
2298 "Unknown terminal type");
b6660415 2299
6ed8eeff
KL
2300 /* If we already have a terminal on the given device, use that. If
2301 all such terminals are suspended, create a new one instead. */
a4c6993d 2302 /* XXX Perhaps this should be made explicit by having init_tty
6ed8eeff 2303 always create a new terminal and separating terminal and frame
b6660415 2304 creation on Lisp level. */
6ed8eeff
KL
2305 terminal = get_named_tty (name);
2306 if (terminal)
2307 return terminal;
428a555e 2308
6ed8eeff 2309 terminal = create_terminal ();
3224dac1
KL
2310 tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info));
2311 bzero (tty, sizeof (struct tty_display_info));
2312 tty->next = tty_list;
2313 tty_list = tty;
428a555e 2314
6ed8eeff
KL
2315 terminal->type = output_termcap;
2316 terminal->display_info.tty = tty;
2317 tty->terminal = terminal;
28d440ab 2318
7b00d185
KL
2319 tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
2320 Wcm_clear (tty);
daf01701 2321
6ed8eeff 2322 terminal->rif = 0; /* ttys don't support window-based redisplay. */
3224dac1 2323
6ed8eeff
KL
2324 terminal->cursor_to_hook = &tty_cursor_to;
2325 terminal->raw_cursor_to_hook = &tty_raw_cursor_to;
3224dac1 2326
6ed8eeff
KL
2327 terminal->clear_to_end_hook = &tty_clear_to_end;
2328 terminal->clear_frame_hook = &tty_clear_frame;
2329 terminal->clear_end_of_line_hook = &tty_clear_end_of_line;
3224dac1 2330
6ed8eeff 2331 terminal->ins_del_lines_hook = &tty_ins_del_lines;
3224dac1 2332
6ed8eeff
KL
2333 terminal->insert_glyphs_hook = &tty_insert_glyphs;
2334 terminal->write_glyphs_hook = &tty_write_glyphs;
2335 terminal->delete_glyphs_hook = &tty_delete_glyphs;
3224dac1 2336
6ed8eeff 2337 terminal->ring_bell_hook = &tty_ring_bell;
3224dac1 2338
6ed8eeff
KL
2339 terminal->reset_terminal_modes_hook = &tty_reset_terminal_modes;
2340 terminal->set_terminal_modes_hook = &tty_set_terminal_modes;
2341 terminal->update_begin_hook = 0; /* Not needed. */
2342 terminal->update_end_hook = &tty_update_end;
2343 terminal->set_terminal_window_hook = &tty_set_terminal_window;
2344
2345 terminal->mouse_position_hook = 0; /* Not needed. */
2346 terminal->frame_rehighlight_hook = 0; /* Not needed. */
2347 terminal->frame_raise_lower_hook = 0; /* Not needed. */
2348
2349 terminal->set_vertical_scroll_bar_hook = 0; /* Not needed. */
2350 terminal->condemn_scroll_bars_hook = 0; /* Not needed. */
2351 terminal->redeem_scroll_bar_hook = 0; /* Not needed. */
2352 terminal->judge_scroll_bars_hook = 0; /* Not needed. */
2353
2354 terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */
2355 terminal->frame_up_to_date_hook = 0; /* Not needed. */
3224dac1 2356
6ed8eeff
KL
2357 terminal->delete_frame_hook = &delete_tty_output;
2358 terminal->delete_terminal_hook = &delete_tty;
428a555e 2359
28d440ab
KL
2360 if (name)
2361 {
2362 int fd;
0a125897 2363 FILE *file;
0c72d684
KL
2364
2365#ifdef O_IGNORE_CTTY
2366 /* Open the terminal device. Don't recognize it as our
2367 controlling terminal, and don't make it the controlling tty
2368 if we don't have one at the moment. */
2369 fd = emacs_open (name, O_RDWR | O_IGNORE_CTTY | O_NOCTTY, 0);
2370#else
2666355c
KL
2371 /* Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
2372 defined on Hurd. On other systems, we need to dissociate
2373 ourselves from the controlling tty when we want to open a
03a1d6bd 2374 frame on the same terminal. */
0c72d684
KL
2375
2376 fd = emacs_open (name, O_RDWR | O_NOCTTY, 0);
03a1d6bd 2377
0c72d684
KL
2378#endif /* O_IGNORE_CTTY */
2379
28d440ab
KL
2380 if (fd < 0)
2381 {
6ed8eeff 2382 delete_tty (terminal);
fca177d4 2383 error ("Could not open file: %s", name);
28d440ab 2384 }
e7cf0fa0 2385 if (!isatty (fd))
0c72d684
KL
2386 {
2387 close (fd);
2388 error ("Not a tty device: %s", name);
2389 }
2390
03a1d6bd
KL
2391 dissociate_if_controlling_tty (fd);
2392
0a125897 2393 file = fdopen (fd, "w+");
28d7d09f 2394 tty->name = xstrdup (name);
6ed8eeff 2395 terminal->name = xstrdup (name);
28d7d09f
KL
2396 tty->input = file;
2397 tty->output = file;
28d440ab
KL
2398 }
2399 else
2400 {
0c72d684
KL
2401 if (no_controlling_tty)
2402 {
2403 /* Opening a frame on stdout is unsafe if we have
2404 disconnected our controlling terminal. */
2405 error ("There is no controlling terminal any more");
2406 }
28d7d09f 2407 tty->name = 0;
6ed8eeff 2408 terminal->name = xstrdup (ttyname (0));
28d7d09f
KL
2409 tty->input = stdin;
2410 tty->output = stdout;
28d440ab
KL
2411 }
2412
28d7d09f 2413 tty->type = xstrdup (terminal_type);
28d440ab 2414
819b8f00 2415 add_keyboard_wait_descriptor (fileno (tty->input));
daf01701 2416
af645abf
KH
2417 encode_terminal_bufsize = 0;
2418
cb28b9c2 2419#ifdef WINDOWSNT
29f27c39 2420 initialize_w32_display ();
cb28b9c2 2421
fca177d4 2422 Wcm_clear (tty);
cb28b9c2 2423
a678d9ff 2424 area = (char *) xmalloc (2044);
cb28b9c2 2425
428a555e
KL
2426 FrameRows (tty) = FRAME_LINES (f); /* XXX */
2427 FrameCols (tty) = FRAME_COLS (f); /* XXX */
2428 tty->specified_window = FRAME_LINES (f); /* XXX */
cb28b9c2 2429
6ed8eeff 2430 tty->terminal->delete_in_insert_mode = 1;
cb28b9c2 2431
daf01701 2432 UseTabs (tty) = 0;
6ed8eeff 2433 terminal->scroll_region_ok = 0;
cb28b9c2 2434
7e59217d 2435 /* Seems to insert lines when it's not supposed to, messing up the
6ed8eeff 2436 display. In doing a trace, it didn't seem to be called much, so I
7e59217d 2437 don't think we're losing anything by turning it off. */
6ed8eeff
KL
2438 terminal->line_ins_del_ok = 0;
2439 terminal->char_ins_del_ok = 1;
cb28b9c2
RS
2440
2441 baud_rate = 19200;
2442
428a555e
KL
2443 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0; /* XXX */
2444 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none; /* XXX */
acfcd5cd 2445 TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
cb28b9c2 2446
6ed8eeff 2447 return terminal;
eccec691 2448#else /* not WINDOWSNT */
cb28b9c2 2449
6548cf00 2450 Wcm_clear (tty);
08a24c47 2451
3a06a6d9 2452 buffer = (char *) xmalloc (buffer_size);
03a1d6bd
KL
2453
2454 /* On some systems, tgetent tries to access the controlling
2455 terminal. */
2456 sigblock (sigmask (SIGTTOU));
08a24c47 2457 status = tgetent (buffer, terminal_type);
03a1d6bd
KL
2458 sigunblock (sigmask (SIGTTOU));
2459
08a24c47 2460 if (status < 0)
b0347178
KH
2461 {
2462#ifdef TERMINFO
6ed8eeff 2463 maybe_fatal (must_succeed, buffer, terminal,
3224dac1
KL
2464 "Cannot open terminfo database file",
2465 "Cannot open terminfo database file");
b0347178 2466#else
6ed8eeff 2467 maybe_fatal (must_succeed, buffer, terminal,
3224dac1
KL
2468 "Cannot open termcap database file",
2469 "Cannot open termcap database file");
b0347178
KH
2470#endif
2471 }
08a24c47 2472 if (status == 0)
b0347178
KH
2473 {
2474#ifdef TERMINFO
6ed8eeff 2475 maybe_fatal (must_succeed, buffer, terminal,
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\
b0347178
KH
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 TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3224dac1 2482 terminal_type);
b0347178 2483#else
6ed8eeff 2484 maybe_fatal (must_succeed, buffer, terminal,
3224dac1
KL
2485 "Terminal type %s is not defined",
2486 "Terminal type %s is not defined.\n\
0a125897 2487If that is not the actual type of terminal you have,\n\
c5a9c3e6
RS
2488use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2489`setenv TERM ...') to specify the correct type. It may be necessary\n\
e12c1054 2490to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3224dac1 2491 terminal_type);
b0347178
KH
2492#endif
2493 }
3a06a6d9 2494
f730033e 2495#ifndef TERMINFO
3a06a6d9 2496 if (strlen (buffer) >= buffer_size)
08a24c47 2497 abort ();
f730033e 2498 buffer_size = strlen (buffer);
3dd3a502 2499#endif
f730033e 2500 area = (char *) xmalloc (buffer_size);
08a24c47 2501
fca177d4
KL
2502 tty->TS_ins_line = tgetstr ("al", address);
2503 tty->TS_ins_multi_lines = tgetstr ("AL", address);
2504 tty->TS_bell = tgetstr ("bl", address);
6548cf00 2505 BackTab (tty) = tgetstr ("bt", address);
fca177d4
KL
2506 tty->TS_clr_to_bottom = tgetstr ("cd", address);
2507 tty->TS_clr_line = tgetstr ("ce", address);
2508 tty->TS_clr_frame = tgetstr ("cl", address);
6548cf00
KL
2509 ColPosition (tty) = NULL; /* tgetstr ("ch", address); */
2510 AbsPosition (tty) = tgetstr ("cm", address);
2511 CR (tty) = tgetstr ("cr", address);
fca177d4
KL
2512 tty->TS_set_scroll_region = tgetstr ("cs", address);
2513 tty->TS_set_scroll_region_1 = tgetstr ("cS", address);
6548cf00 2514 RowPosition (tty) = tgetstr ("cv", address);
fca177d4
KL
2515 tty->TS_del_char = tgetstr ("dc", address);
2516 tty->TS_del_multi_chars = tgetstr ("DC", address);
2517 tty->TS_del_line = tgetstr ("dl", address);
2518 tty->TS_del_multi_lines = tgetstr ("DL", address);
2519 tty->TS_delete_mode = tgetstr ("dm", address);
2520 tty->TS_end_delete_mode = tgetstr ("ed", address);
2521 tty->TS_end_insert_mode = tgetstr ("ei", address);
6548cf00 2522 Home (tty) = tgetstr ("ho", address);
fca177d4
KL
2523 tty->TS_ins_char = tgetstr ("ic", address);
2524 tty->TS_ins_multi_chars = tgetstr ("IC", address);
2525 tty->TS_insert_mode = tgetstr ("im", address);
2526 tty->TS_pad_inserted_char = tgetstr ("ip", address);
2527 tty->TS_end_keypad_mode = tgetstr ("ke", address);
2528 tty->TS_keypad_mode = tgetstr ("ks", address);
6548cf00
KL
2529 LastLine (tty) = tgetstr ("ll", address);
2530 Right (tty) = tgetstr ("nd", address);
2531 Down (tty) = tgetstr ("do", address);
2532 if (!Down (tty))
2533 Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do" */
08a24c47
JB
2534#ifdef VMS
2535 /* VMS puts a carriage return before each linefeed,
2536 so it is not safe to use linefeeds. */
6548cf00
KL
2537 if (Down (tty) && Down (tty)[0] == '\n' && Down (tty)[1] == '\0')
2538 Down (tty) = 0;
08a24c47
JB
2539#endif /* VMS */
2540 if (tgetflag ("bs"))
6548cf00 2541 Left (tty) = "\b"; /* can't possibly be longer! */
08a24c47 2542 else /* (Actually, "bs" is obsolete...) */
6548cf00
KL
2543 Left (tty) = tgetstr ("le", address);
2544 if (!Left (tty))
2545 Left (tty) = tgetstr ("bc", address); /* Obsolete name for "le" */
fca177d4
KL
2546 tty->TS_pad_char = tgetstr ("pc", address);
2547 tty->TS_repeat = tgetstr ("rp", address);
2548 tty->TS_end_standout_mode = tgetstr ("se", address);
2549 tty->TS_fwd_scroll = tgetstr ("sf", address);
2550 tty->TS_standout_mode = tgetstr ("so", address);
2551 tty->TS_rev_scroll = tgetstr ("sr", address);
6548cf00 2552 tty->Wcm->cm_tab = tgetstr ("ta", address);
fca177d4
KL
2553 tty->TS_end_termcap_modes = tgetstr ("te", address);
2554 tty->TS_termcap_modes = tgetstr ("ti", address);
6548cf00 2555 Up (tty) = tgetstr ("up", address);
fca177d4
KL
2556 tty->TS_visible_bell = tgetstr ("vb", address);
2557 tty->TS_cursor_normal = tgetstr ("ve", address);
2558 tty->TS_cursor_visible = tgetstr ("vs", address);
2559 tty->TS_cursor_invisible = tgetstr ("vi", address);
2560 tty->TS_set_window = tgetstr ("wi", address);
2561
2562 tty->TS_enter_underline_mode = tgetstr ("us", address);
2563 tty->TS_exit_underline_mode = tgetstr ("ue", address);
2564 tty->TS_enter_bold_mode = tgetstr ("md", address);
2565 tty->TS_enter_dim_mode = tgetstr ("mh", address);
2566 tty->TS_enter_blink_mode = tgetstr ("mb", address);
2567 tty->TS_enter_reverse_mode = tgetstr ("mr", address);
2568 tty->TS_enter_alt_charset_mode = tgetstr ("as", address);
2569 tty->TS_exit_alt_charset_mode = tgetstr ("ae", address);
2570 tty->TS_exit_attribute_mode = tgetstr ("me", address);
177c0ea7 2571
6548cf00
KL
2572 MultiUp (tty) = tgetstr ("UP", address);
2573 MultiDown (tty) = tgetstr ("DO", address);
2574 MultiLeft (tty) = tgetstr ("LE", address);
2575 MultiRight (tty) = tgetstr ("RI", address);
08a24c47 2576
e7f90eab
GM
2577 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
2578 color because we can't switch back to the default foreground and
2579 background. */
fca177d4
KL
2580 tty->TS_orig_pair = tgetstr ("op", address);
2581 if (tty->TS_orig_pair)
a168702a 2582 {
fca177d4
KL
2583 tty->TS_set_foreground = tgetstr ("AF", address);
2584 tty->TS_set_background = tgetstr ("AB", address);
2585 if (!tty->TS_set_foreground)
e7f90eab
GM
2586 {
2587 /* SVr4. */
fca177d4
KL
2588 tty->TS_set_foreground = tgetstr ("Sf", address);
2589 tty->TS_set_background = tgetstr ("Sb", address);
e7f90eab 2590 }
177c0ea7 2591
fca177d4
KL
2592 tty->TN_max_colors = tgetnum ("Co");
2593 tty->TN_max_pairs = tgetnum ("pa");
177c0ea7 2594
fca177d4
KL
2595 tty->TN_no_color_video = tgetnum ("NC");
2596 if (tty->TN_no_color_video == -1)
2597 tty->TN_no_color_video = 0;
a168702a 2598 }
a168702a 2599
fca177d4 2600 tty_default_color_capabilities (tty, 1);
ace28297 2601
6548cf00 2602 MagicWrap (tty) = tgetflag ("xn");
e4058338
KH
2603 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
2604 the former flag imply the latter. */
6548cf00 2605 AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
6ed8eeff 2606 terminal->memory_below_frame = tgetflag ("db");
fca177d4 2607 tty->TF_hazeltine = tgetflag ("hz");
6ed8eeff 2608 terminal->must_write_spaces = tgetflag ("in");
fca177d4
KL
2609 tty->meta_key = tgetflag ("km") || tgetflag ("MT");
2610 tty->TF_insmode_motion = tgetflag ("mi");
2611 tty->TF_standout_motion = tgetflag ("ms");
2612 tty->TF_underscore = tgetflag ("ul");
2613 tty->TF_teleray = tgetflag ("xt");
08a24c47 2614
e7cf0fa0 2615#ifdef MULTI_KBOARD
6ed8eeff
KL
2616 terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
2617 init_kboard (terminal->kboard);
2618 terminal->kboard->next_kboard = all_kboards;
2619 all_kboards = terminal->kboard;
2620 terminal->kboard->reference_count++;
e7cf0fa0
KL
2621 /* Don't let the initial kboard remain current longer than necessary.
2622 That would cause problems if a file loaded on startup tries to
2623 prompt in the mini-buffer. */
2624 if (current_kboard == initial_kboard)
6ed8eeff 2625 current_kboard = terminal->kboard;
e7cf0fa0
KL
2626#endif
2627
6ed8eeff 2628 term_get_fkeys (address, terminal->kboard);
5c2c7893 2629
ff11dfa1 2630 /* Get frame size from system, or else from termcap. */
3b12ce12
RS
2631 {
2632 int height, width;
0b0d3e0b 2633 get_tty_size (fileno (tty->input), &width, &height);
0a125897
KL
2634 FrameCols (tty) = width;
2635 FrameRows (tty) = height;
3b12ce12
RS
2636 }
2637
0a125897
KL
2638 if (FrameCols (tty) <= 0)
2639 FrameCols (tty) = tgetnum ("co");
2640 if (FrameRows (tty) <= 0)
2641 FrameRows (tty) = tgetnum ("li");
177c0ea7 2642
0a125897 2643 if (FrameRows (tty) < 3 || FrameCols (tty) < 3)
6ed8eeff 2644 maybe_fatal (must_succeed, NULL, terminal,
3224dac1
KL
2645 "Screen size %dx%d is too small"
2646 "Screen size %dx%d is too small",
0a125897 2647 FrameCols (tty), FrameRows (tty));
ee7a2de4 2648
8a56675d 2649#if 0 /* This is not used anywhere. */
6ed8eeff 2650 tty->terminal->min_padding_speed = tgetnum ("pb");
8a56675d 2651#endif
28d440ab 2652
6548cf00 2653 TabWidth (tty) = tgetnum ("tw");
08a24c47
JB
2654
2655#ifdef VMS
2656 /* These capabilities commonly use ^J.
2657 I don't know why, but sending them on VMS does not work;
2658 it causes following spaces to be lost, sometimes.
2659 For now, the simplest fix is to avoid using these capabilities ever. */
6548cf00
KL
2660 if (Down (tty) && Down (tty)[0] == '\n')
2661 Down (tty) = 0;
08a24c47
JB
2662#endif /* VMS */
2663
fca177d4
KL
2664 if (!tty->TS_bell)
2665 tty->TS_bell = "\07";
08a24c47 2666
fca177d4
KL
2667 if (!tty->TS_fwd_scroll)
2668 tty->TS_fwd_scroll = Down (tty);
08a24c47 2669
fca177d4 2670 PC = tty->TS_pad_char ? *tty->TS_pad_char : 0;
08a24c47 2671
6548cf00
KL
2672 if (TabWidth (tty) < 0)
2673 TabWidth (tty) = 8;
177c0ea7 2674
08a24c47
JB
2675/* Turned off since /etc/termcap seems to have :ta= for most terminals
2676 and newer termcap doc does not seem to say there is a default.
6548cf00
KL
2677 if (!tty->Wcm->cm_tab)
2678 tty->Wcm->cm_tab = "\t";
08a24c47
JB
2679*/
2680
54800acb
MB
2681 /* We don't support standout modes that use `magic cookies', so
2682 turn off any that do. */
fca177d4 2683 if (tty->TS_standout_mode && tgetnum ("sg") >= 0)
54800acb 2684 {
fca177d4
KL
2685 tty->TS_standout_mode = 0;
2686 tty->TS_end_standout_mode = 0;
54800acb 2687 }
fca177d4 2688 if (tty->TS_enter_underline_mode && tgetnum ("ug") >= 0)
54800acb 2689 {
fca177d4
KL
2690 tty->TS_enter_underline_mode = 0;
2691 tty->TS_exit_underline_mode = 0;
54800acb
MB
2692 }
2693
2694 /* If there's no standout mode, try to use underlining instead. */
fca177d4 2695 if (tty->TS_standout_mode == 0)
08a24c47 2696 {
fca177d4
KL
2697 tty->TS_standout_mode = tty->TS_enter_underline_mode;
2698 tty->TS_end_standout_mode = tty->TS_exit_underline_mode;
08a24c47
JB
2699 }
2700
afd359c4
RS
2701 /* If no `se' string, try using a `me' string instead.
2702 If that fails, we can't use standout mode at all. */
fca177d4 2703 if (tty->TS_end_standout_mode == 0)
afd359c4 2704 {
e4bfb3b6 2705 char *s = tgetstr ("me", address);
afd359c4 2706 if (s != 0)
fca177d4 2707 tty->TS_end_standout_mode = s;
afd359c4 2708 else
fca177d4 2709 tty->TS_standout_mode = 0;
afd359c4
RS
2710 }
2711
fca177d4 2712 if (tty->TF_teleray)
08a24c47 2713 {
6548cf00 2714 tty->Wcm->cm_tab = 0;
54800acb 2715 /* We can't support standout mode, because it uses magic cookies. */
fca177d4 2716 tty->TS_standout_mode = 0;
08a24c47 2717 /* But that means we cannot rely on ^M to go to column zero! */
6548cf00 2718 CR (tty) = 0;
08a24c47
JB
2719 /* LF can't be trusted either -- can alter hpos */
2720 /* if move at column 0 thru a line with TS_standout_mode */
6548cf00 2721 Down (tty) = 0;
08a24c47
JB
2722 }
2723
2724 /* Special handling for certain terminal types known to need it */
2725
2726 if (!strcmp (terminal_type, "supdup"))
2727 {
6ed8eeff 2728 terminal->memory_below_frame = 1;
6548cf00 2729 tty->Wcm->cm_losewrap = 1;
08a24c47
JB
2730 }
2731 if (!strncmp (terminal_type, "c10", 3)
2732 || !strcmp (terminal_type, "perq"))
2733 {
2734 /* Supply a makeshift :wi string.
2735 This string is not valid in general since it works only
2736 for windows starting at the upper left corner;
2737 but that is all Emacs uses.
daf01701 2738
ff11dfa1 2739 This string works only if the frame is using
08a24c47
JB
2740 the top of the video memory, because addressing is memory-relative.
2741 So first check the :ti string to see if that is true.
2742
2743 It would be simpler if the :wi string could go in the termcap
2744 entry, but it can't because it is not fully valid.
2745 If it were in the termcap entry, it would confuse other programs. */
fca177d4 2746 if (!tty->TS_set_window)
08a24c47 2747 {
fca177d4 2748 p = tty->TS_termcap_modes;
08a24c47
JB
2749 while (*p && strcmp (p, "\033v "))
2750 p++;
2751 if (*p)
fca177d4 2752 tty->TS_set_window = "\033v%C %C %C %C ";
08a24c47
JB
2753 }
2754 /* Termcap entry often fails to have :in: flag */
6ed8eeff 2755 terminal->must_write_spaces = 1;
08a24c47
JB
2756 /* :ti string typically fails to have \E^G! in it */
2757 /* This limits scope of insert-char to one line. */
fca177d4 2758 strcpy (area, tty->TS_termcap_modes);
08a24c47 2759 strcat (area, "\033\007!");
fca177d4 2760 tty->TS_termcap_modes = area;
08a24c47 2761 area += strlen (area) + 1;
6548cf00 2762 p = AbsPosition (tty);
08a24c47 2763 /* Change all %+ parameters to %C, to handle
28d440ab 2764 values above 96 correctly for the C100. */
08a24c47 2765 while (*p)
28d440ab
KL
2766 {
2767 if (p[0] == '%' && p[1] == '+')
2768 p[1] = 'C';
2769 p++;
2770 }
08a24c47
JB
2771 }
2772
0a125897 2773 tty->specified_window = FrameRows (tty);
08a24c47 2774
6548cf00 2775 if (Wcm_init (tty) == -1) /* can't do cursor motion */
3224dac1 2776 {
6ed8eeff 2777 maybe_fatal (must_succeed, NULL, terminal,
3224dac1 2778 "Terminal type \"%s\" is not powerful enough to run Emacs",
08a24c47 2779#ifdef VMS
3224dac1 2780 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
08a24c47
JB
2781It lacks the ability to position the cursor.\n\
2782If that is not the actual type of terminal you have, use either the\n\
2783DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
e12c1054 2784or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
37dad45a
RS
2785#else /* not VMS */
2786# ifdef TERMINFO
3224dac1 2787 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
0a125897
KL
2788It lacks the ability to position the cursor.\n\
2789If that is not the actual type of terminal you have,\n\
37dad45a
RS
2790use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2791`setenv TERM ...') to specify the correct type. It may be necessary\n\
e12c1054 2792to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
37dad45a 2793# else /* TERMCAP */
3224dac1 2794 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
0a125897 2795It lacks the ability to position the cursor.\n\
08a24c47 2796If that is not the actual type of terminal you have,\n\
c5a9c3e6
RS
2797use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2798`setenv TERM ...') to specify the correct type. It may be necessary\n\
e12c1054 2799to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
37dad45a
RS
2800# endif /* TERMINFO */
2801#endif /*VMS */
3224dac1 2802 terminal_type);
fca177d4 2803 }
daf01701 2804
0a125897 2805 if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
6ed8eeff 2806 maybe_fatal (must_succeed, NULL, terminal,
3224dac1
KL
2807 "Could not determine the frame size",
2808 "Could not determine the frame size");
08a24c47 2809
fca177d4
KL
2810 tty->delete_in_insert_mode
2811 = tty->TS_delete_mode && tty->TS_insert_mode
2812 && !strcmp (tty->TS_delete_mode, tty->TS_insert_mode);
08a24c47 2813
fca177d4
KL
2814 tty->se_is_so = (tty->TS_standout_mode
2815 && tty->TS_end_standout_mode
2816 && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode));
08a24c47 2817
0b0d3e0b 2818 UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8;
08a24c47 2819
6ed8eeff 2820 terminal->scroll_region_ok
6548cf00 2821 = (tty->Wcm->cm_abs
fca177d4 2822 && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
08a24c47 2823
6ed8eeff 2824 terminal->line_ins_del_ok
fca177d4
KL
2825 = (((tty->TS_ins_line || tty->TS_ins_multi_lines)
2826 && (tty->TS_del_line || tty->TS_del_multi_lines))
6ed8eeff 2827 || (terminal->scroll_region_ok
fca177d4 2828 && tty->TS_fwd_scroll && tty->TS_rev_scroll));
28d440ab 2829
6ed8eeff 2830 terminal->char_ins_del_ok
fca177d4
KL
2831 = ((tty->TS_ins_char || tty->TS_insert_mode
2832 || tty->TS_pad_inserted_char || tty->TS_ins_multi_chars)
2833 && (tty->TS_del_char || tty->TS_del_multi_chars));
8a56675d 2834
6ed8eeff 2835 terminal->fast_clear_end_of_line = tty->TS_clr_line != 0;
08a24c47 2836
0b0d3e0b 2837 init_baud_rate (fileno (tty->input));
20a558dc 2838
daf01701
KL
2839#ifdef AIXHFT
2840 /* The HFT system on AIX doesn't optimize for scrolling, so it's
2841 really ugly at times. */
6ed8eeff
KL
2842 terminal->line_ins_del_ok = 0;
2843 terminal->char_ins_del_ok = 0;
daf01701
KL
2844#endif
2845
0a125897
KL
2846 /* Don't do this. I think termcap may still need the buffer. */
2847 /* xfree (buffer); */
28d440ab 2848
0a125897
KL
2849 /* Init system terminal modes (RAW or CBREAK, etc.). */
2850 init_sys_modes (tty);
daf01701 2851
6ed8eeff 2852 return terminal;
7b00d185 2853#endif /* not WINDOWSNT */
08a24c47
JB
2854}
2855
a4c6993d 2856/* Auxiliary error-handling function for init_tty.
6ed8eeff 2857 Free BUFFER and delete TERMINAL, then call error or fatal
da8e1115
KL
2858 with str1 or str2, respectively, according to MUST_SUCCEED. */
2859
3224dac1 2860static void
6ed8eeff 2861maybe_fatal (must_succeed, buffer, terminal, str1, str2, arg1, arg2)
3224dac1
KL
2862 int must_succeed;
2863 char *buffer;
6ed8eeff 2864 struct terminal *terminal;
3224dac1
KL
2865 char *str1, *str2, *arg1, *arg2;
2866{
2867 if (buffer)
2868 xfree (buffer);
2869
6ed8eeff
KL
2870 if (terminal)
2871 delete_tty (terminal);
3224dac1
KL
2872
2873 if (must_succeed)
2874 fatal (str2, arg1, arg2);
2875 else
2876 error (str1, arg1, arg2);
2877
2878 abort ();
2879}
2880
08a24c47 2881/* VARARGS 1 */
dfcf069d 2882void
08a24c47 2883fatal (str, arg1, arg2)
4746118a 2884 char *str, *arg1, *arg2;
08a24c47
JB
2885{
2886 fprintf (stderr, "emacs: ");
2887 fprintf (stderr, str, arg1, arg2);
e12c1054 2888 fprintf (stderr, "\n");
08a24c47
JB
2889 fflush (stderr);
2890 exit (1);
2891}
07c57952 2892
819b8f00
KL
2893\f
2894
0a125897
KL
2895static int deleting_tty = 0;
2896
da8e1115 2897
6ed8eeff 2898/* Delete the given tty terminal, closing all frames on it. */
da8e1115 2899
ed8dad6b 2900static void
6ed8eeff 2901delete_tty (struct terminal *terminal)
fca177d4 2902{
428a555e 2903 struct tty_display_info *tty;
fca177d4 2904 Lisp_Object tail, frame;
4d553a13 2905 char *tty_name;
6ed8eeff 2906 int last_terminal;
4d553a13 2907
0a125897
KL
2908 if (deleting_tty)
2909 /* We get a recursive call when we delete the last frame on this
6ed8eeff 2910 terminal. */
0a125897 2911 return;
fca177d4 2912
6ed8eeff 2913 if (terminal->type != output_termcap)
428a555e
KL
2914 abort ();
2915
6ed8eeff 2916 tty = terminal->display_info.tty;
428a555e 2917
6ed8eeff 2918 last_terminal = 1;
81be1a93
KL
2919 FOR_EACH_FRAME (tail, frame)
2920 {
2921 struct frame *f = XFRAME (frame);
2922 if (FRAME_LIVE_P (f) && (!FRAME_TERMCAP_P (f) || FRAME_TTY (f) != tty))
2923 {
6ed8eeff 2924 last_terminal = 0;
81be1a93
KL
2925 break;
2926 }
2927 }
6ed8eeff
KL
2928 if (last_terminal)
2929 error ("Attempt to delete the sole terminal device with live frames");
81be1a93 2930
fca177d4
KL
2931 if (tty == tty_list)
2932 tty_list = tty->next;
2933 else
2934 {
28d7d09f 2935 struct tty_display_info *p;
fca177d4
KL
2936 for (p = tty_list; p && p->next != tty; p = p->next)
2937 ;
2938
2939 if (! p)
2940 /* This should not happen. */
2941 abort ();
2942
0a125897
KL
2943 p->next = tty->next;
2944 tty->next = 0;
fca177d4
KL
2945 }
2946
81be1a93
KL
2947 deleting_tty = 1;
2948
04c3243c
KL
2949 FOR_EACH_FRAME (tail, frame)
2950 {
2951 struct frame *f = XFRAME (frame);
daf01701 2952 if (FRAME_TERMCAP_P (f) && FRAME_LIVE_P (f) && FRAME_TTY (f) == tty)
04c3243c
KL
2953 {
2954 Fdelete_frame (frame, Qt);
04c3243c
KL
2955 }
2956 }
daf01701 2957
7e59217d 2958 /* reset_sys_modes needs a valid device, so this call needs to be
6ed8eeff 2959 before delete_terminal. */
04c3243c 2960 reset_sys_modes (tty);
fca177d4 2961
6ed8eeff 2962 delete_terminal (terminal);
3224dac1 2963
4d553a13 2964 tty_name = tty->name;
fca177d4
KL
2965 if (tty->type)
2966 xfree (tty->type);
daf01701 2967
fca177d4 2968 if (tty->input)
819b8f00
KL
2969 {
2970 delete_keyboard_wait_descriptor (fileno (tty->input));
2971 if (tty->input != stdin)
2972 fclose (tty->input);
2973 }
2974 if (tty->output && tty->output != stdout && tty->output != tty->input)
fca177d4
KL
2975 fclose (tty->output);
2976 if (tty->termscript)
2977 fclose (tty->termscript);
daf01701 2978
fca177d4 2979 if (tty->old_tty)
0a125897 2980 xfree (tty->old_tty);
fca177d4 2981
0a125897 2982 if (tty->Wcm)
daf01701
KL
2983 xfree (tty->Wcm);
2984
28d7d09f 2985 bzero (tty, sizeof (struct tty_display_info));
fca177d4 2986 xfree (tty);
0a125897 2987 deleting_tty = 0;
fca177d4
KL
2988}
2989
428a555e
KL
2990\f
2991
28d7d09f 2992/* Mark the pointers in the tty_display_info objects.
819b8f00 2993 Called by the Fgarbage_collector. */
da8e1115 2994
fca177d4 2995void
ed8dad6b 2996mark_ttys (void)
fca177d4 2997{
28d7d09f 2998 struct tty_display_info *tty;
0c72d684 2999
819b8f00 3000 for (tty = tty_list; tty; tty = tty->next)
fca177d4 3001 {
819b8f00
KL
3002 if (tty->top_frame)
3003 mark_object (tty->top_frame);
fca177d4
KL
3004 }
3005}
3006
428a555e
KL
3007\f
3008
819b8f00
KL
3009void
3010syms_of_term ()
3011{
3012 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
3013 doc: /* Non-nil means the system uses terminfo rather than termcap.
3014This variable can be used by terminal emulator packages. */);
3015#ifdef TERMINFO
3016 system_uses_terminfo = 1;
3017#else
3018 system_uses_terminfo = 0;
3019#endif
3020
0b0d3e0b
KL
3021 DEFVAR_LISP ("suspend-tty-functions", &Vsuspend_tty_functions,
3022 doc: /* Functions to be run after suspending a tty.
3023The functions are run with one argument, the name of the tty to be suspended.
3024See `suspend-tty'. */);
3025 Vsuspend_tty_functions = Qnil;
3026
3027
3028 DEFVAR_LISP ("resume-tty-functions", &Vresume_tty_functions,
3029 doc: /* Functions to be run after resuming a tty.
3030The functions are run with one argument, the name of the tty that was revived.
3031See `resume-tty'. */);
3032 Vresume_tty_functions = Qnil;
3033
819b8f00
KL
3034 defsubr (&Stty_display_color_p);
3035 defsubr (&Stty_display_color_cells);
072d84a6 3036 defsubr (&Stty_no_underline);
6ed8eeff
KL
3037 defsubr (&Stty_type);
3038 defsubr (&Scontrolling_tty_p);
0b0d3e0b
KL
3039 defsubr (&Ssuspend_tty);
3040 defsubr (&Sresume_tty);
819b8f00
KL
3041}
3042
3043
3044
ab5796a9
MB
3045/* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193
3046 (do not change this comment) */