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