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