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