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