Switch to recommended form of GPLv3 permissions notice.
[bpt/emacs.git] / src / term.c
CommitLineData
d284f58f 1/* Terminal control module for terminals described by TERMCAP
0b5538bd 2 Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1998, 2000, 2001,
8cabe764
GM
3 2002, 2003, 2004, 2005, 2006, 2007, 2008
4 Free Software Foundation, Inc.
08a24c47
JB
5
6This file is part of GNU Emacs.
7
9ec0b715 8GNU Emacs is free software: you can redistribute it and/or modify
08a24c47 9it under the terms of the GNU General Public License as published by
9ec0b715
GM
10the Free Software Foundation, either version 3 of the License, or
11(at your option) any later version.
08a24c47
JB
12
13GNU Emacs is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
9ec0b715 19along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
08a24c47 20
d284f58f 21/* New redisplay, TTY faces by Gerd Moellmann <gerd@gnu.org>. */
08a24c47 22
565620a5 23#include <config.h>
08a24c47
JB
24#include <stdio.h>
25#include <ctype.h>
a168702a 26#include <string.h>
59b3194c 27#include <errno.h>
28d440ab 28#include <sys/file.h>
7eb1e453 29
d8b18043 30#ifdef HAVE_UNISTD_H
1ec5dc77 31#include <unistd.h>
d8b18043 32#endif
7ee72033 33
67ad74df
KL
34#if HAVE_TERMIOS_H
35#include <termios.h> /* For TIOCNOTTY. */
36#endif
03a1d6bd
KL
37
38#include <signal.h>
7c401d15 39#include <stdarg.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;
f4d953fc 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;
288d5132
KH
570 unsigned char *buf;
571 int nchars, nbytes, required;
a4decb7f
KH
572 register int tlen = GLYPH_TABLE_LENGTH;
573 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
288d5132 574 Lisp_Object charset_list;
c5a518df 575
288d5132
KH
576 /* Allocate sufficient size of buffer to store all characters in
577 multibyte-form. But, it may be enlarged on demand if
4c12d738
KH
578 Vglyph_table contains a string or a composite glyph is
579 encountered. */
288d5132
KH
580 required = MAX_MULTIBYTE_LENGTH * src_len;
581 if (encode_terminal_src_size < required)
582 {
583 if (encode_terminal_src_size == 0)
584 encode_terminal_src = xmalloc (required);
585 else
586 encode_terminal_src = xrealloc (encode_terminal_src, required);
587 encode_terminal_src_size = required;
588 }
6589fd67 589
288d5132 590 charset_list = coding_charset_list (coding);
a4decb7f 591
288d5132
KH
592 buf = encode_terminal_src;
593 nchars = 0;
594 while (src < src_end)
a4decb7f 595 {
4c12d738
KH
596 if (src->type == COMPOSITE_GLYPH)
597 {
598 struct composition *cmp = composition_table[src->u.cmp_id];
599 int i;
600
601 nbytes = buf - encode_terminal_src;
602 required = MAX_MULTIBYTE_LENGTH * cmp->glyph_len;
603
604 if (encode_terminal_src_size < nbytes + required)
605 {
606 encode_terminal_src_size = nbytes + required;
607 encode_terminal_src = xrealloc (encode_terminal_src,
608 encode_terminal_src_size);
609 buf = encode_terminal_src + nbytes;
610 }
611
612 for (i = 0; i < cmp->glyph_len; i++)
613 {
614 int c = COMPOSITION_GLYPH (cmp, i);
f4d953fc 615
4c12d738
KH
616 if (! char_charset (c, charset_list, NULL))
617 break;
618 buf += CHAR_STRING (c, buf);
619 nchars++;
620 }
621 if (i == 0)
622 {
623 /* The first character of the composition is not encodable. */
624 *buf++ = '?';
625 nchars++;
626 }
627 }
a4decb7f 628 /* We must skip glyphs to be padded for a wide character. */
4c12d738 629 else if (! CHAR_GLYPH_PADDING_P (*src))
a4decb7f 630 {
f4d953fc 631 GLYPH g;
288d5132
KH
632 int c;
633 Lisp_Object string;
634
4ae0a2c0 635 string = Qnil;
f4d953fc 636 SET_GLYPH_FROM_CHAR_GLYPH (g, src[0]);
32de38e4 637
f4d953fc 638 if (GLYPH_INVALID_P (g) || GLYPH_SIMPLE_P (tbase, tlen, g))
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. */
f4d953fc 652 c = GLYPH_CHAR (g);
32de38e4 653 else
4ae0a2c0 654 /* We have a string in Vglyph_table. */
f4d953fc 655 string = tbase[GLYPH_CHAR (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;
f4d953fc 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 }
f4d953fc 1047
3224dac1
KL
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;
f4d953fc 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;
f4d953fc 1793 Lisp_Object gc;
072d84a6 1794 GLYPH glyph;
177c0ea7 1795
a168702a
GM
1796 temp_it = *it;
1797 temp_it.dp = NULL;
1798 temp_it.what = IT_CHARACTER;
1799 temp_it.len = 1;
7c752c80 1800 temp_it.object = make_number (0);
a168702a
GM
1801 bzero (&temp_it.current, sizeof temp_it.current);
1802
1803 if (what == IT_CONTINUATION)
1804 {
1805 /* Continuation glyph. */
f4d953fc 1806 SET_GLYPH_FROM_CHAR (glyph, '\\');
a168702a 1807 if (it->dp
f4d953fc
KS
1808 && (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc))
1809 && GLYPH_CODE_CHAR_VALID_P (gc))
a168702a 1810 {
f4d953fc
KS
1811 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
1812 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
a168702a 1813 }
a168702a
GM
1814 }
1815 else if (what == IT_TRUNCATION)
1816 {
1817 /* Truncation glyph. */
f4d953fc 1818 SET_GLYPH_FROM_CHAR (glyph, '$');
a168702a 1819 if (it->dp
f4d953fc
KS
1820 && (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc))
1821 && GLYPH_CODE_CHAR_VALID_P (gc))
a168702a 1822 {
f4d953fc
KS
1823 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
1824 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
a168702a 1825 }
a168702a
GM
1826 }
1827 else
1828 abort ();
072d84a6 1829
f4d953fc
KS
1830 temp_it.c = GLYPH_CHAR (glyph);
1831 temp_it.face_id = GLYPH_FACE (glyph);
072d84a6
RS
1832 temp_it.len = CHAR_BYTES (temp_it.c);
1833
1834 produce_glyphs (&temp_it);
1835 it->pixel_width = temp_it.pixel_width;
1836 it->nglyphs = temp_it.pixel_width;
a168702a
GM
1837}
1838
1839
a168702a
GM
1840\f
1841/***********************************************************************
1842 Faces
1843 ***********************************************************************/
1844
4e6ba4a4
GM
1845/* Value is non-zero if attribute ATTR may be used. ATTR should be
1846 one of the enumerators from enum no_color_bit, or a bit set built
1847 from them. Some display attributes may not be used together with
1848 color; the termcap capability `NC' specifies which ones. */
1849
fca177d4
KL
1850#define MAY_USE_WITH_COLORS_P(tty, ATTR) \
1851 (tty->TN_max_colors > 0 \
1852 ? (tty->TN_no_color_video & (ATTR)) == 0 \
1853 : 1)
a168702a 1854
072d84a6
RS
1855/* Turn appearances of face FACE_ID on tty frame F on.
1856 FACE_ID is a realized face ID number, in the face cache. */
a168702a
GM
1857
1858static void
1859turn_on_face (f, face_id)
1860 struct frame *f;
1861 int face_id;
1862{
1863 struct face *face = FACE_FROM_ID (f, face_id);
86a7d192
GM
1864 long fg = face->foreground;
1865 long bg = face->background;
28d7d09f 1866 struct tty_display_info *tty = FRAME_TTY (f);
a168702a 1867
86a7d192
GM
1868 /* Do this first because TS_end_standout_mode may be the same
1869 as TS_exit_attribute_mode, which turns all appearances off. */
fca177d4 1870 if (MAY_USE_WITH_COLORS_P (tty, NC_REVERSE))
86a7d192 1871 {
fca177d4 1872 if (tty->TN_max_colors > 0)
86a7d192
GM
1873 {
1874 if (fg >= 0 && bg >= 0)
1875 {
1876 /* If the terminal supports colors, we can set them
1877 below without using reverse video. The face's fg
1878 and bg colors are set as they should appear on
1879 the screen, i.e. they take the inverse-video'ness
1880 of the face already into account. */
1881 }
1882 else if (inverse_video)
1883 {
1884 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1885 || bg == FACE_TTY_DEFAULT_BG_COLOR)
ed8dad6b 1886 tty_toggle_highlight (tty);
86a7d192
GM
1887 }
1888 else
1889 {
1890 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1891 || bg == FACE_TTY_DEFAULT_FG_COLOR)
ed8dad6b 1892 tty_toggle_highlight (tty);
86a7d192
GM
1893 }
1894 }
1895 else
1896 {
1897 /* If we can't display colors, use reverse video
1898 if the face specifies that. */
37526b42
GM
1899 if (inverse_video)
1900 {
1901 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1902 || bg == FACE_TTY_DEFAULT_BG_COLOR)
ed8dad6b 1903 tty_toggle_highlight (tty);
37526b42
GM
1904 }
1905 else
1906 {
1907 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1908 || bg == FACE_TTY_DEFAULT_FG_COLOR)
ed8dad6b 1909 tty_toggle_highlight (tty);
37526b42 1910 }
86a7d192
GM
1911 }
1912 }
a168702a
GM
1913
1914 if (face->tty_bold_p)
4e6ba4a4 1915 {
fca177d4
KL
1916 if (MAY_USE_WITH_COLORS_P (tty, NC_BOLD))
1917 OUTPUT1_IF (tty, tty->TS_enter_bold_mode);
4e6ba4a4 1918 }
a168702a 1919 else if (face->tty_dim_p)
fca177d4
KL
1920 if (MAY_USE_WITH_COLORS_P (tty, NC_DIM))
1921 OUTPUT1_IF (tty, tty->TS_enter_dim_mode);
a168702a
GM
1922
1923 /* Alternate charset and blinking not yet used. */
4e6ba4a4 1924 if (face->tty_alt_charset_p
fca177d4
KL
1925 && MAY_USE_WITH_COLORS_P (tty, NC_ALT_CHARSET))
1926 OUTPUT1_IF (tty, tty->TS_enter_alt_charset_mode);
a168702a 1927
4e6ba4a4 1928 if (face->tty_blinking_p
fca177d4
KL
1929 && MAY_USE_WITH_COLORS_P (tty, NC_BLINK))
1930 OUTPUT1_IF (tty, tty->TS_enter_blink_mode);
a168702a 1931
fca177d4
KL
1932 if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (tty, NC_UNDERLINE))
1933 OUTPUT1_IF (tty, tty->TS_enter_underline_mode);
a168702a 1934
fca177d4 1935 if (tty->TN_max_colors > 0)
a168702a 1936 {
753d161b 1937 char *ts, *p;
177c0ea7 1938
fbf34973 1939 ts = tty->standout_mode ? tty->TS_set_background : tty->TS_set_foreground;
753d161b 1940 if (fg >= 0 && ts)
a168702a 1941 {
fbf34973 1942 p = tparam (ts, NULL, 0, (int) fg);
6548cf00 1943 OUTPUT (tty, p);
a168702a
GM
1944 xfree (p);
1945 }
1946
fbf34973 1947 ts = tty->standout_mode ? tty->TS_set_foreground : tty->TS_set_background;
753d161b 1948 if (bg >= 0 && ts)
a168702a 1949 {
fbf34973 1950 p = tparam (ts, NULL, 0, (int) bg);
6548cf00 1951 OUTPUT (tty, p);
a168702a
GM
1952 xfree (p);
1953 }
1954 }
1955}
177c0ea7 1956
a168702a
GM
1957
1958/* Turn off appearances of face FACE_ID on tty frame F. */
1959
1960static void
1961turn_off_face (f, face_id)
1962 struct frame *f;
1963 int face_id;
1964{
1965 struct face *face = FACE_FROM_ID (f, face_id);
28d7d09f 1966 struct tty_display_info *tty = FRAME_TTY (f);
a168702a
GM
1967
1968 xassert (face != NULL);
1969
fca177d4 1970 if (tty->TS_exit_attribute_mode)
a168702a
GM
1971 {
1972 /* Capability "me" will turn off appearance modes double-bright,
1973 half-bright, reverse-video, standout, underline. It may or
1974 may not turn off alt-char-mode. */
1975 if (face->tty_bold_p
1976 || face->tty_dim_p
1977 || face->tty_reverse_p
1978 || face->tty_alt_charset_p
1979 || face->tty_blinking_p
1980 || face->tty_underline_p)
65aa5e85 1981 {
fca177d4
KL
1982 OUTPUT1_IF (tty, tty->TS_exit_attribute_mode);
1983 if (strcmp (tty->TS_exit_attribute_mode, tty->TS_end_standout_mode) == 0)
1984 tty->standout_mode = 0;
65aa5e85 1985 }
a168702a
GM
1986
1987 if (face->tty_alt_charset_p)
fca177d4 1988 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
a168702a
GM
1989 }
1990 else
1991 {
1992 /* If we don't have "me" we can only have those appearances
1993 that have exit sequences defined. */
1994 if (face->tty_alt_charset_p)
fca177d4 1995 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
a168702a 1996
54800acb 1997 if (face->tty_underline_p)
fca177d4 1998 OUTPUT_IF (tty, tty->TS_exit_underline_mode);
a168702a
GM
1999 }
2000
2001 /* Switch back to default colors. */
fca177d4 2002 if (tty->TN_max_colors > 0
f9d2fdc4
EZ
2003 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
2004 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
2005 || (face->background != FACE_TTY_DEFAULT_COLOR
2006 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
fca177d4 2007 OUTPUT1_IF (tty, tty->TS_orig_pair);
a168702a 2008}
177c0ea7
JB
2009
2010
b63a55ac
MB
2011/* Return non-zero if the terminal on frame F supports all of the
2012 capabilities in CAPS simultaneously, with foreground and background
2013 colors FG and BG. */
2014
4a8130f2 2015int
fca177d4 2016tty_capable_p (tty, caps, fg, bg)
28d7d09f 2017 struct tty_display_info *tty;
b63a55ac
MB
2018 unsigned caps;
2019 unsigned long fg, bg;
2020{
fca177d4
KL
2021#define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
2022 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
b63a55ac
MB
2023 return 0;
2024
fca177d4
KL
2025 TTY_CAPABLE_P_TRY (tty, TTY_CAP_INVERSE, tty->TS_standout_mode, NC_REVERSE);
2026 TTY_CAPABLE_P_TRY (tty, TTY_CAP_UNDERLINE, tty->TS_enter_underline_mode, NC_UNDERLINE);
2027 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BOLD, tty->TS_enter_bold_mode, NC_BOLD);
2028 TTY_CAPABLE_P_TRY (tty, TTY_CAP_DIM, tty->TS_enter_dim_mode, NC_DIM);
2029 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BLINK, tty->TS_enter_blink_mode, NC_BLINK);
2030 TTY_CAPABLE_P_TRY (tty, TTY_CAP_ALT_CHARSET, tty->TS_enter_alt_charset_mode, NC_ALT_CHARSET);
b63a55ac
MB
2031
2032 /* We can do it! */
2033 return 1;
2034}
2035
a168702a
GM
2036/* Return non-zero if the terminal is capable to display colors. */
2037
2038DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
981e4297 2039 0, 1, 0,
6ed8eeff
KL
2040 doc: /* Return non-nil if the tty device TERMINAL can display colors.
2041
2042TERMINAL can be a terminal id, a frame or nil (meaning the selected
2043frame's terminal). This function always returns nil if TERMINAL
2044is not on a tty device. */)
2045 (terminal)
2046 Lisp_Object terminal;
a168702a 2047{
717a00ef 2048 struct terminal *t = get_tty_terminal (terminal, 0);
6ed8eeff 2049 if (!t)
428a555e 2050 return Qnil;
3224dac1 2051 else
6ed8eeff 2052 return t->display_info.tty->TN_max_colors > 0 ? Qt : Qnil;
a168702a
GM
2053}
2054
bfa62f96
EZ
2055/* Return the number of supported colors. */
2056DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
2057 Stty_display_color_cells, 0, 1, 0,
6ed8eeff
KL
2058 doc: /* Return the number of colors supported by the tty device TERMINAL.
2059
2060TERMINAL can be a terminal id, a frame or nil (meaning the selected
717a00ef 2061frame's terminal). This function always returns 0 if TERMINAL
6ed8eeff
KL
2062is not on a tty device. */)
2063 (terminal)
2064 Lisp_Object terminal;
bfa62f96 2065{
717a00ef 2066 struct terminal *t = get_tty_terminal (terminal, 0);
6ed8eeff 2067 if (!t)
8c8d5f35 2068 return make_number (0);
3224dac1 2069 else
6ed8eeff 2070 return make_number (t->display_info.tty->TN_max_colors);
bfa62f96
EZ
2071}
2072
ace28297 2073#ifndef WINDOWSNT
a168702a 2074
5205ee62
GM
2075/* Declare here rather than in the function, as in the rest of Emacs,
2076 to work around an HPUX compiler bug (?). See
57407fb4 2077 http://lists.gnu.org/archive/html/emacs-devel/2007-08/msg00410.html */
5205ee62
GM
2078static int default_max_colors;
2079static int default_max_pairs;
2080static int default_no_color_video;
2081static char *default_orig_pair;
2082static char *default_set_foreground;
2083static char *default_set_background;
fcf8ff2e 2084
ace28297
EZ
2085/* Save or restore the default color-related capabilities of this
2086 terminal. */
2087static void
28d7d09f 2088tty_default_color_capabilities (struct tty_display_info *tty, int save)
ace28297 2089{
ace28297
EZ
2090
2091 if (save)
2092 {
2093 if (default_orig_pair)
2094 xfree (default_orig_pair);
fca177d4 2095 default_orig_pair = tty->TS_orig_pair ? xstrdup (tty->TS_orig_pair) : NULL;
ace28297
EZ
2096
2097 if (default_set_foreground)
2098 xfree (default_set_foreground);
fca177d4 2099 default_set_foreground = tty->TS_set_foreground ? xstrdup (tty->TS_set_foreground)
ace28297
EZ
2100 : NULL;
2101
2102 if (default_set_background)
2103 xfree (default_set_background);
fca177d4 2104 default_set_background = tty->TS_set_background ? xstrdup (tty->TS_set_background)
ace28297
EZ
2105 : NULL;
2106
fca177d4
KL
2107 default_max_colors = tty->TN_max_colors;
2108 default_max_pairs = tty->TN_max_pairs;
2109 default_no_color_video = tty->TN_no_color_video;
ace28297
EZ
2110 }
2111 else
2112 {
fca177d4
KL
2113 tty->TS_orig_pair = default_orig_pair;
2114 tty->TS_set_foreground = default_set_foreground;
2115 tty->TS_set_background = default_set_background;
2116 tty->TN_max_colors = default_max_colors;
2117 tty->TN_max_pairs = default_max_pairs;
2118 tty->TN_no_color_video = default_no_color_video;
ace28297
EZ
2119 }
2120}
2121
2122/* Setup one of the standard tty color schemes according to MODE.
2123 MODE's value is generally the number of colors which we want to
2124 support; zero means set up for the default capabilities, the ones
a4c6993d 2125 we saw at init_tty time; -1 means turn off color support. */
ed8dad6b 2126static void
28d7d09f 2127tty_setup_colors (struct tty_display_info *tty, int mode)
ace28297 2128{
6b61353c
KH
2129 /* Canonicalize all negative values of MODE. */
2130 if (mode < -1)
2131 mode = -1;
2132
ace28297
EZ
2133 switch (mode)
2134 {
2135 case -1: /* no colors at all */
fca177d4
KL
2136 tty->TN_max_colors = 0;
2137 tty->TN_max_pairs = 0;
2138 tty->TN_no_color_video = 0;
2139 tty->TS_set_foreground = tty->TS_set_background = tty->TS_orig_pair = NULL;
ace28297
EZ
2140 break;
2141 case 0: /* default colors, if any */
2142 default:
fca177d4 2143 tty_default_color_capabilities (tty, 0);
ace28297
EZ
2144 break;
2145 case 8: /* 8 standard ANSI colors */
fca177d4 2146 tty->TS_orig_pair = "\033[0m";
ace28297 2147#ifdef TERMINFO
fca177d4
KL
2148 tty->TS_set_foreground = "\033[3%p1%dm";
2149 tty->TS_set_background = "\033[4%p1%dm";
ace28297 2150#else
fca177d4
KL
2151 tty->TS_set_foreground = "\033[3%dm";
2152 tty->TS_set_background = "\033[4%dm";
ace28297 2153#endif
fca177d4
KL
2154 tty->TN_max_colors = 8;
2155 tty->TN_max_pairs = 64;
2156 tty->TN_no_color_video = 0;
ace28297
EZ
2157 break;
2158 }
2159}
2160
2161void
9b2cd403
SM
2162set_tty_color_mode (tty, f)
2163 struct tty_display_info *tty;
ace28297 2164 struct frame *f;
ace28297 2165{
9b2cd403
SM
2166 Lisp_Object tem, val, color_mode_spec;
2167 Lisp_Object color_mode;
2168 int mode;
ace28297 2169 extern Lisp_Object Qtty_color_mode;
9b2cd403
SM
2170 Lisp_Object tty_color_mode_alist
2171 = Fintern_soft (build_string ("tty-color-mode-alist"), Qnil);
ace28297 2172
c23b5410 2173 tem = assq_no_quit (Qtty_color_mode, f->param_alist);
9b2cd403 2174 val = CONSP (tem) ? XCDR (tem) : Qnil;
ace28297 2175
6b61353c 2176 if (INTEGERP (val))
ace28297
EZ
2177 color_mode = val;
2178 else
2179 {
9b2cd403
SM
2180 tem = (NILP (tty_color_mode_alist) ? Qnil
2181 : Fassq (val, XSYMBOL (tty_color_mode_alist)->value));
2182 color_mode = CONSP (tem) ? XCDR (tem) : Qnil;
ace28297 2183 }
6b61353c 2184
9b2cd403 2185 mode = INTEGERP (color_mode) ? XINT (color_mode) : 0;
ace28297 2186
9b2cd403 2187 if (mode != tty->previous_color_mode)
ace28297 2188 {
9b2cd403
SM
2189 Lisp_Object funsym = intern ("tty-set-up-initial-frame-faces");
2190 tty->previous_color_mode = mode;
2191 tty_setup_colors (tty , mode);
2192 /* This recomputes all the faces given the new color definitions. */
2193 safe_call (1, &funsym);
ace28297
EZ
2194 }
2195}
2196
2197#endif /* !WINDOWSNT */
a168702a
GM
2198
2199\f
28d440ab 2200
6ed8eeff 2201/* Return the tty display object specified by TERMINAL. */
b6660415 2202
6ed8eeff 2203struct terminal *
717a00ef 2204get_tty_terminal (Lisp_Object terminal, int throw)
b6660415 2205{
717a00ef 2206 struct terminal *t = get_terminal (terminal, throw);
62af879c 2207
6ed8eeff 2208 if (t && t->type != output_termcap)
717a00ef
KL
2209 {
2210 if (throw)
2211 error ("Device %d is not a termcap terminal device", t->id);
2212 else
2213 return NULL;
2214 }
b6660415 2215
6ed8eeff 2216 return t;
b6660415
KL
2217}
2218
ab797f65
KL
2219/* Return an active termcap device that uses the tty device with the
2220 given name.
b6660415 2221
7e59217d 2222 This function ignores suspended devices.
da8e1115
KL
2223
2224 Returns NULL if the named terminal device is not opened. */
f4d953fc 2225
6ed8eeff 2226struct terminal *
7e59217d 2227get_named_tty (name)
28d440ab
KL
2228 char *name;
2229{
6ed8eeff
KL
2230 struct terminal *t;
2231
ab797f65
KL
2232 if (!name)
2233 abort ();
2234
2235 for (t = terminal_list; t; t = t->next_terminal)
2236 {
2237 if (t->type == output_termcap
2238 && !strcmp (t->display_info.tty->name, name)
2239 && TERMINAL_ACTIVE_P (t))
2240 return t;
2241 }
28d440ab
KL
2242
2243 return 0;
2244}
2245
2246\f
6ed8eeff
KL
2247DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0,
2248 doc: /* Return the type of the tty device that TERMINAL uses.
ab797f65 2249Returns nil if TERMINAL is not on a tty device.
a3fbb897 2250
6ed8eeff
KL
2251TERMINAL can be a terminal id, a frame or nil (meaning the selected
2252frame's terminal). */)
2253 (terminal)
2254 Lisp_Object terminal;
b6660415 2255{
6ed8eeff 2256 struct terminal *t = get_terminal (terminal, 1);
819b8f00 2257
6ed8eeff 2258 if (t->type != output_termcap)
ab797f65
KL
2259 return Qnil;
2260
6ed8eeff
KL
2261 if (t->display_info.tty->type)
2262 return build_string (t->display_info.tty->type);
819b8f00
KL
2263 else
2264 return Qnil;
2265}
2266
6ed8eeff
KL
2267DEFUN ("controlling-tty-p", Fcontrolling_tty_p, Scontrolling_tty_p, 0, 1, 0,
2268 doc: /* Return non-nil if TERMINAL is on the controlling tty of the Emacs process.
a3fbb897 2269
6ed8eeff
KL
2270TERMINAL can be a terminal id, a frame or nil (meaning the selected
2271frame's terminal). This function always returns nil if TERMINAL
2272is not on a tty device. */)
2273 (terminal)
2274 Lisp_Object terminal;
4a933ef8 2275{
6ed8eeff 2276 struct terminal *t = get_terminal (terminal, 1);
4a933ef8 2277
78048085 2278 if (t->type != output_termcap || strcmp (t->display_info.tty->name, DEV_TTY))
4a933ef8
KL
2279 return Qnil;
2280 else
2281 return Qt;
2282}
2283
a3fbb897 2284DEFUN ("tty-no-underline", Ftty_no_underline, Stty_no_underline, 0, 1, 0,
6ed8eeff 2285 doc: /* Declare that the tty used by TERMINAL does not handle underlining.
a3fbb897
KL
2286This is used to override the terminfo data, for certain terminals that
2287do not really do underlining, but say that they do. This function has
6ed8eeff 2288no effect if used on a non-tty terminal.
a3fbb897 2289
6ed8eeff
KL
2290TERMINAL can be a terminal id, a frame or nil (meaning the selected
2291frame's terminal). This function always returns nil if TERMINAL
2292is not on a tty device. */)
2293 (terminal)
2294 Lisp_Object terminal;
a3fbb897 2295{
6ed8eeff 2296 struct terminal *t = get_terminal (terminal, 1);
a3fbb897 2297
6ed8eeff
KL
2298 if (t->type == output_termcap)
2299 t->display_info.tty->TS_enter_underline_mode = 0;
a3fbb897
KL
2300 return Qnil;
2301}
2302
ed8dad6b
KL
2303\f
2304
2305DEFUN ("suspend-tty", Fsuspend_tty, Ssuspend_tty, 0, 1, 0,
2306 doc: /* Suspend the terminal device TTY.
2307
2308The device is restored to its default state, and Emacs ceases all
2309access to the tty device. Frames that use the device are not deleted,
2310but input is not read from them and if they change, their display is
2311not updated.
2312
2313TTY may be a terminal id, a frame, or nil for the terminal device of
2314the currently selected frame.
2315
e4019195 2316This function runs `suspend-tty-functions' after suspending the
ed8dad6b
KL
2317device. The functions are run with one arg, the id of the suspended
2318terminal device.
2319
2320`suspend-tty' does nothing if it is called on a device that is already
2321suspended.
2322
2323A suspended tty may be resumed by calling `resume-tty' on it. */)
2324 (tty)
2325 Lisp_Object tty;
2326{
717a00ef 2327 struct terminal *t = get_tty_terminal (tty, 1);
ed8dad6b 2328 FILE *f;
f4d953fc 2329
6ed8eeff 2330 if (!t)
ed8dad6b
KL
2331 error ("Unknown tty device");
2332
6ed8eeff 2333 f = t->display_info.tty->input;
f4d953fc 2334
ed8dad6b
KL
2335 if (f)
2336 {
23d4cba5
DN
2337 /* First run `suspend-tty-functions' and then clean up the tty
2338 state because `suspend-tty-functions' might need to change
2339 the tty state. */
2340 if (!NILP (Vrun_hooks))
2341 {
2342 Lisp_Object args[2];
2343 args[0] = intern ("suspend-tty-functions");
2344 XSETTERMINAL (args[1], t);
2345 Frun_hook_with_args (2, args);
2346 }
2347
6ed8eeff 2348 reset_sys_modes (t->display_info.tty);
ed8dad6b
KL
2349
2350 delete_keyboard_wait_descriptor (fileno (f));
f4d953fc 2351
ed8dad6b 2352 fclose (f);
6ed8eeff
KL
2353 if (f != t->display_info.tty->output)
2354 fclose (t->display_info.tty->output);
f4d953fc 2355
6ed8eeff
KL
2356 t->display_info.tty->input = 0;
2357 t->display_info.tty->output = 0;
ed8dad6b 2358
6ed8eeff
KL
2359 if (FRAMEP (t->display_info.tty->top_frame))
2360 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0);
f4d953fc 2361
ed8dad6b
KL
2362 }
2363
4a665758
KL
2364 /* Clear display hooks to prevent further output. */
2365 clear_tty_hooks (t);
2366
ed8dad6b
KL
2367 return Qnil;
2368}
2369
2370DEFUN ("resume-tty", Fresume_tty, Sresume_tty, 0, 1, 0,
2371 doc: /* Resume the previously suspended terminal device TTY.
2372The terminal is opened and reinitialized. Frames that are on the
6ed8eeff 2373suspended terminal are revived.
ed8dad6b 2374
6ed8eeff
KL
2375It is an error to resume a terminal while another terminal is active
2376on the same device.
ed8dad6b 2377
e4019195 2378This function runs `resume-tty-functions' after resuming the terminal.
6ed8eeff 2379The functions are run with one arg, the id of the resumed terminal
ed8dad6b
KL
2380device.
2381
2382`resume-tty' does nothing if it is called on a device that is not
2383suspended.
2384
6ed8eeff
KL
2385TTY may be a terminal id, a frame, or nil for the terminal device of
2386the currently selected frame. */)
ed8dad6b
KL
2387 (tty)
2388 Lisp_Object tty;
2389{
717a00ef 2390 struct terminal *t = get_tty_terminal (tty, 1);
ed8dad6b
KL
2391 int fd;
2392
6ed8eeff 2393 if (!t)
ed8dad6b
KL
2394 error ("Unknown tty device");
2395
6ed8eeff 2396 if (!t->display_info.tty->input)
ed8dad6b 2397 {
6ed8eeff 2398 if (get_named_tty (t->display_info.tty->name))
ed8dad6b
KL
2399 error ("Cannot resume display while another display is active on the same device");
2400
6ed8eeff 2401 fd = emacs_open (t->display_info.tty->name, O_RDWR | O_NOCTTY, 0);
ed8dad6b 2402
59b3194c
KL
2403 if (fd == -1)
2404 error ("Can not reopen tty device %s: %s", t->display_info.tty->name, strerror (errno));
ed8dad6b 2405
78048085 2406 if (strcmp (t->display_info.tty->name, DEV_TTY))
59b3194c 2407 dissociate_if_controlling_tty (fd);
78048085 2408
6ed8eeff
KL
2409 t->display_info.tty->output = fdopen (fd, "w+");
2410 t->display_info.tty->input = t->display_info.tty->output;
78048085 2411
ed8dad6b
KL
2412 add_keyboard_wait_descriptor (fd);
2413
6ed8eeff
KL
2414 if (FRAMEP (t->display_info.tty->top_frame))
2415 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
ed8dad6b 2416
6ed8eeff 2417 init_sys_modes (t->display_info.tty);
ed8dad6b 2418
e4019195 2419 /* Run `resume-tty-functions'. */
ed8dad6b
KL
2420 if (!NILP (Vrun_hooks))
2421 {
2422 Lisp_Object args[2];
e4019195 2423 args[0] = intern ("resume-tty-functions");
59a7bc63 2424 XSETTERMINAL (args[1], t);
ed8dad6b
KL
2425 Frun_hook_with_args (2, args);
2426 }
2427 }
2428
4a665758
KL
2429 set_tty_hooks (t);
2430
ed8dad6b
KL
2431 return Qnil;
2432}
a3fbb897 2433
819b8f00 2434\f
e882229c
NR
2435/***********************************************************************
2436 Mouse
2437 ***********************************************************************/
2438
7e5a23bd 2439#ifdef HAVE_GPM
5faa03ba
RS
2440void
2441term_mouse_moveto (int x, int y)
94da14a0 2442{
1ec5dc77 2443 /* TODO: how to set mouse position?
94da14a0
NR
2444 const char *name;
2445 int fd;
2446 name = (const char *) ttyname (0);
2447 fd = open (name, O_WRONLY);
80fb2ce0 2448 SOME_FUNCTION (x, y, fd);
94da14a0
NR
2449 close (fd);
2450 last_mouse_x = x;
80fb2ce0 2451 last_mouse_y = y; */
94da14a0
NR
2452}
2453
e882229c
NR
2454static void
2455term_show_mouse_face (enum draw_glyphs_face draw)
2456{
6178ce5e 2457 struct window *w = XWINDOW (mouse_face_window);
e882229c 2458 int save_x, save_y;
1ec5dc77 2459 int i;
e882229c 2460
7be1c21a
MB
2461 struct frame *f = XFRAME (w->frame);
2462 struct tty_display_info *tty = FRAME_TTY (f);
2463
e882229c
NR
2464 if (/* If window is in the process of being destroyed, don't bother
2465 to do anything. */
2466 w->current_matrix != NULL
2467 /* Recognize when we are called to operate on rows that don't exist
2468 anymore. This can happen when a window is split. */
2469 && mouse_face_end_row < w->current_matrix->nrows)
2470 {
2471 /* write_glyphs writes at cursor position, so we need to
2472 temporarily move cursor coordinates to the beginning of
2473 the highlight region. */
f4d953fc 2474
e882229c 2475 /* Save current cursor co-ordinates */
7be1c21a
MB
2476 save_y = curY (tty);
2477 save_x = curX (tty);
e882229c
NR
2478
2479 /* Note that mouse_face_beg_row etc. are window relative. */
2480 for (i = mouse_face_beg_row; i <= mouse_face_end_row; i++)
2481 {
2482 int start_hpos, end_hpos, nglyphs;
2483 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
2484
2485 /* Don't do anything if row doesn't have valid contents. */
2486 if (!row->enabled_p)
2487 continue;
2488
2489 /* For all but the first row, the highlight starts at column 0. */
2490 if (i == mouse_face_beg_row)
2491 start_hpos = mouse_face_beg_col;
2492 else
2493 start_hpos = 0;
2494
2495 if (i == mouse_face_end_row)
2496 end_hpos = mouse_face_end_col;
2497 else
2498 {
2499 end_hpos = row->used[TEXT_AREA];
2500 if (draw == DRAW_NORMAL_TEXT)
2501 row->fill_line_p = 1; /* Clear to end of line */
2502 }
2503
2504 if (end_hpos <= start_hpos)
2505 continue;
2506 /* Record that some glyphs of this row are displayed in
2507 mouse-face. */
2508 row->mouse_face_p = draw > 0;
2509
2510 nglyphs = end_hpos - start_hpos;
2511
2512 if (end_hpos >= row->used[TEXT_AREA])
2513 nglyphs = row->used[TEXT_AREA] - start_hpos;
2514
2515 pos_y = row->y + WINDOW_TOP_EDGE_Y (w);
2516 pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos
2517 + WINDOW_LEFT_EDGE_X (w);
f4d953fc 2518
7be1c21a 2519 cursor_to (f, pos_y, pos_x);
e882229c
NR
2520
2521 if (draw == DRAW_MOUSE_FACE)
2522 {
7be1c21a 2523 tty_write_glyphs_with_face (f, row->glyphs[TEXT_AREA] + start_hpos,
e882229c
NR
2524 nglyphs, mouse_face_face_id);
2525 }
2526 else /* draw == DRAW_NORMAL_TEXT */
7be1c21a 2527 write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
e882229c 2528 }
7be1c21a 2529 cursor_to (f, save_y, save_x);
e882229c
NR
2530 }
2531}
2532
2533static void
2534term_clear_mouse_face ()
2535{
6178ce5e 2536 if (!NILP (mouse_face_window))
e882229c
NR
2537 term_show_mouse_face (DRAW_NORMAL_TEXT);
2538
2539 mouse_face_beg_row = mouse_face_beg_col = -1;
2540 mouse_face_end_row = mouse_face_end_col = -1;
6178ce5e 2541 mouse_face_window = Qnil;
e882229c
NR
2542}
2543
2544/* Find the glyph matrix position of buffer position POS in window W.
2545 *HPOS and *VPOS are set to the positions found. W's current glyphs
2546 must be up to date. If POS is above window start return (0, 0).
2547 If POS is after end of W, return end of last line in W.
2548 - taken from msdos.c */
2549static int
2550fast_find_position (struct window *w, int pos, int *hpos, int *vpos)
2551{
2552 int i, lastcol, line_start_position, maybe_next_line_p = 0;
2553 int yb = window_text_bottom_y (w);
2554 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0), *best_row = row;
2555
2556 while (row->y < yb)
2557 {
2558 if (row->used[TEXT_AREA])
2559 line_start_position = row->glyphs[TEXT_AREA]->charpos;
2560 else
2561 line_start_position = 0;
2562
2563 if (line_start_position > pos)
2564 break;
2565 /* If the position sought is the end of the buffer,
2566 don't include the blank lines at the bottom of the window. */
2567 else if (line_start_position == pos
2568 && pos == BUF_ZV (XBUFFER (w->buffer)))
2569 {
2570 maybe_next_line_p = 1;
2571 break;
2572 }
2573 else if (line_start_position > 0)
2574 best_row = row;
2575
2576 /* Don't overstep the last matrix row, lest we get into the
2577 never-never land... */
2578 if (row->y + 1 >= yb)
2579 break;
2580
2581 ++row;
2582 }
2583
2584 /* Find the right column within BEST_ROW. */
2585 lastcol = 0;
2586 row = best_row;
2587 for (i = 0; i < row->used[TEXT_AREA]; i++)
2588 {
2589 struct glyph *glyph = row->glyphs[TEXT_AREA] + i;
2590 int charpos;
2591
2592 charpos = glyph->charpos;
2593 if (charpos == pos)
2594 {
2595 *hpos = i;
2596 *vpos = row->y;
2597 return 1;
2598 }
2599 else if (charpos > pos)
2600 break;
2601 else if (charpos > 0)
2602 lastcol = i;
2603 }
2604
2605 /* If we're looking for the end of the buffer,
2606 and we didn't find it in the line we scanned,
2607 use the start of the following line. */
2608 if (maybe_next_line_p)
2609 {
2610 ++row;
2611 lastcol = 0;
2612 }
2613
2614 *vpos = row->y;
2615 *hpos = lastcol + 1;
2616 return 0;
2617}
2618
2619static void
2620term_mouse_highlight (struct frame *f, int x, int y)
2621{
2622 enum window_part part;
2623 Lisp_Object window;
2624 struct window *w;
2625 struct buffer *b;
2626
2627 if (NILP (Vmouse_highlight)
2628 || !f->glyphs_initialized_p)
2629 return;
2630
e882229c
NR
2631 /* Which window is that in? */
2632 window = window_from_coordinates (f, x, y, &part, &x, &y, 0);
2633
2634 /* Not on a window -> return. */
2635 if (!WINDOWP (window))
2636 return;
2637
6178ce5e 2638 if (!EQ (window, mouse_face_window))
e882229c
NR
2639 term_clear_mouse_face ();
2640
2641 w = XWINDOW (window);
2642
2643 /* Are we in a window whose display is up to date?
2644 And verify the buffer's text has not changed. */
2645 b = XBUFFER (w->buffer);
2646 if (part == ON_TEXT
2647 && EQ (w->window_end_valid, w->buffer)
2648 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
2649 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
2650 {
2651 int pos, i, nrows = w->current_matrix->nrows;
2652 struct glyph_row *row;
2653 struct glyph *glyph;
2654
2655 /* Find the glyph under X/Y. */
2656 glyph = NULL;
2657 if (y >= 0 && y < nrows)
2658 {
2659 row = MATRIX_ROW (w->current_matrix, y);
2660 /* Give up if some row before the one we are looking for is
2661 not enabled. */
2662 for (i = 0; i <= y; i++)
2663 if (!MATRIX_ROW (w->current_matrix, i)->enabled_p)
2664 break;
2665 if (i > y /* all rows upto and including the one at Y are enabled */
2666 && row->displays_text_p
2667 && x < window_box_width (w, TEXT_AREA))
2668 {
2669 glyph = row->glyphs[TEXT_AREA];
2670 if (x >= row->used[TEXT_AREA])
2671 glyph = NULL;
2672 else
2673 {
2674 glyph += x;
2675 if (!BUFFERP (glyph->object))
2676 glyph = NULL;
2677 }
2678 }
2679 }
2680
2681 /* Clear mouse face if X/Y not over text. */
2682 if (glyph == NULL)
2683 {
2684 term_clear_mouse_face ();
2685 return;
2686 }
2687
2688 if (!BUFFERP (glyph->object))
2689 abort ();
2690 pos = glyph->charpos;
2691
2692 /* Check for mouse-face. */
2693 {
2694 extern Lisp_Object Qmouse_face;
2695 Lisp_Object mouse_face, overlay, position, *overlay_vec;
3b8c0c70 2696 int noverlays, obegv, ozv;
e882229c
NR
2697 struct buffer *obuf;
2698
2699 /* If we get an out-of-range value, return now; avoid an error. */
2700 if (pos > BUF_Z (b))
2701 return;
2702
2703 /* Make the window's buffer temporarily current for
2704 overlays_at and compute_char_face. */
2705 obuf = current_buffer;
2706 current_buffer = b;
2707 obegv = BEGV;
2708 ozv = ZV;
2709 BEGV = BEG;
2710 ZV = Z;
2711
2712 /* Is this char mouse-active? */
2713 XSETINT (position, pos);
2714
2715 /* Put all the overlays we want in a vector in overlay_vec. */
2716 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL, 0);
2717 /* Sort overlays into increasing priority order. */
2718 noverlays = sort_overlays (overlay_vec, noverlays, w);
2719
2720 /* Check mouse-face highlighting. */
6178ce5e 2721 if (!(EQ (window, mouse_face_window)
e882229c
NR
2722 && y >= mouse_face_beg_row
2723 && y <= mouse_face_end_row
2724 && (y > mouse_face_beg_row
2725 || x >= mouse_face_beg_col)
2726 && (y < mouse_face_end_row
2727 || x < mouse_face_end_col
2728 || mouse_face_past_end)))
2729 {
2730 /* Clear the display of the old active region, if any. */
2731 term_clear_mouse_face ();
2732
2733 /* Find the highest priority overlay that has a mouse-face
2734 property. */
2735 overlay = Qnil;
2736 for (i = noverlays - 1; i >= 0; --i)
2737 {
2738 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
2739 if (!NILP (mouse_face))
2740 {
2741 overlay = overlay_vec[i];
2742 break;
2743 }
2744 }
2745
2746 /* If no overlay applies, get a text property. */
2747 if (NILP (overlay))
2748 mouse_face = Fget_text_property (position, Qmouse_face,
2749 w->buffer);
2750
2751 /* Handle the overlay case. */
2752 if (!NILP (overlay))
2753 {
2754 /* Find the range of text around this char that
2755 should be active. */
2756 Lisp_Object before, after;
0f8b27ea 2757 EMACS_INT ignore;
e882229c
NR
2758
2759
2760 before = Foverlay_start (overlay);
2761 after = Foverlay_end (overlay);
2762 /* Record this as the current active region. */
2763 fast_find_position (w, XFASTINT (before),
2764 &mouse_face_beg_col,
2765 &mouse_face_beg_row);
2766
2767 mouse_face_past_end
2768 = !fast_find_position (w, XFASTINT (after),
2769 &mouse_face_end_col,
2770 &mouse_face_end_row);
6178ce5e 2771 mouse_face_window = window;
e882229c
NR
2772
2773 mouse_face_face_id
2774 = face_at_buffer_position (w, pos, 0, 0,
2775 &ignore, pos + 1, 1);
2776
2777 /* Display it as active. */
2778 term_show_mouse_face (DRAW_MOUSE_FACE);
2779 }
2780 /* Handle the text property case. */
2781 else if (!NILP (mouse_face))
2782 {
2783 /* Find the range of text around this char that
2784 should be active. */
2785 Lisp_Object before, after, beginning, end;
0f8b27ea 2786 EMACS_INT ignore;
e882229c
NR
2787
2788 beginning = Fmarker_position (w->start);
2789 XSETINT (end, (BUF_Z (b) - XFASTINT (w->window_end_pos)));
2790 before
2791 = Fprevious_single_property_change (make_number (pos + 1),
2792 Qmouse_face,
2793 w->buffer, beginning);
2794 after
2795 = Fnext_single_property_change (position, Qmouse_face,
2796 w->buffer, end);
2797
2798 /* Record this as the current active region. */
2799 fast_find_position (w, XFASTINT (before),
2800 &mouse_face_beg_col,
2801 &mouse_face_beg_row);
2802 mouse_face_past_end
2803 = !fast_find_position (w, XFASTINT (after),
2804 &mouse_face_end_col,
2805 &mouse_face_end_row);
6178ce5e 2806 mouse_face_window = window;
e882229c
NR
2807
2808 mouse_face_face_id
2809 = face_at_buffer_position (w, pos, 0, 0,
2810 &ignore, pos + 1, 1);
2811
2812 /* Display it as active. */
2813 term_show_mouse_face (DRAW_MOUSE_FACE);
2814 }
2815 }
2816
2817 /* Look for a `help-echo' property. */
2818 {
2819 Lisp_Object help;
2820 extern Lisp_Object Qhelp_echo;
2821
2822 /* Check overlays first. */
2823 help = Qnil;
2824 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
2825 {
2826 overlay = overlay_vec[i];
2827 help = Foverlay_get (overlay, Qhelp_echo);
2828 }
2829
2830 if (!NILP (help))
2831 {
2832 help_echo_string = help;
2833 help_echo_window = window;
2834 help_echo_object = overlay;
2835 help_echo_pos = pos;
2836 }
2837 /* Try text properties. */
2838 else if (NILP (help)
2839 && ((STRINGP (glyph->object)
2840 && glyph->charpos >= 0
2841 && glyph->charpos < SCHARS (glyph->object))
2842 || (BUFFERP (glyph->object)
2843 && glyph->charpos >= BEGV
2844 && glyph->charpos < ZV)))
2845 {
2846 help = Fget_text_property (make_number (glyph->charpos),
2847 Qhelp_echo, glyph->object);
2848 if (!NILP (help))
2849 {
2850 help_echo_string = help;
2851 help_echo_window = window;
2852 help_echo_object = glyph->object;
2853 help_echo_pos = glyph->charpos;
2854 }
2855 }
2856 }
2857
2858 BEGV = obegv;
2859 ZV = ozv;
2860 current_buffer = obuf;
2861 }
2862 }
2863}
2864
2865static int
2866term_mouse_movement (FRAME_PTR frame, Gpm_Event *event)
2867{
2868 /* Has the mouse moved off the glyph it was on at the last sighting? */
2869 if (event->x != last_mouse_x || event->y != last_mouse_y)
2870 {
2871 frame->mouse_moved = 1;
80fb2ce0 2872 term_mouse_highlight (frame, event->x, event->y);
e882229c
NR
2873 /* Remember which glyph we're now on. */
2874 last_mouse_x = event->x;
2875 last_mouse_y = event->y;
2876 return 1;
2877 }
2878 return 0;
2879}
2880
2881/* Return the current position of the mouse.
2882
2883 Set *f to the frame the mouse is in, or zero if the mouse is in no
2884 Emacs frame. If it is set to zero, all the other arguments are
2885 garbage.
2886
2887 Set *bar_window to Qnil, and *x and *y to the column and
2888 row of the character cell the mouse is over.
2889
2890 Set *time to the time the mouse was at the returned position.
2891
80fb2ce0 2892 This clears mouse_moved until the next motion
94da14a0 2893 event arrives. */
e882229c
NR
2894static void
2895term_mouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
2896 enum scroll_bar_part *part, Lisp_Object *x,
2897 Lisp_Object *y, unsigned long *time)
2898{
e882229c 2899 struct timeval now;
e882229c
NR
2900
2901 *fp = SELECTED_FRAME ();
94da14a0 2902 (*fp)->mouse_moved = 0;
e882229c
NR
2903
2904 *bar_window = Qnil;
2905 *part = 0;
2906
80fb2ce0 2907 XSETINT (*x, last_mouse_x);
94da14a0 2908 XSETINT (*y, last_mouse_y);
e882229c
NR
2909 gettimeofday(&now, 0);
2910 *time = (now.tv_sec * 1000) + (now.tv_usec / 1000);
e882229c
NR
2911}
2912
2913/* Prepare a mouse-event in *RESULT for placement in the input queue.
2914
2915 If the event is a button press, then note that we have grabbed
2916 the mouse. */
2917
2918static Lisp_Object
2919term_mouse_click (struct input_event *result, Gpm_Event *event,
2920 struct frame *f)
2921{
2922 struct timeval now;
2923 int i, j;
2924
2925 result->kind = GPM_CLICK_EVENT;
2926 for (i = 0, j = GPM_B_LEFT; i < 3; i++, j >>= 1 )
2927 {
2928 if (event->buttons & j) {
2929 result->code = i; /* button number */
2930 break;
2931 }
2932 }
2933 gettimeofday(&now, 0);
2934 result->timestamp = (now.tv_sec * 1000) + (now.tv_usec / 1000);
2935
2936 if (event->type & GPM_UP)
2937 result->modifiers = up_modifier;
2938 else if (event->type & GPM_DOWN)
2939 result->modifiers = down_modifier;
2940 else
2941 result->modifiers = 0;
f4d953fc 2942
e882229c
NR
2943 if (event->type & GPM_SINGLE)
2944 result->modifiers |= click_modifier;
f4d953fc 2945
e882229c
NR
2946 if (event->type & GPM_DOUBLE)
2947 result->modifiers |= double_modifier;
2948
2949 if (event->type & GPM_TRIPLE)
2950 result->modifiers |= triple_modifier;
2951
2952 if (event->type & GPM_DRAG)
2953 result->modifiers |= drag_modifier;
2954
80fb2ce0 2955 if (!(event->type & (GPM_MOVE | GPM_DRAG))) {
e882229c
NR
2956
2957 /* 1 << KG_SHIFT */
2958 if (event->modifiers & (1 << 0))
2959 result->modifiers |= shift_modifier;
2960
2961 /* 1 << KG_CTRL */
2962 if (event->modifiers & (1 << 2))
2963 result->modifiers |= ctrl_modifier;
2964
2965 /* 1 << KG_ALT || KG_ALTGR */
2966 if (event->modifiers & (1 << 3)
2967 || event->modifiers & (1 << 1))
2968 result->modifiers |= meta_modifier;
2969 }
2970
80fb2ce0
NR
2971 XSETINT (result->x, event->x);
2972 XSETINT (result->y, event->y);
e882229c
NR
2973 XSETFRAME (result->frame_or_window, f);
2974 result->arg = Qnil;
2975 return Qnil;
2976}
2977
f4d953fc 2978int
7be1c21a 2979handle_one_term_event (struct tty_display_info *tty, Gpm_Event *event, struct input_event* hold_quit)
e882229c 2980{
7be1c21a 2981 struct frame *f = XFRAME (tty->top_frame);
e882229c
NR
2982 struct input_event ie;
2983 int do_help = 0;
2984 int count = 0;
2985
2986 EVENT_INIT (ie);
2987 ie.kind = NO_EVENT;
2988 ie.arg = Qnil;
2989
80fb2ce0 2990 if (event->type & (GPM_MOVE | GPM_DRAG)) {
e882229c
NR
2991 previous_help_echo_string = help_echo_string;
2992 help_echo_string = Qnil;
2993
6178ce5e 2994 Gpm_DrawPointer (event->x, event->y, fileno (tty->output));
e882229c 2995
80fb2ce0
NR
2996 if (!term_mouse_movement (f, event))
2997 help_echo_string = previous_help_echo_string;
e882229c
NR
2998
2999 /* If the contents of the global variable help_echo_string
3000 has changed, generate a HELP_EVENT. */
3001 if (!NILP (help_echo_string)
3002 || !NILP (previous_help_echo_string))
3003 do_help = 1;
3004
3005 goto done;
3006 }
3007 else {
3008 f->mouse_moved = 0;
3009 term_mouse_click (&ie, event, f);
e882229c
NR
3010 }
3011
3012 done:
3013 if (ie.kind != NO_EVENT)
3014 {
3015 kbd_buffer_store_event_hold (&ie, hold_quit);
3016 count++;
3017 }
3018
3019 if (do_help
3020 && !(hold_quit && hold_quit->kind != NO_EVENT))
3021 {
3022 Lisp_Object frame;
3023
3024 if (f)
3025 XSETFRAME (frame, f);
3026 else
3027 frame = Qnil;
3028
3029 gen_help_event (help_echo_string, frame, help_echo_window,
3030 help_echo_object, help_echo_pos);
3031 count++;
3032 }
3033
3034 return count;
3035}
3036
6178ce5e 3037DEFUN ("gpm-mouse-start", Fgpm_mouse_start, Sgpm_mouse_start,
e882229c 3038 0, 0, 0,
71f44e7a 3039 doc: /* Open a connection to Gpm.
6178ce5e 3040Gpm-mouse can only be activated for one tty at a time. */)
e882229c
NR
3041 ()
3042{
71f44e7a
SM
3043 struct frame *f = SELECTED_FRAME ();
3044 struct tty_display_info *tty
3045 = ((f)->output_method == output_termcap
3046 ? (f)->terminal->display_info.tty : NULL);
e882229c
NR
3047 Gpm_Connect connection;
3048
6178ce5e
SM
3049 if (!tty)
3050 error ("Gpm-mouse only works in the GNU/Linux console");
4ce5ab77
SM
3051 if (gpm_tty == tty)
3052 return Qnil; /* Already activated, nothing to do. */
3053 if (gpm_tty)
3054 error ("Gpm-mouse can only be activated for one tty at a time");
71f44e7a 3055
e882229c
NR
3056 connection.eventMask = ~0;
3057 connection.defaultMask = ~GPM_HARD;
3058 connection.maxMod = ~0;
3059 connection.minMod = 0;
80fb2ce0 3060 gpm_zerobased = 1;
e882229c
NR
3061
3062 if (Gpm_Open (&connection, 0) < 0)
6178ce5e 3063 error ("Gpm-mouse failed to connect to the gpm daemon");
e882229c
NR
3064 else
3065 {
71f44e7a 3066 gpm_tty = tty;
1023cbed
SM
3067 /* `init_sys_modes' arranges for mouse movements sent through gpm_fd
3068 to generate SIGIOs. Apparently we need to call reset_sys_modes
3069 before calling init_sys_modes. */
7be1c21a
MB
3070 reset_sys_modes (tty);
3071 init_sys_modes (tty);
e882229c 3072 add_gpm_wait_descriptor (gpm_fd);
6178ce5e 3073 return Qnil;
e882229c
NR
3074 }
3075}
3076
6178ce5e 3077DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop, Sgpm_mouse_stop,
e882229c
NR
3078 0, 0, 0,
3079 doc: /* Close a connection to Gpm. */)
3080 ()
3081{
4ce5ab77
SM
3082 struct frame *f = SELECTED_FRAME ();
3083 struct tty_display_info *tty
3084 = ((f)->output_method == output_termcap
3085 ? (f)->terminal->display_info.tty : NULL);
3086
3087 if (!tty || gpm_tty != tty)
3088 return Qnil; /* Not activated on this terminal, nothing to do. */
f4d953fc 3089
6178ce5e
SM
3090 if (gpm_fd >= 0)
3091 delete_gpm_wait_descriptor (gpm_fd);
3092 while (Gpm_Close()); /* close all the stack */
3093 gpm_tty = NULL;
3094 return Qnil;
e882229c 3095}
7e5a23bd 3096#endif /* HAVE_GPM */
e882229c
NR
3097
3098\f
a168702a
GM
3099/***********************************************************************
3100 Initialization
3101 ***********************************************************************/
3102
ed8dad6b
KL
3103/* Initialize the tty-dependent part of frame F. The frame must
3104 already have its device initialized. */
3224dac1 3105
dfcf069d 3106void
ed8dad6b 3107create_tty_output (struct frame *f)
28d440ab 3108{
ed8dad6b
KL
3109 struct tty_output *t;
3110
3111 if (! FRAME_TERMCAP_P (f))
428a555e
KL
3112 abort ();
3113
ed8dad6b
KL
3114 t = xmalloc (sizeof (struct tty_output));
3115 bzero (t, sizeof (struct tty_output));
b6660415 3116
6ed8eeff 3117 t->display_info = FRAME_TERMINAL (f)->display_info.tty;
bedb9c0e 3118
ed8dad6b 3119 f->output_data.tty = t;
3224dac1
KL
3120}
3121
ed8dad6b 3122/* Delete the tty-dependent part of frame F. */
da8e1115 3123
ed8dad6b
KL
3124static void
3125delete_tty_output (struct frame *f)
3224dac1 3126{
ed8dad6b 3127 if (! FRAME_TERMCAP_P (f))
3224dac1
KL
3128 abort ();
3129
ed8dad6b 3130 xfree (f->output_data.tty);
28d440ab
KL
3131}
3132
ed8dad6b 3133\f
47cc8819 3134/* Reset the hooks in TERMINAL. */
ed8dad6b 3135
4a665758
KL
3136static void
3137clear_tty_hooks (struct terminal *terminal)
3138{
3139 terminal->rif = 0;
3140 terminal->cursor_to_hook = 0;
3141 terminal->raw_cursor_to_hook = 0;
3142 terminal->clear_to_end_hook = 0;
3143 terminal->clear_frame_hook = 0;
3144 terminal->clear_end_of_line_hook = 0;
3145 terminal->ins_del_lines_hook = 0;
3146 terminal->insert_glyphs_hook = 0;
3147 terminal->write_glyphs_hook = 0;
3148 terminal->delete_glyphs_hook = 0;
3149 terminal->ring_bell_hook = 0;
3150 terminal->reset_terminal_modes_hook = 0;
3151 terminal->set_terminal_modes_hook = 0;
3152 terminal->update_begin_hook = 0;
3153 terminal->update_end_hook = 0;
3154 terminal->set_terminal_window_hook = 0;
3155 terminal->mouse_position_hook = 0;
3156 terminal->frame_rehighlight_hook = 0;
3157 terminal->frame_raise_lower_hook = 0;
974b73e8 3158 terminal->fullscreen_hook = 0;
4a665758
KL
3159 terminal->set_vertical_scroll_bar_hook = 0;
3160 terminal->condemn_scroll_bars_hook = 0;
3161 terminal->redeem_scroll_bar_hook = 0;
3162 terminal->judge_scroll_bars_hook = 0;
3163 terminal->read_socket_hook = 0;
3164 terminal->frame_up_to_date_hook = 0;
3165
3166 /* Leave these two set, or suspended frames are not deleted
3167 correctly. */
3168 terminal->delete_frame_hook = &delete_tty_output;
3169 terminal->delete_terminal_hook = &delete_tty;
3170}
3171
47cc8819
DN
3172/* Initialize hooks in TERMINAL with the values needed for a tty. */
3173
4a665758
KL
3174static void
3175set_tty_hooks (struct terminal *terminal)
3176{
3177 terminal->rif = 0; /* ttys don't support window-based redisplay. */
3178
3179 terminal->cursor_to_hook = &tty_cursor_to;
3180 terminal->raw_cursor_to_hook = &tty_raw_cursor_to;
3181
3182 terminal->clear_to_end_hook = &tty_clear_to_end;
3183 terminal->clear_frame_hook = &tty_clear_frame;
3184 terminal->clear_end_of_line_hook = &tty_clear_end_of_line;
3185
3186 terminal->ins_del_lines_hook = &tty_ins_del_lines;
3187
3188 terminal->insert_glyphs_hook = &tty_insert_glyphs;
3189 terminal->write_glyphs_hook = &tty_write_glyphs;
3190 terminal->delete_glyphs_hook = &tty_delete_glyphs;
3191
3192 terminal->ring_bell_hook = &tty_ring_bell;
f4d953fc 3193
4a665758
KL
3194 terminal->reset_terminal_modes_hook = &tty_reset_terminal_modes;
3195 terminal->set_terminal_modes_hook = &tty_set_terminal_modes;
3196 terminal->update_begin_hook = 0; /* Not needed. */
3197 terminal->update_end_hook = &tty_update_end;
3198 terminal->set_terminal_window_hook = &tty_set_terminal_window;
3199
3200 terminal->mouse_position_hook = 0; /* Not needed. */
3201 terminal->frame_rehighlight_hook = 0; /* Not needed. */
3202 terminal->frame_raise_lower_hook = 0; /* Not needed. */
3203
3204 terminal->set_vertical_scroll_bar_hook = 0; /* Not needed. */
3205 terminal->condemn_scroll_bars_hook = 0; /* Not needed. */
3206 terminal->redeem_scroll_bar_hook = 0; /* Not needed. */
3207 terminal->judge_scroll_bars_hook = 0; /* Not needed. */
3208
3209 terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */
3210 terminal->frame_up_to_date_hook = 0; /* Not needed. */
f4d953fc 3211
4a665758
KL
3212 terminal->delete_frame_hook = &delete_tty_output;
3213 terminal->delete_terminal_hook = &delete_tty;
3214}
3215
03a1d6bd 3216/* Drop the controlling terminal if fd is the same device. */
ed8dad6b 3217static void
03a1d6bd
KL
3218dissociate_if_controlling_tty (int fd)
3219{
5d333979 3220#ifndef WINDOWSNT
03a1d6bd 3221 int pgid;
8516815b 3222 EMACS_GET_TTY_PGRP (fd, &pgid); /* If tcgetpgrp succeeds, fd is the ctty. */
03a1d6bd
KL
3223 if (pgid != -1)
3224 {
8516815b 3225#if defined (USG) && !defined (BSD_PGRPS)
03a1d6bd
KL
3226 setpgrp ();
3227 no_controlling_tty = 1;
de52dcbb
DN
3228#elif defined (CYGWIN)
3229 setsid ();
3230 no_controlling_tty = 1;
03a1d6bd
KL
3231#else
3232#ifdef TIOCNOTTY /* Try BSD ioctls. */
8516815b 3233 sigblock (sigmask (SIGTTOU));
78048085 3234 fd = emacs_open (DEV_TTY, O_RDWR, 0);
8516815b
KL
3235 if (fd != -1 && ioctl (fd, TIOCNOTTY, 0) != -1)
3236 {
3237 no_controlling_tty = 1;
3238 }
3239 if (fd != -1)
3240 emacs_close (fd);
3241 sigunblock (sigmask (SIGTTOU));
03a1d6bd 3242#else
8516815b
KL
3243 /* Unknown system. */
3244 croak ();
03a1d6bd
KL
3245#endif /* ! TIOCNOTTY */
3246#endif /* ! USG */
71a96040 3247 }
78048085 3248#endif /* !WINDOWSNT */
03a1d6bd
KL
3249}
3250
520c4dfd
KL
3251static void maybe_fatal();
3252
3224dac1
KL
3253/* Create a termcap display on the tty device with the given name and
3254 type.
3255
ab797f65 3256 If NAME is NULL, then use the controlling tty, i.e., "/dev/tty".
3224dac1
KL
3257 Otherwise NAME should be a path to the tty device file,
3258 e.g. "/dev/pts/7".
28d440ab 3259
3224dac1
KL
3260 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
3261
3262 If MUST_SUCCEED is true, then all errors are fatal. */
da8e1115 3263
6ed8eeff 3264struct terminal *
a4c6993d 3265init_tty (char *name, char *terminal_type, int must_succeed)
08a24c47 3266{
59b3194c 3267 char *area = NULL;
08a24c47 3268 char **address = &area;
6b61353c
KH
3269 char *buffer = NULL;
3270 int buffer_size = 4096;
59b3194c 3271 register char *p = NULL;
08a24c47 3272 int status;
59b3194c
KL
3273 struct tty_display_info *tty = NULL;
3274 struct terminal *terminal = NULL;
3275 int ctty = 0; /* 1 if asked to open controlling tty. */
28d440ab 3276
3224dac1
KL
3277 if (!terminal_type)
3278 maybe_fatal (must_succeed, 0, 0,
3279 "Unknown terminal type",
3280 "Unknown terminal type");
b6660415 3281
ab797f65 3282 if (name == NULL)
78048085
EZ
3283 name = DEV_TTY;
3284 if (!strcmp (name, DEV_TTY))
ab797f65
KL
3285 ctty = 1;
3286
6ed8eeff
KL
3287 /* If we already have a terminal on the given device, use that. If
3288 all such terminals are suspended, create a new one instead. */
a4c6993d 3289 /* XXX Perhaps this should be made explicit by having init_tty
6ed8eeff 3290 always create a new terminal and separating terminal and frame
b6660415 3291 creation on Lisp level. */
6ed8eeff
KL
3292 terminal = get_named_tty (name);
3293 if (terminal)
3294 return terminal;
78048085 3295
6ed8eeff 3296 terminal = create_terminal ();
3224dac1
KL
3297 tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info));
3298 bzero (tty, sizeof (struct tty_display_info));
3299 tty->next = tty_list;
3300 tty_list = tty;
428a555e 3301
6ed8eeff
KL
3302 terminal->type = output_termcap;
3303 terminal->display_info.tty = tty;
3304 tty->terminal = terminal;
28d440ab 3305
7b00d185
KL
3306 tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
3307 Wcm_clear (tty);
daf01701 3308
55d5acfa 3309#ifndef WINDOWSNT
4a665758 3310 set_tty_hooks (terminal);
78048085 3311
59b3194c
KL
3312 {
3313 int fd;
3314 FILE *file;
0c72d684
KL
3315
3316#ifdef O_IGNORE_CTTY
59b3194c 3317 if (!ctty)
0c72d684
KL
3318 /* Open the terminal device. Don't recognize it as our
3319 controlling terminal, and don't make it the controlling tty
3320 if we don't have one at the moment. */
3321 fd = emacs_open (name, O_RDWR | O_IGNORE_CTTY | O_NOCTTY, 0);
59b3194c 3322 else
0c72d684 3323#else
2666355c 3324 /* Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
59b3194c
KL
3325 defined on Hurd. On other systems, we need to explicitly
3326 dissociate ourselves from the controlling tty when we want to
3327 open a frame on the same terminal. */
0c72d684 3328 fd = emacs_open (name, O_RDWR | O_NOCTTY, 0);
0c72d684
KL
3329#endif /* O_IGNORE_CTTY */
3330
59b3194c
KL
3331 if (fd < 0)
3332 maybe_fatal (must_succeed, buffer, terminal,
3333 "Could not open file: %s",
3334 "Could not open file: %s",
3335 name);
3336 if (!isatty (fd))
3337 {
3338 close (fd);
3339 maybe_fatal (must_succeed, buffer, terminal,
3340 "Not a tty device: %s",
3341 "Not a tty device: %s",
3342 name);
3343 }
0c72d684 3344
59b3194c
KL
3345#ifndef O_IGNORE_CTTY
3346 if (!ctty)
03a1d6bd 3347 dissociate_if_controlling_tty (fd);
59b3194c
KL
3348#endif
3349
3350 file = fdopen (fd, "w+");
3351 tty->name = xstrdup (name);
3352 terminal->name = xstrdup (name);
3353 tty->input = file;
3354 tty->output = file;
3355 }
78048085 3356
28d7d09f 3357 tty->type = xstrdup (terminal_type);
28d440ab 3358
819b8f00 3359 add_keyboard_wait_descriptor (fileno (tty->input));
daf01701 3360
55d5acfa 3361#endif
08a24c47 3362
288d5132
KH
3363 encode_terminal_src_size = 0;
3364 encode_terminal_dst_size = 0;
af645abf 3365
7e5a23bd 3366#ifdef HAVE_GPM
88acaaf2 3367 terminal->mouse_position_hook = term_mouse_position;
6178ce5e 3368 mouse_face_window = Qnil;
e882229c
NR
3369#endif
3370
cb28b9c2 3371#ifdef WINDOWSNT
953bf0dc 3372 initialize_w32_display (terminal);
a0236551
JR
3373 /* The following two are inaccessible from w32console.c. */
3374 terminal->delete_frame_hook = &delete_tty_output;
3375 terminal->delete_terminal_hook = &delete_tty;
cb28b9c2 3376
78048085
EZ
3377 tty->name = xstrdup (name);
3378 terminal->name = xstrdup (name);
3379 tty->type = xstrdup (terminal_type);
cb28b9c2 3380
55d5acfa 3381 tty->output = stdout;
a0236551
JR
3382 tty->input = stdin;
3383 add_keyboard_wait_descriptor (0);
cb28b9c2 3384
a0236551 3385 Wcm_clear (tty);
cb28b9c2 3386
5d333979
JR
3387 {
3388 struct frame *f = XFRAME (selected_frame);
cb28b9c2 3389
a0236551
JR
3390 FrameRows (tty) = FRAME_LINES (f);
3391 FrameCols (tty) = FRAME_COLS (f);
3392 tty->specified_window = FRAME_LINES (f);
cb28b9c2 3393
a0236551
JR
3394 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
3395 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
5d333979
JR
3396 }
3397 tty->delete_in_insert_mode = 1;
cb28b9c2 3398
daf01701 3399 UseTabs (tty) = 0;
6ed8eeff 3400 terminal->scroll_region_ok = 0;
cb28b9c2 3401
7e59217d 3402 /* Seems to insert lines when it's not supposed to, messing up the
6ed8eeff 3403 display. In doing a trace, it didn't seem to be called much, so I
7e59217d 3404 don't think we're losing anything by turning it off. */
6ed8eeff
KL
3405 terminal->line_ins_del_ok = 0;
3406 terminal->char_ins_del_ok = 1;
cb28b9c2
RS
3407
3408 baud_rate = 19200;
3409
5d333979 3410 tty->TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
cb28b9c2 3411
eccec691 3412#else /* not WINDOWSNT */
cb28b9c2 3413
6548cf00 3414 Wcm_clear (tty);
08a24c47 3415
6b61353c 3416 buffer = (char *) xmalloc (buffer_size);
78048085 3417
03a1d6bd
KL
3418 /* On some systems, tgetent tries to access the controlling
3419 terminal. */
3420 sigblock (sigmask (SIGTTOU));
08a24c47 3421 status = tgetent (buffer, terminal_type);
03a1d6bd 3422 sigunblock (sigmask (SIGTTOU));
78048085 3423
08a24c47 3424 if (status < 0)
b0347178
KH
3425 {
3426#ifdef TERMINFO
6ed8eeff 3427 maybe_fatal (must_succeed, buffer, terminal,
3224dac1
KL
3428 "Cannot open terminfo database file",
3429 "Cannot open terminfo database file");
b0347178 3430#else
6ed8eeff 3431 maybe_fatal (must_succeed, buffer, terminal,
3224dac1
KL
3432 "Cannot open termcap database file",
3433 "Cannot open termcap database file");
b0347178
KH
3434#endif
3435 }
08a24c47 3436 if (status == 0)
b0347178
KH
3437 {
3438#ifdef TERMINFO
6ed8eeff 3439 maybe_fatal (must_succeed, buffer, terminal,
3224dac1
KL
3440 "Terminal type %s is not defined",
3441 "Terminal type %s is not defined.\n\
b0347178
KH
3442If that is not the actual type of terminal you have,\n\
3443use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3444`setenv TERM ...') to specify the correct type. It may be necessary\n\
e12c1054 3445to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3224dac1 3446 terminal_type);
b0347178 3447#else
6ed8eeff 3448 maybe_fatal (must_succeed, buffer, terminal,
3224dac1
KL
3449 "Terminal type %s is not defined",
3450 "Terminal type %s is not defined.\n\
c5a9c3e6
RS
3451If that is not the actual type of terminal you have,\n\
3452use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3453`setenv TERM ...') to specify the correct type. It may be necessary\n\
e12c1054 3454to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3224dac1 3455 terminal_type);
b0347178
KH
3456#endif
3457 }
6b61353c
KH
3458
3459#ifndef TERMINFO
3460 if (strlen (buffer) >= buffer_size)
08a24c47 3461 abort ();
6b61353c
KH
3462 buffer_size = strlen (buffer);
3463#endif
3464 area = (char *) xmalloc (buffer_size);
08a24c47 3465
fca177d4
KL
3466 tty->TS_ins_line = tgetstr ("al", address);
3467 tty->TS_ins_multi_lines = tgetstr ("AL", address);
3468 tty->TS_bell = tgetstr ("bl", address);
6548cf00 3469 BackTab (tty) = tgetstr ("bt", address);
fca177d4
KL
3470 tty->TS_clr_to_bottom = tgetstr ("cd", address);
3471 tty->TS_clr_line = tgetstr ("ce", address);
3472 tty->TS_clr_frame = tgetstr ("cl", address);
6548cf00
KL
3473 ColPosition (tty) = NULL; /* tgetstr ("ch", address); */
3474 AbsPosition (tty) = tgetstr ("cm", address);
3475 CR (tty) = tgetstr ("cr", address);
fca177d4
KL
3476 tty->TS_set_scroll_region = tgetstr ("cs", address);
3477 tty->TS_set_scroll_region_1 = tgetstr ("cS", address);
6548cf00 3478 RowPosition (tty) = tgetstr ("cv", address);
fca177d4
KL
3479 tty->TS_del_char = tgetstr ("dc", address);
3480 tty->TS_del_multi_chars = tgetstr ("DC", address);
3481 tty->TS_del_line = tgetstr ("dl", address);
3482 tty->TS_del_multi_lines = tgetstr ("DL", address);
3483 tty->TS_delete_mode = tgetstr ("dm", address);
3484 tty->TS_end_delete_mode = tgetstr ("ed", address);
3485 tty->TS_end_insert_mode = tgetstr ("ei", address);
6548cf00 3486 Home (tty) = tgetstr ("ho", address);
fca177d4
KL
3487 tty->TS_ins_char = tgetstr ("ic", address);
3488 tty->TS_ins_multi_chars = tgetstr ("IC", address);
3489 tty->TS_insert_mode = tgetstr ("im", address);
3490 tty->TS_pad_inserted_char = tgetstr ("ip", address);
3491 tty->TS_end_keypad_mode = tgetstr ("ke", address);
3492 tty->TS_keypad_mode = tgetstr ("ks", address);
6548cf00
KL
3493 LastLine (tty) = tgetstr ("ll", address);
3494 Right (tty) = tgetstr ("nd", address);
3495 Down (tty) = tgetstr ("do", address);
3496 if (!Down (tty))
3497 Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do" */
08a24c47
JB
3498#ifdef VMS
3499 /* VMS puts a carriage return before each linefeed,
3500 so it is not safe to use linefeeds. */
6548cf00
KL
3501 if (Down (tty) && Down (tty)[0] == '\n' && Down (tty)[1] == '\0')
3502 Down (tty) = 0;
08a24c47
JB
3503#endif /* VMS */
3504 if (tgetflag ("bs"))
6548cf00 3505 Left (tty) = "\b"; /* can't possibly be longer! */
08a24c47 3506 else /* (Actually, "bs" is obsolete...) */
6548cf00
KL
3507 Left (tty) = tgetstr ("le", address);
3508 if (!Left (tty))
3509 Left (tty) = tgetstr ("bc", address); /* Obsolete name for "le" */
fca177d4
KL
3510 tty->TS_pad_char = tgetstr ("pc", address);
3511 tty->TS_repeat = tgetstr ("rp", address);
3512 tty->TS_end_standout_mode = tgetstr ("se", address);
3513 tty->TS_fwd_scroll = tgetstr ("sf", address);
3514 tty->TS_standout_mode = tgetstr ("so", address);
3515 tty->TS_rev_scroll = tgetstr ("sr", address);
6548cf00 3516 tty->Wcm->cm_tab = tgetstr ("ta", address);
fca177d4
KL
3517 tty->TS_end_termcap_modes = tgetstr ("te", address);
3518 tty->TS_termcap_modes = tgetstr ("ti", address);
6548cf00 3519 Up (tty) = tgetstr ("up", address);
fca177d4
KL
3520 tty->TS_visible_bell = tgetstr ("vb", address);
3521 tty->TS_cursor_normal = tgetstr ("ve", address);
3522 tty->TS_cursor_visible = tgetstr ("vs", address);
3523 tty->TS_cursor_invisible = tgetstr ("vi", address);
3524 tty->TS_set_window = tgetstr ("wi", address);
3525
3526 tty->TS_enter_underline_mode = tgetstr ("us", address);
3527 tty->TS_exit_underline_mode = tgetstr ("ue", address);
3528 tty->TS_enter_bold_mode = tgetstr ("md", address);
3529 tty->TS_enter_dim_mode = tgetstr ("mh", address);
3530 tty->TS_enter_blink_mode = tgetstr ("mb", address);
3531 tty->TS_enter_reverse_mode = tgetstr ("mr", address);
3532 tty->TS_enter_alt_charset_mode = tgetstr ("as", address);
3533 tty->TS_exit_alt_charset_mode = tgetstr ("ae", address);
3534 tty->TS_exit_attribute_mode = tgetstr ("me", address);
177c0ea7 3535
6548cf00
KL
3536 MultiUp (tty) = tgetstr ("UP", address);
3537 MultiDown (tty) = tgetstr ("DO", address);
3538 MultiLeft (tty) = tgetstr ("LE", address);
3539 MultiRight (tty) = tgetstr ("RI", address);
08a24c47 3540
e7f90eab
GM
3541 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
3542 color because we can't switch back to the default foreground and
3543 background. */
fca177d4
KL
3544 tty->TS_orig_pair = tgetstr ("op", address);
3545 if (tty->TS_orig_pair)
a168702a 3546 {
fca177d4
KL
3547 tty->TS_set_foreground = tgetstr ("AF", address);
3548 tty->TS_set_background = tgetstr ("AB", address);
3549 if (!tty->TS_set_foreground)
e7f90eab
GM
3550 {
3551 /* SVr4. */
fca177d4
KL
3552 tty->TS_set_foreground = tgetstr ("Sf", address);
3553 tty->TS_set_background = tgetstr ("Sb", address);
e7f90eab 3554 }
177c0ea7 3555
fca177d4
KL
3556 tty->TN_max_colors = tgetnum ("Co");
3557 tty->TN_max_pairs = tgetnum ("pa");
177c0ea7 3558
fca177d4
KL
3559 tty->TN_no_color_video = tgetnum ("NC");
3560 if (tty->TN_no_color_video == -1)
3561 tty->TN_no_color_video = 0;
a168702a 3562 }
a168702a 3563
fca177d4 3564 tty_default_color_capabilities (tty, 1);
ace28297 3565
6548cf00 3566 MagicWrap (tty) = tgetflag ("xn");
e4058338
KH
3567 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
3568 the former flag imply the latter. */
6548cf00 3569 AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
6ed8eeff 3570 terminal->memory_below_frame = tgetflag ("db");
fca177d4 3571 tty->TF_hazeltine = tgetflag ("hz");
6ed8eeff 3572 terminal->must_write_spaces = tgetflag ("in");
fca177d4
KL
3573 tty->meta_key = tgetflag ("km") || tgetflag ("MT");
3574 tty->TF_insmode_motion = tgetflag ("mi");
3575 tty->TF_standout_motion = tgetflag ("ms");
3576 tty->TF_underscore = tgetflag ("ul");
3577 tty->TF_teleray = tgetflag ("xt");
08a24c47 3578
953bf0dc 3579#endif /* !WINDOWSNT */
e7cf0fa0 3580#ifdef MULTI_KBOARD
6ed8eeff
KL
3581 terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
3582 init_kboard (terminal->kboard);
70b8d0a4 3583 terminal->kboard->Vwindow_system = Qnil;
6ed8eeff
KL
3584 terminal->kboard->next_kboard = all_kboards;
3585 all_kboards = terminal->kboard;
3586 terminal->kboard->reference_count++;
e7cf0fa0
KL
3587 /* Don't let the initial kboard remain current longer than necessary.
3588 That would cause problems if a file loaded on startup tries to
3589 prompt in the mini-buffer. */
3590 if (current_kboard == initial_kboard)
6ed8eeff 3591 current_kboard = terminal->kboard;
953bf0dc 3592#ifndef WINDOWSNT
6ed8eeff 3593 term_get_fkeys (address, terminal->kboard);
80ca7302 3594#endif
953bf0dc 3595#endif
5c2c7893 3596
953bf0dc 3597#ifndef WINDOWSNT
ff11dfa1 3598 /* Get frame size from system, or else from termcap. */
3b12ce12
RS
3599 {
3600 int height, width;
0b0d3e0b 3601 get_tty_size (fileno (tty->input), &width, &height);
0a125897
KL
3602 FrameCols (tty) = width;
3603 FrameRows (tty) = height;
3b12ce12
RS
3604 }
3605
0a125897
KL
3606 if (FrameCols (tty) <= 0)
3607 FrameCols (tty) = tgetnum ("co");
3608 if (FrameRows (tty) <= 0)
3609 FrameRows (tty) = tgetnum ("li");
177c0ea7 3610
0a125897 3611 if (FrameRows (tty) < 3 || FrameCols (tty) < 3)
6ed8eeff 3612 maybe_fatal (must_succeed, NULL, terminal,
3224dac1
KL
3613 "Screen size %dx%d is too small"
3614 "Screen size %dx%d is too small",
0a125897 3615 FrameCols (tty), FrameRows (tty));
ee7a2de4 3616
8a56675d 3617#if 0 /* This is not used anywhere. */
6ed8eeff 3618 tty->terminal->min_padding_speed = tgetnum ("pb");
8a56675d 3619#endif
28d440ab 3620
6548cf00 3621 TabWidth (tty) = tgetnum ("tw");
08a24c47
JB
3622
3623#ifdef VMS
3624 /* These capabilities commonly use ^J.
3625 I don't know why, but sending them on VMS does not work;
3626 it causes following spaces to be lost, sometimes.
3627 For now, the simplest fix is to avoid using these capabilities ever. */
6548cf00
KL
3628 if (Down (tty) && Down (tty)[0] == '\n')
3629 Down (tty) = 0;
08a24c47
JB
3630#endif /* VMS */
3631
fca177d4
KL
3632 if (!tty->TS_bell)
3633 tty->TS_bell = "\07";
08a24c47 3634
fca177d4
KL
3635 if (!tty->TS_fwd_scroll)
3636 tty->TS_fwd_scroll = Down (tty);
08a24c47 3637
fca177d4 3638 PC = tty->TS_pad_char ? *tty->TS_pad_char : 0;
08a24c47 3639
6548cf00
KL
3640 if (TabWidth (tty) < 0)
3641 TabWidth (tty) = 8;
177c0ea7 3642
08a24c47
JB
3643/* Turned off since /etc/termcap seems to have :ta= for most terminals
3644 and newer termcap doc does not seem to say there is a default.
6548cf00
KL
3645 if (!tty->Wcm->cm_tab)
3646 tty->Wcm->cm_tab = "\t";
08a24c47
JB
3647*/
3648
54800acb
MB
3649 /* We don't support standout modes that use `magic cookies', so
3650 turn off any that do. */
fca177d4 3651 if (tty->TS_standout_mode && tgetnum ("sg") >= 0)
54800acb 3652 {
fca177d4
KL
3653 tty->TS_standout_mode = 0;
3654 tty->TS_end_standout_mode = 0;
54800acb 3655 }
fca177d4 3656 if (tty->TS_enter_underline_mode && tgetnum ("ug") >= 0)
54800acb 3657 {
fca177d4
KL
3658 tty->TS_enter_underline_mode = 0;
3659 tty->TS_exit_underline_mode = 0;
54800acb
MB
3660 }
3661
3662 /* If there's no standout mode, try to use underlining instead. */
fca177d4 3663 if (tty->TS_standout_mode == 0)
08a24c47 3664 {
fca177d4
KL
3665 tty->TS_standout_mode = tty->TS_enter_underline_mode;
3666 tty->TS_end_standout_mode = tty->TS_exit_underline_mode;
08a24c47
JB
3667 }
3668
afd359c4
RS
3669 /* If no `se' string, try using a `me' string instead.
3670 If that fails, we can't use standout mode at all. */
fca177d4 3671 if (tty->TS_end_standout_mode == 0)
afd359c4 3672 {
e4bfb3b6 3673 char *s = tgetstr ("me", address);
afd359c4 3674 if (s != 0)
fca177d4 3675 tty->TS_end_standout_mode = s;
afd359c4 3676 else
fca177d4 3677 tty->TS_standout_mode = 0;
afd359c4
RS
3678 }
3679
fca177d4 3680 if (tty->TF_teleray)
08a24c47 3681 {
6548cf00 3682 tty->Wcm->cm_tab = 0;
54800acb 3683 /* We can't support standout mode, because it uses magic cookies. */
fca177d4 3684 tty->TS_standout_mode = 0;
08a24c47 3685 /* But that means we cannot rely on ^M to go to column zero! */
6548cf00 3686 CR (tty) = 0;
08a24c47
JB
3687 /* LF can't be trusted either -- can alter hpos */
3688 /* if move at column 0 thru a line with TS_standout_mode */
6548cf00 3689 Down (tty) = 0;
08a24c47
JB
3690 }
3691
3692 /* Special handling for certain terminal types known to need it */
3693
3694 if (!strcmp (terminal_type, "supdup"))
3695 {
6ed8eeff 3696 terminal->memory_below_frame = 1;
6548cf00 3697 tty->Wcm->cm_losewrap = 1;
08a24c47
JB
3698 }
3699 if (!strncmp (terminal_type, "c10", 3)
3700 || !strcmp (terminal_type, "perq"))
3701 {
3702 /* Supply a makeshift :wi string.
3703 This string is not valid in general since it works only
3704 for windows starting at the upper left corner;
3705 but that is all Emacs uses.
3706
ff11dfa1 3707 This string works only if the frame is using
08a24c47
JB
3708 the top of the video memory, because addressing is memory-relative.
3709 So first check the :ti string to see if that is true.
3710
3711 It would be simpler if the :wi string could go in the termcap
3712 entry, but it can't because it is not fully valid.
3713 If it were in the termcap entry, it would confuse other programs. */
fca177d4 3714 if (!tty->TS_set_window)
08a24c47 3715 {
fca177d4 3716 p = tty->TS_termcap_modes;
08a24c47
JB
3717 while (*p && strcmp (p, "\033v "))
3718 p++;
3719 if (*p)
fca177d4 3720 tty->TS_set_window = "\033v%C %C %C %C ";
08a24c47
JB
3721 }
3722 /* Termcap entry often fails to have :in: flag */
6ed8eeff 3723 terminal->must_write_spaces = 1;
08a24c47
JB
3724 /* :ti string typically fails to have \E^G! in it */
3725 /* This limits scope of insert-char to one line. */
fca177d4 3726 strcpy (area, tty->TS_termcap_modes);
08a24c47 3727 strcat (area, "\033\007!");
fca177d4 3728 tty->TS_termcap_modes = area;
08a24c47 3729 area += strlen (area) + 1;
6548cf00 3730 p = AbsPosition (tty);
08a24c47 3731 /* Change all %+ parameters to %C, to handle
28d440ab 3732 values above 96 correctly for the C100. */
08a24c47 3733 while (*p)
28d440ab
KL
3734 {
3735 if (p[0] == '%' && p[1] == '+')
3736 p[1] = 'C';
3737 p++;
3738 }
08a24c47
JB
3739 }
3740
0a125897 3741 tty->specified_window = FrameRows (tty);
08a24c47 3742
6548cf00 3743 if (Wcm_init (tty) == -1) /* can't do cursor motion */
3224dac1 3744 {
6ed8eeff 3745 maybe_fatal (must_succeed, NULL, terminal,
3224dac1 3746 "Terminal type \"%s\" is not powerful enough to run Emacs",
08a24c47 3747#ifdef VMS
3224dac1 3748 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
08a24c47
JB
3749It lacks the ability to position the cursor.\n\
3750If that is not the actual type of terminal you have, use either the\n\
3751DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
e12c1054 3752or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
37dad45a
RS
3753#else /* not VMS */
3754# ifdef TERMINFO
3224dac1 3755 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
37dad45a
RS
3756It lacks the ability to position the cursor.\n\
3757If that is not the actual type of terminal you have,\n\
3758use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3759`setenv TERM ...') to specify the correct type. It may be necessary\n\
e12c1054 3760to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
37dad45a 3761# else /* TERMCAP */
3224dac1 3762 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
08a24c47
JB
3763It lacks the ability to position the cursor.\n\
3764If that is not the actual type of terminal you have,\n\
c5a9c3e6
RS
3765use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3766`setenv TERM ...') to specify the correct type. It may be necessary\n\
e12c1054 3767to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
37dad45a
RS
3768# endif /* TERMINFO */
3769#endif /*VMS */
3224dac1 3770 terminal_type);
fca177d4 3771 }
daf01701 3772
0a125897 3773 if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
6ed8eeff 3774 maybe_fatal (must_succeed, NULL, terminal,
3224dac1
KL
3775 "Could not determine the frame size",
3776 "Could not determine the frame size");
08a24c47 3777
fca177d4
KL
3778 tty->delete_in_insert_mode
3779 = tty->TS_delete_mode && tty->TS_insert_mode
3780 && !strcmp (tty->TS_delete_mode, tty->TS_insert_mode);
08a24c47 3781
fca177d4
KL
3782 tty->se_is_so = (tty->TS_standout_mode
3783 && tty->TS_end_standout_mode
3784 && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode));
08a24c47 3785
0b0d3e0b 3786 UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8;
08a24c47 3787
6ed8eeff 3788 terminal->scroll_region_ok
6548cf00 3789 = (tty->Wcm->cm_abs
fca177d4 3790 && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
08a24c47 3791
6ed8eeff 3792 terminal->line_ins_del_ok
fca177d4
KL
3793 = (((tty->TS_ins_line || tty->TS_ins_multi_lines)
3794 && (tty->TS_del_line || tty->TS_del_multi_lines))
6ed8eeff 3795 || (terminal->scroll_region_ok
fca177d4 3796 && tty->TS_fwd_scroll && tty->TS_rev_scroll));
08a24c47 3797
6ed8eeff 3798 terminal->char_ins_del_ok
fca177d4
KL
3799 = ((tty->TS_ins_char || tty->TS_insert_mode
3800 || tty->TS_pad_inserted_char || tty->TS_ins_multi_chars)
3801 && (tty->TS_del_char || tty->TS_del_multi_chars));
08a24c47 3802
6ed8eeff 3803 terminal->fast_clear_end_of_line = tty->TS_clr_line != 0;
08a24c47 3804
0b0d3e0b 3805 init_baud_rate (fileno (tty->input));
20a558dc 3806
daf01701
KL
3807#ifdef AIXHFT
3808 /* The HFT system on AIX doesn't optimize for scrolling, so it's
3809 really ugly at times. */
6ed8eeff
KL
3810 terminal->line_ins_del_ok = 0;
3811 terminal->char_ins_del_ok = 0;
daf01701
KL
3812#endif
3813
0a125897
KL
3814 /* Don't do this. I think termcap may still need the buffer. */
3815 /* xfree (buffer); */
28d440ab 3816
635e3b29
JR
3817#endif /* not WINDOWSNT */
3818
0a125897
KL
3819 /* Init system terminal modes (RAW or CBREAK, etc.). */
3820 init_sys_modes (tty);
daf01701 3821
6ed8eeff 3822 return terminal;
08a24c47
JB
3823}
3824
a4c6993d 3825/* Auxiliary error-handling function for init_tty.
6ed8eeff 3826 Free BUFFER and delete TERMINAL, then call error or fatal
da8e1115 3827 with str1 or str2, respectively, according to MUST_SUCCEED. */
6b61353c 3828
3224dac1 3829static void
6ed8eeff 3830maybe_fatal (must_succeed, buffer, terminal, str1, str2, arg1, arg2)
3224dac1
KL
3831 int must_succeed;
3832 char *buffer;
6ed8eeff 3833 struct terminal *terminal;
3224dac1
KL
3834 char *str1, *str2, *arg1, *arg2;
3835{
3836 if (buffer)
3837 xfree (buffer);
3838
6ed8eeff
KL
3839 if (terminal)
3840 delete_tty (terminal);
f4d953fc 3841
3224dac1
KL
3842 if (must_succeed)
3843 fatal (str2, arg1, arg2);
3844 else
3845 error (str1, arg1, arg2);
3846
3847 abort ();
08a24c47
JB
3848}
3849
dfcf069d 3850void
7c401d15 3851fatal (const char *str, ...)
08a24c47 3852{
7c401d15
DN
3853 va_list ap;
3854 va_start (ap, str);
08a24c47 3855 fprintf (stderr, "emacs: ");
7c401d15
DN
3856 vfprintf (stderr, str, ap);
3857 va_end (ap);
08a24c47
JB
3858 fflush (stderr);
3859 exit (1);
3860}
07c57952 3861
819b8f00
KL
3862\f
3863
6ed8eeff 3864/* Delete the given tty terminal, closing all frames on it. */
da8e1115 3865
ed8dad6b 3866static void
6ed8eeff 3867delete_tty (struct terminal *terminal)
072d84a6 3868{
428a555e 3869 struct tty_display_info *tty;
fca177d4 3870 Lisp_Object tail, frame;
6ed8eeff 3871 int last_terminal;
f4d953fc 3872
ab797f65
KL
3873 /* Protect against recursive calls. Fdelete_frame in
3874 delete_terminal calls us back when it deletes our last frame. */
59a7bc63 3875 if (!terminal->name)
0a125897 3876 return;
fca177d4 3877
6ed8eeff 3878 if (terminal->type != output_termcap)
428a555e
KL
3879 abort ();
3880
6ed8eeff 3881 tty = terminal->display_info.tty;
f4d953fc 3882
6ed8eeff 3883 last_terminal = 1;
81be1a93
KL
3884 FOR_EACH_FRAME (tail, frame)
3885 {
3886 struct frame *f = XFRAME (frame);
3887 if (FRAME_LIVE_P (f) && (!FRAME_TERMCAP_P (f) || FRAME_TTY (f) != tty))
3888 {
6ed8eeff 3889 last_terminal = 0;
81be1a93
KL
3890 break;
3891 }
3892 }
6ed8eeff
KL
3893 if (last_terminal)
3894 error ("Attempt to delete the sole terminal device with live frames");
f4d953fc 3895
fca177d4
KL
3896 if (tty == tty_list)
3897 tty_list = tty->next;
3898 else
3899 {
28d7d09f 3900 struct tty_display_info *p;
fca177d4
KL
3901 for (p = tty_list; p && p->next != tty; p = p->next)
3902 ;
3903
3904 if (! p)
3905 /* This should not happen. */
3906 abort ();
3907
0a125897
KL
3908 p->next = tty->next;
3909 tty->next = 0;
fca177d4
KL
3910 }
3911
7e59217d 3912 /* reset_sys_modes needs a valid device, so this call needs to be
6ed8eeff 3913 before delete_terminal. */
04c3243c 3914 reset_sys_modes (tty);
fca177d4 3915
6ed8eeff 3916 delete_terminal (terminal);
3224dac1 3917
ab797f65
KL
3918 if (tty->name)
3919 xfree (tty->name);
3920
fca177d4
KL
3921 if (tty->type)
3922 xfree (tty->type);
daf01701 3923
fca177d4 3924 if (tty->input)
819b8f00
KL
3925 {
3926 delete_keyboard_wait_descriptor (fileno (tty->input));
3927 if (tty->input != stdin)
3928 fclose (tty->input);
3929 }
3930 if (tty->output && tty->output != stdout && tty->output != tty->input)
fca177d4
KL
3931 fclose (tty->output);
3932 if (tty->termscript)
3933 fclose (tty->termscript);
daf01701 3934
fca177d4 3935 if (tty->old_tty)
0a125897 3936 xfree (tty->old_tty);
fca177d4 3937
0a125897 3938 if (tty->Wcm)
daf01701
KL
3939 xfree (tty->Wcm);
3940
28d7d09f 3941 bzero (tty, sizeof (struct tty_display_info));
fca177d4 3942 xfree (tty);
fca177d4
KL
3943}
3944
428a555e
KL
3945\f
3946
28d7d09f 3947/* Mark the pointers in the tty_display_info objects.
819b8f00 3948 Called by the Fgarbage_collector. */
da8e1115 3949
fca177d4 3950void
ed8dad6b 3951mark_ttys (void)
fca177d4 3952{
28d7d09f 3953 struct tty_display_info *tty;
0c72d684 3954
819b8f00 3955 for (tty = tty_list; tty; tty = tty->next)
3b6fc48f 3956 mark_object (tty->top_frame);
072d84a6
RS
3957}
3958
428a555e
KL
3959\f
3960
dfcf069d 3961void
07c57952
KH
3962syms_of_term ()
3963{
7ee72033
MB
3964 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
3965 doc: /* Non-nil means the system uses terminfo rather than termcap.
228299fa 3966This variable can be used by terminal emulator packages. */);
07c57952
KH
3967#ifdef TERMINFO
3968 system_uses_terminfo = 1;
3969#else
3970 system_uses_terminfo = 0;
3971#endif
c291d9ef 3972
e4019195
DN
3973 DEFVAR_LISP ("suspend-tty-functions", &Vsuspend_tty_functions,
3974 doc: /* Functions to be run after suspending a tty.
ab797f65 3975The functions are run with one argument, the terminal id to be suspended.
0b0d3e0b 3976See `suspend-tty'. */);
e4019195 3977 Vsuspend_tty_functions = Qnil;
0b0d3e0b
KL
3978
3979
e4019195
DN
3980 DEFVAR_LISP ("resume-tty-functions", &Vresume_tty_functions,
3981 doc: /* Functions to be run after resuming a tty.
ab797f65 3982The functions are run with one argument, the terminal id that was revived.
0b0d3e0b 3983See `resume-tty'. */);
e4019195 3984 Vresume_tty_functions = Qnil;
a168702a 3985
0db017c0
SM
3986 DEFVAR_BOOL ("visible-cursor", &visible_cursor,
3987 doc: /* Non-nil means to make the cursor very visible.
3988This only has an effect when running in a text terminal.
3989What means \"very visible\" is up to your terminal. It may make the cursor
3990bigger, or it may make it blink, or it may do nothing at all. */);
3991 visible_cursor = 1;
3992
a168702a 3993 defsubr (&Stty_display_color_p);
bfa62f96 3994 defsubr (&Stty_display_color_cells);
072d84a6 3995 defsubr (&Stty_no_underline);
6ed8eeff
KL
3996 defsubr (&Stty_type);
3997 defsubr (&Scontrolling_tty_p);
0b0d3e0b
KL
3998 defsubr (&Ssuspend_tty);
3999 defsubr (&Sresume_tty);
7e5a23bd 4000#ifdef HAVE_GPM
6178ce5e
SM
4001 defsubr (&Sgpm_mouse_start);
4002 defsubr (&Sgpm_mouse_stop);
94da14a0 4003
6178ce5e 4004 staticpro (&mouse_face_window);
7e5a23bd 4005#endif /* HAVE_GPM */
07c57952 4006}
a168702a 4007
819b8f00
KL
4008
4009
6b61353c
KH
4010/* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193
4011 (do not change this comment) */