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