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