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