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