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