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