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