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