(access_keymap): Remove the value 2 for t_ok which was used
[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,
8cabe764
GM
3 2002, 2003, 2004, 2005, 2006, 2007, 2008
4 Free Software Foundation, Inc.
08a24c47
JB
5
6This file is part of GNU Emacs.
7
8GNU Emacs is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
684d6f5b 10the Free Software Foundation; either version 3, or (at your option)
08a24c47
JB
11any later version.
12
13GNU Emacs is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with GNU Emacs; see the file COPYING. If not, write to
4fc5845f
LK
20the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21Boston, MA 02110-1301, USA. */
08a24c47 22
d284f58f 23/* New redisplay, TTY faces by Gerd Moellmann <gerd@gnu.org>. */
08a24c47 24
565620a5 25#include <config.h>
08a24c47
JB
26#include <stdio.h>
27#include <ctype.h>
a168702a 28#include <string.h>
59b3194c 29#include <errno.h>
28d440ab 30#include <sys/file.h>
7eb1e453 31
d8b18043 32#ifdef HAVE_UNISTD_H
1ec5dc77 33#include <unistd.h>
d8b18043 34#endif
7ee72033 35
67ad74df
KL
36#if HAVE_TERMIOS_H
37#include <termios.h> /* For TIOCNOTTY. */
38#endif
03a1d6bd
KL
39
40#include <signal.h>
7c401d15 41#include <stdarg.h>
0c72d684 42
9628b887 43#include "lisp.h"
08a24c47
JB
44#include "termchar.h"
45#include "termopts.h"
9332ea03
KH
46#include "buffer.h"
47#include "character.h"
a4decb7f
KH
48#include "charset.h"
49#include "coding.h"
4c12d738 50#include "composite.h"
2538fae4 51#include "keyboard.h"
ff11dfa1 52#include "frame.h"
08a24c47
JB
53#include "disptab.h"
54#include "termhooks.h"
dfcf069d 55#include "dispextern.h"
a168702a 56#include "window.h"
8feddab4 57#include "keymap.h"
1a935bfd 58#include "blockinput.h"
03a1d6bd
KL
59#include "syssignal.h"
60#include "systty.h"
c9612b8e 61#include "intervals.h"
a168702a 62
ff23e1dd
GM
63/* For now, don't try to include termcap.h. On some systems,
64 configure finds a non-standard termcap.h that the main build
65 won't find. */
66
67#if defined HAVE_TERMCAP_H && 0
b0f61f15 68#include <termcap.h>
46d1b2bc
DL
69#else
70extern void tputs P_ ((const char *, int, int (*)(int)));
71extern int tgetent P_ ((char *, const char *));
72extern int tgetflag P_ ((char *id));
73extern int tgetnum P_ ((char *id));
b0f61f15
GM
74#endif
75
eccec691 76#include "cm.h"
dfcf069d
AS
77#ifdef HAVE_X_WINDOWS
78#include "xterm.h"
79#endif
e0f712ba 80#ifdef MAC_OS
1a578e9b
AC
81#include "macterm.h"
82#endif
c8951b18 83
28d440ab
KL
84#ifndef O_RDWR
85#define O_RDWR 2
86#endif
6b61353c 87
0c72d684
KL
88#ifndef O_NOCTTY
89#define O_NOCTTY 0
90#endif
6b61353c 91
78048085
EZ
92/* The name of the default console device. */
93#ifdef WINDOWSNT
94#define DEV_TTY "CONOUT$"
95#else
96#define DEV_TTY "/dev/tty"
97#endif
a168702a 98
ed8dad6b 99static void tty_set_scroll_region P_ ((struct frame *f, int start, int stop));
a168702a
GM
100static void turn_on_face P_ ((struct frame *, int face_id));
101static void turn_off_face P_ ((struct frame *, int face_id));
28d7d09f
KL
102static void tty_show_cursor P_ ((struct tty_display_info *));
103static void tty_hide_cursor P_ ((struct tty_display_info *));
ed8dad6b 104static void tty_background_highlight P_ ((struct tty_display_info *tty));
4a665758
KL
105static void clear_tty_hooks P_ ((struct terminal *terminal));
106static void set_tty_hooks P_ ((struct terminal *terminal));
ed8dad6b 107static void dissociate_if_controlling_tty P_ ((int fd));
6ed8eeff 108static void delete_tty P_ ((struct terminal *));
a168702a 109
6548cf00
KL
110#define OUTPUT(tty, a) \
111 emacs_tputs ((tty), a, \
112 (int) (FRAME_LINES (XFRAME (selected_frame)) \
113 - curY (tty)), \
114 cmputc)
115
28d440ab
KL
116#define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
117#define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
a168702a 118
28d440ab 119#define OUTPUT_IF(tty, a) \
6548cf00
KL
120 do { \
121 if (a) \
122 emacs_tputs ((tty), a, \
123 (int) (FRAME_LINES (XFRAME (selected_frame)) \
124 - curY (tty) ), \
125 cmputc); \
126 } while (0)
177c0ea7 127
28d440ab 128#define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
c291d9ef 129
0db017c0
SM
130/* If true, use "vs", otherwise use "ve" to make the cursor visible. */
131
132static int visible_cursor;
133
f46c2aff 134/* Display space properties */
08a24c47 135
f46c2aff 136extern Lisp_Object Qspace, QCalign_to, QCwidth;
08a24c47 137
0b0d3e0b 138/* Functions to call after suspending a tty. */
e4019195 139Lisp_Object Vsuspend_tty_functions;
08a24c47 140
0b0d3e0b 141/* Functions to call after resuming a tty. */
e4019195 142Lisp_Object Vresume_tty_functions;
08a24c47 143
428a555e 144/* Chain of all tty device parameters. */
28d7d09f 145struct tty_display_info *tty_list;
08a24c47 146
fca177d4
KL
147/* Nonzero means no need to redraw the entire frame on resuming a
148 suspended Emacs. This is useful on terminals with multiple
149 pages, where one page is used for Emacs and another for all
150 else. */
08a24c47 151int no_redraw_on_reenter;
4e6ba4a4
GM
152
153/* Meaning of bits in no_color_video. Each bit set means that the
154 corresponding attribute cannot be combined with colors. */
155
156enum no_color_bit
157{
158 NC_STANDOUT = 1 << 0,
159 NC_UNDERLINE = 1 << 1,
160 NC_REVERSE = 1 << 2,
161 NC_BLINK = 1 << 3,
162 NC_DIM = 1 << 4,
163 NC_BOLD = 1 << 5,
164 NC_INVIS = 1 << 6,
165 NC_PROTECT = 1 << 7,
166 NC_ALT_CHARSET = 1 << 8
167};
168
08a24c47
JB
169/* internal state */
170
8dd0c7cb 171/* The largest frame width in any call to calculate_costs. */
a168702a 172
9882535b 173int max_frame_cols;
a168702a 174
8dd0c7cb 175/* The largest frame height in any call to calculate_costs. */
a168702a 176
9882535b 177int max_frame_lines;
8dd0c7cb 178
0c72d684
KL
179/* Non-zero if we have dropped our controlling tty and therefore
180 should not open a frame on stdout. */
181static int no_controlling_tty;
08a24c47 182
07c57952 183/* Provided for lisp packages. */
a168702a 184
07c57952
KH
185static int system_uses_terminfo;
186
08a24c47 187char *tparam ();
e4bfb3b6
RS
188
189extern char *tgetstr ();
08a24c47 190\f
cb28b9c2 191
7e5a23bd 192#ifdef HAVE_GPM
e882229c 193#include <sys/fcntl.h>
e882229c 194
b870aa61
SM
195static void term_clear_mouse_face ();
196static void term_mouse_highlight (struct frame *f, int x, int y);
197
71f44e7a
SM
198/* The device for which we have enabled gpm support (or NULL). */
199struct tty_display_info *gpm_tty = NULL;
e882229c
NR
200
201/* These variables describe the range of text currently shown in its
202 mouse-face, together with the window they apply to. As long as
203 the mouse stays within this range, we need not redraw anything on
204 its account. Rows and columns are glyph matrix positions in
205 MOUSE_FACE_WINDOW. */
206static int mouse_face_beg_row, mouse_face_beg_col;
207static int mouse_face_end_row, mouse_face_end_col;
208static int mouse_face_past_end;
6178ce5e 209static Lisp_Object mouse_face_window;
e882229c
NR
210static int mouse_face_face_id;
211
e882229c
NR
212static int pos_x, pos_y;
213static int last_mouse_x, last_mouse_y;
7e5a23bd 214#endif /* HAVE_GPM */
e882229c 215
da8e1115 216/* Ring the bell on a tty. */
c291d9ef 217
ed8dad6b 218static void
385ed61f 219tty_ring_bell (struct frame *f)
3224dac1 220{
3224dac1 221 struct tty_display_info *tty = FRAME_TTY (f);
c291d9ef 222
b6660415
KL
223 if (tty->output)
224 {
225 OUTPUT (tty, (tty->TS_visible_bell && visible_bell
226 ? tty->TS_visible_bell
227 : tty->TS_bell));
228 fflush (tty->output);
08a24c47 229 }
08a24c47
JB
230}
231
da8e1115
KL
232/* Set up termcap modes for Emacs. */
233
dfcf069d 234void
6ed8eeff 235tty_set_terminal_modes (struct terminal *terminal)
08a24c47 236{
6ed8eeff 237 struct tty_display_info *tty = terminal->display_info.tty;
f4d953fc 238
0b0d3e0b 239 if (tty->output)
08a24c47 240 {
fbf34973
KL
241 if (tty->TS_termcap_modes)
242 OUTPUT (tty, tty->TS_termcap_modes);
3ae9c96a 243 else
fbf34973
KL
244 {
245 /* Output enough newlines to scroll all the old screen contents
246 off the screen, so it won't be overwritten and lost. */
247 int i;
a3c07f68 248 current_tty = tty;
fbf34973 249 for (i = 0; i < FRAME_LINES (XFRAME (selected_frame)); i++)
a3c07f68 250 cmputc ('\n');
fbf34973
KL
251 }
252
0b0d3e0b 253 OUTPUT_IF (tty, tty->TS_termcap_modes);
b58cb614 254 OUTPUT_IF (tty, visible_cursor ? tty->TS_cursor_visible : tty->TS_cursor_normal);
0b0d3e0b
KL
255 OUTPUT_IF (tty, tty->TS_keypad_mode);
256 losecursor (tty);
2f98e6e3 257 fflush (tty->output);
08a24c47 258 }
08a24c47
JB
259}
260
da8e1115
KL
261/* Reset termcap modes before exiting Emacs. */
262
dfcf069d 263void
6ed8eeff 264tty_reset_terminal_modes (struct terminal *terminal)
08a24c47 265{
6ed8eeff 266 struct tty_display_info *tty = terminal->display_info.tty;
0b0d3e0b
KL
267
268 if (tty->output)
08a24c47 269 {
ed8dad6b
KL
270 tty_turn_off_highlight (tty);
271 tty_turn_off_insert (tty);
0b0d3e0b
KL
272 OUTPUT_IF (tty, tty->TS_end_keypad_mode);
273 OUTPUT_IF (tty, tty->TS_cursor_normal);
274 OUTPUT_IF (tty, tty->TS_end_termcap_modes);
275 OUTPUT_IF (tty, tty->TS_orig_pair);
d284f58f 276 /* Output raw CR so kernel can track the cursor hpos. */
0b0d3e0b 277 current_tty = tty;
d284f58f 278 cmputc ('\r');
2f98e6e3 279 fflush (tty->output);
08a24c47 280 }
08a24c47
JB
281}
282
6ed8eeff 283/* Flag the end of a display update on a termcap terminal. */
08a24c47 284
ed8dad6b 285static void
3224dac1 286tty_update_end (struct frame *f)
08a24c47 287{
3224dac1 288 struct tty_display_info *tty = FRAME_TTY (f);
177c0ea7 289
3224dac1
KL
290 if (!XWINDOW (selected_window)->cursor_off_p)
291 tty_show_cursor (tty);
ed8dad6b
KL
292 tty_turn_off_insert (tty);
293 tty_background_highlight (tty);
08a24c47
JB
294}
295
da8e1115
KL
296/* The implementation of set_terminal_window for termcap frames. */
297
ed8dad6b 298static void
385ed61f 299tty_set_terminal_window (struct frame *f, int size)
08a24c47 300{
3224dac1
KL
301 struct tty_display_info *tty = FRAME_TTY (f);
302
303 tty->specified_window = size ? size : FRAME_LINES (f);
304 if (FRAME_SCROLL_REGION_OK (f))
ed8dad6b 305 tty_set_scroll_region (f, 0, tty->specified_window);
08a24c47
JB
306}
307
ed8dad6b
KL
308static void
309tty_set_scroll_region (struct frame *f, int start, int stop)
08a24c47
JB
310{
311 char *buf;
28d7d09f 312 struct tty_display_info *tty = FRAME_TTY (f);
177c0ea7 313
fca177d4
KL
314 if (tty->TS_set_scroll_region)
315 buf = tparam (tty->TS_set_scroll_region, 0, 0, start, stop - 1);
316 else if (tty->TS_set_scroll_region_1)
317 buf = tparam (tty->TS_set_scroll_region_1, 0, 0,
ed02974b
KL
318 FRAME_LINES (f), start,
319 FRAME_LINES (f) - stop,
320 FRAME_LINES (f));
08a24c47 321 else
fca177d4 322 buf = tparam (tty->TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (f));
177c0ea7 323
6548cf00 324 OUTPUT (tty, buf);
9ac0d9e0 325 xfree (buf);
6548cf00 326 losecursor (tty);
08a24c47 327}
d284f58f 328
08a24c47 329\f
d284f58f 330static void
ed8dad6b 331tty_turn_on_insert (struct tty_display_info *tty)
08a24c47 332{
fca177d4
KL
333 if (!tty->insert_mode)
334 OUTPUT (tty, tty->TS_insert_mode);
335 tty->insert_mode = 1;
08a24c47
JB
336}
337
dfcf069d 338void
ed8dad6b 339tty_turn_off_insert (struct tty_display_info *tty)
08a24c47 340{
fca177d4
KL
341 if (tty->insert_mode)
342 OUTPUT (tty, tty->TS_end_insert_mode);
343 tty->insert_mode = 0;
08a24c47
JB
344}
345\f
54800acb 346/* Handle highlighting. */
08a24c47 347
dfcf069d 348void
ed8dad6b 349tty_turn_off_highlight (struct tty_display_info *tty)
08a24c47 350{
fca177d4
KL
351 if (tty->standout_mode)
352 OUTPUT_IF (tty, tty->TS_end_standout_mode);
353 tty->standout_mode = 0;
08a24c47
JB
354}
355
d284f58f 356static void
ed8dad6b 357tty_turn_on_highlight (struct tty_display_info *tty)
08a24c47 358{
fca177d4
KL
359 if (!tty->standout_mode)
360 OUTPUT_IF (tty, tty->TS_standout_mode);
361 tty->standout_mode = 1;
08a24c47
JB
362}
363
86a7d192 364static void
ed8dad6b 365tty_toggle_highlight (struct tty_display_info *tty)
86a7d192 366{
fca177d4 367 if (tty->standout_mode)
ed8dad6b 368 tty_turn_off_highlight (tty);
86a7d192 369 else
ed8dad6b 370 tty_turn_on_highlight (tty);
86a7d192
GM
371}
372
a168702a
GM
373
374/* Make cursor invisible. */
375
376static void
28d7d09f 377tty_hide_cursor (struct tty_display_info *tty)
a168702a 378{
fca177d4 379 if (tty->cursor_hidden == 0)
d284f58f 380 {
fca177d4
KL
381 tty->cursor_hidden = 1;
382 OUTPUT_IF (tty, tty->TS_cursor_invisible);
d284f58f 383 }
a168702a
GM
384}
385
386
387/* Ensure that cursor is visible. */
388
389static void
28d7d09f 390tty_show_cursor (struct tty_display_info *tty)
a168702a 391{
fca177d4 392 if (tty->cursor_hidden)
d284f58f 393 {
fca177d4
KL
394 tty->cursor_hidden = 0;
395 OUTPUT_IF (tty, tty->TS_cursor_normal);
0db017c0 396 if (visible_cursor)
b58cb614 397 OUTPUT_IF (tty, tty->TS_cursor_visible);
d284f58f 398 }
a168702a
GM
399}
400
401
08a24c47
JB
402/* Set standout mode to the state it should be in for
403 empty space inside windows. What this is,
404 depends on the user option inverse-video. */
405
ed8dad6b
KL
406static void
407tty_background_highlight (struct tty_display_info *tty)
08a24c47 408{
08a24c47 409 if (inverse_video)
ed8dad6b 410 tty_turn_on_highlight (tty);
08a24c47 411 else
ed8dad6b 412 tty_turn_off_highlight (tty);
08a24c47
JB
413}
414
415/* Set standout mode to the mode specified for the text to be output. */
416
dfcf069d 417static void
ed8dad6b 418tty_highlight_if_desired (struct tty_display_info *tty)
08a24c47 419{
8ede64a5 420 if (inverse_video)
ed8dad6b 421 tty_turn_on_highlight (tty);
8ede64a5 422 else
ed8dad6b 423 tty_turn_off_highlight (tty);
08a24c47
JB
424}
425\f
426
a168702a
GM
427/* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
428 frame-relative coordinates. */
08a24c47 429
ed8dad6b 430static void
385ed61f 431tty_cursor_to (struct frame *f, int vpos, int hpos)
08a24c47 432{
3224dac1 433 struct tty_display_info *tty = FRAME_TTY (f);
08a24c47 434
36cae867
KH
435 /* Detect the case where we are called from reset_sys_modes
436 and the costs have never been calculated. Do nothing. */
fca177d4 437 if (! tty->costs_set)
36cae867
KH
438 return;
439
6548cf00
KL
440 if (curY (tty) == vpos
441 && curX (tty) == hpos)
08a24c47 442 return;
fca177d4 443 if (!tty->TF_standout_motion)
ed8dad6b 444 tty_background_highlight (tty);
fca177d4 445 if (!tty->TF_insmode_motion)
ed8dad6b 446 tty_turn_off_insert (tty);
6548cf00 447 cmgoto (tty, vpos, hpos);
08a24c47
JB
448}
449
450/* Similar but don't take any account of the wasted characters. */
451
ed8dad6b 452static void
385ed61f 453tty_raw_cursor_to (struct frame *f, int row, int col)
08a24c47 454{
3224dac1
KL
455 struct tty_display_info *tty = FRAME_TTY (f);
456
6548cf00
KL
457 if (curY (tty) == row
458 && curX (tty) == col)
08a24c47 459 return;
fca177d4 460 if (!tty->TF_standout_motion)
ed8dad6b 461 tty_background_highlight (tty);
fca177d4 462 if (!tty->TF_insmode_motion)
ed8dad6b 463 tty_turn_off_insert (tty);
6548cf00 464 cmgoto (tty, row, col);
08a24c47
JB
465}
466\f
467/* Erase operations */
468
da8e1115
KL
469/* Clear from cursor to end of frame on a termcap device. */
470
ed8dad6b 471static void
385ed61f 472tty_clear_to_end (struct frame *f)
08a24c47
JB
473{
474 register int i;
3224dac1 475 struct tty_display_info *tty = FRAME_TTY (f);
08a24c47 476
fca177d4 477 if (tty->TS_clr_to_bottom)
08a24c47 478 {
ed8dad6b 479 tty_background_highlight (tty);
fca177d4 480 OUTPUT (tty, tty->TS_clr_to_bottom);
08a24c47
JB
481 }
482 else
483 {
6548cf00 484 for (i = curY (tty); i < FRAME_LINES (f); i++)
08a24c47 485 {
385ed61f
KL
486 cursor_to (f, i, 0);
487 clear_end_of_line (f, FRAME_COLS (f));
08a24c47
JB
488 }
489 }
490}
491
da8e1115 492/* Clear an entire termcap frame. */
08a24c47 493
ed8dad6b 494static void
385ed61f 495tty_clear_frame (struct frame *f)
08a24c47 496{
3224dac1 497 struct tty_display_info *tty = FRAME_TTY (f);
177c0ea7 498
fca177d4 499 if (tty->TS_clr_frame)
08a24c47 500 {
ed8dad6b 501 tty_background_highlight (tty);
fca177d4 502 OUTPUT (tty, tty->TS_clr_frame);
6548cf00 503 cmat (tty, 0, 0);
08a24c47
JB
504 }
505 else
506 {
385ed61f
KL
507 cursor_to (f, 0, 0);
508 clear_to_end (f);
08a24c47
JB
509 }
510}
511
da8e1115 512/* An implementation of clear_end_of_line for termcap frames.
08a24c47
JB
513
514 Note that the cursor may be moved, on terminals lacking a `ce' string. */
515
ed8dad6b 516static void
385ed61f 517tty_clear_end_of_line (struct frame *f, int first_unused_hpos)
08a24c47
JB
518{
519 register int i;
3224dac1 520 struct tty_display_info *tty = FRAME_TTY (f);
08a24c47 521
36cae867
KH
522 /* Detect the case where we are called from reset_sys_modes
523 and the costs have never been calculated. Do nothing. */
fca177d4 524 if (! tty->costs_set)
36cae867
KH
525 return;
526
6548cf00 527 if (curX (tty) >= first_unused_hpos)
08a24c47 528 return;
ed8dad6b 529 tty_background_highlight (tty);
fca177d4 530 if (tty->TS_clr_line)
08a24c47 531 {
fca177d4 532 OUTPUT1 (tty, tty->TS_clr_line);
08a24c47
JB
533 }
534 else
535 { /* have to do it the hard way */
ed8dad6b 536 tty_turn_off_insert (tty);
08a24c47 537
a168702a 538 /* Do not write in last row last col with Auto-wrap on. */
6548cf00 539 if (AutoWrap (tty)
0a125897
KL
540 && curY (tty) == FrameRows (tty) - 1
541 && first_unused_hpos == FrameCols (tty))
08a24c47
JB
542 first_unused_hpos--;
543
6548cf00 544 for (i = curX (tty); i < first_unused_hpos; i++)
08a24c47 545 {
0b0d3e0b
KL
546 if (tty->termscript)
547 fputc (' ', tty->termscript);
548 fputc (' ', tty->output);
08a24c47 549 }
6548cf00 550 cmplus (tty, first_unused_hpos - curX (tty));
08a24c47
JB
551 }
552}
553\f
288d5132
KH
554/* Buffers to store the source and result of code conversion for terminal. */
555static unsigned char *encode_terminal_src;
556static unsigned char *encode_terminal_dst;
557/* Allocated sizes of the above buffers. */
558static int encode_terminal_src_size;
559static int encode_terminal_dst_size;
560
561/* Encode SRC_LEN glyphs starting at SRC to terminal output codes.
562 Set CODING->produced to the byte-length of the resulting byte
563 sequence, and return a pointer to that byte sequence. */
564
565unsigned char *
566encode_terminal_code (src, src_len, coding)
a168702a 567 struct glyph *src;
a4decb7f 568 int src_len;
288d5132 569 struct coding_system *coding;
a4decb7f 570{
feef4f84 571 struct glyph *src_end = src + src_len;
288d5132
KH
572 unsigned char *buf;
573 int nchars, nbytes, required;
a4decb7f
KH
574 register int tlen = GLYPH_TABLE_LENGTH;
575 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
288d5132 576 Lisp_Object charset_list;
c5a518df 577
288d5132
KH
578 /* Allocate sufficient size of buffer to store all characters in
579 multibyte-form. But, it may be enlarged on demand if
4c12d738
KH
580 Vglyph_table contains a string or a composite glyph is
581 encountered. */
288d5132
KH
582 required = MAX_MULTIBYTE_LENGTH * src_len;
583 if (encode_terminal_src_size < required)
584 {
585 if (encode_terminal_src_size == 0)
586 encode_terminal_src = xmalloc (required);
587 else
588 encode_terminal_src = xrealloc (encode_terminal_src, required);
589 encode_terminal_src_size = required;
590 }
6589fd67 591
288d5132 592 charset_list = coding_charset_list (coding);
a4decb7f 593
288d5132
KH
594 buf = encode_terminal_src;
595 nchars = 0;
596 while (src < src_end)
a4decb7f 597 {
4c12d738
KH
598 if (src->type == COMPOSITE_GLYPH)
599 {
600 struct composition *cmp = composition_table[src->u.cmp_id];
601 int i;
602
603 nbytes = buf - encode_terminal_src;
604 required = MAX_MULTIBYTE_LENGTH * cmp->glyph_len;
605
606 if (encode_terminal_src_size < nbytes + required)
607 {
608 encode_terminal_src_size = nbytes + required;
609 encode_terminal_src = xrealloc (encode_terminal_src,
610 encode_terminal_src_size);
611 buf = encode_terminal_src + nbytes;
612 }
613
614 for (i = 0; i < cmp->glyph_len; i++)
615 {
616 int c = COMPOSITION_GLYPH (cmp, i);
f4d953fc 617
4c12d738
KH
618 if (! char_charset (c, charset_list, NULL))
619 break;
620 buf += CHAR_STRING (c, buf);
621 nchars++;
622 }
623 if (i == 0)
624 {
625 /* The first character of the composition is not encodable. */
626 *buf++ = '?';
627 nchars++;
628 }
629 }
a4decb7f 630 /* We must skip glyphs to be padded for a wide character. */
4c12d738 631 else if (! CHAR_GLYPH_PADDING_P (*src))
a4decb7f 632 {
f4d953fc 633 GLYPH g;
288d5132
KH
634 int c;
635 Lisp_Object string;
636
4ae0a2c0 637 string = Qnil;
f4d953fc 638 SET_GLYPH_FROM_CHAR_GLYPH (g, src[0]);
32de38e4 639
f4d953fc 640 if (GLYPH_INVALID_P (g) || GLYPH_SIMPLE_P (tbase, tlen, g))
288d5132
KH
641 {
642 /* This glyph doesn't has an entry in Vglyph_table. */
643 c = src->u.ch;
644 }
32de38e4 645 else
a4decb7f 646 {
32de38e4 647 /* This glyph has an entry in Vglyph_table,
a4decb7f
KH
648 so process any alias before testing for simpleness. */
649 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
32de38e4
KH
650
651 if (GLYPH_SIMPLE_P (tbase, tlen, g))
4ae0a2c0
KH
652 /* We set the multi-byte form of a character in G
653 (that should be an ASCII character) at WORKBUF. */
f4d953fc 654 c = GLYPH_CHAR (g);
32de38e4 655 else
4ae0a2c0 656 /* We have a string in Vglyph_table. */
f4d953fc 657 string = tbase[GLYPH_CHAR (g)];
171d7f24 658 }
177c0ea7 659
4ae0a2c0 660 if (NILP (string))
c42869c4 661 {
4c12d738
KH
662 nbytes = buf - encode_terminal_src;
663 if (encode_terminal_src_size < nbytes + MAX_MULTIBYTE_LENGTH)
664 {
665 encode_terminal_src_size = nbytes + MAX_MULTIBYTE_LENGTH;
666 encode_terminal_src = xrealloc (encode_terminal_src,
667 encode_terminal_src_size);
668 buf = encode_terminal_src + nbytes;
669 }
288d5132 670 if (char_charset (c, charset_list, NULL))
c5a518df 671 {
288d5132
KH
672 /* Store the multibyte form of C at BUF. */
673 buf += CHAR_STRING (c, buf);
674 nchars++;
c5a518df
KH
675 }
676 else
677 {
288d5132
KH
678 /* C is not encodable. */
679 *buf++ = '?';
c5a518df 680 nchars++;
288d5132
KH
681 while (src + 1 < src_end && CHAR_GLYPH_PADDING_P (src[1]))
682 {
683 *buf++ = '?';
684 nchars++;
685 src++;
686 }
c5a518df 687 }
4ae0a2c0
KH
688 }
689 else
690 {
288d5132
KH
691 unsigned char *p = SDATA (string), *pend = p + SBYTES (string);
692
693 if (! STRING_MULTIBYTE (string))
694 string = string_to_multibyte (string);
695 nbytes = buf - encode_terminal_src;
54c4c546 696 if (encode_terminal_src_size < nbytes + SBYTES (string))
4ae0a2c0 697 {
288d5132
KH
698 encode_terminal_src_size = nbytes + SBYTES (string);
699 encode_terminal_src = xrealloc (encode_terminal_src,
700 encode_terminal_src_size);
701 buf = encode_terminal_src + nbytes;
4ae0a2c0 702 }
288d5132
KH
703 bcopy (SDATA (string), buf, SBYTES (string));
704 buf += SBYTES (string);
705 nchars += SCHARS (string);
c42869c4 706 }
a4decb7f 707 }
288d5132
KH
708 src++;
709 }
710
711 if (nchars == 0)
712 {
713 coding->produced = 0;
714 return NULL;
a4decb7f 715 }
177c0ea7 716
288d5132
KH
717 nbytes = buf - encode_terminal_src;
718 coding->source = encode_terminal_src;
719 if (encode_terminal_dst_size == 0)
4ae0a2c0 720 {
288d5132
KH
721 encode_terminal_dst_size = encode_terminal_src_size;
722 encode_terminal_dst = xmalloc (encode_terminal_dst_size);
4ae0a2c0 723 }
288d5132
KH
724 coding->destination = encode_terminal_dst;
725 coding->dst_bytes = encode_terminal_dst_size;
726 encode_coding_object (coding, Qnil, 0, 0, nchars, nbytes, Qnil);
c5a518df 727 /* coding->destination may have been reallocated. */
288d5132
KH
728 encode_terminal_dst = coding->destination;
729 encode_terminal_dst_size = coding->dst_bytes;
4ae0a2c0 730
288d5132 731 return (encode_terminal_dst);
a4decb7f
KH
732}
733
08a24c47 734
c73bd236 735
da8e1115
KL
736/* An implementation of write_glyphs for termcap frames. */
737
ed8dad6b 738static void
385ed61f 739tty_write_glyphs (struct frame *f, struct glyph *string, int len)
08a24c47 740{
288d5132
KH
741 unsigned char *conversion_buffer;
742 struct coding_system *coding;
08a24c47 743
3224dac1 744 struct tty_display_info *tty = FRAME_TTY (f);
08a24c47 745
ed8dad6b 746 tty_turn_off_insert (tty);
fca177d4 747 tty_hide_cursor (tty);
08a24c47 748
a168702a 749 /* Don't dare write in last column of bottom line, if Auto-Wrap,
ff11dfa1 750 since that would scroll the whole frame on some terminals. */
08a24c47 751
6548cf00
KL
752 if (AutoWrap (tty)
753 && curY (tty) + 1 == FRAME_LINES (f)
754 && (curX (tty) + len) == FRAME_COLS (f))
08a24c47 755 len --;
a4decb7f
KH
756 if (len <= 0)
757 return;
08a24c47 758
6548cf00 759 cmplus (tty, len);
177c0ea7 760
af645abf
KH
761 /* If terminal_coding does any conversion, use it, otherwise use
762 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
763 because it always return 1 if the member src_multibyte is 1. */
fad2f685
KL
764 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
765 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
6589fd67
KH
766 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
767 the tail. */
af645abf 768 coding->mode &= ~CODING_MODE_LAST_BLOCK;
177c0ea7 769
a4decb7f 770 while (len > 0)
08a24c47 771 {
a168702a 772 /* Identify a run of glyphs with the same face. */
32de38e4 773 int face_id = string->face_id;
a168702a 774 int n;
177c0ea7 775
a168702a 776 for (n = 1; n < len; ++n)
32de38e4 777 if (string[n].face_id != face_id)
a168702a
GM
778 break;
779
780 /* Turn appearance modes of the face of the run on. */
ed8dad6b 781 tty_highlight_if_desired (tty);
a168702a
GM
782 turn_on_face (f, face_id);
783
288d5132
KH
784 if (n == len)
785 /* This is the last run. */
786 coding->mode |= CODING_MODE_LAST_BLOCK;
787 conversion_buffer = encode_terminal_code (string, n, coding);
788 if (coding->produced > 0)
08a24c47 789 {
1a935bfd 790 BLOCK_INPUT;
fad2f685
KL
791 fwrite (conversion_buffer, 1, coding->produced, tty->output);
792 if (ferror (tty->output))
793 clearerr (tty->output);
794 if (tty->termscript)
795 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
1a935bfd 796 UNBLOCK_INPUT;
08a24c47 797 }
288d5132
KH
798 len -= n;
799 string += n;
a168702a
GM
800
801 /* Turn appearance modes off. */
802 turn_off_face (f, face_id);
ed8dad6b 803 tty_turn_off_highlight (tty);
a4decb7f 804 }
177c0ea7 805
6548cf00 806 cmcheckmagic (tty);
08a24c47
JB
807}
808
b870aa61
SM
809#ifdef HAVE_GPM /* Only used by GPM code. */
810
7be1c21a
MB
811static void
812tty_write_glyphs_with_face (f, string, len, face_id)
813 register struct frame *f;
e882229c
NR
814 register struct glyph *string;
815 register int len, face_id;
816{
e882229c
NR
817 unsigned char *conversion_buffer;
818 struct coding_system *coding;
819
7be1c21a
MB
820 struct tty_display_info *tty = FRAME_TTY (f);
821
822 tty_turn_off_insert (tty);
823 tty_hide_cursor (tty);
e882229c
NR
824
825 /* Don't dare write in last column of bottom line, if Auto-Wrap,
826 since that would scroll the whole frame on some terminals. */
827
7be1c21a
MB
828 if (AutoWrap (tty)
829 && curY (tty) + 1 == FRAME_LINES (f)
830 && (curX (tty) + len) == FRAME_COLS (f))
e882229c
NR
831 len --;
832 if (len <= 0)
833 return;
834
7be1c21a 835 cmplus (tty, len);
e882229c
NR
836
837 /* If terminal_coding does any conversion, use it, otherwise use
838 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
839 because it always return 1 if the member src_multibyte is 1. */
7be1c21a
MB
840 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
841 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
e882229c
NR
842 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
843 the tail. */
844 coding->mode &= ~CODING_MODE_LAST_BLOCK;
845
e882229c 846 /* Turn appearance modes of the face. */
7be1c21a 847 tty_highlight_if_desired (tty);
e882229c
NR
848 turn_on_face (f, face_id);
849
850 coding->mode |= CODING_MODE_LAST_BLOCK;
851 conversion_buffer = encode_terminal_code (string, len, coding);
852 if (coding->produced > 0)
853 {
854 BLOCK_INPUT;
7be1c21a
MB
855 fwrite (conversion_buffer, 1, coding->produced, tty->output);
856 if (ferror (tty->output))
857 clearerr (tty->output);
858 if (tty->termscript)
859 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
e882229c
NR
860 UNBLOCK_INPUT;
861 }
862
863 /* Turn appearance modes off. */
864 turn_off_face (f, face_id);
7be1c21a 865 tty_turn_off_highlight (tty);
e882229c 866
7be1c21a 867 cmcheckmagic (tty);
e882229c 868}
b870aa61 869#endif
e882229c 870
da8e1115 871/* An implementation of insert_glyphs for termcap frames. */
177c0ea7 872
ed8dad6b 873static void
385ed61f 874tty_insert_glyphs (struct frame *f, struct glyph *start, int len)
08a24c47
JB
875{
876 char *buf;
6bbd7a29 877 struct glyph *glyph = NULL;
af645abf
KH
878 unsigned char *conversion_buffer;
879 unsigned char space[1];
880 struct coding_system *coding;
08a24c47 881
3224dac1 882 struct tty_display_info *tty = FRAME_TTY (f);
a168702a 883
fca177d4 884 if (tty->TS_ins_multi_chars)
08a24c47 885 {
fca177d4 886 buf = tparam (tty->TS_ins_multi_chars, 0, 0, len);
6548cf00 887 OUTPUT1 (tty, buf);
9ac0d9e0 888 xfree (buf);
08a24c47 889 if (start)
385ed61f 890 write_glyphs (f, start, len);
08a24c47
JB
891 return;
892 }
893
ed8dad6b 894 tty_turn_on_insert (tty);
6548cf00 895 cmplus (tty, len);
288d5132
KH
896
897 if (! start)
898 space[0] = SPACEGLYPH;
899
900 /* If terminal_coding does any conversion, use it, otherwise use
901 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
902 because it always return 1 if the member src_multibyte is 1. */
fad2f685
KL
903 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
904 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
288d5132
KH
905 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
906 the tail. */
907 coding->mode &= ~CODING_MODE_LAST_BLOCK;
908
07109bf9 909 while (len-- > 0)
08a24c47 910 {
fca177d4 911 OUTPUT1_IF (tty, tty->TS_ins_char);
08a24c47 912 if (!start)
32de38e4 913 {
288d5132
KH
914 conversion_buffer = space;
915 coding->produced = 1;
32de38e4 916 }
08a24c47 917 else
08a24c47 918 {
ed8dad6b 919 tty_highlight_if_desired (tty);
32de38e4 920 turn_on_face (f, start->face_id);
816be8b8 921 glyph = start;
a168702a 922 ++start;
a4decb7f
KH
923 /* We must open sufficient space for a character which
924 occupies more than one column. */
a168702a 925 while (len && CHAR_GLYPH_PADDING_P (*start))
a4decb7f 926 {
fca177d4 927 OUTPUT1_IF (tty, tty->TS_ins_char);
a4decb7f
KH
928 start++, len--;
929 }
288d5132
KH
930
931 if (len <= 0)
932 /* This is the last glyph. */
933 coding->mode |= CODING_MODE_LAST_BLOCK;
934
fad2f685 935 conversion_buffer = encode_terminal_code (glyph, 1, coding);
32de38e4 936 }
a4decb7f 937
288d5132 938 if (coding->produced > 0)
08a24c47 939 {
1a935bfd 940 BLOCK_INPUT;
fad2f685 941 fwrite (conversion_buffer, 1, coding->produced, tty->output);
0b0d3e0b
KL
942 if (ferror (tty->output))
943 clearerr (tty->output);
944 if (tty->termscript)
fad2f685 945 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
1a935bfd 946 UNBLOCK_INPUT;
08a24c47
JB
947 }
948
fca177d4 949 OUTPUT1_IF (tty, tty->TS_pad_inserted_char);
32de38e4 950 if (start)
65aa5e85
GM
951 {
952 turn_off_face (f, glyph->face_id);
ed8dad6b 953 tty_turn_off_highlight (tty);
65aa5e85 954 }
9a6b6f92 955 }
177c0ea7 956
6548cf00 957 cmcheckmagic (tty);
08a24c47
JB
958}
959
da8e1115
KL
960/* An implementation of delete_glyphs for termcap frames. */
961
ed8dad6b 962static void
385ed61f 963tty_delete_glyphs (struct frame *f, int n)
08a24c47
JB
964{
965 char *buf;
966 register int i;
967
3224dac1 968 struct tty_display_info *tty = FRAME_TTY (f);
08a24c47 969
fca177d4 970 if (tty->delete_in_insert_mode)
08a24c47 971 {
ed8dad6b 972 tty_turn_on_insert (tty);
08a24c47
JB
973 }
974 else
975 {
ed8dad6b 976 tty_turn_off_insert (tty);
fca177d4 977 OUTPUT_IF (tty, tty->TS_delete_mode);
08a24c47
JB
978 }
979
fca177d4 980 if (tty->TS_del_multi_chars)
08a24c47 981 {
fca177d4 982 buf = tparam (tty->TS_del_multi_chars, 0, 0, n);
6548cf00 983 OUTPUT1 (tty, buf);
9ac0d9e0 984 xfree (buf);
08a24c47
JB
985 }
986 else
987 for (i = 0; i < n; i++)
fca177d4
KL
988 OUTPUT1 (tty, tty->TS_del_char);
989 if (!tty->delete_in_insert_mode)
990 OUTPUT_IF (tty, tty->TS_end_delete_mode);
08a24c47
JB
991}
992\f
da8e1115 993/* An implementation of ins_del_lines for termcap frames. */
08a24c47 994
ed8dad6b 995static void
385ed61f 996tty_ins_del_lines (struct frame *f, int vpos, int n)
08a24c47 997{
3224dac1
KL
998 struct tty_display_info *tty = FRAME_TTY (f);
999 char *multi = n > 0 ? tty->TS_ins_multi_lines : tty->TS_del_multi_lines;
1000 char *single = n > 0 ? tty->TS_ins_line : tty->TS_del_line;
1001 char *scroll = n > 0 ? tty->TS_rev_scroll : tty->TS_fwd_scroll;
08a24c47
JB
1002
1003 register int i = n > 0 ? n : -n;
1004 register char *buf;
1005
08a24c47
JB
1006 /* If the lines below the insertion are being pushed
1007 into the end of the window, this is the same as clearing;
1008 and we know the lines are already clear, since the matching
1009 deletion has already been done. So can ignore this. */
1010 /* If the lines below the deletion are blank lines coming
1011 out of the end of the window, don't bother,
1012 as there will be a matching inslines later that will flush them. */
3224dac1
KL
1013 if (FRAME_SCROLL_REGION_OK (f)
1014 && vpos + i >= tty->specified_window)
08a24c47 1015 return;
3224dac1
KL
1016 if (!FRAME_MEMORY_BELOW_FRAME (f)
1017 && vpos + i >= FRAME_LINES (f))
08a24c47 1018 return;
f4d953fc 1019
08a24c47
JB
1020 if (multi)
1021 {
6839f1e2 1022 raw_cursor_to (f, vpos, 0);
ed8dad6b 1023 tty_background_highlight (tty);
08a24c47 1024 buf = tparam (multi, 0, 0, i);
3224dac1 1025 OUTPUT (tty, buf);
9ac0d9e0 1026 xfree (buf);
08a24c47
JB
1027 }
1028 else if (single)
1029 {
6839f1e2 1030 raw_cursor_to (f, vpos, 0);
ed8dad6b 1031 tty_background_highlight (tty);
08a24c47 1032 while (--i >= 0)
3224dac1
KL
1033 OUTPUT (tty, single);
1034 if (tty->TF_teleray)
1035 curX (tty) = 0;
08a24c47
JB
1036 }
1037 else
1038 {
ed8dad6b 1039 tty_set_scroll_region (f, vpos, tty->specified_window);
08a24c47 1040 if (n < 0)
6839f1e2 1041 raw_cursor_to (f, tty->specified_window - 1, 0);
08a24c47 1042 else
6839f1e2 1043 raw_cursor_to (f, vpos, 0);
ed8dad6b 1044 tty_background_highlight (tty);
08a24c47 1045 while (--i >= 0)
3224dac1 1046 OUTPUTL (tty, scroll, tty->specified_window - vpos);
ed8dad6b 1047 tty_set_scroll_region (f, 0, tty->specified_window);
08a24c47 1048 }
f4d953fc 1049
3224dac1
KL
1050 if (!FRAME_SCROLL_REGION_OK (f)
1051 && FRAME_MEMORY_BELOW_FRAME (f)
1052 && n < 0)
08a24c47 1053 {
385ed61f
KL
1054 cursor_to (f, FRAME_LINES (f) + n, 0);
1055 clear_to_end (f);
08a24c47
JB
1056 }
1057}
1058\f
1059/* Compute cost of sending "str", in characters,
1060 not counting any line-dependent padding. */
1061
1062int
6839f1e2 1063string_cost (char *str)
08a24c47
JB
1064{
1065 cost = 0;
1066 if (str)
1067 tputs (str, 0, evalcost);
1068 return cost;
1069}
1070
1071/* Compute cost of sending "str", in characters,
1072 counting any line-dependent padding at one line. */
1073
1074static int
6839f1e2 1075string_cost_one_line (char *str)
08a24c47
JB
1076{
1077 cost = 0;
1078 if (str)
1079 tputs (str, 1, evalcost);
1080 return cost;
1081}
1082
1083/* Compute per line amount of line-dependent padding,
1084 in tenths of characters. */
1085
1086int
6839f1e2 1087per_line_cost (char *str)
08a24c47
JB
1088{
1089 cost = 0;
1090 if (str)
1091 tputs (str, 0, evalcost);
1092 cost = - cost;
1093 if (str)
1094 tputs (str, 10, evalcost);
1095 return cost;
1096}
1097
1098#ifndef old
1099/* char_ins_del_cost[n] is cost of inserting N characters.
8dd0c7cb 1100 char_ins_del_cost[-n] is cost of deleting N characters.
9882535b 1101 The length of this vector is based on max_frame_cols. */
08a24c47
JB
1102
1103int *char_ins_del_vector;
1104
9882535b 1105#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
08a24c47
JB
1106#endif
1107
1108/* ARGSUSED */
1109static void
6839f1e2 1110calculate_ins_del_char_costs (struct frame *f)
08a24c47 1111{
28d7d09f 1112 struct tty_display_info *tty = FRAME_TTY (f);
08a24c47
JB
1113 int ins_startup_cost, del_startup_cost;
1114 int ins_cost_per_char, del_cost_per_char;
1115 register int i;
1116 register int *p;
1117
fca177d4 1118 if (tty->TS_ins_multi_chars)
08a24c47
JB
1119 {
1120 ins_cost_per_char = 0;
fca177d4 1121 ins_startup_cost = string_cost_one_line (tty->TS_ins_multi_chars);
08a24c47 1122 }
fca177d4
KL
1123 else if (tty->TS_ins_char || tty->TS_pad_inserted_char
1124 || (tty->TS_insert_mode && tty->TS_end_insert_mode))
08a24c47 1125 {
fca177d4
KL
1126 ins_startup_cost = (30 * (string_cost (tty->TS_insert_mode)
1127 + string_cost (tty->TS_end_insert_mode))) / 100;
1128 ins_cost_per_char = (string_cost_one_line (tty->TS_ins_char)
1129 + string_cost_one_line (tty->TS_pad_inserted_char));
08a24c47
JB
1130 }
1131 else
1132 {
1133 ins_startup_cost = 9999;
1134 ins_cost_per_char = 0;
1135 }
1136
fca177d4 1137 if (tty->TS_del_multi_chars)
08a24c47
JB
1138 {
1139 del_cost_per_char = 0;
fca177d4 1140 del_startup_cost = string_cost_one_line (tty->TS_del_multi_chars);
08a24c47 1141 }
fca177d4 1142 else if (tty->TS_del_char)
08a24c47 1143 {
fca177d4
KL
1144 del_startup_cost = (string_cost (tty->TS_delete_mode)
1145 + string_cost (tty->TS_end_delete_mode));
1146 if (tty->delete_in_insert_mode)
08a24c47 1147 del_startup_cost /= 2;
fca177d4 1148 del_cost_per_char = string_cost_one_line (tty->TS_del_char);
08a24c47
JB
1149 }
1150 else
1151 {
1152 del_startup_cost = 9999;
1153 del_cost_per_char = 0;
1154 }
1155
1156 /* Delete costs are at negative offsets */
fca177d4
KL
1157 p = &char_ins_del_cost (f)[0];
1158 for (i = FRAME_COLS (f); --i >= 0;)
08a24c47
JB
1159 *--p = (del_startup_cost += del_cost_per_char);
1160
1161 /* Doing nothing is free */
fca177d4 1162 p = &char_ins_del_cost (f)[0];
08a24c47
JB
1163 *p++ = 0;
1164
1165 /* Insert costs are at positive offsets */
fca177d4 1166 for (i = FRAME_COLS (f); --i >= 0;)
08a24c47
JB
1167 *p++ = (ins_startup_cost += ins_cost_per_char);
1168}
1169
dfcf069d 1170void
6839f1e2 1171calculate_costs (struct frame *frame)
08a24c47 1172{
9f732a77 1173 FRAME_COST_BAUD_RATE (frame) = baud_rate;
08a24c47 1174
28d440ab 1175 if (FRAME_TERMCAP_P (frame))
daf01701
KL
1176 {
1177 struct tty_display_info *tty = FRAME_TTY (frame);
1178 register char *f = (tty->TS_set_scroll_region
1179 ? tty->TS_set_scroll_region
1180 : tty->TS_set_scroll_region_1);
08a24c47 1181
daf01701 1182 FRAME_SCROLL_REGION_COST (frame) = string_cost (f);
08a24c47 1183
daf01701 1184 tty->costs_set = 1;
08a24c47 1185
daf01701
KL
1186 /* These variables are only used for terminal stuff. They are
1187 allocated once for the terminal frame of X-windows emacs, but not
1188 used afterwards.
8dd0c7cb 1189
daf01701
KL
1190 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1191 X turns off char_ins_del_ok. */
08a24c47 1192
daf01701
KL
1193 max_frame_lines = max (max_frame_lines, FRAME_LINES (frame));
1194 max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
08a24c47 1195
daf01701
KL
1196 if (char_ins_del_vector != 0)
1197 char_ins_del_vector
1198 = (int *) xrealloc (char_ins_del_vector,
1199 (sizeof (int)
1200 + 2 * max_frame_cols * sizeof (int)));
1201 else
1202 char_ins_del_vector
1203 = (int *) xmalloc (sizeof (int)
1204 + 2 * max_frame_cols * sizeof (int));
08a24c47 1205
daf01701
KL
1206 bzero (char_ins_del_vector, (sizeof (int)
1207 + 2 * max_frame_cols * sizeof (int)));
08a24c47 1208
daf01701
KL
1209
1210 if (f && (!tty->TS_ins_line && !tty->TS_del_line))
1211 do_line_insertion_deletion_costs (frame,
1212 tty->TS_rev_scroll, tty->TS_ins_multi_lines,
1213 tty->TS_fwd_scroll, tty->TS_del_multi_lines,
1214 f, f, 1);
1215 else
1216 do_line_insertion_deletion_costs (frame,
1217 tty->TS_ins_line, tty->TS_ins_multi_lines,
1218 tty->TS_del_line, tty->TS_del_multi_lines,
1219 0, 0, 1);
1220
1221 calculate_ins_del_char_costs (frame);
1222
1223 /* Don't use TS_repeat if its padding is worse than sending the chars */
1224 if (tty->TS_repeat && per_line_cost (tty->TS_repeat) * baud_rate < 9000)
1225 tty->RPov = string_cost (tty->TS_repeat);
1226 else
1227 tty->RPov = FRAME_COLS (frame) * 2;
08a24c47 1228
daf01701
KL
1229 cmcostinit (FRAME_TTY (frame)); /* set up cursor motion costs */
1230 }
08a24c47
JB
1231}
1232\f
a796ac82
JB
1233struct fkey_table {
1234 char *cap, *name;
1235};
1236
01d8deb0
ER
1237 /* Termcap capability names that correspond directly to X keysyms.
1238 Some of these (marked "terminfo") aren't supplied by old-style
1239 (Berkeley) termcap entries. They're listed in X keysym order;
1240 except we put the keypad keys first, so that if they clash with
1241 other keys (as on the IBM PC keyboard) they get overridden.
1242 */
1243
a168702a
GM
1244static struct fkey_table keys[] =
1245{
8103ad1a
PJ
1246 {"kh", "home"}, /* termcap */
1247 {"kl", "left"}, /* termcap */
1248 {"ku", "up"}, /* termcap */
1249 {"kr", "right"}, /* termcap */
1250 {"kd", "down"}, /* termcap */
1251 {"%8", "prior"}, /* terminfo */
1252 {"%5", "next"}, /* terminfo */
1253 {"@7", "end"}, /* terminfo */
1254 {"@1", "begin"}, /* terminfo */
1255 {"*6", "select"}, /* terminfo */
1256 {"%9", "print"}, /* terminfo */
1257 {"@4", "execute"}, /* terminfo --- actually the `command' key */
01d8deb0
ER
1258 /*
1259 * "insert" --- see below
1260 */
8103ad1a
PJ
1261 {"&8", "undo"}, /* terminfo */
1262 {"%0", "redo"}, /* terminfo */
1263 {"%7", "menu"}, /* terminfo --- actually the `options' key */
1264 {"@0", "find"}, /* terminfo */
1265 {"@2", "cancel"}, /* terminfo */
1266 {"%1", "help"}, /* terminfo */
01d8deb0
ER
1267 /*
1268 * "break" goes here, but can't be reliably intercepted with termcap
1269 */
8103ad1a 1270 {"&4", "reset"}, /* terminfo --- actually `restart' */
01d8deb0
ER
1271 /*
1272 * "system" and "user" --- no termcaps
1273 */
8103ad1a
PJ
1274 {"kE", "clearline"}, /* terminfo */
1275 {"kA", "insertline"}, /* terminfo */
1276 {"kL", "deleteline"}, /* terminfo */
1277 {"kI", "insertchar"}, /* terminfo */
1278 {"kD", "deletechar"}, /* terminfo */
1279 {"kB", "backtab"}, /* terminfo */
01d8deb0
ER
1280 /*
1281 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1282 */
8103ad1a 1283 {"@8", "kp-enter"}, /* terminfo */
01d8deb0
ER
1284 /*
1285 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1286 * "kp-multiply", "kp-add", "kp-separator",
1287 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1288 * --- no termcaps for any of these.
1289 */
8103ad1a 1290 {"K4", "kp-1"}, /* terminfo */
01d8deb0
ER
1291 /*
1292 * "kp-2" --- no termcap
1293 */
8103ad1a 1294 {"K5", "kp-3"}, /* terminfo */
01d8deb0
ER
1295 /*
1296 * "kp-4" --- no termcap
1297 */
8103ad1a 1298 {"K2", "kp-5"}, /* terminfo */
01d8deb0
ER
1299 /*
1300 * "kp-6" --- no termcap
1301 */
8103ad1a 1302 {"K1", "kp-7"}, /* terminfo */
01d8deb0
ER
1303 /*
1304 * "kp-8" --- no termcap
1305 */
8103ad1a 1306 {"K3", "kp-9"}, /* terminfo */
01d8deb0
ER
1307 /*
1308 * "kp-equal" --- no termcap
1309 */
8103ad1a
PJ
1310 {"k1", "f1"},
1311 {"k2", "f2"},
1312 {"k3", "f3"},
1313 {"k4", "f4"},
1314 {"k5", "f5"},
1315 {"k6", "f6"},
1316 {"k7", "f7"},
1317 {"k8", "f8"},
60ec7b7e
DN
1318 {"k9", "f9"},
1319
1320 {"&0", "S-cancel"}, /*shifted cancel key*/
1321 {"&9", "S-begin"}, /*shifted begin key*/
1322 {"*0", "S-find"}, /*shifted find key*/
1323 {"*1", "S-execute"}, /*shifted execute? actually shifted command key*/
1324 {"*4", "S-delete"}, /*shifted delete-character key*/
1325 {"*7", "S-end"}, /*shifted end key*/
1326 {"*8", "S-clearline"}, /*shifted clear-to end-of-line key*/
1327 {"#1", "S-help"}, /*shifted help key*/
1328 {"#2", "S-home"}, /*shifted home key*/
1329 {"#3", "S-insert"}, /*shifted insert-character key*/
1330 {"#4", "S-left"}, /*shifted left-arrow key*/
1331 {"%d", "S-menu"}, /*shifted menu? actually shifted options key*/
1332 {"%c", "S-next"}, /*shifted next key*/
1333 {"%e", "S-prior"}, /*shifted previous key*/
1334 {"%f", "S-print"}, /*shifted print key*/
1335 {"%g", "S-redo"}, /*shifted redo key*/
1336 {"%i", "S-right"}, /*shifted right-arrow key*/
1337 {"!3", "S-undo"} /*shifted undo key*/
a796ac82
JB
1338 };
1339
e7cf0fa0
KL
1340static char **term_get_fkeys_address;
1341static KBOARD *term_get_fkeys_kboard;
f2a00342 1342static Lisp_Object term_get_fkeys_1 ();
465db27b 1343
4f4a84ec 1344/* Find the escape codes sent by the function keys for Vinput_decode_map.
177c0ea7 1345 This function scans the termcap function key sequence entries, and
4f4a84ec 1346 adds entries to Vinput_decode_map for each function key it finds. */
01d8deb0 1347
ed8dad6b 1348static void
e7cf0fa0 1349term_get_fkeys (address, kboard)
5c2c7893 1350 char **address;
e7cf0fa0 1351 KBOARD *kboard;
f2a00342
RM
1352{
1353 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1354 errors during the call. The only errors should be from Fdefine_key
1355 when given a key sequence containing an invalid prefix key. If the
1356 termcap defines function keys which use a prefix that is already bound
1357 to a command by the default bindings, we should silently ignore that
1358 function key specification, rather than giving the user an error and
1359 refusing to run at all on such a terminal. */
1360
1361 extern Lisp_Object Fidentity ();
e7cf0fa0
KL
1362 term_get_fkeys_address = address;
1363 term_get_fkeys_kboard = kboard;
f2a00342
RM
1364 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1365}
1366
1367static Lisp_Object
1368term_get_fkeys_1 ()
5c2c7893 1369{
5c2c7893
JB
1370 int i;
1371
e7cf0fa0
KL
1372 char **address = term_get_fkeys_address;
1373 KBOARD *kboard = term_get_fkeys_kboard;
f4d953fc 1374
3e65092f 1375 /* This can happen if CANNOT_DUMP or with strange options. */
4f4a84ec
SM
1376 if (!KEYMAPP (kboard->Vinput_decode_map))
1377 kboard->Vinput_decode_map = Fmake_sparse_keymap (Qnil);
3e65092f 1378
5c2c7893
JB
1379 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1380 {
1381 char *sequence = tgetstr (keys[i].cap, address);
1382 if (sequence)
4f4a84ec 1383 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence),
f2a00342
RM
1384 Fmake_vector (make_number (1),
1385 intern (keys[i].name)));
5c2c7893 1386 }
a796ac82
JB
1387
1388 /* The uses of the "k0" capability are inconsistent; sometimes it
1389 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
eb8c3be9 1390 We will attempt to politely accommodate both systems by testing for
a796ac82
JB
1391 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1392 */
1393 {
1394 char *k_semi = tgetstr ("k;", address);
1395 char *k0 = tgetstr ("k0", address);
1396 char *k0_name = "f10";
1397
1398 if (k_semi)
1399 {
95c11956
SM
1400 if (k0)
1401 /* Define f0 first, so that f10 takes precedence in case the
1402 key sequences happens to be the same. */
4f4a84ec 1403 Fdefine_key (kboard->Vinput_decode_map, build_string (k0),
95c11956 1404 Fmake_vector (make_number (1), intern ("f0")));
4f4a84ec 1405 Fdefine_key (kboard->Vinput_decode_map, build_string (k_semi),
f2a00342 1406 Fmake_vector (make_number (1), intern ("f10")));
a796ac82 1407 }
95c11956 1408 else if (k0)
4f4a84ec 1409 Fdefine_key (kboard->Vinput_decode_map, build_string (k0),
f2a00342 1410 Fmake_vector (make_number (1), intern (k0_name)));
a796ac82 1411 }
01d8deb0
ER
1412
1413 /* Set up cookies for numbered function keys above f10. */
1414 {
1415 char fcap[3], fkey[4];
1416
fc4f24da 1417 fcap[0] = 'F'; fcap[2] = '\0';
01d8deb0
ER
1418 for (i = 11; i < 64; i++)
1419 {
1420 if (i <= 19)
1421 fcap[1] = '1' + i - 11;
1422 else if (i <= 45)
b59ab95c 1423 fcap[1] = 'A' + i - 20;
01d8deb0 1424 else
b59ab95c 1425 fcap[1] = 'a' + i - 46;
01d8deb0 1426
fc4f24da
RS
1427 {
1428 char *sequence = tgetstr (fcap, address);
1429 if (sequence)
1430 {
465db27b 1431 sprintf (fkey, "f%d", i);
4f4a84ec 1432 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence),
f2a00342
RM
1433 Fmake_vector (make_number (1),
1434 intern (fkey)));
fc4f24da
RS
1435 }
1436 }
01d8deb0
ER
1437 }
1438 }
1439
1440 /*
1441 * Various mappings to try and get a better fit.
1442 */
1443 {
fc4f24da
RS
1444#define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1445 if (!tgetstr (cap1, address)) \
1446 { \
1447 char *sequence = tgetstr (cap2, address); \
e7cf0fa0 1448 if (sequence) \
4f4a84ec 1449 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence), \
e7cf0fa0
KL
1450 Fmake_vector (make_number (1), \
1451 intern (sym))); \
fc4f24da 1452 }
177c0ea7 1453
01d8deb0 1454 /* if there's no key_next keycap, map key_npage to `next' keysym */
27b61785 1455 CONDITIONAL_REASSIGN ("%5", "kN", "next");
01d8deb0 1456 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
381d11a1 1457 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
01d8deb0 1458 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
27b61785 1459 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
403c995b
RS
1460 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1461 CONDITIONAL_REASSIGN ("@7", "kH", "end");
0a7f697a
KH
1462
1463 /* IBM has their own non-standard dialect of terminfo.
1464 If the standard name isn't found, try the IBM name. */
1465 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1466 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1467 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1468 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1469 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1470 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1471 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1472 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1473 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1dd40212 1474#undef CONDITIONAL_REASSIGN
01d8deb0 1475 }
a168702a
GM
1476
1477 return Qnil;
5c2c7893
JB
1478}
1479
1480\f
a168702a
GM
1481/***********************************************************************
1482 Character Display Information
1483 ***********************************************************************/
1484
47021b11
KS
1485/* Avoid name clash with functions defined in xterm.c */
1486#ifdef static
1487#define append_glyph append_glyph_term
1488#define produce_stretch_glyph produce_stretch_glyph_term
4c12d738
KH
1489#define append_composite_glyph append_composite_glyph_term
1490#define produce_composite_glyph produce_composite_glyph_term
47021b11
KS
1491#endif
1492
a168702a 1493static void append_glyph P_ ((struct it *));
6b61353c 1494static void produce_stretch_glyph P_ ((struct it *));
4c12d738
KH
1495static void append_composite_glyph P_ ((struct it *));
1496static void produce_composite_glyph P_ ((struct it *));
a168702a
GM
1497
1498/* Append glyphs to IT's glyph_row. Called from produce_glyphs for
d2b4c17d
KH
1499 terminal frames if IT->glyph_row != NULL. IT->char_to_display is
1500 the character for which to produce glyphs; IT->face_id contains the
1501 character's face. Padding glyphs are appended if IT->c has a
1502 IT->pixel_width > 1. */
177c0ea7 1503
a168702a
GM
1504static void
1505append_glyph (it)
1506 struct it *it;
1507{
1508 struct glyph *glyph, *end;
1509 int i;
1510
1511 xassert (it->glyph_row);
1512 glyph = (it->glyph_row->glyphs[it->area]
1513 + it->glyph_row->used[it->area]);
1514 end = it->glyph_row->glyphs[1 + it->area];
1515
177c0ea7
JB
1516 for (i = 0;
1517 i < it->pixel_width && glyph < end;
a168702a
GM
1518 ++i)
1519 {
1520 glyph->type = CHAR_GLYPH;
d13f3e2e 1521 glyph->pixel_width = 1;
d2b4c17d 1522 glyph->u.ch = it->char_to_display;
32de38e4
KH
1523 glyph->face_id = it->face_id;
1524 glyph->padding_p = i > 0;
a168702a
GM
1525 glyph->charpos = CHARPOS (it->position);
1526 glyph->object = it->object;
177c0ea7 1527
a168702a
GM
1528 ++it->glyph_row->used[it->area];
1529 ++glyph;
1530 }
1531}
1532
1533
b50fe468
RS
1534/* Produce glyphs for the display element described by IT. *IT
1535 specifies what we want to produce a glyph for (character, image, ...),
1536 and where in the glyph matrix we currently are (glyph row and hpos).
1537 produce_glyphs fills in output fields of *IT with information such as the
1538 pixel width and height of a character, and maybe output actual glyphs at
a168702a 1539 the same time if IT->glyph_row is non-null. See the explanation of
b50fe468
RS
1540 struct display_iterator in dispextern.h for an overview.
1541
1542 produce_glyphs also stores the result of glyph width, ascent
1543 etc. computations in *IT.
1544
1545 IT->glyph_row may be null, in which case produce_glyphs does not
1546 actually fill in the glyphs. This is used in the move_* functions
1547 in xdisp.c for text width and height computations.
1548
1549 Callers usually don't call produce_glyphs directly;
1550 instead they use the macro PRODUCE_GLYPHS. */
a168702a 1551
177c0ea7 1552void
a168702a
GM
1553produce_glyphs (it)
1554 struct it *it;
1555{
1556 /* If a hook is installed, let it do the work. */
4c12d738
KH
1557
1558 /* Nothing but characters are supported on terminal frames. */
a168702a 1559 xassert (it->what == IT_CHARACTER
c7cba11d 1560 || it->what == IT_COMPOSITION
a168702a 1561 || it->what == IT_STRETCH);
177c0ea7 1562
6b61353c
KH
1563 if (it->what == IT_STRETCH)
1564 {
1565 produce_stretch_glyph (it);
1566 goto done;
1567 }
1568
4c12d738
KH
1569 if (it->what == IT_COMPOSITION)
1570 {
1571 produce_composite_glyph (it);
1572 goto done;
1573 }
a168702a 1574
d2b4c17d
KH
1575 /* Maybe translate single-byte characters to multibyte. */
1576 it->char_to_display = it->c;
1577
a168702a
GM
1578 if (it->c >= 040 && it->c < 0177)
1579 {
1580 it->pixel_width = it->nglyphs = 1;
1581 if (it->glyph_row)
1582 append_glyph (it);
1583 }
1584 else if (it->c == '\n')
1585 it->pixel_width = it->nglyphs = 0;
1586 else if (it->c == '\t')
1587 {
2efdbcdd 1588 int absolute_x = (it->current_x
a168702a 1589 + it->continuation_lines_width);
177c0ea7
JB
1590 int next_tab_x
1591 = (((1 + absolute_x + it->tab_width - 1)
a168702a
GM
1592 / it->tab_width)
1593 * it->tab_width);
1594 int nspaces;
1595
1596 /* If part of the TAB has been displayed on the previous line
1597 which is continued now, continuation_lines_width will have
1598 been incremented already by the part that fitted on the
1599 continued line. So, we will get the right number of spaces
1600 here. */
1601 nspaces = next_tab_x - absolute_x;
177c0ea7 1602
a168702a
GM
1603 if (it->glyph_row)
1604 {
1605 int n = nspaces;
177c0ea7 1606
d2b4c17d 1607 it->char_to_display = ' ';
a168702a 1608 it->pixel_width = it->len = 1;
177c0ea7 1609
a168702a
GM
1610 while (n--)
1611 append_glyph (it);
a168702a
GM
1612 }
1613
1614 it->pixel_width = nspaces;
1615 it->nglyphs = nspaces;
1616 }
c5a518df 1617 else if (CHAR_BYTE8_P (it->c))
add44890 1618 {
5b203baa
KH
1619 if (unibyte_display_via_language_environment
1620 && (it->c >= 0240))
1621 {
1622 it->char_to_display = unibyte_char_to_multibyte (it->c);
1623 it->pixel_width = CHAR_WIDTH (it->char_to_display);
1624 it->nglyphs = it->pixel_width;
1625 if (it->glyph_row)
1626 append_glyph (it);
1627 }
1628 else
1629 {
1630 /* Coming here means that it->c is from display table, thus
1631 we must send the raw 8-bit byte as is to the terminal.
1632 Although there's no way to know how many columns it
1633 occupies on a screen, it is a good assumption that a
1634 single byte code has 1-column width. */
1635 it->pixel_width = it->nglyphs = 1;
1636 if (it->glyph_row)
1637 append_glyph (it);
1638 }
add44890 1639 }
a168702a
GM
1640 else
1641 {
9332ea03 1642 it->pixel_width = CHAR_WIDTH (it->c);
a168702a 1643 it->nglyphs = it->pixel_width;
177c0ea7 1644
a168702a
GM
1645 if (it->glyph_row)
1646 append_glyph (it);
1647 }
1648
6b61353c 1649 done:
177c0ea7 1650 /* Advance current_x by the pixel width as a convenience for
a168702a
GM
1651 the caller. */
1652 if (it->area == TEXT_AREA)
1653 it->current_x += it->pixel_width;
cfe8a05e
GM
1654 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1655 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
a168702a
GM
1656}
1657
1658
6b61353c
KH
1659/* Produce a stretch glyph for iterator IT. IT->object is the value
1660 of the glyph property displayed. The value must be a list
1661 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1662 being recognized:
1663
1664 1. `:width WIDTH' specifies that the space should be WIDTH *
1665 canonical char width wide. WIDTH may be an integer or floating
1666 point number.
1667
1668 2. `:align-to HPOS' specifies that the space should be wide enough
1669 to reach HPOS, a value in canonical character units. */
1670
1671static void
1672produce_stretch_glyph (it)
1673 struct it *it;
1674{
1675 /* (space :width WIDTH ...) */
1676 Lisp_Object prop, plist;
1677 int width = 0, align_to = -1;
1678 int zero_width_ok_p = 0;
1679 double tem;
1680
1681 /* List should start with `space'. */
1682 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1683 plist = XCDR (it->object);
1684
1685 /* Compute the width of the stretch. */
1686 if ((prop = Fplist_get (plist, QCwidth), !NILP (prop))
1687 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, 0))
1688 {
1689 /* Absolute width `:width WIDTH' specified and valid. */
1690 zero_width_ok_p = 1;
1691 width = (int)(tem + 0.5);
1692 }
1693 else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
1694 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, &align_to))
1695 {
1696 if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
feef4f84 1697 align_to = (align_to < 0
6b61353c
KH
1698 ? 0
1699 : align_to - window_box_left_offset (it->w, TEXT_AREA));
1700 else if (align_to < 0)
1701 align_to = window_box_left_offset (it->w, TEXT_AREA);
1702 width = max (0, (int)(tem + 0.5) + align_to - it->current_x);
1703 zero_width_ok_p = 1;
1704 }
1705 else
1706 /* Nothing specified -> width defaults to canonical char width. */
1707 width = FRAME_COLUMN_WIDTH (it->f);
1708
1709 if (width <= 0 && (width < 0 || !zero_width_ok_p))
1710 width = 1;
1711
1712 if (width > 0 && it->glyph_row)
1713 {
1714 Lisp_Object o_object = it->object;
1715 Lisp_Object object = it->stack[it->sp - 1].string;
1716 int n = width;
6b61353c
KH
1717
1718 if (!STRINGP (object))
1719 object = it->w->buffer;
1720 it->object = object;
d2b4c17d 1721 it->char_to_display = ' ';
6b61353c
KH
1722 it->pixel_width = it->len = 1;
1723 while (n--)
1724 append_glyph (it);
1725 it->object = o_object;
6b61353c
KH
1726 }
1727 it->pixel_width = width;
1728 it->nglyphs = width;
1729}
1730
1731
4c12d738
KH
1732/* Append glyphs to IT's glyph_row for the composition IT->cmp_id.
1733 Called from produce_composite_glyph for terminal frames if
1734 IT->glyph_row != NULL. IT->face_id contains the character's
1735 face. */
1736
1737static void
1738append_composite_glyph (it)
1739 struct it *it;
1740{
1741 struct glyph *glyph;
1742
1743 xassert (it->glyph_row);
1744 glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
1745 if (glyph < it->glyph_row->glyphs[1 + it->area])
1746 {
1747 glyph->type = COMPOSITE_GLYPH;
1748 glyph->pixel_width = it->pixel_width;
1749 glyph->u.cmp_id = it->cmp_id;
1750 glyph->face_id = it->face_id;
1751 glyph->padding_p = 0;
1752 glyph->charpos = CHARPOS (it->position);
1753 glyph->object = it->object;
1754
1755 ++it->glyph_row->used[it->area];
1756 ++glyph;
1757 }
1758}
1759
1760
1761/* Produce a composite glyph for iterator IT. IT->cmp_id is the ID of
1762 the composition. We simply produces components of the composition
1763 assuming that that the terminal has a capability to layout/render
1764 it correctly. */
1765
1766static void
1767produce_composite_glyph (it)
1768 struct it *it;
1769{
1770 struct composition *cmp = composition_table[it->cmp_id];
1771 int c;
1772
1773 xassert (cmp->glyph_len > 0);
1774 c = COMPOSITION_GLYPH (cmp, 0);
1775 it->pixel_width = CHAR_WIDTH (it->c);
1776 it->nglyphs = 1;
1777
1778 if (it->glyph_row)
1779 append_composite_glyph (it);
1780}
1781
1782
a168702a
GM
1783/* Get information about special display element WHAT in an
1784 environment described by IT. WHAT is one of IT_TRUNCATION or
1785 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1786 non-null glyph_row member. This function ensures that fields like
1787 face_id, c, len of IT are left untouched. */
1788
1789void
1790produce_special_glyphs (it, what)
1791 struct it *it;
1792 enum display_element_type what;
1793{
1794 struct it temp_it;
f4d953fc 1795 Lisp_Object gc;
072d84a6 1796 GLYPH glyph;
177c0ea7 1797
a168702a
GM
1798 temp_it = *it;
1799 temp_it.dp = NULL;
1800 temp_it.what = IT_CHARACTER;
1801 temp_it.len = 1;
7c752c80 1802 temp_it.object = make_number (0);
a168702a
GM
1803 bzero (&temp_it.current, sizeof temp_it.current);
1804
1805 if (what == IT_CONTINUATION)
1806 {
1807 /* Continuation glyph. */
f4d953fc 1808 SET_GLYPH_FROM_CHAR (glyph, '\\');
a168702a 1809 if (it->dp
f4d953fc
KS
1810 && (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc))
1811 && GLYPH_CODE_CHAR_VALID_P (gc))
a168702a 1812 {
f4d953fc
KS
1813 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
1814 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
a168702a 1815 }
a168702a
GM
1816 }
1817 else if (what == IT_TRUNCATION)
1818 {
1819 /* Truncation glyph. */
f4d953fc 1820 SET_GLYPH_FROM_CHAR (glyph, '$');
a168702a 1821 if (it->dp
f4d953fc
KS
1822 && (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc))
1823 && GLYPH_CODE_CHAR_VALID_P (gc))
a168702a 1824 {
f4d953fc
KS
1825 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
1826 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
a168702a 1827 }
a168702a
GM
1828 }
1829 else
1830 abort ();
072d84a6 1831
f4d953fc
KS
1832 temp_it.c = GLYPH_CHAR (glyph);
1833 temp_it.face_id = GLYPH_FACE (glyph);
072d84a6
RS
1834 temp_it.len = CHAR_BYTES (temp_it.c);
1835
1836 produce_glyphs (&temp_it);
1837 it->pixel_width = temp_it.pixel_width;
1838 it->nglyphs = temp_it.pixel_width;
a168702a
GM
1839}
1840
1841
a168702a
GM
1842\f
1843/***********************************************************************
1844 Faces
1845 ***********************************************************************/
1846
4e6ba4a4
GM
1847/* Value is non-zero if attribute ATTR may be used. ATTR should be
1848 one of the enumerators from enum no_color_bit, or a bit set built
1849 from them. Some display attributes may not be used together with
1850 color; the termcap capability `NC' specifies which ones. */
1851
fca177d4
KL
1852#define MAY_USE_WITH_COLORS_P(tty, ATTR) \
1853 (tty->TN_max_colors > 0 \
1854 ? (tty->TN_no_color_video & (ATTR)) == 0 \
1855 : 1)
a168702a 1856
072d84a6
RS
1857/* Turn appearances of face FACE_ID on tty frame F on.
1858 FACE_ID is a realized face ID number, in the face cache. */
a168702a
GM
1859
1860static void
1861turn_on_face (f, face_id)
1862 struct frame *f;
1863 int face_id;
1864{
1865 struct face *face = FACE_FROM_ID (f, face_id);
86a7d192
GM
1866 long fg = face->foreground;
1867 long bg = face->background;
28d7d09f 1868 struct tty_display_info *tty = FRAME_TTY (f);
a168702a 1869
86a7d192
GM
1870 /* Do this first because TS_end_standout_mode may be the same
1871 as TS_exit_attribute_mode, which turns all appearances off. */
fca177d4 1872 if (MAY_USE_WITH_COLORS_P (tty, NC_REVERSE))
86a7d192 1873 {
fca177d4 1874 if (tty->TN_max_colors > 0)
86a7d192
GM
1875 {
1876 if (fg >= 0 && bg >= 0)
1877 {
1878 /* If the terminal supports colors, we can set them
1879 below without using reverse video. The face's fg
1880 and bg colors are set as they should appear on
1881 the screen, i.e. they take the inverse-video'ness
1882 of the face already into account. */
1883 }
1884 else if (inverse_video)
1885 {
1886 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1887 || bg == FACE_TTY_DEFAULT_BG_COLOR)
ed8dad6b 1888 tty_toggle_highlight (tty);
86a7d192
GM
1889 }
1890 else
1891 {
1892 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1893 || bg == FACE_TTY_DEFAULT_FG_COLOR)
ed8dad6b 1894 tty_toggle_highlight (tty);
86a7d192
GM
1895 }
1896 }
1897 else
1898 {
1899 /* If we can't display colors, use reverse video
1900 if the face specifies that. */
37526b42
GM
1901 if (inverse_video)
1902 {
1903 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1904 || bg == FACE_TTY_DEFAULT_BG_COLOR)
ed8dad6b 1905 tty_toggle_highlight (tty);
37526b42
GM
1906 }
1907 else
1908 {
1909 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1910 || bg == FACE_TTY_DEFAULT_FG_COLOR)
ed8dad6b 1911 tty_toggle_highlight (tty);
37526b42 1912 }
86a7d192
GM
1913 }
1914 }
a168702a
GM
1915
1916 if (face->tty_bold_p)
4e6ba4a4 1917 {
fca177d4
KL
1918 if (MAY_USE_WITH_COLORS_P (tty, NC_BOLD))
1919 OUTPUT1_IF (tty, tty->TS_enter_bold_mode);
4e6ba4a4 1920 }
a168702a 1921 else if (face->tty_dim_p)
fca177d4
KL
1922 if (MAY_USE_WITH_COLORS_P (tty, NC_DIM))
1923 OUTPUT1_IF (tty, tty->TS_enter_dim_mode);
a168702a
GM
1924
1925 /* Alternate charset and blinking not yet used. */
4e6ba4a4 1926 if (face->tty_alt_charset_p
fca177d4
KL
1927 && MAY_USE_WITH_COLORS_P (tty, NC_ALT_CHARSET))
1928 OUTPUT1_IF (tty, tty->TS_enter_alt_charset_mode);
a168702a 1929
4e6ba4a4 1930 if (face->tty_blinking_p
fca177d4
KL
1931 && MAY_USE_WITH_COLORS_P (tty, NC_BLINK))
1932 OUTPUT1_IF (tty, tty->TS_enter_blink_mode);
a168702a 1933
fca177d4
KL
1934 if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (tty, NC_UNDERLINE))
1935 OUTPUT1_IF (tty, tty->TS_enter_underline_mode);
a168702a 1936
fca177d4 1937 if (tty->TN_max_colors > 0)
a168702a 1938 {
753d161b 1939 char *ts, *p;
177c0ea7 1940
fbf34973 1941 ts = tty->standout_mode ? tty->TS_set_background : tty->TS_set_foreground;
753d161b 1942 if (fg >= 0 && ts)
a168702a 1943 {
fbf34973 1944 p = tparam (ts, NULL, 0, (int) fg);
6548cf00 1945 OUTPUT (tty, p);
a168702a
GM
1946 xfree (p);
1947 }
1948
fbf34973 1949 ts = tty->standout_mode ? tty->TS_set_foreground : tty->TS_set_background;
753d161b 1950 if (bg >= 0 && ts)
a168702a 1951 {
fbf34973 1952 p = tparam (ts, NULL, 0, (int) bg);
6548cf00 1953 OUTPUT (tty, p);
a168702a
GM
1954 xfree (p);
1955 }
1956 }
1957}
177c0ea7 1958
a168702a
GM
1959
1960/* Turn off appearances of face FACE_ID on tty frame F. */
1961
1962static void
1963turn_off_face (f, face_id)
1964 struct frame *f;
1965 int face_id;
1966{
1967 struct face *face = FACE_FROM_ID (f, face_id);
28d7d09f 1968 struct tty_display_info *tty = FRAME_TTY (f);
a168702a
GM
1969
1970 xassert (face != NULL);
1971
fca177d4 1972 if (tty->TS_exit_attribute_mode)
a168702a
GM
1973 {
1974 /* Capability "me" will turn off appearance modes double-bright,
1975 half-bright, reverse-video, standout, underline. It may or
1976 may not turn off alt-char-mode. */
1977 if (face->tty_bold_p
1978 || face->tty_dim_p
1979 || face->tty_reverse_p
1980 || face->tty_alt_charset_p
1981 || face->tty_blinking_p
1982 || face->tty_underline_p)
65aa5e85 1983 {
fca177d4
KL
1984 OUTPUT1_IF (tty, tty->TS_exit_attribute_mode);
1985 if (strcmp (tty->TS_exit_attribute_mode, tty->TS_end_standout_mode) == 0)
1986 tty->standout_mode = 0;
65aa5e85 1987 }
a168702a
GM
1988
1989 if (face->tty_alt_charset_p)
fca177d4 1990 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
a168702a
GM
1991 }
1992 else
1993 {
1994 /* If we don't have "me" we can only have those appearances
1995 that have exit sequences defined. */
1996 if (face->tty_alt_charset_p)
fca177d4 1997 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
a168702a 1998
54800acb 1999 if (face->tty_underline_p)
fca177d4 2000 OUTPUT_IF (tty, tty->TS_exit_underline_mode);
a168702a
GM
2001 }
2002
2003 /* Switch back to default colors. */
fca177d4 2004 if (tty->TN_max_colors > 0
f9d2fdc4
EZ
2005 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
2006 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
2007 || (face->background != FACE_TTY_DEFAULT_COLOR
2008 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
fca177d4 2009 OUTPUT1_IF (tty, tty->TS_orig_pair);
a168702a 2010}
177c0ea7
JB
2011
2012
b63a55ac
MB
2013/* Return non-zero if the terminal on frame F supports all of the
2014 capabilities in CAPS simultaneously, with foreground and background
2015 colors FG and BG. */
2016
4a8130f2 2017int
fca177d4 2018tty_capable_p (tty, caps, fg, bg)
28d7d09f 2019 struct tty_display_info *tty;
b63a55ac
MB
2020 unsigned caps;
2021 unsigned long fg, bg;
2022{
fca177d4
KL
2023#define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
2024 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
b63a55ac
MB
2025 return 0;
2026
fca177d4
KL
2027 TTY_CAPABLE_P_TRY (tty, TTY_CAP_INVERSE, tty->TS_standout_mode, NC_REVERSE);
2028 TTY_CAPABLE_P_TRY (tty, TTY_CAP_UNDERLINE, tty->TS_enter_underline_mode, NC_UNDERLINE);
2029 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BOLD, tty->TS_enter_bold_mode, NC_BOLD);
2030 TTY_CAPABLE_P_TRY (tty, TTY_CAP_DIM, tty->TS_enter_dim_mode, NC_DIM);
2031 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BLINK, tty->TS_enter_blink_mode, NC_BLINK);
2032 TTY_CAPABLE_P_TRY (tty, TTY_CAP_ALT_CHARSET, tty->TS_enter_alt_charset_mode, NC_ALT_CHARSET);
b63a55ac
MB
2033
2034 /* We can do it! */
2035 return 1;
2036}
2037
a168702a
GM
2038/* Return non-zero if the terminal is capable to display colors. */
2039
2040DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
981e4297 2041 0, 1, 0,
6ed8eeff
KL
2042 doc: /* Return non-nil if the tty device TERMINAL can display colors.
2043
2044TERMINAL can be a terminal id, a frame or nil (meaning the selected
2045frame's terminal). This function always returns nil if TERMINAL
2046is not on a tty device. */)
2047 (terminal)
2048 Lisp_Object terminal;
a168702a 2049{
717a00ef 2050 struct terminal *t = get_tty_terminal (terminal, 0);
6ed8eeff 2051 if (!t)
428a555e 2052 return Qnil;
3224dac1 2053 else
6ed8eeff 2054 return t->display_info.tty->TN_max_colors > 0 ? Qt : Qnil;
a168702a
GM
2055}
2056
bfa62f96
EZ
2057/* Return the number of supported colors. */
2058DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
2059 Stty_display_color_cells, 0, 1, 0,
6ed8eeff
KL
2060 doc: /* Return the number of colors supported by the tty device TERMINAL.
2061
2062TERMINAL can be a terminal id, a frame or nil (meaning the selected
717a00ef 2063frame's terminal). This function always returns 0 if TERMINAL
6ed8eeff
KL
2064is not on a tty device. */)
2065 (terminal)
2066 Lisp_Object terminal;
bfa62f96 2067{
717a00ef 2068 struct terminal *t = get_tty_terminal (terminal, 0);
6ed8eeff 2069 if (!t)
8c8d5f35 2070 return make_number (0);
3224dac1 2071 else
6ed8eeff 2072 return make_number (t->display_info.tty->TN_max_colors);
bfa62f96
EZ
2073}
2074
ace28297 2075#ifndef WINDOWSNT
a168702a 2076
5205ee62
GM
2077/* Declare here rather than in the function, as in the rest of Emacs,
2078 to work around an HPUX compiler bug (?). See
57407fb4 2079 http://lists.gnu.org/archive/html/emacs-devel/2007-08/msg00410.html */
5205ee62
GM
2080static int default_max_colors;
2081static int default_max_pairs;
2082static int default_no_color_video;
2083static char *default_orig_pair;
2084static char *default_set_foreground;
2085static char *default_set_background;
fcf8ff2e 2086
ace28297
EZ
2087/* Save or restore the default color-related capabilities of this
2088 terminal. */
2089static void
28d7d09f 2090tty_default_color_capabilities (struct tty_display_info *tty, int save)
ace28297 2091{
ace28297
EZ
2092
2093 if (save)
2094 {
2095 if (default_orig_pair)
2096 xfree (default_orig_pair);
fca177d4 2097 default_orig_pair = tty->TS_orig_pair ? xstrdup (tty->TS_orig_pair) : NULL;
ace28297
EZ
2098
2099 if (default_set_foreground)
2100 xfree (default_set_foreground);
fca177d4 2101 default_set_foreground = tty->TS_set_foreground ? xstrdup (tty->TS_set_foreground)
ace28297
EZ
2102 : NULL;
2103
2104 if (default_set_background)
2105 xfree (default_set_background);
fca177d4 2106 default_set_background = tty->TS_set_background ? xstrdup (tty->TS_set_background)
ace28297
EZ
2107 : NULL;
2108
fca177d4
KL
2109 default_max_colors = tty->TN_max_colors;
2110 default_max_pairs = tty->TN_max_pairs;
2111 default_no_color_video = tty->TN_no_color_video;
ace28297
EZ
2112 }
2113 else
2114 {
fca177d4
KL
2115 tty->TS_orig_pair = default_orig_pair;
2116 tty->TS_set_foreground = default_set_foreground;
2117 tty->TS_set_background = default_set_background;
2118 tty->TN_max_colors = default_max_colors;
2119 tty->TN_max_pairs = default_max_pairs;
2120 tty->TN_no_color_video = default_no_color_video;
ace28297
EZ
2121 }
2122}
2123
2124/* Setup one of the standard tty color schemes according to MODE.
2125 MODE's value is generally the number of colors which we want to
2126 support; zero means set up for the default capabilities, the ones
a4c6993d 2127 we saw at init_tty time; -1 means turn off color support. */
ed8dad6b 2128static void
28d7d09f 2129tty_setup_colors (struct tty_display_info *tty, int mode)
ace28297 2130{
6b61353c
KH
2131 /* Canonicalize all negative values of MODE. */
2132 if (mode < -1)
2133 mode = -1;
2134
ace28297
EZ
2135 switch (mode)
2136 {
2137 case -1: /* no colors at all */
fca177d4
KL
2138 tty->TN_max_colors = 0;
2139 tty->TN_max_pairs = 0;
2140 tty->TN_no_color_video = 0;
2141 tty->TS_set_foreground = tty->TS_set_background = tty->TS_orig_pair = NULL;
ace28297
EZ
2142 break;
2143 case 0: /* default colors, if any */
2144 default:
fca177d4 2145 tty_default_color_capabilities (tty, 0);
ace28297
EZ
2146 break;
2147 case 8: /* 8 standard ANSI colors */
fca177d4 2148 tty->TS_orig_pair = "\033[0m";
ace28297 2149#ifdef TERMINFO
fca177d4
KL
2150 tty->TS_set_foreground = "\033[3%p1%dm";
2151 tty->TS_set_background = "\033[4%p1%dm";
ace28297 2152#else
fca177d4
KL
2153 tty->TS_set_foreground = "\033[3%dm";
2154 tty->TS_set_background = "\033[4%dm";
ace28297 2155#endif
fca177d4
KL
2156 tty->TN_max_colors = 8;
2157 tty->TN_max_pairs = 64;
2158 tty->TN_no_color_video = 0;
ace28297
EZ
2159 break;
2160 }
2161}
2162
2163void
2164set_tty_color_mode (f, val)
2165 struct frame *f;
2166 Lisp_Object val;
2167{
dfc7a077 2168 Lisp_Object color_mode_spec, current_mode_spec;
ace28297
EZ
2169 Lisp_Object color_mode, current_mode;
2170 int mode, old_mode;
2171 extern Lisp_Object Qtty_color_mode;
2172 Lisp_Object tty_color_mode_alist;
2173
2174 tty_color_mode_alist = Fintern_soft (build_string ("tty-color-mode-alist"),
2175 Qnil);
2176
6b61353c 2177 if (INTEGERP (val))
ace28297
EZ
2178 color_mode = val;
2179 else
2180 {
2181 if (NILP (tty_color_mode_alist))
2182 color_mode_spec = Qnil;
2183 else
2184 color_mode_spec = Fassq (val, XSYMBOL (tty_color_mode_alist)->value);
ace28297
EZ
2185
2186 if (CONSP (color_mode_spec))
2187 color_mode = XCDR (color_mode_spec);
2188 else
2189 color_mode = Qnil;
2190 }
6b61353c
KH
2191
2192 current_mode_spec = assq_no_quit (Qtty_color_mode, f->param_alist);
2193
ace28297
EZ
2194 if (CONSP (current_mode_spec))
2195 current_mode = XCDR (current_mode_spec);
2196 else
2197 current_mode = Qnil;
6b61353c 2198 if (INTEGERP (color_mode))
ace28297
EZ
2199 mode = XINT (color_mode);
2200 else
2201 mode = 0; /* meaning default */
6b61353c 2202 if (INTEGERP (current_mode))
ace28297
EZ
2203 old_mode = XINT (current_mode);
2204 else
2205 old_mode = 0;
2206
2207 if (mode != old_mode)
2208 {
fca177d4 2209 tty_setup_colors (FRAME_TTY (f), mode);
ace28297
EZ
2210 /* This recomputes all the faces given the new color
2211 definitions. */
2212 call0 (intern ("tty-set-up-initial-frame-faces"));
2213 redraw_frame (f);
2214 }
2215}
2216
2217#endif /* !WINDOWSNT */
a168702a
GM
2218
2219\f
28d440ab 2220
6ed8eeff 2221/* Return the tty display object specified by TERMINAL. */
b6660415 2222
6ed8eeff 2223struct terminal *
717a00ef 2224get_tty_terminal (Lisp_Object terminal, int throw)
b6660415 2225{
717a00ef 2226 struct terminal *t = get_terminal (terminal, throw);
62af879c 2227
6ed8eeff 2228 if (t && t->type != output_termcap)
717a00ef
KL
2229 {
2230 if (throw)
2231 error ("Device %d is not a termcap terminal device", t->id);
2232 else
2233 return NULL;
2234 }
b6660415 2235
6ed8eeff 2236 return t;
b6660415
KL
2237}
2238
ab797f65
KL
2239/* Return an active termcap device that uses the tty device with the
2240 given name.
b6660415 2241
7e59217d 2242 This function ignores suspended devices.
da8e1115
KL
2243
2244 Returns NULL if the named terminal device is not opened. */
f4d953fc 2245
6ed8eeff 2246struct terminal *
7e59217d 2247get_named_tty (name)
28d440ab
KL
2248 char *name;
2249{
6ed8eeff
KL
2250 struct terminal *t;
2251
ab797f65
KL
2252 if (!name)
2253 abort ();
2254
2255 for (t = terminal_list; t; t = t->next_terminal)
2256 {
2257 if (t->type == output_termcap
2258 && !strcmp (t->display_info.tty->name, name)
2259 && TERMINAL_ACTIVE_P (t))
2260 return t;
2261 }
28d440ab
KL
2262
2263 return 0;
2264}
2265
2266\f
6ed8eeff
KL
2267DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0,
2268 doc: /* Return the type of the tty device that TERMINAL uses.
ab797f65 2269Returns nil if TERMINAL is not on a tty device.
a3fbb897 2270
6ed8eeff
KL
2271TERMINAL can be a terminal id, a frame or nil (meaning the selected
2272frame's terminal). */)
2273 (terminal)
2274 Lisp_Object terminal;
b6660415 2275{
6ed8eeff 2276 struct terminal *t = get_terminal (terminal, 1);
819b8f00 2277
6ed8eeff 2278 if (t->type != output_termcap)
ab797f65
KL
2279 return Qnil;
2280
6ed8eeff
KL
2281 if (t->display_info.tty->type)
2282 return build_string (t->display_info.tty->type);
819b8f00
KL
2283 else
2284 return Qnil;
2285}
2286
6ed8eeff
KL
2287DEFUN ("controlling-tty-p", Fcontrolling_tty_p, Scontrolling_tty_p, 0, 1, 0,
2288 doc: /* Return non-nil if TERMINAL is on the controlling tty of the Emacs process.
a3fbb897 2289
6ed8eeff
KL
2290TERMINAL can be a terminal id, a frame or nil (meaning the selected
2291frame's terminal). This function always returns nil if TERMINAL
2292is not on a tty device. */)
2293 (terminal)
2294 Lisp_Object terminal;
4a933ef8 2295{
6ed8eeff 2296 struct terminal *t = get_terminal (terminal, 1);
4a933ef8 2297
78048085 2298 if (t->type != output_termcap || strcmp (t->display_info.tty->name, DEV_TTY))
4a933ef8
KL
2299 return Qnil;
2300 else
2301 return Qt;
2302}
2303
a3fbb897 2304DEFUN ("tty-no-underline", Ftty_no_underline, Stty_no_underline, 0, 1, 0,
6ed8eeff 2305 doc: /* Declare that the tty used by TERMINAL does not handle underlining.
a3fbb897
KL
2306This is used to override the terminfo data, for certain terminals that
2307do not really do underlining, but say that they do. This function has
6ed8eeff 2308no effect if used on a non-tty terminal.
a3fbb897 2309
6ed8eeff
KL
2310TERMINAL can be a terminal id, a frame or nil (meaning the selected
2311frame's terminal). This function always returns nil if TERMINAL
2312is not on a tty device. */)
2313 (terminal)
2314 Lisp_Object terminal;
a3fbb897 2315{
6ed8eeff 2316 struct terminal *t = get_terminal (terminal, 1);
a3fbb897 2317
6ed8eeff
KL
2318 if (t->type == output_termcap)
2319 t->display_info.tty->TS_enter_underline_mode = 0;
a3fbb897
KL
2320 return Qnil;
2321}
2322
ed8dad6b
KL
2323\f
2324
2325DEFUN ("suspend-tty", Fsuspend_tty, Ssuspend_tty, 0, 1, 0,
2326 doc: /* Suspend the terminal device TTY.
2327
2328The device is restored to its default state, and Emacs ceases all
2329access to the tty device. Frames that use the device are not deleted,
2330but input is not read from them and if they change, their display is
2331not updated.
2332
2333TTY may be a terminal id, a frame, or nil for the terminal device of
2334the currently selected frame.
2335
e4019195 2336This function runs `suspend-tty-functions' after suspending the
ed8dad6b
KL
2337device. The functions are run with one arg, the id of the suspended
2338terminal device.
2339
2340`suspend-tty' does nothing if it is called on a device that is already
2341suspended.
2342
2343A suspended tty may be resumed by calling `resume-tty' on it. */)
2344 (tty)
2345 Lisp_Object tty;
2346{
717a00ef 2347 struct terminal *t = get_tty_terminal (tty, 1);
ed8dad6b 2348 FILE *f;
f4d953fc 2349
6ed8eeff 2350 if (!t)
ed8dad6b
KL
2351 error ("Unknown tty device");
2352
6ed8eeff 2353 f = t->display_info.tty->input;
f4d953fc 2354
ed8dad6b
KL
2355 if (f)
2356 {
23d4cba5
DN
2357 /* First run `suspend-tty-functions' and then clean up the tty
2358 state because `suspend-tty-functions' might need to change
2359 the tty state. */
2360 if (!NILP (Vrun_hooks))
2361 {
2362 Lisp_Object args[2];
2363 args[0] = intern ("suspend-tty-functions");
2364 XSETTERMINAL (args[1], t);
2365 Frun_hook_with_args (2, args);
2366 }
2367
6ed8eeff 2368 reset_sys_modes (t->display_info.tty);
ed8dad6b
KL
2369
2370 delete_keyboard_wait_descriptor (fileno (f));
f4d953fc 2371
ed8dad6b 2372 fclose (f);
6ed8eeff
KL
2373 if (f != t->display_info.tty->output)
2374 fclose (t->display_info.tty->output);
f4d953fc 2375
6ed8eeff
KL
2376 t->display_info.tty->input = 0;
2377 t->display_info.tty->output = 0;
ed8dad6b 2378
6ed8eeff
KL
2379 if (FRAMEP (t->display_info.tty->top_frame))
2380 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0);
f4d953fc 2381
ed8dad6b
KL
2382 }
2383
4a665758
KL
2384 /* Clear display hooks to prevent further output. */
2385 clear_tty_hooks (t);
2386
ed8dad6b
KL
2387 return Qnil;
2388}
2389
2390DEFUN ("resume-tty", Fresume_tty, Sresume_tty, 0, 1, 0,
2391 doc: /* Resume the previously suspended terminal device TTY.
2392The terminal is opened and reinitialized. Frames that are on the
6ed8eeff 2393suspended terminal are revived.
ed8dad6b 2394
6ed8eeff
KL
2395It is an error to resume a terminal while another terminal is active
2396on the same device.
ed8dad6b 2397
e4019195 2398This function runs `resume-tty-functions' after resuming the terminal.
6ed8eeff 2399The functions are run with one arg, the id of the resumed terminal
ed8dad6b
KL
2400device.
2401
2402`resume-tty' does nothing if it is called on a device that is not
2403suspended.
2404
6ed8eeff
KL
2405TTY may be a terminal id, a frame, or nil for the terminal device of
2406the currently selected frame. */)
ed8dad6b
KL
2407 (tty)
2408 Lisp_Object tty;
2409{
717a00ef 2410 struct terminal *t = get_tty_terminal (tty, 1);
ed8dad6b
KL
2411 int fd;
2412
6ed8eeff 2413 if (!t)
ed8dad6b
KL
2414 error ("Unknown tty device");
2415
6ed8eeff 2416 if (!t->display_info.tty->input)
ed8dad6b 2417 {
6ed8eeff 2418 if (get_named_tty (t->display_info.tty->name))
ed8dad6b
KL
2419 error ("Cannot resume display while another display is active on the same device");
2420
6ed8eeff 2421 fd = emacs_open (t->display_info.tty->name, O_RDWR | O_NOCTTY, 0);
ed8dad6b 2422
59b3194c
KL
2423 if (fd == -1)
2424 error ("Can not reopen tty device %s: %s", t->display_info.tty->name, strerror (errno));
ed8dad6b 2425
78048085 2426 if (strcmp (t->display_info.tty->name, DEV_TTY))
59b3194c 2427 dissociate_if_controlling_tty (fd);
78048085 2428
6ed8eeff
KL
2429 t->display_info.tty->output = fdopen (fd, "w+");
2430 t->display_info.tty->input = t->display_info.tty->output;
78048085 2431
ed8dad6b
KL
2432 add_keyboard_wait_descriptor (fd);
2433
6ed8eeff
KL
2434 if (FRAMEP (t->display_info.tty->top_frame))
2435 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
ed8dad6b 2436
6ed8eeff 2437 init_sys_modes (t->display_info.tty);
ed8dad6b 2438
e4019195 2439 /* Run `resume-tty-functions'. */
ed8dad6b
KL
2440 if (!NILP (Vrun_hooks))
2441 {
2442 Lisp_Object args[2];
e4019195 2443 args[0] = intern ("resume-tty-functions");
59a7bc63 2444 XSETTERMINAL (args[1], t);
ed8dad6b
KL
2445 Frun_hook_with_args (2, args);
2446 }
2447 }
2448
4a665758
KL
2449 set_tty_hooks (t);
2450
ed8dad6b
KL
2451 return Qnil;
2452}
a3fbb897 2453
819b8f00 2454\f
e882229c
NR
2455/***********************************************************************
2456 Mouse
2457 ***********************************************************************/
2458
7e5a23bd 2459#ifdef HAVE_GPM
5faa03ba
RS
2460void
2461term_mouse_moveto (int x, int y)
94da14a0 2462{
1ec5dc77 2463 /* TODO: how to set mouse position?
94da14a0
NR
2464 const char *name;
2465 int fd;
2466 name = (const char *) ttyname (0);
2467 fd = open (name, O_WRONLY);
80fb2ce0 2468 SOME_FUNCTION (x, y, fd);
94da14a0
NR
2469 close (fd);
2470 last_mouse_x = x;
80fb2ce0 2471 last_mouse_y = y; */
94da14a0
NR
2472}
2473
e882229c
NR
2474static void
2475term_show_mouse_face (enum draw_glyphs_face draw)
2476{
6178ce5e 2477 struct window *w = XWINDOW (mouse_face_window);
e882229c 2478 int save_x, save_y;
1ec5dc77 2479 int i;
e882229c 2480
7be1c21a
MB
2481 struct frame *f = XFRAME (w->frame);
2482 struct tty_display_info *tty = FRAME_TTY (f);
2483
e882229c
NR
2484 if (/* If window is in the process of being destroyed, don't bother
2485 to do anything. */
2486 w->current_matrix != NULL
2487 /* Recognize when we are called to operate on rows that don't exist
2488 anymore. This can happen when a window is split. */
2489 && mouse_face_end_row < w->current_matrix->nrows)
2490 {
2491 /* write_glyphs writes at cursor position, so we need to
2492 temporarily move cursor coordinates to the beginning of
2493 the highlight region. */
f4d953fc 2494
e882229c 2495 /* Save current cursor co-ordinates */
7be1c21a
MB
2496 save_y = curY (tty);
2497 save_x = curX (tty);
e882229c
NR
2498
2499 /* Note that mouse_face_beg_row etc. are window relative. */
2500 for (i = mouse_face_beg_row; i <= mouse_face_end_row; i++)
2501 {
2502 int start_hpos, end_hpos, nglyphs;
2503 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
2504
2505 /* Don't do anything if row doesn't have valid contents. */
2506 if (!row->enabled_p)
2507 continue;
2508
2509 /* For all but the first row, the highlight starts at column 0. */
2510 if (i == mouse_face_beg_row)
2511 start_hpos = mouse_face_beg_col;
2512 else
2513 start_hpos = 0;
2514
2515 if (i == mouse_face_end_row)
2516 end_hpos = mouse_face_end_col;
2517 else
2518 {
2519 end_hpos = row->used[TEXT_AREA];
2520 if (draw == DRAW_NORMAL_TEXT)
2521 row->fill_line_p = 1; /* Clear to end of line */
2522 }
2523
2524 if (end_hpos <= start_hpos)
2525 continue;
2526 /* Record that some glyphs of this row are displayed in
2527 mouse-face. */
2528 row->mouse_face_p = draw > 0;
2529
2530 nglyphs = end_hpos - start_hpos;
2531
2532 if (end_hpos >= row->used[TEXT_AREA])
2533 nglyphs = row->used[TEXT_AREA] - start_hpos;
2534
2535 pos_y = row->y + WINDOW_TOP_EDGE_Y (w);
2536 pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos
2537 + WINDOW_LEFT_EDGE_X (w);
f4d953fc 2538
7be1c21a 2539 cursor_to (f, pos_y, pos_x);
e882229c
NR
2540
2541 if (draw == DRAW_MOUSE_FACE)
2542 {
7be1c21a 2543 tty_write_glyphs_with_face (f, row->glyphs[TEXT_AREA] + start_hpos,
e882229c
NR
2544 nglyphs, mouse_face_face_id);
2545 }
2546 else /* draw == DRAW_NORMAL_TEXT */
7be1c21a 2547 write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
e882229c 2548 }
7be1c21a 2549 cursor_to (f, save_y, save_x);
e882229c
NR
2550 }
2551}
2552
2553static void
2554term_clear_mouse_face ()
2555{
6178ce5e 2556 if (!NILP (mouse_face_window))
e882229c
NR
2557 term_show_mouse_face (DRAW_NORMAL_TEXT);
2558
2559 mouse_face_beg_row = mouse_face_beg_col = -1;
2560 mouse_face_end_row = mouse_face_end_col = -1;
6178ce5e 2561 mouse_face_window = Qnil;
e882229c
NR
2562}
2563
2564/* Find the glyph matrix position of buffer position POS in window W.
2565 *HPOS and *VPOS are set to the positions found. W's current glyphs
2566 must be up to date. If POS is above window start return (0, 0).
2567 If POS is after end of W, return end of last line in W.
2568 - taken from msdos.c */
2569static int
2570fast_find_position (struct window *w, int pos, int *hpos, int *vpos)
2571{
2572 int i, lastcol, line_start_position, maybe_next_line_p = 0;
2573 int yb = window_text_bottom_y (w);
2574 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0), *best_row = row;
2575
2576 while (row->y < yb)
2577 {
2578 if (row->used[TEXT_AREA])
2579 line_start_position = row->glyphs[TEXT_AREA]->charpos;
2580 else
2581 line_start_position = 0;
2582
2583 if (line_start_position > pos)
2584 break;
2585 /* If the position sought is the end of the buffer,
2586 don't include the blank lines at the bottom of the window. */
2587 else if (line_start_position == pos
2588 && pos == BUF_ZV (XBUFFER (w->buffer)))
2589 {
2590 maybe_next_line_p = 1;
2591 break;
2592 }
2593 else if (line_start_position > 0)
2594 best_row = row;
2595
2596 /* Don't overstep the last matrix row, lest we get into the
2597 never-never land... */
2598 if (row->y + 1 >= yb)
2599 break;
2600
2601 ++row;
2602 }
2603
2604 /* Find the right column within BEST_ROW. */
2605 lastcol = 0;
2606 row = best_row;
2607 for (i = 0; i < row->used[TEXT_AREA]; i++)
2608 {
2609 struct glyph *glyph = row->glyphs[TEXT_AREA] + i;
2610 int charpos;
2611
2612 charpos = glyph->charpos;
2613 if (charpos == pos)
2614 {
2615 *hpos = i;
2616 *vpos = row->y;
2617 return 1;
2618 }
2619 else if (charpos > pos)
2620 break;
2621 else if (charpos > 0)
2622 lastcol = i;
2623 }
2624
2625 /* If we're looking for the end of the buffer,
2626 and we didn't find it in the line we scanned,
2627 use the start of the following line. */
2628 if (maybe_next_line_p)
2629 {
2630 ++row;
2631 lastcol = 0;
2632 }
2633
2634 *vpos = row->y;
2635 *hpos = lastcol + 1;
2636 return 0;
2637}
2638
2639static void
2640term_mouse_highlight (struct frame *f, int x, int y)
2641{
2642 enum window_part part;
2643 Lisp_Object window;
2644 struct window *w;
2645 struct buffer *b;
2646
2647 if (NILP (Vmouse_highlight)
2648 || !f->glyphs_initialized_p)
2649 return;
2650
e882229c
NR
2651 /* Which window is that in? */
2652 window = window_from_coordinates (f, x, y, &part, &x, &y, 0);
2653
2654 /* Not on a window -> return. */
2655 if (!WINDOWP (window))
2656 return;
2657
6178ce5e 2658 if (!EQ (window, mouse_face_window))
e882229c
NR
2659 term_clear_mouse_face ();
2660
2661 w = XWINDOW (window);
2662
2663 /* Are we in a window whose display is up to date?
2664 And verify the buffer's text has not changed. */
2665 b = XBUFFER (w->buffer);
2666 if (part == ON_TEXT
2667 && EQ (w->window_end_valid, w->buffer)
2668 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
2669 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
2670 {
2671 int pos, i, nrows = w->current_matrix->nrows;
2672 struct glyph_row *row;
2673 struct glyph *glyph;
2674
2675 /* Find the glyph under X/Y. */
2676 glyph = NULL;
2677 if (y >= 0 && y < nrows)
2678 {
2679 row = MATRIX_ROW (w->current_matrix, y);
2680 /* Give up if some row before the one we are looking for is
2681 not enabled. */
2682 for (i = 0; i <= y; i++)
2683 if (!MATRIX_ROW (w->current_matrix, i)->enabled_p)
2684 break;
2685 if (i > y /* all rows upto and including the one at Y are enabled */
2686 && row->displays_text_p
2687 && x < window_box_width (w, TEXT_AREA))
2688 {
2689 glyph = row->glyphs[TEXT_AREA];
2690 if (x >= row->used[TEXT_AREA])
2691 glyph = NULL;
2692 else
2693 {
2694 glyph += x;
2695 if (!BUFFERP (glyph->object))
2696 glyph = NULL;
2697 }
2698 }
2699 }
2700
2701 /* Clear mouse face if X/Y not over text. */
2702 if (glyph == NULL)
2703 {
2704 term_clear_mouse_face ();
2705 return;
2706 }
2707
2708 if (!BUFFERP (glyph->object))
2709 abort ();
2710 pos = glyph->charpos;
2711
2712 /* Check for mouse-face. */
2713 {
2714 extern Lisp_Object Qmouse_face;
2715 Lisp_Object mouse_face, overlay, position, *overlay_vec;
3b8c0c70 2716 int noverlays, obegv, ozv;
e882229c
NR
2717 struct buffer *obuf;
2718
2719 /* If we get an out-of-range value, return now; avoid an error. */
2720 if (pos > BUF_Z (b))
2721 return;
2722
2723 /* Make the window's buffer temporarily current for
2724 overlays_at and compute_char_face. */
2725 obuf = current_buffer;
2726 current_buffer = b;
2727 obegv = BEGV;
2728 ozv = ZV;
2729 BEGV = BEG;
2730 ZV = Z;
2731
2732 /* Is this char mouse-active? */
2733 XSETINT (position, pos);
2734
2735 /* Put all the overlays we want in a vector in overlay_vec. */
2736 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL, 0);
2737 /* Sort overlays into increasing priority order. */
2738 noverlays = sort_overlays (overlay_vec, noverlays, w);
2739
2740 /* Check mouse-face highlighting. */
6178ce5e 2741 if (!(EQ (window, mouse_face_window)
e882229c
NR
2742 && y >= mouse_face_beg_row
2743 && y <= mouse_face_end_row
2744 && (y > mouse_face_beg_row
2745 || x >= mouse_face_beg_col)
2746 && (y < mouse_face_end_row
2747 || x < mouse_face_end_col
2748 || mouse_face_past_end)))
2749 {
2750 /* Clear the display of the old active region, if any. */
2751 term_clear_mouse_face ();
2752
2753 /* Find the highest priority overlay that has a mouse-face
2754 property. */
2755 overlay = Qnil;
2756 for (i = noverlays - 1; i >= 0; --i)
2757 {
2758 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
2759 if (!NILP (mouse_face))
2760 {
2761 overlay = overlay_vec[i];
2762 break;
2763 }
2764 }
2765
2766 /* If no overlay applies, get a text property. */
2767 if (NILP (overlay))
2768 mouse_face = Fget_text_property (position, Qmouse_face,
2769 w->buffer);
2770
2771 /* Handle the overlay case. */
2772 if (!NILP (overlay))
2773 {
2774 /* Find the range of text around this char that
2775 should be active. */
2776 Lisp_Object before, after;
0f8b27ea 2777 EMACS_INT ignore;
e882229c
NR
2778
2779
2780 before = Foverlay_start (overlay);
2781 after = Foverlay_end (overlay);
2782 /* Record this as the current active region. */
2783 fast_find_position (w, XFASTINT (before),
2784 &mouse_face_beg_col,
2785 &mouse_face_beg_row);
2786
2787 mouse_face_past_end
2788 = !fast_find_position (w, XFASTINT (after),
2789 &mouse_face_end_col,
2790 &mouse_face_end_row);
6178ce5e 2791 mouse_face_window = window;
e882229c
NR
2792
2793 mouse_face_face_id
2794 = face_at_buffer_position (w, pos, 0, 0,
2795 &ignore, pos + 1, 1);
2796
2797 /* Display it as active. */
2798 term_show_mouse_face (DRAW_MOUSE_FACE);
2799 }
2800 /* Handle the text property case. */
2801 else if (!NILP (mouse_face))
2802 {
2803 /* Find the range of text around this char that
2804 should be active. */
2805 Lisp_Object before, after, beginning, end;
0f8b27ea 2806 EMACS_INT ignore;
e882229c
NR
2807
2808 beginning = Fmarker_position (w->start);
2809 XSETINT (end, (BUF_Z (b) - XFASTINT (w->window_end_pos)));
2810 before
2811 = Fprevious_single_property_change (make_number (pos + 1),
2812 Qmouse_face,
2813 w->buffer, beginning);
2814 after
2815 = Fnext_single_property_change (position, Qmouse_face,
2816 w->buffer, end);
2817
2818 /* Record this as the current active region. */
2819 fast_find_position (w, XFASTINT (before),
2820 &mouse_face_beg_col,
2821 &mouse_face_beg_row);
2822 mouse_face_past_end
2823 = !fast_find_position (w, XFASTINT (after),
2824 &mouse_face_end_col,
2825 &mouse_face_end_row);
6178ce5e 2826 mouse_face_window = window;
e882229c
NR
2827
2828 mouse_face_face_id
2829 = face_at_buffer_position (w, pos, 0, 0,
2830 &ignore, pos + 1, 1);
2831
2832 /* Display it as active. */
2833 term_show_mouse_face (DRAW_MOUSE_FACE);
2834 }
2835 }
2836
2837 /* Look for a `help-echo' property. */
2838 {
2839 Lisp_Object help;
2840 extern Lisp_Object Qhelp_echo;
2841
2842 /* Check overlays first. */
2843 help = Qnil;
2844 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
2845 {
2846 overlay = overlay_vec[i];
2847 help = Foverlay_get (overlay, Qhelp_echo);
2848 }
2849
2850 if (!NILP (help))
2851 {
2852 help_echo_string = help;
2853 help_echo_window = window;
2854 help_echo_object = overlay;
2855 help_echo_pos = pos;
2856 }
2857 /* Try text properties. */
2858 else if (NILP (help)
2859 && ((STRINGP (glyph->object)
2860 && glyph->charpos >= 0
2861 && glyph->charpos < SCHARS (glyph->object))
2862 || (BUFFERP (glyph->object)
2863 && glyph->charpos >= BEGV
2864 && glyph->charpos < ZV)))
2865 {
2866 help = Fget_text_property (make_number (glyph->charpos),
2867 Qhelp_echo, glyph->object);
2868 if (!NILP (help))
2869 {
2870 help_echo_string = help;
2871 help_echo_window = window;
2872 help_echo_object = glyph->object;
2873 help_echo_pos = glyph->charpos;
2874 }
2875 }
2876 }
2877
2878 BEGV = obegv;
2879 ZV = ozv;
2880 current_buffer = obuf;
2881 }
2882 }
2883}
2884
2885static int
2886term_mouse_movement (FRAME_PTR frame, Gpm_Event *event)
2887{
2888 /* Has the mouse moved off the glyph it was on at the last sighting? */
2889 if (event->x != last_mouse_x || event->y != last_mouse_y)
2890 {
2891 frame->mouse_moved = 1;
80fb2ce0 2892 term_mouse_highlight (frame, event->x, event->y);
e882229c
NR
2893 /* Remember which glyph we're now on. */
2894 last_mouse_x = event->x;
2895 last_mouse_y = event->y;
2896 return 1;
2897 }
2898 return 0;
2899}
2900
2901/* Return the current position of the mouse.
2902
2903 Set *f to the frame the mouse is in, or zero if the mouse is in no
2904 Emacs frame. If it is set to zero, all the other arguments are
2905 garbage.
2906
2907 Set *bar_window to Qnil, and *x and *y to the column and
2908 row of the character cell the mouse is over.
2909
2910 Set *time to the time the mouse was at the returned position.
2911
80fb2ce0 2912 This clears mouse_moved until the next motion
94da14a0 2913 event arrives. */
e882229c
NR
2914static void
2915term_mouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
2916 enum scroll_bar_part *part, Lisp_Object *x,
2917 Lisp_Object *y, unsigned long *time)
2918{
e882229c 2919 struct timeval now;
e882229c
NR
2920
2921 *fp = SELECTED_FRAME ();
94da14a0 2922 (*fp)->mouse_moved = 0;
e882229c
NR
2923
2924 *bar_window = Qnil;
2925 *part = 0;
2926
80fb2ce0 2927 XSETINT (*x, last_mouse_x);
94da14a0 2928 XSETINT (*y, last_mouse_y);
e882229c
NR
2929 gettimeofday(&now, 0);
2930 *time = (now.tv_sec * 1000) + (now.tv_usec / 1000);
e882229c
NR
2931}
2932
2933/* Prepare a mouse-event in *RESULT for placement in the input queue.
2934
2935 If the event is a button press, then note that we have grabbed
2936 the mouse. */
2937
2938static Lisp_Object
2939term_mouse_click (struct input_event *result, Gpm_Event *event,
2940 struct frame *f)
2941{
2942 struct timeval now;
2943 int i, j;
2944
2945 result->kind = GPM_CLICK_EVENT;
2946 for (i = 0, j = GPM_B_LEFT; i < 3; i++, j >>= 1 )
2947 {
2948 if (event->buttons & j) {
2949 result->code = i; /* button number */
2950 break;
2951 }
2952 }
2953 gettimeofday(&now, 0);
2954 result->timestamp = (now.tv_sec * 1000) + (now.tv_usec / 1000);
2955
2956 if (event->type & GPM_UP)
2957 result->modifiers = up_modifier;
2958 else if (event->type & GPM_DOWN)
2959 result->modifiers = down_modifier;
2960 else
2961 result->modifiers = 0;
f4d953fc 2962
e882229c
NR
2963 if (event->type & GPM_SINGLE)
2964 result->modifiers |= click_modifier;
f4d953fc 2965
e882229c
NR
2966 if (event->type & GPM_DOUBLE)
2967 result->modifiers |= double_modifier;
2968
2969 if (event->type & GPM_TRIPLE)
2970 result->modifiers |= triple_modifier;
2971
2972 if (event->type & GPM_DRAG)
2973 result->modifiers |= drag_modifier;
2974
80fb2ce0 2975 if (!(event->type & (GPM_MOVE | GPM_DRAG))) {
e882229c
NR
2976
2977 /* 1 << KG_SHIFT */
2978 if (event->modifiers & (1 << 0))
2979 result->modifiers |= shift_modifier;
2980
2981 /* 1 << KG_CTRL */
2982 if (event->modifiers & (1 << 2))
2983 result->modifiers |= ctrl_modifier;
2984
2985 /* 1 << KG_ALT || KG_ALTGR */
2986 if (event->modifiers & (1 << 3)
2987 || event->modifiers & (1 << 1))
2988 result->modifiers |= meta_modifier;
2989 }
2990
80fb2ce0
NR
2991 XSETINT (result->x, event->x);
2992 XSETINT (result->y, event->y);
e882229c
NR
2993 XSETFRAME (result->frame_or_window, f);
2994 result->arg = Qnil;
2995 return Qnil;
2996}
2997
f4d953fc 2998int
7be1c21a 2999handle_one_term_event (struct tty_display_info *tty, Gpm_Event *event, struct input_event* hold_quit)
e882229c 3000{
7be1c21a 3001 struct frame *f = XFRAME (tty->top_frame);
e882229c
NR
3002 struct input_event ie;
3003 int do_help = 0;
3004 int count = 0;
3005
3006 EVENT_INIT (ie);
3007 ie.kind = NO_EVENT;
3008 ie.arg = Qnil;
3009
80fb2ce0 3010 if (event->type & (GPM_MOVE | GPM_DRAG)) {
e882229c
NR
3011 previous_help_echo_string = help_echo_string;
3012 help_echo_string = Qnil;
3013
6178ce5e 3014 Gpm_DrawPointer (event->x, event->y, fileno (tty->output));
e882229c 3015
80fb2ce0
NR
3016 if (!term_mouse_movement (f, event))
3017 help_echo_string = previous_help_echo_string;
e882229c
NR
3018
3019 /* If the contents of the global variable help_echo_string
3020 has changed, generate a HELP_EVENT. */
3021 if (!NILP (help_echo_string)
3022 || !NILP (previous_help_echo_string))
3023 do_help = 1;
3024
3025 goto done;
3026 }
3027 else {
3028 f->mouse_moved = 0;
3029 term_mouse_click (&ie, event, f);
e882229c
NR
3030 }
3031
3032 done:
3033 if (ie.kind != NO_EVENT)
3034 {
3035 kbd_buffer_store_event_hold (&ie, hold_quit);
3036 count++;
3037 }
3038
3039 if (do_help
3040 && !(hold_quit && hold_quit->kind != NO_EVENT))
3041 {
3042 Lisp_Object frame;
3043
3044 if (f)
3045 XSETFRAME (frame, f);
3046 else
3047 frame = Qnil;
3048
3049 gen_help_event (help_echo_string, frame, help_echo_window,
3050 help_echo_object, help_echo_pos);
3051 count++;
3052 }
3053
3054 return count;
3055}
3056
6178ce5e 3057DEFUN ("gpm-mouse-start", Fgpm_mouse_start, Sgpm_mouse_start,
e882229c 3058 0, 0, 0,
71f44e7a 3059 doc: /* Open a connection to Gpm.
6178ce5e 3060Gpm-mouse can only be activated for one tty at a time. */)
e882229c
NR
3061 ()
3062{
71f44e7a
SM
3063 struct frame *f = SELECTED_FRAME ();
3064 struct tty_display_info *tty
3065 = ((f)->output_method == output_termcap
3066 ? (f)->terminal->display_info.tty : NULL);
e882229c
NR
3067 Gpm_Connect connection;
3068
6178ce5e
SM
3069 if (!tty)
3070 error ("Gpm-mouse only works in the GNU/Linux console");
4ce5ab77
SM
3071 if (gpm_tty == tty)
3072 return Qnil; /* Already activated, nothing to do. */
3073 if (gpm_tty)
3074 error ("Gpm-mouse can only be activated for one tty at a time");
71f44e7a 3075
e882229c
NR
3076 connection.eventMask = ~0;
3077 connection.defaultMask = ~GPM_HARD;
3078 connection.maxMod = ~0;
3079 connection.minMod = 0;
80fb2ce0 3080 gpm_zerobased = 1;
e882229c
NR
3081
3082 if (Gpm_Open (&connection, 0) < 0)
6178ce5e 3083 error ("Gpm-mouse failed to connect to the gpm daemon");
e882229c
NR
3084 else
3085 {
71f44e7a 3086 gpm_tty = tty;
1023cbed
SM
3087 /* `init_sys_modes' arranges for mouse movements sent through gpm_fd
3088 to generate SIGIOs. Apparently we need to call reset_sys_modes
3089 before calling init_sys_modes. */
7be1c21a
MB
3090 reset_sys_modes (tty);
3091 init_sys_modes (tty);
e882229c 3092 add_gpm_wait_descriptor (gpm_fd);
6178ce5e 3093 return Qnil;
e882229c
NR
3094 }
3095}
3096
6178ce5e 3097DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop, Sgpm_mouse_stop,
e882229c
NR
3098 0, 0, 0,
3099 doc: /* Close a connection to Gpm. */)
3100 ()
3101{
4ce5ab77
SM
3102 struct frame *f = SELECTED_FRAME ();
3103 struct tty_display_info *tty
3104 = ((f)->output_method == output_termcap
3105 ? (f)->terminal->display_info.tty : NULL);
3106
3107 if (!tty || gpm_tty != tty)
3108 return Qnil; /* Not activated on this terminal, nothing to do. */
f4d953fc 3109
6178ce5e
SM
3110 if (gpm_fd >= 0)
3111 delete_gpm_wait_descriptor (gpm_fd);
3112 while (Gpm_Close()); /* close all the stack */
3113 gpm_tty = NULL;
3114 return Qnil;
e882229c 3115}
7e5a23bd 3116#endif /* HAVE_GPM */
e882229c
NR
3117
3118\f
a168702a
GM
3119/***********************************************************************
3120 Initialization
3121 ***********************************************************************/
3122
ed8dad6b
KL
3123/* Initialize the tty-dependent part of frame F. The frame must
3124 already have its device initialized. */
3224dac1 3125
dfcf069d 3126void
ed8dad6b 3127create_tty_output (struct frame *f)
28d440ab 3128{
ed8dad6b
KL
3129 struct tty_output *t;
3130
3131 if (! FRAME_TERMCAP_P (f))
428a555e
KL
3132 abort ();
3133
ed8dad6b
KL
3134 t = xmalloc (sizeof (struct tty_output));
3135 bzero (t, sizeof (struct tty_output));
b6660415 3136
6ed8eeff 3137 t->display_info = FRAME_TERMINAL (f)->display_info.tty;
bedb9c0e 3138
ed8dad6b 3139 f->output_data.tty = t;
3224dac1
KL
3140}
3141
ed8dad6b 3142/* Delete the tty-dependent part of frame F. */
da8e1115 3143
ed8dad6b
KL
3144static void
3145delete_tty_output (struct frame *f)
3224dac1 3146{
ed8dad6b 3147 if (! FRAME_TERMCAP_P (f))
3224dac1
KL
3148 abort ();
3149
ed8dad6b 3150 xfree (f->output_data.tty);
28d440ab
KL
3151}
3152
ed8dad6b 3153\f
47cc8819 3154/* Reset the hooks in TERMINAL. */
ed8dad6b 3155
4a665758
KL
3156static void
3157clear_tty_hooks (struct terminal *terminal)
3158{
3159 terminal->rif = 0;
3160 terminal->cursor_to_hook = 0;
3161 terminal->raw_cursor_to_hook = 0;
3162 terminal->clear_to_end_hook = 0;
3163 terminal->clear_frame_hook = 0;
3164 terminal->clear_end_of_line_hook = 0;
3165 terminal->ins_del_lines_hook = 0;
3166 terminal->insert_glyphs_hook = 0;
3167 terminal->write_glyphs_hook = 0;
3168 terminal->delete_glyphs_hook = 0;
3169 terminal->ring_bell_hook = 0;
3170 terminal->reset_terminal_modes_hook = 0;
3171 terminal->set_terminal_modes_hook = 0;
3172 terminal->update_begin_hook = 0;
3173 terminal->update_end_hook = 0;
3174 terminal->set_terminal_window_hook = 0;
3175 terminal->mouse_position_hook = 0;
3176 terminal->frame_rehighlight_hook = 0;
3177 terminal->frame_raise_lower_hook = 0;
974b73e8 3178 terminal->fullscreen_hook = 0;
4a665758
KL
3179 terminal->set_vertical_scroll_bar_hook = 0;
3180 terminal->condemn_scroll_bars_hook = 0;
3181 terminal->redeem_scroll_bar_hook = 0;
3182 terminal->judge_scroll_bars_hook = 0;
3183 terminal->read_socket_hook = 0;
3184 terminal->frame_up_to_date_hook = 0;
3185
3186 /* Leave these two set, or suspended frames are not deleted
3187 correctly. */
3188 terminal->delete_frame_hook = &delete_tty_output;
3189 terminal->delete_terminal_hook = &delete_tty;
3190}
3191
47cc8819
DN
3192/* Initialize hooks in TERMINAL with the values needed for a tty. */
3193
4a665758
KL
3194static void
3195set_tty_hooks (struct terminal *terminal)
3196{
3197 terminal->rif = 0; /* ttys don't support window-based redisplay. */
3198
3199 terminal->cursor_to_hook = &tty_cursor_to;
3200 terminal->raw_cursor_to_hook = &tty_raw_cursor_to;
3201
3202 terminal->clear_to_end_hook = &tty_clear_to_end;
3203 terminal->clear_frame_hook = &tty_clear_frame;
3204 terminal->clear_end_of_line_hook = &tty_clear_end_of_line;
3205
3206 terminal->ins_del_lines_hook = &tty_ins_del_lines;
3207
3208 terminal->insert_glyphs_hook = &tty_insert_glyphs;
3209 terminal->write_glyphs_hook = &tty_write_glyphs;
3210 terminal->delete_glyphs_hook = &tty_delete_glyphs;
3211
3212 terminal->ring_bell_hook = &tty_ring_bell;
f4d953fc 3213
4a665758
KL
3214 terminal->reset_terminal_modes_hook = &tty_reset_terminal_modes;
3215 terminal->set_terminal_modes_hook = &tty_set_terminal_modes;
3216 terminal->update_begin_hook = 0; /* Not needed. */
3217 terminal->update_end_hook = &tty_update_end;
3218 terminal->set_terminal_window_hook = &tty_set_terminal_window;
3219
3220 terminal->mouse_position_hook = 0; /* Not needed. */
3221 terminal->frame_rehighlight_hook = 0; /* Not needed. */
3222 terminal->frame_raise_lower_hook = 0; /* Not needed. */
3223
3224 terminal->set_vertical_scroll_bar_hook = 0; /* Not needed. */
3225 terminal->condemn_scroll_bars_hook = 0; /* Not needed. */
3226 terminal->redeem_scroll_bar_hook = 0; /* Not needed. */
3227 terminal->judge_scroll_bars_hook = 0; /* Not needed. */
3228
3229 terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */
3230 terminal->frame_up_to_date_hook = 0; /* Not needed. */
f4d953fc 3231
4a665758
KL
3232 terminal->delete_frame_hook = &delete_tty_output;
3233 terminal->delete_terminal_hook = &delete_tty;
3234}
3235
03a1d6bd 3236/* Drop the controlling terminal if fd is the same device. */
ed8dad6b 3237static void
03a1d6bd
KL
3238dissociate_if_controlling_tty (int fd)
3239{
5d333979 3240#ifndef WINDOWSNT
03a1d6bd 3241 int pgid;
8516815b 3242 EMACS_GET_TTY_PGRP (fd, &pgid); /* If tcgetpgrp succeeds, fd is the ctty. */
03a1d6bd
KL
3243 if (pgid != -1)
3244 {
8516815b 3245#if defined (USG) && !defined (BSD_PGRPS)
03a1d6bd
KL
3246 setpgrp ();
3247 no_controlling_tty = 1;
de52dcbb
DN
3248#elif defined (CYGWIN)
3249 setsid ();
3250 no_controlling_tty = 1;
03a1d6bd
KL
3251#else
3252#ifdef TIOCNOTTY /* Try BSD ioctls. */
8516815b 3253 sigblock (sigmask (SIGTTOU));
78048085 3254 fd = emacs_open (DEV_TTY, O_RDWR, 0);
8516815b
KL
3255 if (fd != -1 && ioctl (fd, TIOCNOTTY, 0) != -1)
3256 {
3257 no_controlling_tty = 1;
3258 }
3259 if (fd != -1)
3260 emacs_close (fd);
3261 sigunblock (sigmask (SIGTTOU));
03a1d6bd 3262#else
8516815b
KL
3263 /* Unknown system. */
3264 croak ();
03a1d6bd
KL
3265#endif /* ! TIOCNOTTY */
3266#endif /* ! USG */
71a96040 3267 }
78048085 3268#endif /* !WINDOWSNT */
03a1d6bd
KL
3269}
3270
520c4dfd
KL
3271static void maybe_fatal();
3272
3224dac1
KL
3273/* Create a termcap display on the tty device with the given name and
3274 type.
3275
ab797f65 3276 If NAME is NULL, then use the controlling tty, i.e., "/dev/tty".
3224dac1
KL
3277 Otherwise NAME should be a path to the tty device file,
3278 e.g. "/dev/pts/7".
28d440ab 3279
3224dac1
KL
3280 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
3281
3282 If MUST_SUCCEED is true, then all errors are fatal. */
da8e1115 3283
6ed8eeff 3284struct terminal *
a4c6993d 3285init_tty (char *name, char *terminal_type, int must_succeed)
08a24c47 3286{
59b3194c 3287 char *area = NULL;
08a24c47 3288 char **address = &area;
6b61353c
KH
3289 char *buffer = NULL;
3290 int buffer_size = 4096;
59b3194c 3291 register char *p = NULL;
08a24c47 3292 int status;
59b3194c
KL
3293 struct tty_display_info *tty = NULL;
3294 struct terminal *terminal = NULL;
3295 int ctty = 0; /* 1 if asked to open controlling tty. */
28d440ab 3296
3224dac1
KL
3297 if (!terminal_type)
3298 maybe_fatal (must_succeed, 0, 0,
3299 "Unknown terminal type",
3300 "Unknown terminal type");
b6660415 3301
ab797f65 3302 if (name == NULL)
78048085
EZ
3303 name = DEV_TTY;
3304 if (!strcmp (name, DEV_TTY))
ab797f65
KL
3305 ctty = 1;
3306
6ed8eeff
KL
3307 /* If we already have a terminal on the given device, use that. If
3308 all such terminals are suspended, create a new one instead. */
a4c6993d 3309 /* XXX Perhaps this should be made explicit by having init_tty
6ed8eeff 3310 always create a new terminal and separating terminal and frame
b6660415 3311 creation on Lisp level. */
6ed8eeff
KL
3312 terminal = get_named_tty (name);
3313 if (terminal)
3314 return terminal;
78048085 3315
6ed8eeff 3316 terminal = create_terminal ();
3224dac1
KL
3317 tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info));
3318 bzero (tty, sizeof (struct tty_display_info));
3319 tty->next = tty_list;
3320 tty_list = tty;
428a555e 3321
6ed8eeff
KL
3322 terminal->type = output_termcap;
3323 terminal->display_info.tty = tty;
3324 tty->terminal = terminal;
28d440ab 3325
7b00d185
KL
3326 tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
3327 Wcm_clear (tty);
daf01701 3328
55d5acfa 3329#ifndef WINDOWSNT
4a665758 3330 set_tty_hooks (terminal);
78048085 3331
59b3194c
KL
3332 {
3333 int fd;
3334 FILE *file;
0c72d684
KL
3335
3336#ifdef O_IGNORE_CTTY
59b3194c 3337 if (!ctty)
0c72d684
KL
3338 /* Open the terminal device. Don't recognize it as our
3339 controlling terminal, and don't make it the controlling tty
3340 if we don't have one at the moment. */
3341 fd = emacs_open (name, O_RDWR | O_IGNORE_CTTY | O_NOCTTY, 0);
59b3194c 3342 else
0c72d684 3343#else
2666355c 3344 /* Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
59b3194c
KL
3345 defined on Hurd. On other systems, we need to explicitly
3346 dissociate ourselves from the controlling tty when we want to
3347 open a frame on the same terminal. */
0c72d684 3348 fd = emacs_open (name, O_RDWR | O_NOCTTY, 0);
0c72d684
KL
3349#endif /* O_IGNORE_CTTY */
3350
59b3194c
KL
3351 if (fd < 0)
3352 maybe_fatal (must_succeed, buffer, terminal,
3353 "Could not open file: %s",
3354 "Could not open file: %s",
3355 name);
3356 if (!isatty (fd))
3357 {
3358 close (fd);
3359 maybe_fatal (must_succeed, buffer, terminal,
3360 "Not a tty device: %s",
3361 "Not a tty device: %s",
3362 name);
3363 }
0c72d684 3364
59b3194c
KL
3365#ifndef O_IGNORE_CTTY
3366 if (!ctty)
03a1d6bd 3367 dissociate_if_controlling_tty (fd);
59b3194c
KL
3368#endif
3369
3370 file = fdopen (fd, "w+");
3371 tty->name = xstrdup (name);
3372 terminal->name = xstrdup (name);
3373 tty->input = file;
3374 tty->output = file;
3375 }
78048085 3376
28d7d09f 3377 tty->type = xstrdup (terminal_type);
28d440ab 3378
819b8f00 3379 add_keyboard_wait_descriptor (fileno (tty->input));
daf01701 3380
55d5acfa 3381#endif
08a24c47 3382
288d5132
KH
3383 encode_terminal_src_size = 0;
3384 encode_terminal_dst_size = 0;
af645abf 3385
7e5a23bd 3386#ifdef HAVE_GPM
88acaaf2 3387 terminal->mouse_position_hook = term_mouse_position;
6178ce5e 3388 mouse_face_window = Qnil;
e882229c
NR
3389#endif
3390
cb28b9c2 3391#ifdef WINDOWSNT
953bf0dc 3392 initialize_w32_display (terminal);
a0236551
JR
3393 /* The following two are inaccessible from w32console.c. */
3394 terminal->delete_frame_hook = &delete_tty_output;
3395 terminal->delete_terminal_hook = &delete_tty;
cb28b9c2 3396
78048085
EZ
3397 tty->name = xstrdup (name);
3398 terminal->name = xstrdup (name);
3399 tty->type = xstrdup (terminal_type);
cb28b9c2 3400
55d5acfa 3401 tty->output = stdout;
a0236551
JR
3402 tty->input = stdin;
3403 add_keyboard_wait_descriptor (0);
cb28b9c2 3404
a0236551 3405 Wcm_clear (tty);
cb28b9c2 3406
5d333979
JR
3407 {
3408 struct frame *f = XFRAME (selected_frame);
cb28b9c2 3409
a0236551
JR
3410 FrameRows (tty) = FRAME_LINES (f);
3411 FrameCols (tty) = FRAME_COLS (f);
3412 tty->specified_window = FRAME_LINES (f);
cb28b9c2 3413
a0236551
JR
3414 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
3415 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
5d333979
JR
3416 }
3417 tty->delete_in_insert_mode = 1;
cb28b9c2 3418
daf01701 3419 UseTabs (tty) = 0;
6ed8eeff 3420 terminal->scroll_region_ok = 0;
cb28b9c2 3421
7e59217d 3422 /* Seems to insert lines when it's not supposed to, messing up the
6ed8eeff 3423 display. In doing a trace, it didn't seem to be called much, so I
7e59217d 3424 don't think we're losing anything by turning it off. */
6ed8eeff
KL
3425 terminal->line_ins_del_ok = 0;
3426 terminal->char_ins_del_ok = 1;
cb28b9c2
RS
3427
3428 baud_rate = 19200;
3429
5d333979 3430 tty->TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
cb28b9c2 3431
eccec691 3432#else /* not WINDOWSNT */
cb28b9c2 3433
6548cf00 3434 Wcm_clear (tty);
08a24c47 3435
6b61353c 3436 buffer = (char *) xmalloc (buffer_size);
78048085 3437
03a1d6bd
KL
3438 /* On some systems, tgetent tries to access the controlling
3439 terminal. */
3440 sigblock (sigmask (SIGTTOU));
08a24c47 3441 status = tgetent (buffer, terminal_type);
03a1d6bd 3442 sigunblock (sigmask (SIGTTOU));
78048085 3443
08a24c47 3444 if (status < 0)
b0347178
KH
3445 {
3446#ifdef TERMINFO
6ed8eeff 3447 maybe_fatal (must_succeed, buffer, terminal,
3224dac1
KL
3448 "Cannot open terminfo database file",
3449 "Cannot open terminfo database file");
b0347178 3450#else
6ed8eeff 3451 maybe_fatal (must_succeed, buffer, terminal,
3224dac1
KL
3452 "Cannot open termcap database file",
3453 "Cannot open termcap database file");
b0347178
KH
3454#endif
3455 }
08a24c47 3456 if (status == 0)
b0347178
KH
3457 {
3458#ifdef TERMINFO
6ed8eeff 3459 maybe_fatal (must_succeed, buffer, terminal,
3224dac1
KL
3460 "Terminal type %s is not defined",
3461 "Terminal type %s is not defined.\n\
b0347178
KH
3462If that is not the actual type of terminal you have,\n\
3463use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3464`setenv TERM ...') to specify the correct type. It may be necessary\n\
e12c1054 3465to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3224dac1 3466 terminal_type);
b0347178 3467#else
6ed8eeff 3468 maybe_fatal (must_succeed, buffer, terminal,
3224dac1
KL
3469 "Terminal type %s is not defined",
3470 "Terminal type %s is not defined.\n\
c5a9c3e6
RS
3471If that is not the actual type of terminal you have,\n\
3472use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3473`setenv TERM ...') to specify the correct type. It may be necessary\n\
e12c1054 3474to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3224dac1 3475 terminal_type);
b0347178
KH
3476#endif
3477 }
6b61353c
KH
3478
3479#ifndef TERMINFO
3480 if (strlen (buffer) >= buffer_size)
08a24c47 3481 abort ();
6b61353c
KH
3482 buffer_size = strlen (buffer);
3483#endif
3484 area = (char *) xmalloc (buffer_size);
08a24c47 3485
fca177d4
KL
3486 tty->TS_ins_line = tgetstr ("al", address);
3487 tty->TS_ins_multi_lines = tgetstr ("AL", address);
3488 tty->TS_bell = tgetstr ("bl", address);
6548cf00 3489 BackTab (tty) = tgetstr ("bt", address);
fca177d4
KL
3490 tty->TS_clr_to_bottom = tgetstr ("cd", address);
3491 tty->TS_clr_line = tgetstr ("ce", address);
3492 tty->TS_clr_frame = tgetstr ("cl", address);
6548cf00
KL
3493 ColPosition (tty) = NULL; /* tgetstr ("ch", address); */
3494 AbsPosition (tty) = tgetstr ("cm", address);
3495 CR (tty) = tgetstr ("cr", address);
fca177d4
KL
3496 tty->TS_set_scroll_region = tgetstr ("cs", address);
3497 tty->TS_set_scroll_region_1 = tgetstr ("cS", address);
6548cf00 3498 RowPosition (tty) = tgetstr ("cv", address);
fca177d4
KL
3499 tty->TS_del_char = tgetstr ("dc", address);
3500 tty->TS_del_multi_chars = tgetstr ("DC", address);
3501 tty->TS_del_line = tgetstr ("dl", address);
3502 tty->TS_del_multi_lines = tgetstr ("DL", address);
3503 tty->TS_delete_mode = tgetstr ("dm", address);
3504 tty->TS_end_delete_mode = tgetstr ("ed", address);
3505 tty->TS_end_insert_mode = tgetstr ("ei", address);
6548cf00 3506 Home (tty) = tgetstr ("ho", address);
fca177d4
KL
3507 tty->TS_ins_char = tgetstr ("ic", address);
3508 tty->TS_ins_multi_chars = tgetstr ("IC", address);
3509 tty->TS_insert_mode = tgetstr ("im", address);
3510 tty->TS_pad_inserted_char = tgetstr ("ip", address);
3511 tty->TS_end_keypad_mode = tgetstr ("ke", address);
3512 tty->TS_keypad_mode = tgetstr ("ks", address);
6548cf00
KL
3513 LastLine (tty) = tgetstr ("ll", address);
3514 Right (tty) = tgetstr ("nd", address);
3515 Down (tty) = tgetstr ("do", address);
3516 if (!Down (tty))
3517 Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do" */
08a24c47
JB
3518#ifdef VMS
3519 /* VMS puts a carriage return before each linefeed,
3520 so it is not safe to use linefeeds. */
6548cf00
KL
3521 if (Down (tty) && Down (tty)[0] == '\n' && Down (tty)[1] == '\0')
3522 Down (tty) = 0;
08a24c47
JB
3523#endif /* VMS */
3524 if (tgetflag ("bs"))
6548cf00 3525 Left (tty) = "\b"; /* can't possibly be longer! */
08a24c47 3526 else /* (Actually, "bs" is obsolete...) */
6548cf00
KL
3527 Left (tty) = tgetstr ("le", address);
3528 if (!Left (tty))
3529 Left (tty) = tgetstr ("bc", address); /* Obsolete name for "le" */
fca177d4
KL
3530 tty->TS_pad_char = tgetstr ("pc", address);
3531 tty->TS_repeat = tgetstr ("rp", address);
3532 tty->TS_end_standout_mode = tgetstr ("se", address);
3533 tty->TS_fwd_scroll = tgetstr ("sf", address);
3534 tty->TS_standout_mode = tgetstr ("so", address);
3535 tty->TS_rev_scroll = tgetstr ("sr", address);
6548cf00 3536 tty->Wcm->cm_tab = tgetstr ("ta", address);
fca177d4
KL
3537 tty->TS_end_termcap_modes = tgetstr ("te", address);
3538 tty->TS_termcap_modes = tgetstr ("ti", address);
6548cf00 3539 Up (tty) = tgetstr ("up", address);
fca177d4
KL
3540 tty->TS_visible_bell = tgetstr ("vb", address);
3541 tty->TS_cursor_normal = tgetstr ("ve", address);
3542 tty->TS_cursor_visible = tgetstr ("vs", address);
3543 tty->TS_cursor_invisible = tgetstr ("vi", address);
3544 tty->TS_set_window = tgetstr ("wi", address);
3545
3546 tty->TS_enter_underline_mode = tgetstr ("us", address);
3547 tty->TS_exit_underline_mode = tgetstr ("ue", address);
3548 tty->TS_enter_bold_mode = tgetstr ("md", address);
3549 tty->TS_enter_dim_mode = tgetstr ("mh", address);
3550 tty->TS_enter_blink_mode = tgetstr ("mb", address);
3551 tty->TS_enter_reverse_mode = tgetstr ("mr", address);
3552 tty->TS_enter_alt_charset_mode = tgetstr ("as", address);
3553 tty->TS_exit_alt_charset_mode = tgetstr ("ae", address);
3554 tty->TS_exit_attribute_mode = tgetstr ("me", address);
177c0ea7 3555
6548cf00
KL
3556 MultiUp (tty) = tgetstr ("UP", address);
3557 MultiDown (tty) = tgetstr ("DO", address);
3558 MultiLeft (tty) = tgetstr ("LE", address);
3559 MultiRight (tty) = tgetstr ("RI", address);
08a24c47 3560
e7f90eab
GM
3561 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
3562 color because we can't switch back to the default foreground and
3563 background. */
fca177d4
KL
3564 tty->TS_orig_pair = tgetstr ("op", address);
3565 if (tty->TS_orig_pair)
a168702a 3566 {
fca177d4
KL
3567 tty->TS_set_foreground = tgetstr ("AF", address);
3568 tty->TS_set_background = tgetstr ("AB", address);
3569 if (!tty->TS_set_foreground)
e7f90eab
GM
3570 {
3571 /* SVr4. */
fca177d4
KL
3572 tty->TS_set_foreground = tgetstr ("Sf", address);
3573 tty->TS_set_background = tgetstr ("Sb", address);
e7f90eab 3574 }
177c0ea7 3575
fca177d4
KL
3576 tty->TN_max_colors = tgetnum ("Co");
3577 tty->TN_max_pairs = tgetnum ("pa");
177c0ea7 3578
fca177d4
KL
3579 tty->TN_no_color_video = tgetnum ("NC");
3580 if (tty->TN_no_color_video == -1)
3581 tty->TN_no_color_video = 0;
a168702a 3582 }
a168702a 3583
fca177d4 3584 tty_default_color_capabilities (tty, 1);
ace28297 3585
6548cf00 3586 MagicWrap (tty) = tgetflag ("xn");
e4058338
KH
3587 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
3588 the former flag imply the latter. */
6548cf00 3589 AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
6ed8eeff 3590 terminal->memory_below_frame = tgetflag ("db");
fca177d4 3591 tty->TF_hazeltine = tgetflag ("hz");
6ed8eeff 3592 terminal->must_write_spaces = tgetflag ("in");
fca177d4
KL
3593 tty->meta_key = tgetflag ("km") || tgetflag ("MT");
3594 tty->TF_insmode_motion = tgetflag ("mi");
3595 tty->TF_standout_motion = tgetflag ("ms");
3596 tty->TF_underscore = tgetflag ("ul");
3597 tty->TF_teleray = tgetflag ("xt");
08a24c47 3598
953bf0dc 3599#endif /* !WINDOWSNT */
e7cf0fa0 3600#ifdef MULTI_KBOARD
6ed8eeff
KL
3601 terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
3602 init_kboard (terminal->kboard);
70b8d0a4 3603 terminal->kboard->Vwindow_system = Qnil;
6ed8eeff
KL
3604 terminal->kboard->next_kboard = all_kboards;
3605 all_kboards = terminal->kboard;
3606 terminal->kboard->reference_count++;
e7cf0fa0
KL
3607 /* Don't let the initial kboard remain current longer than necessary.
3608 That would cause problems if a file loaded on startup tries to
3609 prompt in the mini-buffer. */
3610 if (current_kboard == initial_kboard)
6ed8eeff 3611 current_kboard = terminal->kboard;
953bf0dc 3612#ifndef WINDOWSNT
6ed8eeff 3613 term_get_fkeys (address, terminal->kboard);
80ca7302 3614#endif
953bf0dc 3615#endif
5c2c7893 3616
953bf0dc 3617#ifndef WINDOWSNT
ff11dfa1 3618 /* Get frame size from system, or else from termcap. */
3b12ce12
RS
3619 {
3620 int height, width;
0b0d3e0b 3621 get_tty_size (fileno (tty->input), &width, &height);
0a125897
KL
3622 FrameCols (tty) = width;
3623 FrameRows (tty) = height;
3b12ce12
RS
3624 }
3625
0a125897
KL
3626 if (FrameCols (tty) <= 0)
3627 FrameCols (tty) = tgetnum ("co");
3628 if (FrameRows (tty) <= 0)
3629 FrameRows (tty) = tgetnum ("li");
177c0ea7 3630
0a125897 3631 if (FrameRows (tty) < 3 || FrameCols (tty) < 3)
6ed8eeff 3632 maybe_fatal (must_succeed, NULL, terminal,
3224dac1
KL
3633 "Screen size %dx%d is too small"
3634 "Screen size %dx%d is too small",
0a125897 3635 FrameCols (tty), FrameRows (tty));
ee7a2de4 3636
8a56675d 3637#if 0 /* This is not used anywhere. */
6ed8eeff 3638 tty->terminal->min_padding_speed = tgetnum ("pb");
8a56675d 3639#endif
28d440ab 3640
6548cf00 3641 TabWidth (tty) = tgetnum ("tw");
08a24c47
JB
3642
3643#ifdef VMS
3644 /* These capabilities commonly use ^J.
3645 I don't know why, but sending them on VMS does not work;
3646 it causes following spaces to be lost, sometimes.
3647 For now, the simplest fix is to avoid using these capabilities ever. */
6548cf00
KL
3648 if (Down (tty) && Down (tty)[0] == '\n')
3649 Down (tty) = 0;
08a24c47
JB
3650#endif /* VMS */
3651
fca177d4
KL
3652 if (!tty->TS_bell)
3653 tty->TS_bell = "\07";
08a24c47 3654
fca177d4
KL
3655 if (!tty->TS_fwd_scroll)
3656 tty->TS_fwd_scroll = Down (tty);
08a24c47 3657
fca177d4 3658 PC = tty->TS_pad_char ? *tty->TS_pad_char : 0;
08a24c47 3659
6548cf00
KL
3660 if (TabWidth (tty) < 0)
3661 TabWidth (tty) = 8;
177c0ea7 3662
08a24c47
JB
3663/* Turned off since /etc/termcap seems to have :ta= for most terminals
3664 and newer termcap doc does not seem to say there is a default.
6548cf00
KL
3665 if (!tty->Wcm->cm_tab)
3666 tty->Wcm->cm_tab = "\t";
08a24c47
JB
3667*/
3668
54800acb
MB
3669 /* We don't support standout modes that use `magic cookies', so
3670 turn off any that do. */
fca177d4 3671 if (tty->TS_standout_mode && tgetnum ("sg") >= 0)
54800acb 3672 {
fca177d4
KL
3673 tty->TS_standout_mode = 0;
3674 tty->TS_end_standout_mode = 0;
54800acb 3675 }
fca177d4 3676 if (tty->TS_enter_underline_mode && tgetnum ("ug") >= 0)
54800acb 3677 {
fca177d4
KL
3678 tty->TS_enter_underline_mode = 0;
3679 tty->TS_exit_underline_mode = 0;
54800acb
MB
3680 }
3681
3682 /* If there's no standout mode, try to use underlining instead. */
fca177d4 3683 if (tty->TS_standout_mode == 0)
08a24c47 3684 {
fca177d4
KL
3685 tty->TS_standout_mode = tty->TS_enter_underline_mode;
3686 tty->TS_end_standout_mode = tty->TS_exit_underline_mode;
08a24c47
JB
3687 }
3688
afd359c4
RS
3689 /* If no `se' string, try using a `me' string instead.
3690 If that fails, we can't use standout mode at all. */
fca177d4 3691 if (tty->TS_end_standout_mode == 0)
afd359c4 3692 {
e4bfb3b6 3693 char *s = tgetstr ("me", address);
afd359c4 3694 if (s != 0)
fca177d4 3695 tty->TS_end_standout_mode = s;
afd359c4 3696 else
fca177d4 3697 tty->TS_standout_mode = 0;
afd359c4
RS
3698 }
3699
fca177d4 3700 if (tty->TF_teleray)
08a24c47 3701 {
6548cf00 3702 tty->Wcm->cm_tab = 0;
54800acb 3703 /* We can't support standout mode, because it uses magic cookies. */
fca177d4 3704 tty->TS_standout_mode = 0;
08a24c47 3705 /* But that means we cannot rely on ^M to go to column zero! */
6548cf00 3706 CR (tty) = 0;
08a24c47
JB
3707 /* LF can't be trusted either -- can alter hpos */
3708 /* if move at column 0 thru a line with TS_standout_mode */
6548cf00 3709 Down (tty) = 0;
08a24c47
JB
3710 }
3711
3712 /* Special handling for certain terminal types known to need it */
3713
3714 if (!strcmp (terminal_type, "supdup"))
3715 {
6ed8eeff 3716 terminal->memory_below_frame = 1;
6548cf00 3717 tty->Wcm->cm_losewrap = 1;
08a24c47
JB
3718 }
3719 if (!strncmp (terminal_type, "c10", 3)
3720 || !strcmp (terminal_type, "perq"))
3721 {
3722 /* Supply a makeshift :wi string.
3723 This string is not valid in general since it works only
3724 for windows starting at the upper left corner;
3725 but that is all Emacs uses.
3726
ff11dfa1 3727 This string works only if the frame is using
08a24c47
JB
3728 the top of the video memory, because addressing is memory-relative.
3729 So first check the :ti string to see if that is true.
3730
3731 It would be simpler if the :wi string could go in the termcap
3732 entry, but it can't because it is not fully valid.
3733 If it were in the termcap entry, it would confuse other programs. */
fca177d4 3734 if (!tty->TS_set_window)
08a24c47 3735 {
fca177d4 3736 p = tty->TS_termcap_modes;
08a24c47
JB
3737 while (*p && strcmp (p, "\033v "))
3738 p++;
3739 if (*p)
fca177d4 3740 tty->TS_set_window = "\033v%C %C %C %C ";
08a24c47
JB
3741 }
3742 /* Termcap entry often fails to have :in: flag */
6ed8eeff 3743 terminal->must_write_spaces = 1;
08a24c47
JB
3744 /* :ti string typically fails to have \E^G! in it */
3745 /* This limits scope of insert-char to one line. */
fca177d4 3746 strcpy (area, tty->TS_termcap_modes);
08a24c47 3747 strcat (area, "\033\007!");
fca177d4 3748 tty->TS_termcap_modes = area;
08a24c47 3749 area += strlen (area) + 1;
6548cf00 3750 p = AbsPosition (tty);
08a24c47 3751 /* Change all %+ parameters to %C, to handle
28d440ab 3752 values above 96 correctly for the C100. */
08a24c47 3753 while (*p)
28d440ab
KL
3754 {
3755 if (p[0] == '%' && p[1] == '+')
3756 p[1] = 'C';
3757 p++;
3758 }
08a24c47
JB
3759 }
3760
0a125897 3761 tty->specified_window = FrameRows (tty);
08a24c47 3762
6548cf00 3763 if (Wcm_init (tty) == -1) /* can't do cursor motion */
3224dac1 3764 {
6ed8eeff 3765 maybe_fatal (must_succeed, NULL, terminal,
3224dac1 3766 "Terminal type \"%s\" is not powerful enough to run Emacs",
08a24c47 3767#ifdef VMS
3224dac1 3768 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
08a24c47
JB
3769It lacks the ability to position the cursor.\n\
3770If that is not the actual type of terminal you have, use either the\n\
3771DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
e12c1054 3772or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
37dad45a
RS
3773#else /* not VMS */
3774# ifdef TERMINFO
3224dac1 3775 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
37dad45a
RS
3776It lacks the ability to position the cursor.\n\
3777If that is not the actual type of terminal you have,\n\
3778use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3779`setenv TERM ...') to specify the correct type. It may be necessary\n\
e12c1054 3780to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
37dad45a 3781# else /* TERMCAP */
3224dac1 3782 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
08a24c47
JB
3783It lacks the ability to position the cursor.\n\
3784If that is not the actual type of terminal you have,\n\
c5a9c3e6
RS
3785use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3786`setenv TERM ...') to specify the correct type. It may be necessary\n\
e12c1054 3787to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
37dad45a
RS
3788# endif /* TERMINFO */
3789#endif /*VMS */
3224dac1 3790 terminal_type);
fca177d4 3791 }
daf01701 3792
0a125897 3793 if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
6ed8eeff 3794 maybe_fatal (must_succeed, NULL, terminal,
3224dac1
KL
3795 "Could not determine the frame size",
3796 "Could not determine the frame size");
08a24c47 3797
fca177d4
KL
3798 tty->delete_in_insert_mode
3799 = tty->TS_delete_mode && tty->TS_insert_mode
3800 && !strcmp (tty->TS_delete_mode, tty->TS_insert_mode);
08a24c47 3801
fca177d4
KL
3802 tty->se_is_so = (tty->TS_standout_mode
3803 && tty->TS_end_standout_mode
3804 && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode));
08a24c47 3805
0b0d3e0b 3806 UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8;
08a24c47 3807
6ed8eeff 3808 terminal->scroll_region_ok
6548cf00 3809 = (tty->Wcm->cm_abs
fca177d4 3810 && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
08a24c47 3811
6ed8eeff 3812 terminal->line_ins_del_ok
fca177d4
KL
3813 = (((tty->TS_ins_line || tty->TS_ins_multi_lines)
3814 && (tty->TS_del_line || tty->TS_del_multi_lines))
6ed8eeff 3815 || (terminal->scroll_region_ok
fca177d4 3816 && tty->TS_fwd_scroll && tty->TS_rev_scroll));
08a24c47 3817
6ed8eeff 3818 terminal->char_ins_del_ok
fca177d4
KL
3819 = ((tty->TS_ins_char || tty->TS_insert_mode
3820 || tty->TS_pad_inserted_char || tty->TS_ins_multi_chars)
3821 && (tty->TS_del_char || tty->TS_del_multi_chars));
08a24c47 3822
6ed8eeff 3823 terminal->fast_clear_end_of_line = tty->TS_clr_line != 0;
08a24c47 3824
0b0d3e0b 3825 init_baud_rate (fileno (tty->input));
20a558dc 3826
daf01701
KL
3827#ifdef AIXHFT
3828 /* The HFT system on AIX doesn't optimize for scrolling, so it's
3829 really ugly at times. */
6ed8eeff
KL
3830 terminal->line_ins_del_ok = 0;
3831 terminal->char_ins_del_ok = 0;
daf01701
KL
3832#endif
3833
0a125897
KL
3834 /* Don't do this. I think termcap may still need the buffer. */
3835 /* xfree (buffer); */
28d440ab 3836
635e3b29
JR
3837#endif /* not WINDOWSNT */
3838
0a125897
KL
3839 /* Init system terminal modes (RAW or CBREAK, etc.). */
3840 init_sys_modes (tty);
daf01701 3841
6ed8eeff 3842 return terminal;
08a24c47
JB
3843}
3844
a4c6993d 3845/* Auxiliary error-handling function for init_tty.
6ed8eeff 3846 Free BUFFER and delete TERMINAL, then call error or fatal
da8e1115 3847 with str1 or str2, respectively, according to MUST_SUCCEED. */
6b61353c 3848
3224dac1 3849static void
6ed8eeff 3850maybe_fatal (must_succeed, buffer, terminal, str1, str2, arg1, arg2)
3224dac1
KL
3851 int must_succeed;
3852 char *buffer;
6ed8eeff 3853 struct terminal *terminal;
3224dac1
KL
3854 char *str1, *str2, *arg1, *arg2;
3855{
3856 if (buffer)
3857 xfree (buffer);
3858
6ed8eeff
KL
3859 if (terminal)
3860 delete_tty (terminal);
f4d953fc 3861
3224dac1
KL
3862 if (must_succeed)
3863 fatal (str2, arg1, arg2);
3864 else
3865 error (str1, arg1, arg2);
3866
3867 abort ();
08a24c47
JB
3868}
3869
dfcf069d 3870void
7c401d15 3871fatal (const char *str, ...)
08a24c47 3872{
7c401d15
DN
3873 va_list ap;
3874 va_start (ap, str);
08a24c47 3875 fprintf (stderr, "emacs: ");
7c401d15
DN
3876 vfprintf (stderr, str, ap);
3877 va_end (ap);
08a24c47
JB
3878 fflush (stderr);
3879 exit (1);
3880}
07c57952 3881
819b8f00
KL
3882\f
3883
6ed8eeff 3884/* Delete the given tty terminal, closing all frames on it. */
da8e1115 3885
ed8dad6b 3886static void
6ed8eeff 3887delete_tty (struct terminal *terminal)
072d84a6 3888{
428a555e 3889 struct tty_display_info *tty;
fca177d4 3890 Lisp_Object tail, frame;
6ed8eeff 3891 int last_terminal;
f4d953fc 3892
ab797f65
KL
3893 /* Protect against recursive calls. Fdelete_frame in
3894 delete_terminal calls us back when it deletes our last frame. */
59a7bc63 3895 if (!terminal->name)
0a125897 3896 return;
fca177d4 3897
6ed8eeff 3898 if (terminal->type != output_termcap)
428a555e
KL
3899 abort ();
3900
6ed8eeff 3901 tty = terminal->display_info.tty;
f4d953fc 3902
6ed8eeff 3903 last_terminal = 1;
81be1a93
KL
3904 FOR_EACH_FRAME (tail, frame)
3905 {
3906 struct frame *f = XFRAME (frame);
3907 if (FRAME_LIVE_P (f) && (!FRAME_TERMCAP_P (f) || FRAME_TTY (f) != tty))
3908 {
6ed8eeff 3909 last_terminal = 0;
81be1a93
KL
3910 break;
3911 }
3912 }
6ed8eeff
KL
3913 if (last_terminal)
3914 error ("Attempt to delete the sole terminal device with live frames");
f4d953fc 3915
fca177d4
KL
3916 if (tty == tty_list)
3917 tty_list = tty->next;
3918 else
3919 {
28d7d09f 3920 struct tty_display_info *p;
fca177d4
KL
3921 for (p = tty_list; p && p->next != tty; p = p->next)
3922 ;
3923
3924 if (! p)
3925 /* This should not happen. */
3926 abort ();
3927
0a125897
KL
3928 p->next = tty->next;
3929 tty->next = 0;
fca177d4
KL
3930 }
3931
7e59217d 3932 /* reset_sys_modes needs a valid device, so this call needs to be
6ed8eeff 3933 before delete_terminal. */
04c3243c 3934 reset_sys_modes (tty);
fca177d4 3935
6ed8eeff 3936 delete_terminal (terminal);
3224dac1 3937
ab797f65
KL
3938 if (tty->name)
3939 xfree (tty->name);
3940
fca177d4
KL
3941 if (tty->type)
3942 xfree (tty->type);
daf01701 3943
fca177d4 3944 if (tty->input)
819b8f00
KL
3945 {
3946 delete_keyboard_wait_descriptor (fileno (tty->input));
3947 if (tty->input != stdin)
3948 fclose (tty->input);
3949 }
3950 if (tty->output && tty->output != stdout && tty->output != tty->input)
fca177d4
KL
3951 fclose (tty->output);
3952 if (tty->termscript)
3953 fclose (tty->termscript);
daf01701 3954
fca177d4 3955 if (tty->old_tty)
0a125897 3956 xfree (tty->old_tty);
fca177d4 3957
0a125897 3958 if (tty->Wcm)
daf01701
KL
3959 xfree (tty->Wcm);
3960
28d7d09f 3961 bzero (tty, sizeof (struct tty_display_info));
fca177d4 3962 xfree (tty);
fca177d4
KL
3963}
3964
428a555e
KL
3965\f
3966
28d7d09f 3967/* Mark the pointers in the tty_display_info objects.
819b8f00 3968 Called by the Fgarbage_collector. */
da8e1115 3969
fca177d4 3970void
ed8dad6b 3971mark_ttys (void)
fca177d4 3972{
28d7d09f 3973 struct tty_display_info *tty;
0c72d684 3974
819b8f00 3975 for (tty = tty_list; tty; tty = tty->next)
3b6fc48f 3976 mark_object (tty->top_frame);
072d84a6
RS
3977}
3978
428a555e
KL
3979\f
3980
dfcf069d 3981void
07c57952
KH
3982syms_of_term ()
3983{
7ee72033
MB
3984 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
3985 doc: /* Non-nil means the system uses terminfo rather than termcap.
228299fa 3986This variable can be used by terminal emulator packages. */);
07c57952
KH
3987#ifdef TERMINFO
3988 system_uses_terminfo = 1;
3989#else
3990 system_uses_terminfo = 0;
3991#endif
c291d9ef 3992
e4019195
DN
3993 DEFVAR_LISP ("suspend-tty-functions", &Vsuspend_tty_functions,
3994 doc: /* Functions to be run after suspending a tty.
ab797f65 3995The functions are run with one argument, the terminal id to be suspended.
0b0d3e0b 3996See `suspend-tty'. */);
e4019195 3997 Vsuspend_tty_functions = Qnil;
0b0d3e0b
KL
3998
3999
e4019195
DN
4000 DEFVAR_LISP ("resume-tty-functions", &Vresume_tty_functions,
4001 doc: /* Functions to be run after resuming a tty.
ab797f65 4002The functions are run with one argument, the terminal id that was revived.
0b0d3e0b 4003See `resume-tty'. */);
e4019195 4004 Vresume_tty_functions = Qnil;
a168702a 4005
0db017c0
SM
4006 DEFVAR_BOOL ("visible-cursor", &visible_cursor,
4007 doc: /* Non-nil means to make the cursor very visible.
4008This only has an effect when running in a text terminal.
4009What means \"very visible\" is up to your terminal. It may make the cursor
4010bigger, or it may make it blink, or it may do nothing at all. */);
4011 visible_cursor = 1;
4012
a168702a 4013 defsubr (&Stty_display_color_p);
bfa62f96 4014 defsubr (&Stty_display_color_cells);
072d84a6 4015 defsubr (&Stty_no_underline);
6ed8eeff
KL
4016 defsubr (&Stty_type);
4017 defsubr (&Scontrolling_tty_p);
0b0d3e0b
KL
4018 defsubr (&Ssuspend_tty);
4019 defsubr (&Sresume_tty);
7e5a23bd 4020#ifdef HAVE_GPM
6178ce5e
SM
4021 defsubr (&Sgpm_mouse_start);
4022 defsubr (&Sgpm_mouse_stop);
94da14a0 4023
6178ce5e 4024 staticpro (&mouse_face_window);
7e5a23bd 4025#endif /* HAVE_GPM */
07c57952 4026}
a168702a 4027
819b8f00
KL
4028
4029
6b61353c
KH
4030/* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193
4031 (do not change this comment) */