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