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