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