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