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