Don't read too many characters from the tty.
[bpt/emacs.git] / src / term.c
CommitLineData
d284f58f 1/* Terminal control module for terminals described by TERMCAP
4a8130f2 2 Copyright (C) 1985, 86, 87, 93, 94, 95, 98, 2000, 2001, 2002
d284f58f 3 Free Software Foundation, Inc.
08a24c47
JB
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
4746118a 9the Free Software Foundation; either version 2, or (at your option)
08a24c47
JB
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
19the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
08a24c47 21
d284f58f 22/* New redisplay, TTY faces by Gerd Moellmann <gerd@gnu.org>. */
08a24c47 23
565620a5 24#include <config.h>
08a24c47
JB
25#include <stdio.h>
26#include <ctype.h>
a168702a 27#include <string.h>
7ee72033 28
28d440ab
KL
29#include <sys/file.h>
30
0c72d684
KL
31#include <unistd.h> /* For isatty. */
32#include <sys/ioctl.h> /* For TIOCNOTTY. */
33
9628b887 34#include "lisp.h"
08a24c47
JB
35#include "termchar.h"
36#include "termopts.h"
a4decb7f
KH
37#include "charset.h"
38#include "coding.h"
2538fae4 39#include "keyboard.h"
ff11dfa1 40#include "frame.h"
08a24c47
JB
41#include "disptab.h"
42#include "termhooks.h"
dfcf069d 43#include "dispextern.h"
a168702a 44#include "window.h"
8feddab4 45#include "keymap.h"
a168702a 46
ff23e1dd
GM
47/* For now, don't try to include termcap.h. On some systems,
48 configure finds a non-standard termcap.h that the main build
49 won't find. */
50
51#if defined HAVE_TERMCAP_H && 0
b0f61f15 52#include <termcap.h>
46d1b2bc
DL
53#else
54extern void tputs P_ ((const char *, int, int (*)(int)));
55extern int tgetent P_ ((char *, const char *));
56extern int tgetflag P_ ((char *id));
57extern int tgetnum P_ ((char *id));
b0f61f15
GM
58#endif
59
eccec691 60#include "cm.h"
dfcf069d
AS
61#ifdef HAVE_X_WINDOWS
62#include "xterm.h"
63#endif
e0f712ba 64#ifdef MAC_OS
1a578e9b
AC
65#include "macterm.h"
66#endif
c8951b18 67
28d440ab
KL
68#ifndef O_RDWR
69#define O_RDWR 2
70#endif
71
0c72d684
KL
72#ifndef O_NOCTTY
73#define O_NOCTTY 0
74#endif
75
a168702a
GM
76static void turn_on_face P_ ((struct frame *, int face_id));
77static void turn_off_face P_ ((struct frame *, int face_id));
28d7d09f
KL
78static void tty_show_cursor P_ ((struct tty_display_info *));
79static void tty_hide_cursor P_ ((struct tty_display_info *));
fca177d4 80
3224dac1 81void delete_initial_display P_ ((struct display *));
428a555e
KL
82void delete_tty P_ ((struct display *));
83void create_tty_output P_ ((struct frame *));
84void delete_tty_output P_ ((struct frame *));
a168702a 85
6548cf00
KL
86#define OUTPUT(tty, a) \
87 emacs_tputs ((tty), a, \
88 (int) (FRAME_LINES (XFRAME (selected_frame)) \
89 - curY (tty)), \
90 cmputc)
91
28d440ab
KL
92#define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
93#define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
a168702a 94
28d440ab 95#define OUTPUT_IF(tty, a) \
6548cf00
KL
96 do { \
97 if (a) \
98 emacs_tputs ((tty), a, \
99 (int) (FRAME_LINES (XFRAME (selected_frame)) \
100 - curY (tty) ), \
101 cmputc); \
102 } while (0)
177c0ea7 103
28d440ab 104#define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
08a24c47 105
c291d9ef 106/* Function to use to ring the bell. */
a168702a 107
c291d9ef
RS
108Lisp_Object Vring_bell_function;
109
4d553a13
KL
110/* Functions to call after a tty was deleted. */
111Lisp_Object Vdelete_tty_after_functions;
112
428a555e
KL
113/* Chain of all displays currently in use. */
114struct display *display_list;
28d440ab 115
3224dac1
KL
116/* The initial display device, created by initial_term_init. */
117struct display *initial_display;
118
428a555e 119/* Chain of all tty device parameters. */
28d7d09f 120struct tty_display_info *tty_list;
08a24c47 121
fca177d4
KL
122/* Nonzero means no need to redraw the entire frame on resuming a
123 suspended Emacs. This is useful on terminals with multiple
124 pages, where one page is used for Emacs and another for all
125 else. */
08a24c47 126int no_redraw_on_reenter;
819b8f00
KL
127
128Lisp_Object Qframe_tty_name, Qframe_tty_type;
129
20a558dc 130
4e6ba4a4
GM
131
132/* Meaning of bits in no_color_video. Each bit set means that the
133 corresponding attribute cannot be combined with colors. */
134
135enum no_color_bit
136{
137 NC_STANDOUT = 1 << 0,
138 NC_UNDERLINE = 1 << 1,
139 NC_REVERSE = 1 << 2,
140 NC_BLINK = 1 << 3,
141 NC_DIM = 1 << 4,
142 NC_BOLD = 1 << 5,
143 NC_INVIS = 1 << 6,
144 NC_PROTECT = 1 << 7,
145 NC_ALT_CHARSET = 1 << 8
146};
147
08a24c47
JB
148/* internal state */
149
8dd0c7cb 150/* The largest frame width in any call to calculate_costs. */
a168702a 151
9882535b 152int max_frame_cols;
a168702a 153
8dd0c7cb 154/* The largest frame height in any call to calculate_costs. */
a168702a 155
9882535b 156int max_frame_lines;
8dd0c7cb 157
ff11dfa1 158/* Frame currently being redisplayed; 0 if not currently redisplaying.
08a24c47
JB
159 (Direct output does not count). */
160
ff11dfa1 161FRAME_PTR updating_frame;
08a24c47 162
0c72d684
KL
163/* Non-zero if we have dropped our controlling tty and therefore
164 should not open a frame on stdout. */
165static int no_controlling_tty;
166
07c57952 167/* Provided for lisp packages. */
a168702a 168
07c57952
KH
169static int system_uses_terminfo;
170
08a24c47 171char *tparam ();
e4bfb3b6
RS
172
173extern char *tgetstr ();
08a24c47 174\f
cb28b9c2 175
1a89b7c6
AI
176#ifdef WINDOWSNT
177/* We aren't X windows, but we aren't termcap either. This makes me
178 uncertain as to what value to use for frame.output_method. For
179 this file, we'll define FRAME_TERMCAP_P to be zero so that our
180 output hooks get called instead of the termcap functions. Probably
181 the best long-term solution is to define an output_windows_nt... */
182
183#undef FRAME_TERMCAP_P
184#define FRAME_TERMCAP_P(_f_) 0
185#endif /* WINDOWSNT */
186
dfcf069d 187void
08a24c47
JB
188ring_bell ()
189{
4ca927b4 190 struct frame *f = XFRAME (selected_frame);
6548cf00 191
d284f58f 192 if (!NILP (Vring_bell_function))
c291d9ef
RS
193 {
194 Lisp_Object function;
195
196 /* Temporarily set the global variable to nil
197 so that if we get an error, it stays nil
198 and we don't call it over and over.
199
200 We don't specbind it, because that would carefully
201 restore the bad value if there's an error
202 and make the loop of errors happen anyway. */
177c0ea7 203
c291d9ef
RS
204 function = Vring_bell_function;
205 Vring_bell_function = Qnil;
206
207 call0 (function);
208
209 Vring_bell_function = function;
08a24c47 210 }
428a555e
KL
211 else if (FRAME_DISPLAY (f)->ring_bell_hook)
212 (*FRAME_DISPLAY (f)->ring_bell_hook) ();
08a24c47
JB
213}
214
da8e1115
KL
215/* Ring the bell on a tty. */
216
3224dac1
KL
217void
218tty_ring_bell ()
219{
4ca927b4 220 struct frame *f = XFRAME (selected_frame);
3224dac1
KL
221 struct tty_display_info *tty = FRAME_TTY (f);
222
223 OUTPUT (tty, (tty->TS_visible_bell && visible_bell
224 ? tty->TS_visible_bell
225 : tty->TS_bell));
226}
227
da8e1115
KL
228/* Set up termcap modes for Emacs. */
229
230void
231tty_set_terminal_modes (struct display *display)
fca177d4 232{
3224dac1
KL
233 struct tty_display_info *tty = display->display_info.tty;
234
fca177d4
KL
235 OUTPUT_IF (tty, tty->TS_termcap_modes);
236 OUTPUT_IF (tty, tty->TS_cursor_visible);
237 OUTPUT_IF (tty, tty->TS_keypad_mode);
238 losecursor (tty);
239}
240
da8e1115
KL
241/* Reset termcap modes before exiting Emacs. */
242
243void
244tty_reset_terminal_modes (struct display *display)
fca177d4 245{
3224dac1
KL
246 struct tty_display_info *tty = display->display_info.tty;
247
fca177d4
KL
248 turn_off_highlight (tty);
249 turn_off_insert (tty);
250 OUTPUT_IF (tty, tty->TS_end_keypad_mode);
251 OUTPUT_IF (tty, tty->TS_cursor_normal);
252 OUTPUT_IF (tty, tty->TS_end_termcap_modes);
253 OUTPUT_IF (tty, tty->TS_orig_pair);
254 /* Output raw CR so kernel can track the cursor hpos. */
255 current_tty = tty;
256 cmputc ('\r');
257}
258
dfcf069d 259void
ff11dfa1 260update_begin (f)
d284f58f 261 struct frame *f;
08a24c47 262{
ff11dfa1 263 updating_frame = f;
428a555e
KL
264 if (FRAME_DISPLAY (f)->update_begin_hook)
265 (*FRAME_DISPLAY (f)->update_begin_hook) (f);
08a24c47
JB
266}
267
dfcf069d 268void
ff11dfa1 269update_end (f)
d284f58f 270 struct frame *f;
08a24c47 271{
428a555e
KL
272 if (FRAME_DISPLAY (f)->update_end_hook)
273 (*FRAME_DISPLAY (f)->update_end_hook) (f);
d284f58f 274 updating_frame = NULL;
08a24c47
JB
275}
276
da8e1115
KL
277/* Flag the end of a display update on a termcap display. */
278
3224dac1
KL
279void
280tty_update_end (struct frame *f)
281{
282 struct tty_display_info *tty = FRAME_TTY (f);
283
284 if (!XWINDOW (selected_window)->cursor_off_p)
285 tty_show_cursor (tty);
286 turn_off_insert (tty);
287 background_highlight (tty);
288}
289
da8e1115
KL
290/* Specify how many text lines, from the top of the window,
291 should be affected by insert-lines and delete-lines operations.
292 This, and those operations, are used only within an update
293 that is bounded by calls to update_begin and update_end. */
294
dfcf069d 295void
08a24c47
JB
296set_terminal_window (size)
297 int size;
298{
c3b4957f 299 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
3224dac1 300
428a555e
KL
301 if (FRAME_DISPLAY (f)->set_terminal_window_hook)
302 (*FRAME_DISPLAY (f)->set_terminal_window_hook) (size);
3224dac1
KL
303}
304
da8e1115
KL
305/* The implementation of set_terminal_window for termcap frames. */
306
3224dac1
KL
307void
308tty_set_terminal_window (int size)
309{
c3b4957f 310 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
3224dac1
KL
311
312 struct tty_display_info *tty = FRAME_TTY (f);
313
314 tty->specified_window = size ? size : FRAME_LINES (f);
315 if (FRAME_SCROLL_REGION_OK (f))
316 set_scroll_region (0, tty->specified_window);
08a24c47
JB
317}
318
dfcf069d 319void
08a24c47
JB
320set_scroll_region (start, stop)
321 int start, stop;
322{
323 char *buf;
c3b4957f 324 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
3224dac1 325
28d7d09f 326 struct tty_display_info *tty = FRAME_TTY (f);
177c0ea7 327
fca177d4
KL
328 if (tty->TS_set_scroll_region)
329 buf = tparam (tty->TS_set_scroll_region, 0, 0, start, stop - 1);
330 else if (tty->TS_set_scroll_region_1)
331 buf = tparam (tty->TS_set_scroll_region_1, 0, 0,
ed02974b
KL
332 FRAME_LINES (f), start,
333 FRAME_LINES (f) - stop,
334 FRAME_LINES (f));
08a24c47 335 else
fca177d4 336 buf = tparam (tty->TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (f));
177c0ea7 337
6548cf00 338 OUTPUT (tty, buf);
9ac0d9e0 339 xfree (buf);
6548cf00 340 losecursor (tty);
08a24c47 341}
d284f58f 342
08a24c47 343\f
d284f58f 344static void
28d7d09f 345turn_on_insert (struct tty_display_info *tty)
08a24c47 346{
fca177d4
KL
347 if (!tty->insert_mode)
348 OUTPUT (tty, tty->TS_insert_mode);
349 tty->insert_mode = 1;
08a24c47
JB
350}
351
dfcf069d 352void
28d7d09f 353turn_off_insert (struct tty_display_info *tty)
08a24c47 354{
fca177d4
KL
355 if (tty->insert_mode)
356 OUTPUT (tty, tty->TS_end_insert_mode);
357 tty->insert_mode = 0;
08a24c47
JB
358}
359\f
54800acb 360/* Handle highlighting. */
08a24c47 361
dfcf069d 362void
28d7d09f 363turn_off_highlight (struct tty_display_info *tty)
08a24c47 364{
fca177d4
KL
365 if (tty->standout_mode)
366 OUTPUT_IF (tty, tty->TS_end_standout_mode);
367 tty->standout_mode = 0;
08a24c47
JB
368}
369
d284f58f 370static void
28d7d09f 371turn_on_highlight (struct tty_display_info *tty)
08a24c47 372{
fca177d4
KL
373 if (!tty->standout_mode)
374 OUTPUT_IF (tty, tty->TS_standout_mode);
375 tty->standout_mode = 1;
08a24c47
JB
376}
377
86a7d192 378static void
28d7d09f 379toggle_highlight (struct tty_display_info *tty)
86a7d192 380{
fca177d4
KL
381 if (tty->standout_mode)
382 turn_off_highlight (tty);
86a7d192 383 else
fca177d4 384 turn_on_highlight (tty);
86a7d192
GM
385}
386
a168702a
GM
387
388/* Make cursor invisible. */
389
390static void
28d7d09f 391tty_hide_cursor (struct tty_display_info *tty)
a168702a 392{
fca177d4 393 if (tty->cursor_hidden == 0)
d284f58f 394 {
fca177d4
KL
395 tty->cursor_hidden = 1;
396 OUTPUT_IF (tty, tty->TS_cursor_invisible);
d284f58f 397 }
a168702a
GM
398}
399
400
401/* Ensure that cursor is visible. */
402
403static void
28d7d09f 404tty_show_cursor (struct tty_display_info *tty)
a168702a 405{
fca177d4 406 if (tty->cursor_hidden)
d284f58f 407 {
fca177d4
KL
408 tty->cursor_hidden = 0;
409 OUTPUT_IF (tty, tty->TS_cursor_normal);
410 OUTPUT_IF (tty, tty->TS_cursor_visible);
d284f58f 411 }
a168702a
GM
412}
413
414
08a24c47
JB
415/* Set standout mode to the state it should be in for
416 empty space inside windows. What this is,
417 depends on the user option inverse-video. */
418
dfcf069d 419void
28d7d09f 420background_highlight (struct tty_display_info *tty)
08a24c47 421{
08a24c47 422 if (inverse_video)
fca177d4 423 turn_on_highlight (tty);
08a24c47 424 else
fca177d4 425 turn_off_highlight (tty);
08a24c47
JB
426}
427
428/* Set standout mode to the mode specified for the text to be output. */
429
dfcf069d 430static void
28d7d09f 431highlight_if_desired (struct tty_display_info *tty)
08a24c47 432{
8ede64a5 433 if (inverse_video)
fca177d4 434 turn_on_highlight (tty);
8ede64a5 435 else
fca177d4 436 turn_off_highlight (tty);
08a24c47
JB
437}
438\f
439
a168702a
GM
440/* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
441 frame-relative coordinates. */
08a24c47 442
dfcf069d 443void
a168702a
GM
444cursor_to (vpos, hpos)
445 int vpos, hpos;
08a24c47 446{
c3b4957f 447 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
daf01701 448
428a555e 449 if (FRAME_DISPLAY (f)->cursor_to_hook)
3224dac1
KL
450 (*FRAME_DISPLAY (f)->cursor_to_hook) (vpos, hpos);
451}
08a24c47 452
3224dac1
KL
453void
454tty_cursor_to (int vpos, int hpos)
455{
c3b4957f 456 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
3224dac1
KL
457
458 struct tty_display_info *tty = FRAME_TTY (f);
6548cf00 459
36cae867
KH
460 /* Detect the case where we are called from reset_sys_modes
461 and the costs have never been calculated. Do nothing. */
fca177d4 462 if (! tty->costs_set)
36cae867
KH
463 return;
464
6548cf00
KL
465 if (curY (tty) == vpos
466 && curX (tty) == hpos)
08a24c47 467 return;
fca177d4
KL
468 if (!tty->TF_standout_motion)
469 background_highlight (tty);
470 if (!tty->TF_insmode_motion)
471 turn_off_insert (tty);
6548cf00 472 cmgoto (tty, vpos, hpos);
08a24c47
JB
473}
474
475/* Similar but don't take any account of the wasted characters. */
476
dfcf069d 477void
08a24c47 478raw_cursor_to (row, col)
4746118a 479 int row, col;
08a24c47 480{
c3b4957f 481 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
3224dac1 482
428a555e 483 if (FRAME_DISPLAY (f)->raw_cursor_to_hook)
3224dac1
KL
484 (*FRAME_DISPLAY (f)->raw_cursor_to_hook) (row, col);
485}
486
487void
488tty_raw_cursor_to (int row, int col)
489{
c3b4957f 490 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
3224dac1
KL
491
492 struct tty_display_info *tty = FRAME_TTY (f);
493
6548cf00
KL
494 if (curY (tty) == row
495 && curX (tty) == col)
08a24c47 496 return;
fca177d4
KL
497 if (!tty->TF_standout_motion)
498 background_highlight (tty);
499 if (!tty->TF_insmode_motion)
500 turn_off_insert (tty);
6548cf00 501 cmgoto (tty, row, col);
08a24c47
JB
502}
503\f
504/* Erase operations */
505
da8e1115 506/* Clear from cursor to end of frame. */
dfcf069d 507void
08a24c47
JB
508clear_to_end ()
509{
c3b4957f 510 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
daf01701 511
428a555e 512 if (FRAME_DISPLAY (f)->clear_to_end_hook)
3224dac1
KL
513 (*FRAME_DISPLAY (f)->clear_to_end_hook) ();
514}
515
da8e1115
KL
516/* Clear from cursor to end of frame on a termcap device. */
517
3224dac1
KL
518void
519tty_clear_to_end (void)
520{
521 register int i;
c3b4957f 522 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
3224dac1
KL
523 struct tty_display_info *tty = FRAME_TTY (f);
524
fca177d4 525 if (tty->TS_clr_to_bottom)
08a24c47 526 {
fca177d4
KL
527 background_highlight (tty);
528 OUTPUT (tty, tty->TS_clr_to_bottom);
08a24c47
JB
529 }
530 else
531 {
6548cf00 532 for (i = curY (tty); i < FRAME_LINES (f); i++)
08a24c47
JB
533 {
534 cursor_to (i, 0);
ed02974b 535 clear_end_of_line (FRAME_COLS (f));
08a24c47
JB
536 }
537 }
538}
539
ff11dfa1 540/* Clear entire frame */
08a24c47 541
dfcf069d 542void
ff11dfa1 543clear_frame ()
08a24c47 544{
6548cf00 545 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
daf01701 546
428a555e 547 if (FRAME_DISPLAY (f)->clear_frame_hook)
3224dac1
KL
548 (*FRAME_DISPLAY (f)->clear_frame_hook) ();
549}
550
da8e1115
KL
551/* Clear an entire termcap frame. */
552
3224dac1
KL
553void
554tty_clear_frame ()
555{
c3b4957f 556 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
3224dac1
KL
557
558 struct tty_display_info *tty = FRAME_TTY (f);
559
fca177d4 560 if (tty->TS_clr_frame)
08a24c47 561 {
fca177d4
KL
562 background_highlight (tty);
563 OUTPUT (tty, tty->TS_clr_frame);
6548cf00 564 cmat (tty, 0, 0);
08a24c47
JB
565 }
566 else
567 {
568 cursor_to (0, 0);
569 clear_to_end ();
570 }
571}
572
08a24c47
JB
573/* Clear from cursor to end of line.
574 Assume that the line is already clear starting at column first_unused_hpos.
08a24c47
JB
575
576 Note that the cursor may be moved, on terminals lacking a `ce' string. */
577
dfcf069d 578void
8ede64a5 579clear_end_of_line (first_unused_hpos)
08a24c47
JB
580 int first_unused_hpos;
581{
c3b4957f 582 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
daf01701 583
428a555e 584 if (FRAME_DISPLAY (f)->clear_end_of_line_hook)
3224dac1 585 (*FRAME_DISPLAY (f)->clear_end_of_line_hook) (first_unused_hpos);
0a125897 586}
6548cf00 587
da8e1115
KL
588/* An implementation of clear_end_of_line for termcap frames.
589
590 Note that the cursor may be moved, on terminals lacking a `ce' string. */
591
0a125897 592void
3224dac1 593tty_clear_end_of_line (int first_unused_hpos)
0a125897
KL
594{
595 register int i;
c3b4957f 596 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
3224dac1
KL
597 struct tty_display_info *tty = FRAME_TTY (f);
598
36cae867
KH
599 /* Detect the case where we are called from reset_sys_modes
600 and the costs have never been calculated. Do nothing. */
fca177d4 601 if (! tty->costs_set)
36cae867
KH
602 return;
603
6548cf00 604 if (curX (tty) >= first_unused_hpos)
08a24c47 605 return;
fca177d4
KL
606 background_highlight (tty);
607 if (tty->TS_clr_line)
08a24c47 608 {
fca177d4 609 OUTPUT1 (tty, tty->TS_clr_line);
08a24c47
JB
610 }
611 else
612 { /* have to do it the hard way */
fca177d4 613 turn_off_insert (tty);
08a24c47 614
a168702a 615 /* Do not write in last row last col with Auto-wrap on. */
6548cf00 616 if (AutoWrap (tty)
0a125897
KL
617 && curY (tty) == FrameRows (tty) - 1
618 && first_unused_hpos == FrameCols (tty))
08a24c47
JB
619 first_unused_hpos--;
620
6548cf00 621 for (i = curX (tty); i < first_unused_hpos; i++)
08a24c47 622 {
6548cf00
KL
623 if (TTY_TERMSCRIPT (tty))
624 fputc (' ', TTY_TERMSCRIPT (tty));
625 fputc (' ', TTY_OUTPUT (tty));
08a24c47 626 }
6548cf00 627 cmplus (tty, first_unused_hpos - curX (tty));
08a24c47
JB
628 }
629}
630\f
a4decb7f
KH
631/* Encode SRC_LEN glyphs starting at SRC to terminal output codes and
632 store them at DST. Do not write more than DST_LEN bytes. That may
633 require stopping before all SRC_LEN input glyphs have been
634 converted.
635
636 We store the number of glyphs actually converted in *CONSUMED. The
637 return value is the number of bytes store in DST. */
638
639int
640encode_terminal_code (src, dst, src_len, dst_len, consumed)
a168702a 641 struct glyph *src;
a4decb7f
KH
642 int src_len;
643 unsigned char *dst;
644 int dst_len, *consumed;
645{
a168702a 646 struct glyph *src_start = src, *src_end = src + src_len;
a4decb7f 647 unsigned char *dst_start = dst, *dst_end = dst + dst_len;
085d5908 648 register GLYPH g;
405ea71c
KR
649 unsigned char workbuf[MAX_MULTIBYTE_LENGTH];
650 const unsigned char *buf;
6589fd67 651 int len;
a4decb7f
KH
652 register int tlen = GLYPH_TABLE_LENGTH;
653 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
f3ac545f 654 int result;
6589fd67
KH
655 struct coding_system *coding;
656
1ac0700a
KH
657 /* If terminal_coding does any conversion, use it, otherwise use
658 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
659 because it always return 1 if the member src_multibyte is 1. */
660 coding = (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK
6589fd67
KH
661 ? &terminal_coding
662 : &safe_terminal_coding);
a4decb7f
KH
663
664 while (src < src_end)
665 {
a4decb7f 666 /* We must skip glyphs to be padded for a wide character. */
a168702a 667 if (! CHAR_GLYPH_PADDING_P (*src))
a4decb7f 668 {
32de38e4
KH
669 g = GLYPH_FROM_CHAR_GLYPH (src[0]);
670
671 if (g < 0 || g >= tlen)
085d5908 672 {
32de38e4
KH
673 /* This glyph doesn't has an entry in Vglyph_table. */
674 if (! CHAR_VALID_P (src->u.ch, 0))
675 {
676 len = 1;
677 buf = " ";
f2ba40be 678 coding->src_multibyte = 0;
32de38e4
KH
679 }
680 else
681 {
682 len = CHAR_STRING (src->u.ch, workbuf);
683 buf = workbuf;
f2ba40be 684 coding->src_multibyte = 1;
32de38e4 685 }
085d5908 686 }
32de38e4 687 else
a4decb7f 688 {
32de38e4 689 /* This glyph has an entry in Vglyph_table,
a4decb7f
KH
690 so process any alias before testing for simpleness. */
691 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
32de38e4
KH
692
693 if (GLYPH_SIMPLE_P (tbase, tlen, g))
694 {
c989b7be
KH
695 /* We set the multi-byte form of a character in G
696 (that should be an ASCII character) at
697 WORKBUF. */
698 workbuf[0] = FAST_GLYPH_CHAR (g);
699 len = 1;
32de38e4 700 buf = workbuf;
f2ba40be 701 coding->src_multibyte = 0;
32de38e4
KH
702 }
703 else
704 {
705 /* We have a string in Vglyph_table. */
706 len = GLYPH_LENGTH (tbase, g);
707 buf = GLYPH_STRING (tbase, g);
f2ba40be 708 coding->src_multibyte = STRING_MULTIBYTE (tbase[g]);
32de38e4 709 }
171d7f24 710 }
177c0ea7 711
f3ac545f 712 result = encode_coding (coding, buf, dst, len, dst_end - dst);
c42869c4 713 len -= coding->consumed;
6589fd67 714 dst += coding->produced;
f3ac545f
KH
715 if (result == CODING_FINISH_INSUFFICIENT_DST
716 || (result == CODING_FINISH_INSUFFICIENT_SRC
717 && len > dst_end - dst))
718 /* The remaining output buffer is too short. We must
719 break the loop here without increasing SRC so that the
720 next call of this function starts from the same glyph. */
721 break;
722
c42869c4
KH
723 if (len > 0)
724 {
f3ac545f
KH
725 /* This is the case that a code of the range 0200..0237
726 exists in buf. We must just write out such a code. */
727 buf += coding->consumed;
728 while (len--)
729 *dst++ = *buf++;
c42869c4 730 }
a4decb7f
KH
731 }
732 src++;
733 }
177c0ea7 734
a4decb7f
KH
735 *consumed = src - src_start;
736 return (dst - dst_start);
737}
738
08a24c47 739
da8e1115
KL
740/* Output LEN glyphs starting at STRING at the nominal cursor position.
741 Advance the nominal cursor over the text. */
742
dfcf069d 743void
08a24c47 744write_glyphs (string, len)
a168702a 745 register struct glyph *string;
08a24c47 746 register int len;
3224dac1 747{
c3b4957f 748 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
3224dac1
KL
749
750 if (FRAME_DISPLAY (f)->write_glyphs_hook)
751 (*FRAME_DISPLAY (f)->write_glyphs_hook) (string, len);
752}
753
da8e1115
KL
754/* An implementation of write_glyphs for termcap frames. */
755
3224dac1
KL
756void
757tty_write_glyphs (struct glyph *string, int len)
08a24c47 758{
a4decb7f 759 int produced, consumed;
d2fdb076
KH
760 unsigned char conversion_buffer[1024];
761 int conversion_buffer_size = sizeof conversion_buffer;
08a24c47 762
c3b4957f 763 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
08a24c47 764
3224dac1 765 struct tty_display_info *tty = FRAME_TTY (f);
6548cf00 766
fca177d4
KL
767 turn_off_insert (tty);
768 tty_hide_cursor (tty);
08a24c47 769
a168702a 770 /* Don't dare write in last column of bottom line, if Auto-Wrap,
ff11dfa1 771 since that would scroll the whole frame on some terminals. */
08a24c47 772
6548cf00
KL
773 if (AutoWrap (tty)
774 && curY (tty) + 1 == FRAME_LINES (f)
775 && (curX (tty) + len) == FRAME_COLS (f))
08a24c47 776 len --;
a4decb7f
KH
777 if (len <= 0)
778 return;
08a24c47 779
6548cf00 780 cmplus (tty, len);
177c0ea7 781
6589fd67
KH
782 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
783 the tail. */
784 terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
177c0ea7 785
a4decb7f 786 while (len > 0)
08a24c47 787 {
a168702a 788 /* Identify a run of glyphs with the same face. */
32de38e4 789 int face_id = string->face_id;
a168702a 790 int n;
177c0ea7 791
a168702a 792 for (n = 1; n < len; ++n)
32de38e4 793 if (string[n].face_id != face_id)
a168702a
GM
794 break;
795
796 /* Turn appearance modes of the face of the run on. */
fca177d4 797 highlight_if_desired (tty);
a168702a
GM
798 turn_on_face (f, face_id);
799
800 while (n > 0)
08a24c47 801 {
d2fdb076
KH
802 /* We use a fixed size (1024 bytes) of conversion buffer.
803 Usually it is sufficient, but if not, we just repeat the
804 loop. */
a168702a
GM
805 produced = encode_terminal_code (string, conversion_buffer,
806 n, conversion_buffer_size,
807 &consumed);
808 if (produced > 0)
809 {
28d440ab 810 fwrite (conversion_buffer, 1, produced,
6548cf00
KL
811 TTY_OUTPUT (tty));
812 if (ferror (TTY_OUTPUT (tty)))
813 clearerr (TTY_OUTPUT (tty));
814 if (TTY_TERMSCRIPT (tty))
28d440ab 815 fwrite (conversion_buffer, 1, produced,
6548cf00 816 TTY_TERMSCRIPT (tty));
a168702a
GM
817 }
818 len -= consumed;
819 n -= consumed;
820 string += consumed;
08a24c47 821 }
a168702a
GM
822
823 /* Turn appearance modes off. */
824 turn_off_face (f, face_id);
fca177d4 825 turn_off_highlight (tty);
a4decb7f 826 }
177c0ea7 827
a4decb7f 828 /* We may have to output some codes to terminate the writing. */
ca1e6a13 829 if (CODING_REQUIRE_FLUSHING (&terminal_coding))
a4decb7f 830 {
6589fd67 831 terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
1814bd62 832 encode_coding (&terminal_coding, "", conversion_buffer,
6589fd67
KH
833 0, conversion_buffer_size);
834 if (terminal_coding.produced > 0)
df8bf431 835 {
28d440ab 836 fwrite (conversion_buffer, 1, terminal_coding.produced,
6548cf00
KL
837 TTY_OUTPUT (tty));
838 if (ferror (TTY_OUTPUT (tty)))
839 clearerr (TTY_OUTPUT (tty));
840 if (TTY_TERMSCRIPT (tty))
6589fd67 841 fwrite (conversion_buffer, 1, terminal_coding.produced,
6548cf00 842 TTY_TERMSCRIPT (tty));
df8bf431 843 }
08a24c47 844 }
177c0ea7 845
6548cf00 846 cmcheckmagic (tty);
08a24c47
JB
847}
848
da8e1115
KL
849/* Insert LEN glyphs from START at the nominal cursor position.
850
851 If start is zero, insert blanks instead of a string at start */
177c0ea7 852
dfcf069d 853void
08a24c47 854insert_glyphs (start, len)
a168702a 855 register struct glyph *start;
08a24c47
JB
856 register int len;
857{
c3b4957f 858 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
daf01701 859
a4decb7f
KH
860 if (len <= 0)
861 return;
862
428a555e 863 if (FRAME_DISPLAY (f)->insert_glyphs_hook)
3224dac1
KL
864 (*FRAME_DISPLAY (f)->insert_glyphs_hook) (start, len);
865}
a168702a 866
da8e1115
KL
867/* An implementation of insert_glyphs for termcap frames. */
868
3224dac1
KL
869void
870tty_insert_glyphs (struct glyph *start, int len)
871{
872 char *buf;
873 struct glyph *glyph = NULL;
c3b4957f 874 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
3224dac1
KL
875
876 struct tty_display_info *tty = FRAME_TTY (f);
08a24c47 877
fca177d4 878 if (tty->TS_ins_multi_chars)
08a24c47 879 {
fca177d4 880 buf = tparam (tty->TS_ins_multi_chars, 0, 0, len);
6548cf00 881 OUTPUT1 (tty, buf);
9ac0d9e0 882 xfree (buf);
08a24c47
JB
883 if (start)
884 write_glyphs (start, len);
885 return;
886 }
887
fca177d4 888 turn_on_insert (tty);
6548cf00 889 cmplus (tty, len);
6589fd67
KH
890 /* The bit CODING_MODE_LAST_BLOCK should be set to 1 only at the tail. */
891 terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
07109bf9 892 while (len-- > 0)
08a24c47 893 {
a4decb7f 894 int produced, consumed;
d2fdb076
KH
895 unsigned char conversion_buffer[1024];
896 int conversion_buffer_size = sizeof conversion_buffer;
a4decb7f 897
fca177d4 898 OUTPUT1_IF (tty, tty->TS_ins_char);
08a24c47 899 if (!start)
32de38e4
KH
900 {
901 conversion_buffer[0] = SPACEGLYPH;
902 produced = 1;
903 }
08a24c47 904 else
08a24c47 905 {
fca177d4 906 highlight_if_desired (tty);
32de38e4 907 turn_on_face (f, start->face_id);
816be8b8 908 glyph = start;
a168702a 909 ++start;
a4decb7f
KH
910 /* We must open sufficient space for a character which
911 occupies more than one column. */
a168702a 912 while (len && CHAR_GLYPH_PADDING_P (*start))
a4decb7f 913 {
fca177d4 914 OUTPUT1_IF (tty, tty->TS_ins_char);
a4decb7f
KH
915 start++, len--;
916 }
a4decb7f 917
32de38e4
KH
918 if (len <= 0)
919 /* This is the last glyph. */
920 terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
921
d2fdb076
KH
922 /* The size of conversion buffer (1024 bytes) is surely
923 sufficient for just one glyph. */
816be8b8 924 produced = encode_terminal_code (glyph, conversion_buffer, 1,
32de38e4
KH
925 conversion_buffer_size, &consumed);
926 }
a4decb7f 927
a4decb7f 928 if (produced > 0)
08a24c47 929 {
28d440ab 930 fwrite (conversion_buffer, 1, produced,
6548cf00
KL
931 TTY_OUTPUT (tty));
932 if (ferror (TTY_OUTPUT (tty)))
933 clearerr (TTY_OUTPUT (tty));
934 if (TTY_TERMSCRIPT (tty))
28d440ab 935 fwrite (conversion_buffer, 1, produced,
6548cf00 936 TTY_TERMSCRIPT (tty));
08a24c47
JB
937 }
938
fca177d4 939 OUTPUT1_IF (tty, tty->TS_pad_inserted_char);
32de38e4 940 if (start)
65aa5e85
GM
941 {
942 turn_off_face (f, glyph->face_id);
fca177d4 943 turn_off_highlight (tty);
65aa5e85 944 }
9a6b6f92 945 }
177c0ea7 946
6548cf00 947 cmcheckmagic (tty);
08a24c47
JB
948}
949
da8e1115
KL
950/* Delete N glyphs at the nominal cursor position. */
951
dfcf069d 952void
08a24c47
JB
953delete_glyphs (n)
954 register int n;
955{
c3b4957f 956 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
08a24c47 957
428a555e 958 if (FRAME_DISPLAY (f)->delete_glyphs_hook)
3224dac1
KL
959 (*FRAME_DISPLAY (f)->delete_glyphs_hook) (n);
960}
08a24c47 961
da8e1115
KL
962/* An implementation of delete_glyphs for termcap frames. */
963
3224dac1
KL
964void
965tty_delete_glyphs (int n)
966{
967 char *buf;
968 register int i;
c3b4957f 969 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
3224dac1
KL
970
971 struct tty_display_info *tty = FRAME_TTY (f);
6548cf00 972
fca177d4 973 if (tty->delete_in_insert_mode)
08a24c47 974 {
fca177d4 975 turn_on_insert (tty);
08a24c47
JB
976 }
977 else
978 {
fca177d4
KL
979 turn_off_insert (tty);
980 OUTPUT_IF (tty, tty->TS_delete_mode);
08a24c47 981 }
daf01701 982
fca177d4 983 if (tty->TS_del_multi_chars)
08a24c47 984 {
fca177d4 985 buf = tparam (tty->TS_del_multi_chars, 0, 0, n);
6548cf00 986 OUTPUT1 (tty, buf);
9ac0d9e0 987 xfree (buf);
08a24c47
JB
988 }
989 else
990 for (i = 0; i < n; i++)
fca177d4
KL
991 OUTPUT1 (tty, tty->TS_del_char);
992 if (!tty->delete_in_insert_mode)
993 OUTPUT_IF (tty, tty->TS_end_delete_mode);
08a24c47
JB
994}
995\f
996/* Insert N lines at vpos VPOS. If N is negative, delete -N lines. */
997
dfcf069d 998void
08a24c47
JB
999ins_del_lines (vpos, n)
1000 int vpos, n;
1001{
c3b4957f 1002 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
3224dac1 1003
428a555e 1004 if (FRAME_DISPLAY (f)->ins_del_lines_hook)
3224dac1
KL
1005 (*FRAME_DISPLAY (f)->ins_del_lines_hook) (vpos, n);
1006}
1007
da8e1115
KL
1008/* An implementation of ins_del_lines for termcap frames. */
1009
3224dac1
KL
1010void
1011tty_ins_del_lines (int vpos, int n)
1012{
c3b4957f 1013 struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
3224dac1
KL
1014
1015 struct tty_display_info *tty = FRAME_TTY (f);
1016 char *multi = n > 0 ? tty->TS_ins_multi_lines : tty->TS_del_multi_lines;
1017 char *single = n > 0 ? tty->TS_ins_line : tty->TS_del_line;
1018 char *scroll = n > 0 ? tty->TS_rev_scroll : tty->TS_fwd_scroll;
1019
1020 register int i = n > 0 ? n : -n;
1021 register char *buf;
1022
1023 /* If the lines below the insertion are being pushed
1024 into the end of the window, this is the same as clearing;
1025 and we know the lines are already clear, since the matching
1026 deletion has already been done. So can ignore this. */
1027 /* If the lines below the deletion are blank lines coming
1028 out of the end of the window, don't bother,
1029 as there will be a matching inslines later that will flush them. */
1030 if (FRAME_SCROLL_REGION_OK (f)
1031 && vpos + i >= tty->specified_window)
1032 return;
1033 if (!FRAME_MEMORY_BELOW_FRAME (f)
1034 && vpos + i >= FRAME_LINES (f))
1035 return;
1036
1037 if (multi)
08a24c47 1038 {
3224dac1
KL
1039 raw_cursor_to (vpos, 0);
1040 background_highlight (tty);
1041 buf = tparam (multi, 0, 0, i);
1042 OUTPUT (tty, buf);
1043 xfree (buf);
1044 }
1045 else if (single)
1046 {
1047 raw_cursor_to (vpos, 0);
1048 background_highlight (tty);
1049 while (--i >= 0)
1050 OUTPUT (tty, single);
1051 if (tty->TF_teleray)
1052 curX (tty) = 0;
08a24c47 1053 }
08a24c47
JB
1054 else
1055 {
3224dac1
KL
1056 set_scroll_region (vpos, tty->specified_window);
1057 if (n < 0)
1058 raw_cursor_to (tty->specified_window - 1, 0);
08a24c47 1059 else
3224dac1
KL
1060 raw_cursor_to (vpos, 0);
1061 background_highlight (tty);
1062 while (--i >= 0)
1063 OUTPUTL (tty, scroll, tty->specified_window - vpos);
1064 set_scroll_region (0, tty->specified_window);
1065 }
1066
1067 if (!FRAME_SCROLL_REGION_OK (f)
1068 && FRAME_MEMORY_BELOW_FRAME (f)
1069 && n < 0)
1070 {
1071 cursor_to (FRAME_LINES (f) + n, 0);
1072 clear_to_end ();
08a24c47
JB
1073 }
1074}
1075\f
1076/* Compute cost of sending "str", in characters,
1077 not counting any line-dependent padding. */
1078
1079int
1080string_cost (str)
1081 char *str;
1082{
1083 cost = 0;
1084 if (str)
1085 tputs (str, 0, evalcost);
1086 return cost;
1087}
1088
1089/* Compute cost of sending "str", in characters,
1090 counting any line-dependent padding at one line. */
1091
1092static int
1093string_cost_one_line (str)
1094 char *str;
1095{
1096 cost = 0;
1097 if (str)
1098 tputs (str, 1, evalcost);
1099 return cost;
1100}
1101
1102/* Compute per line amount of line-dependent padding,
1103 in tenths of characters. */
1104
1105int
1106per_line_cost (str)
1107 register char *str;
1108{
1109 cost = 0;
1110 if (str)
1111 tputs (str, 0, evalcost);
1112 cost = - cost;
1113 if (str)
1114 tputs (str, 10, evalcost);
1115 return cost;
1116}
1117
1118#ifndef old
1119/* char_ins_del_cost[n] is cost of inserting N characters.
8dd0c7cb 1120 char_ins_del_cost[-n] is cost of deleting N characters.
9882535b 1121 The length of this vector is based on max_frame_cols. */
08a24c47
JB
1122
1123int *char_ins_del_vector;
1124
9882535b 1125#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
08a24c47
JB
1126#endif
1127
1128/* ARGSUSED */
1129static void
fca177d4
KL
1130calculate_ins_del_char_costs (f)
1131 FRAME_PTR f;
08a24c47 1132{
28d7d09f 1133 struct tty_display_info *tty = FRAME_TTY (f);
08a24c47
JB
1134 int ins_startup_cost, del_startup_cost;
1135 int ins_cost_per_char, del_cost_per_char;
1136 register int i;
1137 register int *p;
1138
fca177d4 1139 if (tty->TS_ins_multi_chars)
08a24c47
JB
1140 {
1141 ins_cost_per_char = 0;
fca177d4 1142 ins_startup_cost = string_cost_one_line (tty->TS_ins_multi_chars);
08a24c47 1143 }
fca177d4
KL
1144 else if (tty->TS_ins_char || tty->TS_pad_inserted_char
1145 || (tty->TS_insert_mode && tty->TS_end_insert_mode))
08a24c47 1146 {
fca177d4
KL
1147 ins_startup_cost = (30 * (string_cost (tty->TS_insert_mode)
1148 + string_cost (tty->TS_end_insert_mode))) / 100;
1149 ins_cost_per_char = (string_cost_one_line (tty->TS_ins_char)
1150 + string_cost_one_line (tty->TS_pad_inserted_char));
08a24c47
JB
1151 }
1152 else
1153 {
1154 ins_startup_cost = 9999;
1155 ins_cost_per_char = 0;
1156 }
1157
fca177d4 1158 if (tty->TS_del_multi_chars)
08a24c47
JB
1159 {
1160 del_cost_per_char = 0;
fca177d4 1161 del_startup_cost = string_cost_one_line (tty->TS_del_multi_chars);
08a24c47 1162 }
fca177d4 1163 else if (tty->TS_del_char)
08a24c47 1164 {
fca177d4
KL
1165 del_startup_cost = (string_cost (tty->TS_delete_mode)
1166 + string_cost (tty->TS_end_delete_mode));
1167 if (tty->delete_in_insert_mode)
08a24c47 1168 del_startup_cost /= 2;
fca177d4 1169 del_cost_per_char = string_cost_one_line (tty->TS_del_char);
08a24c47
JB
1170 }
1171 else
1172 {
1173 del_startup_cost = 9999;
1174 del_cost_per_char = 0;
1175 }
1176
1177 /* Delete costs are at negative offsets */
fca177d4
KL
1178 p = &char_ins_del_cost (f)[0];
1179 for (i = FRAME_COLS (f); --i >= 0;)
08a24c47
JB
1180 *--p = (del_startup_cost += del_cost_per_char);
1181
1182 /* Doing nothing is free */
fca177d4 1183 p = &char_ins_del_cost (f)[0];
08a24c47
JB
1184 *p++ = 0;
1185
1186 /* Insert costs are at positive offsets */
fca177d4 1187 for (i = FRAME_COLS (f); --i >= 0;)
08a24c47
JB
1188 *p++ = (ins_startup_cost += ins_cost_per_char);
1189}
1190
dfcf069d 1191void
ff11dfa1
JB
1192calculate_costs (frame)
1193 FRAME_PTR 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)));
1230
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"},
1340 {"k9", "f9"}
a796ac82
JB
1341 };
1342
f2a00342
RM
1343static char **term_get_fkeys_arg;
1344static Lisp_Object term_get_fkeys_1 ();
465db27b 1345
01d8deb0 1346/* Find the escape codes sent by the function keys for Vfunction_key_map.
177c0ea7 1347 This function scans the termcap function key sequence entries, and
01d8deb0
ER
1348 adds entries to Vfunction_key_map for each function key it finds. */
1349
5c2c7893
JB
1350void
1351term_get_fkeys (address)
1352 char **address;
f2a00342
RM
1353{
1354 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1355 errors during the call. The only errors should be from Fdefine_key
1356 when given a key sequence containing an invalid prefix key. If the
1357 termcap defines function keys which use a prefix that is already bound
1358 to a command by the default bindings, we should silently ignore that
1359 function key specification, rather than giving the user an error and
1360 refusing to run at all on such a terminal. */
1361
1362 extern Lisp_Object Fidentity ();
f2a00342
RM
1363 term_get_fkeys_arg = address;
1364 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1365}
1366
1367static Lisp_Object
1368term_get_fkeys_1 ()
5c2c7893 1369{
5c2c7893
JB
1370 int i;
1371
37085233 1372 char **address = term_get_fkeys_arg;
f778aff2 1373
3e65092f
RS
1374 /* This can happen if CANNOT_DUMP or with strange options. */
1375 if (!initialized)
1376 Vfunction_key_map = Fmake_sparse_keymap (Qnil);
1377
5c2c7893
JB
1378 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1379 {
1380 char *sequence = tgetstr (keys[i].cap, address);
1381 if (sequence)
f2a00342
RM
1382 Fdefine_key (Vfunction_key_map, build_string (sequence),
1383 Fmake_vector (make_number (1),
1384 intern (keys[i].name)));
5c2c7893 1385 }
a796ac82
JB
1386
1387 /* The uses of the "k0" capability are inconsistent; sometimes it
1388 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
eb8c3be9 1389 We will attempt to politely accommodate both systems by testing for
a796ac82
JB
1390 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1391 */
1392 {
1393 char *k_semi = tgetstr ("k;", address);
1394 char *k0 = tgetstr ("k0", address);
1395 char *k0_name = "f10";
1396
1397 if (k_semi)
1398 {
95c11956
SM
1399 if (k0)
1400 /* Define f0 first, so that f10 takes precedence in case the
1401 key sequences happens to be the same. */
1402 Fdefine_key (Vfunction_key_map, build_string (k0),
1403 Fmake_vector (make_number (1), intern ("f0")));
f2a00342
RM
1404 Fdefine_key (Vfunction_key_map, build_string (k_semi),
1405 Fmake_vector (make_number (1), intern ("f10")));
a796ac82 1406 }
95c11956 1407 else if (k0)
f2a00342
RM
1408 Fdefine_key (Vfunction_key_map, build_string (k0),
1409 Fmake_vector (make_number (1), intern (k0_name)));
a796ac82 1410 }
01d8deb0
ER
1411
1412 /* Set up cookies for numbered function keys above f10. */
1413 {
1414 char fcap[3], fkey[4];
1415
fc4f24da 1416 fcap[0] = 'F'; fcap[2] = '\0';
01d8deb0
ER
1417 for (i = 11; i < 64; i++)
1418 {
1419 if (i <= 19)
1420 fcap[1] = '1' + i - 11;
1421 else if (i <= 45)
b59ab95c 1422 fcap[1] = 'A' + i - 20;
01d8deb0 1423 else
b59ab95c 1424 fcap[1] = 'a' + i - 46;
01d8deb0 1425
fc4f24da
RS
1426 {
1427 char *sequence = tgetstr (fcap, address);
1428 if (sequence)
1429 {
465db27b 1430 sprintf (fkey, "f%d", i);
f2a00342
RM
1431 Fdefine_key (Vfunction_key_map, build_string (sequence),
1432 Fmake_vector (make_number (1),
1433 intern (fkey)));
fc4f24da
RS
1434 }
1435 }
01d8deb0
ER
1436 }
1437 }
1438
1439 /*
1440 * Various mappings to try and get a better fit.
1441 */
1442 {
fc4f24da
RS
1443#define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1444 if (!tgetstr (cap1, address)) \
1445 { \
1446 char *sequence = tgetstr (cap2, address); \
1447 if (sequence) \
f2a00342
RM
1448 Fdefine_key (Vfunction_key_map, build_string (sequence), \
1449 Fmake_vector (make_number (1), \
1450 intern (sym))); \
fc4f24da 1451 }
177c0ea7 1452
01d8deb0 1453 /* if there's no key_next keycap, map key_npage to `next' keysym */
27b61785 1454 CONDITIONAL_REASSIGN ("%5", "kN", "next");
01d8deb0 1455 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
381d11a1 1456 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
01d8deb0 1457 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
27b61785 1458 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
403c995b
RS
1459 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1460 CONDITIONAL_REASSIGN ("@7", "kH", "end");
0a7f697a
KH
1461
1462 /* IBM has their own non-standard dialect of terminfo.
1463 If the standard name isn't found, try the IBM name. */
1464 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1465 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1466 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1467 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1468 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1469 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1470 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1471 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1472 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1dd40212 1473#undef CONDITIONAL_REASSIGN
01d8deb0 1474 }
a168702a
GM
1475
1476 return Qnil;
5c2c7893
JB
1477}
1478
1479\f
a168702a
GM
1480/***********************************************************************
1481 Character Display Information
1482 ***********************************************************************/
1483
1484static void append_glyph P_ ((struct it *));
1485
1486
1487/* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1488 terminal frames if IT->glyph_row != NULL. IT->c is the character
1489 for which to produce glyphs; IT->face_id contains the character's
1490 face. Padding glyphs are appended if IT->c has a IT->pixel_width >
1491 1. */
177c0ea7 1492
a168702a
GM
1493static void
1494append_glyph (it)
1495 struct it *it;
1496{
1497 struct glyph *glyph, *end;
1498 int i;
1499
1500 xassert (it->glyph_row);
1501 glyph = (it->glyph_row->glyphs[it->area]
1502 + it->glyph_row->used[it->area]);
1503 end = it->glyph_row->glyphs[1 + it->area];
1504
177c0ea7
JB
1505 for (i = 0;
1506 i < it->pixel_width && glyph < end;
a168702a
GM
1507 ++i)
1508 {
1509 glyph->type = CHAR_GLYPH;
d13f3e2e 1510 glyph->pixel_width = 1;
32de38e4
KH
1511 glyph->u.ch = it->c;
1512 glyph->face_id = it->face_id;
1513 glyph->padding_p = i > 0;
a168702a
GM
1514 glyph->charpos = CHARPOS (it->position);
1515 glyph->object = it->object;
177c0ea7 1516
a168702a
GM
1517 ++it->glyph_row->used[it->area];
1518 ++glyph;
1519 }
1520}
1521
1522
b50fe468
RS
1523/* Produce glyphs for the display element described by IT. *IT
1524 specifies what we want to produce a glyph for (character, image, ...),
1525 and where in the glyph matrix we currently are (glyph row and hpos).
1526 produce_glyphs fills in output fields of *IT with information such as the
1527 pixel width and height of a character, and maybe output actual glyphs at
a168702a 1528 the same time if IT->glyph_row is non-null. See the explanation of
b50fe468
RS
1529 struct display_iterator in dispextern.h for an overview.
1530
1531 produce_glyphs also stores the result of glyph width, ascent
1532 etc. computations in *IT.
1533
1534 IT->glyph_row may be null, in which case produce_glyphs does not
1535 actually fill in the glyphs. This is used in the move_* functions
1536 in xdisp.c for text width and height computations.
1537
1538 Callers usually don't call produce_glyphs directly;
1539 instead they use the macro PRODUCE_GLYPHS. */
a168702a 1540
177c0ea7 1541void
a168702a
GM
1542produce_glyphs (it)
1543 struct it *it;
1544{
1545 /* If a hook is installed, let it do the work. */
1546 xassert (it->what == IT_CHARACTER
c7cba11d 1547 || it->what == IT_COMPOSITION
a168702a
GM
1548 || it->what == IT_IMAGE
1549 || it->what == IT_STRETCH);
177c0ea7 1550
c7cba11d
KH
1551 /* Nothing but characters are supported on terminal frames. For a
1552 composition sequence, it->c is the first character of the
1553 sequence. */
1554 xassert (it->what == IT_CHARACTER
1555 || it->what == IT_COMPOSITION);
a168702a
GM
1556
1557 if (it->c >= 040 && it->c < 0177)
1558 {
1559 it->pixel_width = it->nglyphs = 1;
1560 if (it->glyph_row)
1561 append_glyph (it);
1562 }
1563 else if (it->c == '\n')
1564 it->pixel_width = it->nglyphs = 0;
1565 else if (it->c == '\t')
1566 {
2efdbcdd 1567 int absolute_x = (it->current_x
a168702a 1568 + it->continuation_lines_width);
177c0ea7
JB
1569 int next_tab_x
1570 = (((1 + absolute_x + it->tab_width - 1)
a168702a
GM
1571 / it->tab_width)
1572 * it->tab_width);
1573 int nspaces;
1574
1575 /* If part of the TAB has been displayed on the previous line
1576 which is continued now, continuation_lines_width will have
1577 been incremented already by the part that fitted on the
1578 continued line. So, we will get the right number of spaces
1579 here. */
1580 nspaces = next_tab_x - absolute_x;
177c0ea7 1581
a168702a
GM
1582 if (it->glyph_row)
1583 {
1584 int n = nspaces;
177c0ea7 1585
a168702a
GM
1586 it->c = ' ';
1587 it->pixel_width = it->len = 1;
177c0ea7 1588
a168702a
GM
1589 while (n--)
1590 append_glyph (it);
177c0ea7 1591
a168702a
GM
1592 it->c = '\t';
1593 }
1594
1595 it->pixel_width = nspaces;
1596 it->nglyphs = nspaces;
1597 }
add44890
EZ
1598 else if (SINGLE_BYTE_CHAR_P (it->c))
1599 {
cf872af5 1600 /* Coming here means that it->c is from display table, thus we
add44890
EZ
1601 must send the code as is to the terminal. Although there's
1602 no way to know how many columns it occupies on a screen, it
1603 is a good assumption that a single byte code has 1-column
1604 width. */
1605 it->pixel_width = it->nglyphs = 1;
1606 if (it->glyph_row)
1607 append_glyph (it);
1608 }
a168702a
GM
1609 else
1610 {
c7cba11d
KH
1611 /* A multi-byte character. The display width is fixed for all
1612 characters of the set. Some of the glyphs may have to be
1613 ignored because they are already displayed in a continued
1614 line. */
a168702a
GM
1615 int charset = CHAR_CHARSET (it->c);
1616
c7cba11d 1617 it->pixel_width = CHARSET_WIDTH (charset);
a168702a 1618 it->nglyphs = it->pixel_width;
177c0ea7 1619
a168702a
GM
1620 if (it->glyph_row)
1621 append_glyph (it);
1622 }
1623
177c0ea7 1624 /* Advance current_x by the pixel width as a convenience for
a168702a
GM
1625 the caller. */
1626 if (it->area == TEXT_AREA)
1627 it->current_x += it->pixel_width;
cfe8a05e
GM
1628 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1629 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
a168702a
GM
1630}
1631
1632
1633/* Get information about special display element WHAT in an
1634 environment described by IT. WHAT is one of IT_TRUNCATION or
1635 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1636 non-null glyph_row member. This function ensures that fields like
1637 face_id, c, len of IT are left untouched. */
1638
1639void
1640produce_special_glyphs (it, what)
1641 struct it *it;
1642 enum display_element_type what;
1643{
1644 struct it temp_it;
177c0ea7 1645
a168702a
GM
1646 temp_it = *it;
1647 temp_it.dp = NULL;
1648 temp_it.what = IT_CHARACTER;
1649 temp_it.len = 1;
7c752c80 1650 temp_it.object = make_number (0);
a168702a
GM
1651 bzero (&temp_it.current, sizeof temp_it.current);
1652
1653 if (what == IT_CONTINUATION)
1654 {
1655 /* Continuation glyph. */
1656 if (it->dp
1657 && INTEGERP (DISP_CONTINUE_GLYPH (it->dp))
1658 && GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (it->dp))))
1659 {
1660 temp_it.c = FAST_GLYPH_CHAR (XINT (DISP_CONTINUE_GLYPH (it->dp)));
68526af5 1661 temp_it.len = CHAR_BYTES (temp_it.c);
a168702a
GM
1662 }
1663 else
1664 temp_it.c = '\\';
177c0ea7 1665
a168702a
GM
1666 produce_glyphs (&temp_it);
1667 it->pixel_width = temp_it.pixel_width;
1668 it->nglyphs = temp_it.pixel_width;
1669 }
1670 else if (what == IT_TRUNCATION)
1671 {
1672 /* Truncation glyph. */
1673 if (it->dp
1674 && INTEGERP (DISP_TRUNC_GLYPH (it->dp))
1675 && GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (it->dp))))
1676 {
1677 temp_it.c = FAST_GLYPH_CHAR (XINT (DISP_TRUNC_GLYPH (it->dp)));
68526af5 1678 temp_it.len = CHAR_BYTES (temp_it.c);
a168702a
GM
1679 }
1680 else
1681 temp_it.c = '$';
177c0ea7 1682
a168702a
GM
1683 produce_glyphs (&temp_it);
1684 it->pixel_width = temp_it.pixel_width;
1685 it->nglyphs = temp_it.pixel_width;
1686 }
1687 else
1688 abort ();
1689}
1690
1691
a168702a
GM
1692\f
1693/***********************************************************************
1694 Faces
1695 ***********************************************************************/
1696
4e6ba4a4
GM
1697/* Value is non-zero if attribute ATTR may be used. ATTR should be
1698 one of the enumerators from enum no_color_bit, or a bit set built
1699 from them. Some display attributes may not be used together with
1700 color; the termcap capability `NC' specifies which ones. */
1701
fca177d4
KL
1702#define MAY_USE_WITH_COLORS_P(tty, ATTR) \
1703 (tty->TN_max_colors > 0 \
1704 ? (tty->TN_no_color_video & (ATTR)) == 0 \
1705 : 1)
a168702a
GM
1706
1707/* Turn appearances of face FACE_ID on tty frame F on. */
1708
1709static void
1710turn_on_face (f, face_id)
1711 struct frame *f;
1712 int face_id;
1713{
1714 struct face *face = FACE_FROM_ID (f, face_id);
86a7d192
GM
1715 long fg = face->foreground;
1716 long bg = face->background;
28d7d09f 1717 struct tty_display_info *tty = FRAME_TTY (f);
a168702a 1718
86a7d192
GM
1719 /* Do this first because TS_end_standout_mode may be the same
1720 as TS_exit_attribute_mode, which turns all appearances off. */
fca177d4 1721 if (MAY_USE_WITH_COLORS_P (tty, NC_REVERSE))
86a7d192 1722 {
fca177d4 1723 if (tty->TN_max_colors > 0)
86a7d192
GM
1724 {
1725 if (fg >= 0 && bg >= 0)
1726 {
1727 /* If the terminal supports colors, we can set them
1728 below without using reverse video. The face's fg
1729 and bg colors are set as they should appear on
1730 the screen, i.e. they take the inverse-video'ness
1731 of the face already into account. */
1732 }
1733 else if (inverse_video)
1734 {
1735 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1736 || bg == FACE_TTY_DEFAULT_BG_COLOR)
fca177d4 1737 toggle_highlight (tty);
86a7d192
GM
1738 }
1739 else
1740 {
1741 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1742 || bg == FACE_TTY_DEFAULT_FG_COLOR)
fca177d4 1743 toggle_highlight (tty);
86a7d192
GM
1744 }
1745 }
1746 else
1747 {
1748 /* If we can't display colors, use reverse video
1749 if the face specifies that. */
37526b42
GM
1750 if (inverse_video)
1751 {
1752 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1753 || bg == FACE_TTY_DEFAULT_BG_COLOR)
fca177d4 1754 toggle_highlight (tty);
37526b42
GM
1755 }
1756 else
1757 {
1758 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1759 || bg == FACE_TTY_DEFAULT_FG_COLOR)
fca177d4 1760 toggle_highlight (tty);
37526b42 1761 }
86a7d192
GM
1762 }
1763 }
a168702a
GM
1764
1765 if (face->tty_bold_p)
4e6ba4a4 1766 {
fca177d4
KL
1767 if (MAY_USE_WITH_COLORS_P (tty, NC_BOLD))
1768 OUTPUT1_IF (tty, tty->TS_enter_bold_mode);
4e6ba4a4 1769 }
a168702a 1770 else if (face->tty_dim_p)
fca177d4
KL
1771 if (MAY_USE_WITH_COLORS_P (tty, NC_DIM))
1772 OUTPUT1_IF (tty, tty->TS_enter_dim_mode);
a168702a
GM
1773
1774 /* Alternate charset and blinking not yet used. */
4e6ba4a4 1775 if (face->tty_alt_charset_p
fca177d4
KL
1776 && MAY_USE_WITH_COLORS_P (tty, NC_ALT_CHARSET))
1777 OUTPUT1_IF (tty, tty->TS_enter_alt_charset_mode);
a168702a 1778
4e6ba4a4 1779 if (face->tty_blinking_p
fca177d4
KL
1780 && MAY_USE_WITH_COLORS_P (tty, NC_BLINK))
1781 OUTPUT1_IF (tty, tty->TS_enter_blink_mode);
a168702a 1782
fca177d4
KL
1783 if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (tty, NC_UNDERLINE))
1784 OUTPUT1_IF (tty, tty->TS_enter_underline_mode);
a168702a 1785
fca177d4 1786 if (tty->TN_max_colors > 0)
a168702a
GM
1787 {
1788 char *p;
177c0ea7 1789
fca177d4 1790 if (fg >= 0 && tty->TS_set_foreground)
a168702a 1791 {
fca177d4 1792 p = tparam (tty->TS_set_foreground, NULL, 0, (int) fg);
6548cf00 1793 OUTPUT (tty, p);
a168702a
GM
1794 xfree (p);
1795 }
1796
fca177d4 1797 if (bg >= 0 && tty->TS_set_background)
a168702a 1798 {
fca177d4 1799 p = tparam (tty->TS_set_background, NULL, 0, (int) bg);
6548cf00 1800 OUTPUT (tty, p);
a168702a
GM
1801 xfree (p);
1802 }
1803 }
1804}
177c0ea7 1805
a168702a
GM
1806
1807/* Turn off appearances of face FACE_ID on tty frame F. */
1808
1809static void
1810turn_off_face (f, face_id)
1811 struct frame *f;
1812 int face_id;
1813{
1814 struct face *face = FACE_FROM_ID (f, face_id);
28d7d09f 1815 struct tty_display_info *tty = FRAME_TTY (f);
a168702a
GM
1816
1817 xassert (face != NULL);
1818
fca177d4 1819 if (tty->TS_exit_attribute_mode)
a168702a
GM
1820 {
1821 /* Capability "me" will turn off appearance modes double-bright,
1822 half-bright, reverse-video, standout, underline. It may or
1823 may not turn off alt-char-mode. */
1824 if (face->tty_bold_p
1825 || face->tty_dim_p
1826 || face->tty_reverse_p
1827 || face->tty_alt_charset_p
1828 || face->tty_blinking_p
1829 || face->tty_underline_p)
65aa5e85 1830 {
fca177d4
KL
1831 OUTPUT1_IF (tty, tty->TS_exit_attribute_mode);
1832 if (strcmp (tty->TS_exit_attribute_mode, tty->TS_end_standout_mode) == 0)
1833 tty->standout_mode = 0;
65aa5e85 1834 }
a168702a
GM
1835
1836 if (face->tty_alt_charset_p)
fca177d4 1837 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
a168702a
GM
1838 }
1839 else
1840 {
1841 /* If we don't have "me" we can only have those appearances
1842 that have exit sequences defined. */
1843 if (face->tty_alt_charset_p)
fca177d4 1844 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
a168702a 1845
54800acb 1846 if (face->tty_underline_p)
fca177d4 1847 OUTPUT_IF (tty, tty->TS_exit_underline_mode);
a168702a
GM
1848 }
1849
1850 /* Switch back to default colors. */
fca177d4 1851 if (tty->TN_max_colors > 0
f9d2fdc4
EZ
1852 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
1853 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
1854 || (face->background != FACE_TTY_DEFAULT_COLOR
1855 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
fca177d4 1856 OUTPUT1_IF (tty, tty->TS_orig_pair);
a168702a 1857}
177c0ea7
JB
1858
1859
b63a55ac
MB
1860/* Return non-zero if the terminal on frame F supports all of the
1861 capabilities in CAPS simultaneously, with foreground and background
1862 colors FG and BG. */
1863
4a8130f2 1864int
fca177d4 1865tty_capable_p (tty, caps, fg, bg)
28d7d09f 1866 struct tty_display_info *tty;
b63a55ac
MB
1867 unsigned caps;
1868 unsigned long fg, bg;
1869{
fca177d4
KL
1870#define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
1871 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
b63a55ac
MB
1872 return 0;
1873
fca177d4
KL
1874 TTY_CAPABLE_P_TRY (tty, TTY_CAP_INVERSE, tty->TS_standout_mode, NC_REVERSE);
1875 TTY_CAPABLE_P_TRY (tty, TTY_CAP_UNDERLINE, tty->TS_enter_underline_mode, NC_UNDERLINE);
1876 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BOLD, tty->TS_enter_bold_mode, NC_BOLD);
1877 TTY_CAPABLE_P_TRY (tty, TTY_CAP_DIM, tty->TS_enter_dim_mode, NC_DIM);
1878 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BLINK, tty->TS_enter_blink_mode, NC_BLINK);
1879 TTY_CAPABLE_P_TRY (tty, TTY_CAP_ALT_CHARSET, tty->TS_enter_alt_charset_mode, NC_ALT_CHARSET);
b63a55ac
MB
1880
1881 /* We can do it! */
1882 return 1;
1883}
1884
24268213
KL
1885/* Return the tty display object specified by DISPLAY. DISPLAY may be
1886 a frame, a string, or nil for the display device of the current
1887 frame. */
3224dac1
KL
1888
1889static struct display *
1890get_tty_display (Lisp_Object display)
1891{
1892 struct display *d;
1893
24268213
KL
1894 if (NILP (display))
1895 display = selected_frame;
1896
3224dac1
KL
1897 if (! FRAMEP (display) && ! STRINGP (display))
1898 return 0;
1899
1900 /* The initial frame does not support colors. */
1901 if (FRAMEP (display) && FRAME_INITIAL_P (XFRAME (display)))
1902 return 0;
1903
1904 if (FRAMEP (display))
1905 {
1906 if (! FRAME_TERMCAP_P (XFRAME (display)))
1907#if 0 /* XXX We need a predicate as the first argument; find one. */
1908 wrong_type_argument ("Not a termcap frame", display);
1909#else /* Until we fix the wrong_type_argument call above, simply throw
1910 a dumb error. */
1911 error ("DISPLAY is not a termcap frame");
1912#endif
1913
1914 d = FRAME_DISPLAY (XFRAME (display));
1915 }
1916 else if (STRINGP (display))
1917 {
1918 char *name = (char *) alloca (SBYTES (display) + 1);
1919 strncpy (name, SDATA (display), SBYTES (display));
1920 name[SBYTES (display)] = 0;
1921
1922 d = get_named_tty_display (name);
1923
1924 if (!d)
1925 error ("There is no tty display on %s", name);
1926 }
1927
1928 return d;
1929}
1930
b63a55ac 1931
a168702a
GM
1932/* Return non-zero if the terminal is capable to display colors. */
1933
1934DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
981e4297 1935 0, 1, 0,
99fdd6bc
EZ
1936 doc: /* Return non-nil if TTY can display colors on DISPLAY. */)
1937 (display)
1938 Lisp_Object display;
a168702a 1939{
3224dac1
KL
1940 struct display *d = get_tty_display (display);
1941 if (!d)
428a555e 1942 return Qnil;
3224dac1
KL
1943 else
1944 return d->display_info.tty->TN_max_colors > 0 ? Qt : Qnil;
a168702a
GM
1945}
1946
bfa62f96
EZ
1947/* Return the number of supported colors. */
1948DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
1949 Stty_display_color_cells, 0, 1, 0,
99fdd6bc
EZ
1950 doc: /* Return the number of colors supported by TTY on DISPLAY. */)
1951 (display)
1952 Lisp_Object display;
bfa62f96 1953{
3224dac1
KL
1954 struct display *d = get_tty_display (display);
1955 if (!d)
428a555e 1956 return Qnil;
3224dac1
KL
1957 else
1958 return make_number (d->display_info.tty->TN_max_colors);
bfa62f96
EZ
1959}
1960
ace28297 1961#ifndef WINDOWSNT
a168702a 1962
ace28297
EZ
1963/* Save or restore the default color-related capabilities of this
1964 terminal. */
1965static void
28d7d09f 1966tty_default_color_capabilities (struct tty_display_info *tty, int save)
ace28297
EZ
1967{
1968 static char
1969 *default_orig_pair, *default_set_foreground, *default_set_background;
1970 static int default_max_colors, default_max_pairs, default_no_color_video;
1971
1972 if (save)
1973 {
1974 if (default_orig_pair)
1975 xfree (default_orig_pair);
fca177d4 1976 default_orig_pair = tty->TS_orig_pair ? xstrdup (tty->TS_orig_pair) : NULL;
ace28297
EZ
1977
1978 if (default_set_foreground)
1979 xfree (default_set_foreground);
fca177d4 1980 default_set_foreground = tty->TS_set_foreground ? xstrdup (tty->TS_set_foreground)
ace28297
EZ
1981 : NULL;
1982
1983 if (default_set_background)
1984 xfree (default_set_background);
fca177d4 1985 default_set_background = tty->TS_set_background ? xstrdup (tty->TS_set_background)
ace28297
EZ
1986 : NULL;
1987
fca177d4
KL
1988 default_max_colors = tty->TN_max_colors;
1989 default_max_pairs = tty->TN_max_pairs;
1990 default_no_color_video = tty->TN_no_color_video;
ace28297
EZ
1991 }
1992 else
1993 {
fca177d4
KL
1994 tty->TS_orig_pair = default_orig_pair;
1995 tty->TS_set_foreground = default_set_foreground;
1996 tty->TS_set_background = default_set_background;
1997 tty->TN_max_colors = default_max_colors;
1998 tty->TN_max_pairs = default_max_pairs;
1999 tty->TN_no_color_video = default_no_color_video;
ace28297
EZ
2000 }
2001}
2002
2003/* Setup one of the standard tty color schemes according to MODE.
2004 MODE's value is generally the number of colors which we want to
2005 support; zero means set up for the default capabilities, the ones
2006 we saw at term_init time; -1 means turn off color support. */
2007void
28d7d09f 2008tty_setup_colors (struct tty_display_info *tty, int mode)
ace28297 2009{
40409f05
EZ
2010 /* Canonicalize all negative values of MODE. */
2011 if (mode < -1)
2012 mode = -1;
2013
ace28297
EZ
2014 switch (mode)
2015 {
2016 case -1: /* no colors at all */
fca177d4
KL
2017 tty->TN_max_colors = 0;
2018 tty->TN_max_pairs = 0;
2019 tty->TN_no_color_video = 0;
2020 tty->TS_set_foreground = tty->TS_set_background = tty->TS_orig_pair = NULL;
ace28297
EZ
2021 break;
2022 case 0: /* default colors, if any */
2023 default:
fca177d4 2024 tty_default_color_capabilities (tty, 0);
ace28297
EZ
2025 break;
2026 case 8: /* 8 standard ANSI colors */
fca177d4 2027 tty->TS_orig_pair = "\033[0m";
ace28297 2028#ifdef TERMINFO
fca177d4
KL
2029 tty->TS_set_foreground = "\033[3%p1%dm";
2030 tty->TS_set_background = "\033[4%p1%dm";
ace28297 2031#else
fca177d4
KL
2032 tty->TS_set_foreground = "\033[3%dm";
2033 tty->TS_set_background = "\033[4%dm";
ace28297 2034#endif
fca177d4
KL
2035 tty->TN_max_colors = 8;
2036 tty->TN_max_pairs = 64;
2037 tty->TN_no_color_video = 0;
ace28297
EZ
2038 break;
2039 }
2040}
2041
2042void
2043set_tty_color_mode (f, val)
2044 struct frame *f;
2045 Lisp_Object val;
2046{
dfc7a077 2047 Lisp_Object color_mode_spec, current_mode_spec;
ace28297
EZ
2048 Lisp_Object color_mode, current_mode;
2049 int mode, old_mode;
2050 extern Lisp_Object Qtty_color_mode;
2051 Lisp_Object tty_color_mode_alist;
2052
2053 tty_color_mode_alist = Fintern_soft (build_string ("tty-color-mode-alist"),
2054 Qnil);
2055
9ac61a89 2056 if (INTEGERP (val))
ace28297
EZ
2057 color_mode = val;
2058 else
2059 {
2060 if (NILP (tty_color_mode_alist))
2061 color_mode_spec = Qnil;
2062 else
2063 color_mode_spec = Fassq (val, XSYMBOL (tty_color_mode_alist)->value);
ace28297
EZ
2064
2065 if (CONSP (color_mode_spec))
2066 color_mode = XCDR (color_mode_spec);
2067 else
2068 color_mode = Qnil;
2069 }
545d91d5
RS
2070
2071 current_mode_spec = assq_no_quit (Qtty_color_mode, f->param_alist);
2072
ace28297
EZ
2073 if (CONSP (current_mode_spec))
2074 current_mode = XCDR (current_mode_spec);
2075 else
2076 current_mode = Qnil;
9ac61a89 2077 if (INTEGERP (color_mode))
ace28297
EZ
2078 mode = XINT (color_mode);
2079 else
2080 mode = 0; /* meaning default */
9ac61a89 2081 if (INTEGERP (current_mode))
ace28297
EZ
2082 old_mode = XINT (current_mode);
2083 else
2084 old_mode = 0;
2085
2086 if (mode != old_mode)
2087 {
fca177d4 2088 tty_setup_colors (FRAME_TTY (f), mode);
ace28297
EZ
2089 /* This recomputes all the faces given the new color
2090 definitions. */
2091 call0 (intern ("tty-set-up-initial-frame-faces"));
2092 redraw_frame (f);
2093 }
2094}
2095
2096#endif /* !WINDOWSNT */
a168702a
GM
2097
2098\f
28d440ab 2099
da8e1115
KL
2100/* Return the termcap display with the given name. If NAME is null,
2101 return the display corresponding to our controlling terminal.
2102
2103 Returns NULL if the named terminal device is not opened. */
2104
3224dac1 2105struct display *
428a555e 2106get_named_tty_display (name)
28d440ab
KL
2107 char *name;
2108{
428a555e
KL
2109 struct display *d;
2110
2111 for (d = display_list; d; d = d->next_display) {
2112 if (d->type == output_termcap
2113 && ((d->display_info.tty->name == 0 && name == 0)
2114 || (name && d->display_info.tty->name
2115 && !strcmp (d->display_info.tty->name, name))))
2116 return d;
28d440ab
KL
2117 };
2118
2119 return 0;
2120}
2121
2122\f
819b8f00
KL
2123
2124DEFUN ("frame-tty-name", Fframe_tty_name, Sframe_tty_name, 0, 1, 0,
2125 doc: /* Return the name of the TTY device that FRAME is displayed on. */)
2126 (frame)
2127 Lisp_Object frame;
2128{
2129 struct frame *f;
2130
2131 if (NILP (frame))
2132 {
2133 f = XFRAME (selected_frame);
2134 }
2135 else
2136 {
2137 CHECK_LIVE_FRAME (frame);
2138 f = XFRAME (frame);
2139 }
2140
2141 if (f->output_method != output_termcap)
2142 wrong_type_argument (Qframe_tty_name, frame);
2143
28d7d09f
KL
2144 if (FRAME_TTY (f)->name)
2145 return build_string (FRAME_TTY (f)->name);
819b8f00
KL
2146 else
2147 return Qnil;
2148}
2149
2150DEFUN ("frame-tty-type", Fframe_tty_type, Sframe_tty_type, 0, 1, 0,
2151 doc: /* Return the type of the TTY device that FRAME is displayed on. */)
2152 (frame)
2153 Lisp_Object frame;
2154{
2155 struct frame *f;
daf01701 2156
819b8f00
KL
2157 if (NILP (frame))
2158 {
2159 f = XFRAME (selected_frame);
2160 }
2161 else
2162 {
2163 CHECK_LIVE_FRAME (frame);
2164 f = XFRAME (frame);
2165 }
2166
2167 if (f->output_method != output_termcap)
2168 wrong_type_argument (Qframe_tty_type, frame);
2169
28d7d09f
KL
2170 if (FRAME_TTY (f)->type)
2171 return build_string (FRAME_TTY (f)->type);
819b8f00
KL
2172 else
2173 return Qnil;
2174}
2175
2176\f
a168702a
GM
2177/***********************************************************************
2178 Initialization
2179 ***********************************************************************/
2180
3224dac1 2181/* Create the bootstrap display device for the initial frame.
da8e1115 2182 Returns a display of type output_initial. */
3224dac1 2183
428a555e 2184struct display *
3224dac1 2185init_initial_display (void)
28d440ab 2186{
428a555e
KL
2187 if (initialized || display_list || tty_list)
2188 abort ();
2189
3224dac1
KL
2190 initial_display = create_display ();
2191 initial_display->type = output_initial;
428a555e 2192
3224dac1
KL
2193 initial_display->delete_display_hook = &delete_initial_display;
2194 /* All other hooks are NULL. */
428a555e 2195
3224dac1
KL
2196 return initial_display;
2197}
2198
2199/* Deletes the bootstrap display device.
2200 Called through delete_display_hook. */
da8e1115 2201
3224dac1
KL
2202void
2203delete_initial_display (struct display *display)
2204{
2205 if (display != initial_display)
2206 abort ();
2207
2208 delete_display (display);
2209 initial_display = NULL;
28d440ab
KL
2210}
2211
3224dac1
KL
2212/* Create a termcap display on the tty device with the given name and
2213 type.
2214
2215 If NAME is NULL, then use the controlling tty, i.e., stdin/stdout.
2216 Otherwise NAME should be a path to the tty device file,
2217 e.g. "/dev/pts/7".
28d440ab 2218
3224dac1
KL
2219 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
2220
2221 If MUST_SUCCEED is true, then all errors are fatal. */
da8e1115 2222
428a555e 2223struct display *
3224dac1 2224term_init (char *name, char *terminal_type, int must_succeed)
08a24c47
JB
2225{
2226 char *area;
2227 char **address = &area;
3a06a6d9 2228 char *buffer = NULL;
5846981b 2229 int buffer_size = 4096;
08a24c47
JB
2230 register char *p;
2231 int status;
28d7d09f 2232 struct tty_display_info *tty;
428a555e 2233 struct display *display;
28d440ab 2234
3224dac1
KL
2235 static void maybe_fatal();
2236
2237 if (!terminal_type)
2238 maybe_fatal (must_succeed, 0, 0,
2239 "Unknown terminal type",
2240 "Unknown terminal type");
2241
428a555e
KL
2242 display = get_named_tty_display (name);
2243 if (display)
3224dac1 2244 return display; /* We have already opened a display there. */
428a555e 2245
3224dac1
KL
2246 display = create_display ();
2247 tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info));
2248 bzero (tty, sizeof (struct tty_display_info));
2249 tty->next = tty_list;
2250 tty_list = tty;
428a555e 2251
3224dac1
KL
2252 display->type = output_termcap;
2253 display->display_info.tty = tty;
2254 tty->display = display;
28d440ab 2255
7b00d185
KL
2256 tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
2257 Wcm_clear (tty);
daf01701 2258
428a555e 2259 display->rif = 0; /* ttys don't support window-based redisplay. */
3224dac1
KL
2260
2261 display->cursor_to_hook = &tty_cursor_to;
2262 display->raw_cursor_to_hook = &tty_raw_cursor_to;
2263
2264 display->clear_to_end_hook = &tty_clear_to_end;
2265 display->clear_frame_hook = &tty_clear_frame;
2266 display->clear_end_of_line_hook = &tty_clear_end_of_line;
2267
2268 display->ins_del_lines_hook = &tty_ins_del_lines;
2269
2270 display->insert_glyphs_hook = &tty_insert_glyphs;
2271 display->write_glyphs_hook = &tty_write_glyphs;
2272 display->delete_glyphs_hook = &tty_delete_glyphs;
2273
2274 display->ring_bell_hook = &tty_ring_bell;
2275
2276 display->reset_terminal_modes_hook = &tty_reset_terminal_modes;
2277 display->set_terminal_modes_hook = &tty_set_terminal_modes;
2278 display->update_begin_hook = 0; /* Not needed. */
2279 display->update_end_hook = &tty_update_end;
2280 display->set_terminal_window_hook = &tty_set_terminal_window;
2281
2282 display->mouse_position_hook = 0; /* Not needed. */
2283 display->frame_rehighlight_hook = 0; /* Not needed. */
2284 display->frame_raise_lower_hook = 0; /* Not needed. */
2285
2286 display->set_vertical_scroll_bar_hook = 0; /* Not needed. */
2287 display->condemn_scroll_bars_hook = 0; /* Not needed. */
2288 display->redeem_scroll_bar_hook = 0; /* Not needed. */
2289 display->judge_scroll_bars_hook = 0; /* Not needed. */
2290
8f1ce423 2291 display->read_socket_hook = &tty_read_avail_input; /* keyboard.c */
3224dac1
KL
2292 display->frame_up_to_date_hook = 0; /* Not needed. */
2293
428a555e
KL
2294 display->delete_frame_hook = &delete_tty_output;
2295 display->delete_display_hook = &delete_tty;
2296
28d440ab
KL
2297 if (name)
2298 {
2299 int fd;
0a125897 2300 FILE *file;
0c72d684
KL
2301
2302#ifdef O_IGNORE_CTTY
2303 /* Open the terminal device. Don't recognize it as our
2304 controlling terminal, and don't make it the controlling tty
2305 if we don't have one at the moment. */
2306 fd = emacs_open (name, O_RDWR | O_IGNORE_CTTY | O_NOCTTY, 0);
2307#else
2308 /* Alas, O_IGNORE_CTTY is a GNU extension that is only defined
2309 on Hurd. On other systems, we need to dissociate ourselves
2310 from the controlling tty when we want to open a frame on the
2311 same terminal. The function setsid should be used for this,
2312 but it didn't work for me. */
2313
2314 fd = emacs_open (name, O_RDWR | O_NOCTTY, 0);
2315
2316#ifdef TIOCNOTTY
2317 /* Drop our controlling tty if it is the same device. */
2318 if (ioctl (fd, TIOCNOTTY, 0) != -1)
2319 {
2320 no_controlling_tty = 1;
2321 }
2322#endif
2323#endif /* O_IGNORE_CTTY */
2324
28d440ab
KL
2325 if (fd < 0)
2326 {
428a555e 2327 delete_tty (display);
fca177d4 2328 error ("Could not open file: %s", name);
28d440ab 2329 }
0c72d684
KL
2330 if (! isatty (fd))
2331 {
2332 close (fd);
2333 error ("Not a tty device: %s", name);
2334 }
2335
0a125897 2336 file = fdopen (fd, "w+");
28d7d09f
KL
2337 tty->name = xstrdup (name);
2338 tty->input = file;
2339 tty->output = file;
28d440ab
KL
2340 }
2341 else
2342 {
0c72d684
KL
2343 if (no_controlling_tty)
2344 {
2345 /* Opening a frame on stdout is unsafe if we have
2346 disconnected our controlling terminal. */
2347 error ("There is no controlling terminal any more");
2348 }
28d7d09f
KL
2349 tty->name = 0;
2350 tty->input = stdin;
2351 tty->output = stdout;
28d440ab
KL
2352 }
2353
28d7d09f 2354 tty->type = xstrdup (terminal_type);
28d440ab 2355
819b8f00 2356 add_keyboard_wait_descriptor (fileno (tty->input));
daf01701 2357
cb28b9c2 2358#ifdef WINDOWSNT
29f27c39 2359 initialize_w32_display ();
cb28b9c2 2360
fca177d4 2361 Wcm_clear (tty);
cb28b9c2 2362
a678d9ff 2363 area = (char *) xmalloc (2044);
cb28b9c2 2364
428a555e
KL
2365 FrameRows (tty) = FRAME_LINES (f); /* XXX */
2366 FrameCols (tty) = FRAME_COLS (f); /* XXX */
2367 tty->specified_window = FRAME_LINES (f); /* XXX */
cb28b9c2 2368
428a555e 2369 tty->display->delete_in_insert_mode = 1;
cb28b9c2 2370
daf01701 2371 UseTabs (tty) = 0;
428a555e 2372 display->scroll_region_ok = 0;
cb28b9c2
RS
2373
2374 /* Seems to insert lines when it's not supposed to, messing
2375 up the display. In doing a trace, it didn't seem to be
2376 called much, so I don't think we're losing anything by
2377 turning it off. */
428a555e
KL
2378 display->line_ins_del_ok = 0;
2379 display->char_ins_del_ok = 1;
cb28b9c2
RS
2380
2381 baud_rate = 19200;
2382
428a555e
KL
2383 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0; /* XXX */
2384 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none; /* XXX */
acfcd5cd 2385 TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
cb28b9c2 2386
428a555e 2387 return display;
eccec691 2388#else /* not WINDOWSNT */
cb28b9c2 2389
6548cf00 2390 Wcm_clear (tty);
08a24c47 2391
3a06a6d9 2392 buffer = (char *) xmalloc (buffer_size);
08a24c47
JB
2393 status = tgetent (buffer, terminal_type);
2394 if (status < 0)
b0347178
KH
2395 {
2396#ifdef TERMINFO
3224dac1
KL
2397 maybe_fatal (must_succeed, buffer, display,
2398 "Cannot open terminfo database file",
2399 "Cannot open terminfo database file");
b0347178 2400#else
3224dac1
KL
2401 maybe_fatal (must_succeed, buffer, display,
2402 "Cannot open termcap database file",
2403 "Cannot open termcap database file");
b0347178
KH
2404#endif
2405 }
08a24c47 2406 if (status == 0)
b0347178
KH
2407 {
2408#ifdef TERMINFO
3224dac1
KL
2409 maybe_fatal (must_succeed, buffer, display,
2410 "Terminal type %s is not defined",
2411 "Terminal type %s is not defined.\n\
0a125897 2412If that is not the actual type of terminal you have,\n\
b0347178
KH
2413use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2414`setenv TERM ...') to specify the correct type. It may be necessary\n\
e12c1054 2415to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3224dac1 2416 terminal_type);
b0347178 2417#else
3224dac1
KL
2418 maybe_fatal (must_succeed, buffer, display,
2419 "Terminal type %s is not defined",
2420 "Terminal type %s is not defined.\n\
0a125897 2421If that is not the actual type of terminal you have,\n\
c5a9c3e6
RS
2422use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2423`setenv TERM ...') to specify the correct type. It may be necessary\n\
e12c1054 2424to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3224dac1 2425 terminal_type);
b0347178
KH
2426#endif
2427 }
3a06a6d9 2428
f730033e 2429#ifndef TERMINFO
3a06a6d9 2430 if (strlen (buffer) >= buffer_size)
08a24c47 2431 abort ();
f730033e 2432 buffer_size = strlen (buffer);
3dd3a502 2433#endif
f730033e 2434 area = (char *) xmalloc (buffer_size);
08a24c47 2435
fca177d4
KL
2436 tty->TS_ins_line = tgetstr ("al", address);
2437 tty->TS_ins_multi_lines = tgetstr ("AL", address);
2438 tty->TS_bell = tgetstr ("bl", address);
6548cf00 2439 BackTab (tty) = tgetstr ("bt", address);
fca177d4
KL
2440 tty->TS_clr_to_bottom = tgetstr ("cd", address);
2441 tty->TS_clr_line = tgetstr ("ce", address);
2442 tty->TS_clr_frame = tgetstr ("cl", address);
6548cf00
KL
2443 ColPosition (tty) = NULL; /* tgetstr ("ch", address); */
2444 AbsPosition (tty) = tgetstr ("cm", address);
2445 CR (tty) = tgetstr ("cr", address);
fca177d4
KL
2446 tty->TS_set_scroll_region = tgetstr ("cs", address);
2447 tty->TS_set_scroll_region_1 = tgetstr ("cS", address);
6548cf00 2448 RowPosition (tty) = tgetstr ("cv", address);
fca177d4
KL
2449 tty->TS_del_char = tgetstr ("dc", address);
2450 tty->TS_del_multi_chars = tgetstr ("DC", address);
2451 tty->TS_del_line = tgetstr ("dl", address);
2452 tty->TS_del_multi_lines = tgetstr ("DL", address);
2453 tty->TS_delete_mode = tgetstr ("dm", address);
2454 tty->TS_end_delete_mode = tgetstr ("ed", address);
2455 tty->TS_end_insert_mode = tgetstr ("ei", address);
6548cf00 2456 Home (tty) = tgetstr ("ho", address);
fca177d4
KL
2457 tty->TS_ins_char = tgetstr ("ic", address);
2458 tty->TS_ins_multi_chars = tgetstr ("IC", address);
2459 tty->TS_insert_mode = tgetstr ("im", address);
2460 tty->TS_pad_inserted_char = tgetstr ("ip", address);
2461 tty->TS_end_keypad_mode = tgetstr ("ke", address);
2462 tty->TS_keypad_mode = tgetstr ("ks", address);
6548cf00
KL
2463 LastLine (tty) = tgetstr ("ll", address);
2464 Right (tty) = tgetstr ("nd", address);
2465 Down (tty) = tgetstr ("do", address);
2466 if (!Down (tty))
2467 Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do" */
08a24c47
JB
2468#ifdef VMS
2469 /* VMS puts a carriage return before each linefeed,
2470 so it is not safe to use linefeeds. */
6548cf00
KL
2471 if (Down (tty) && Down (tty)[0] == '\n' && Down (tty)[1] == '\0')
2472 Down (tty) = 0;
08a24c47
JB
2473#endif /* VMS */
2474 if (tgetflag ("bs"))
6548cf00 2475 Left (tty) = "\b"; /* can't possibly be longer! */
08a24c47 2476 else /* (Actually, "bs" is obsolete...) */
6548cf00
KL
2477 Left (tty) = tgetstr ("le", address);
2478 if (!Left (tty))
2479 Left (tty) = tgetstr ("bc", address); /* Obsolete name for "le" */
fca177d4
KL
2480 tty->TS_pad_char = tgetstr ("pc", address);
2481 tty->TS_repeat = tgetstr ("rp", address);
2482 tty->TS_end_standout_mode = tgetstr ("se", address);
2483 tty->TS_fwd_scroll = tgetstr ("sf", address);
2484 tty->TS_standout_mode = tgetstr ("so", address);
2485 tty->TS_rev_scroll = tgetstr ("sr", address);
6548cf00 2486 tty->Wcm->cm_tab = tgetstr ("ta", address);
fca177d4
KL
2487 tty->TS_end_termcap_modes = tgetstr ("te", address);
2488 tty->TS_termcap_modes = tgetstr ("ti", address);
6548cf00 2489 Up (tty) = tgetstr ("up", address);
fca177d4
KL
2490 tty->TS_visible_bell = tgetstr ("vb", address);
2491 tty->TS_cursor_normal = tgetstr ("ve", address);
2492 tty->TS_cursor_visible = tgetstr ("vs", address);
2493 tty->TS_cursor_invisible = tgetstr ("vi", address);
2494 tty->TS_set_window = tgetstr ("wi", address);
2495
2496 tty->TS_enter_underline_mode = tgetstr ("us", address);
2497 tty->TS_exit_underline_mode = tgetstr ("ue", address);
2498 tty->TS_enter_bold_mode = tgetstr ("md", address);
2499 tty->TS_enter_dim_mode = tgetstr ("mh", address);
2500 tty->TS_enter_blink_mode = tgetstr ("mb", address);
2501 tty->TS_enter_reverse_mode = tgetstr ("mr", address);
2502 tty->TS_enter_alt_charset_mode = tgetstr ("as", address);
2503 tty->TS_exit_alt_charset_mode = tgetstr ("ae", address);
2504 tty->TS_exit_attribute_mode = tgetstr ("me", address);
177c0ea7 2505
6548cf00
KL
2506 MultiUp (tty) = tgetstr ("UP", address);
2507 MultiDown (tty) = tgetstr ("DO", address);
2508 MultiLeft (tty) = tgetstr ("LE", address);
2509 MultiRight (tty) = tgetstr ("RI", address);
08a24c47 2510
e7f90eab
GM
2511 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
2512 color because we can't switch back to the default foreground and
2513 background. */
fca177d4
KL
2514 tty->TS_orig_pair = tgetstr ("op", address);
2515 if (tty->TS_orig_pair)
a168702a 2516 {
fca177d4
KL
2517 tty->TS_set_foreground = tgetstr ("AF", address);
2518 tty->TS_set_background = tgetstr ("AB", address);
2519 if (!tty->TS_set_foreground)
e7f90eab
GM
2520 {
2521 /* SVr4. */
fca177d4
KL
2522 tty->TS_set_foreground = tgetstr ("Sf", address);
2523 tty->TS_set_background = tgetstr ("Sb", address);
e7f90eab 2524 }
177c0ea7 2525
fca177d4
KL
2526 tty->TN_max_colors = tgetnum ("Co");
2527 tty->TN_max_pairs = tgetnum ("pa");
177c0ea7 2528
fca177d4
KL
2529 tty->TN_no_color_video = tgetnum ("NC");
2530 if (tty->TN_no_color_video == -1)
2531 tty->TN_no_color_video = 0;
a168702a 2532 }
a168702a 2533
fca177d4 2534 tty_default_color_capabilities (tty, 1);
ace28297 2535
6548cf00 2536 MagicWrap (tty) = tgetflag ("xn");
e4058338
KH
2537 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
2538 the former flag imply the latter. */
6548cf00 2539 AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
428a555e 2540 display->memory_below_frame = tgetflag ("db");
fca177d4 2541 tty->TF_hazeltine = tgetflag ("hz");
428a555e 2542 display->must_write_spaces = tgetflag ("in");
fca177d4
KL
2543 tty->meta_key = tgetflag ("km") || tgetflag ("MT");
2544 tty->TF_insmode_motion = tgetflag ("mi");
2545 tty->TF_standout_motion = tgetflag ("ms");
2546 tty->TF_underscore = tgetflag ("ul");
2547 tty->TF_teleray = tgetflag ("xt");
08a24c47 2548
5c2c7893
JB
2549 term_get_fkeys (address);
2550
ff11dfa1 2551 /* Get frame size from system, or else from termcap. */
3b12ce12
RS
2552 {
2553 int height, width;
16c290d8 2554 get_tty_size (fileno (TTY_INPUT (tty)), &width, &height);
0a125897
KL
2555 FrameCols (tty) = width;
2556 FrameRows (tty) = height;
3b12ce12
RS
2557 }
2558
0a125897
KL
2559 if (FrameCols (tty) <= 0)
2560 FrameCols (tty) = tgetnum ("co");
2561 if (FrameRows (tty) <= 0)
2562 FrameRows (tty) = tgetnum ("li");
177c0ea7 2563
0a125897 2564 if (FrameRows (tty) < 3 || FrameCols (tty) < 3)
3224dac1
KL
2565 maybe_fatal (must_succeed, NULL, display,
2566 "Screen size %dx%d is too small"
2567 "Screen size %dx%d is too small",
0a125897 2568 FrameCols (tty), FrameRows (tty));
ee7a2de4 2569
8a56675d 2570#if 0 /* This is not used anywhere. */
428a555e 2571 tty->display->min_padding_speed = tgetnum ("pb");
8a56675d 2572#endif
28d440ab 2573
6548cf00 2574 TabWidth (tty) = tgetnum ("tw");
08a24c47
JB
2575
2576#ifdef VMS
2577 /* These capabilities commonly use ^J.
2578 I don't know why, but sending them on VMS does not work;
2579 it causes following spaces to be lost, sometimes.
2580 For now, the simplest fix is to avoid using these capabilities ever. */
6548cf00
KL
2581 if (Down (tty) && Down (tty)[0] == '\n')
2582 Down (tty) = 0;
08a24c47
JB
2583#endif /* VMS */
2584
fca177d4
KL
2585 if (!tty->TS_bell)
2586 tty->TS_bell = "\07";
08a24c47 2587
fca177d4
KL
2588 if (!tty->TS_fwd_scroll)
2589 tty->TS_fwd_scroll = Down (tty);
08a24c47 2590
fca177d4 2591 PC = tty->TS_pad_char ? *tty->TS_pad_char : 0;
08a24c47 2592
6548cf00
KL
2593 if (TabWidth (tty) < 0)
2594 TabWidth (tty) = 8;
177c0ea7 2595
08a24c47
JB
2596/* Turned off since /etc/termcap seems to have :ta= for most terminals
2597 and newer termcap doc does not seem to say there is a default.
6548cf00
KL
2598 if (!tty->Wcm->cm_tab)
2599 tty->Wcm->cm_tab = "\t";
08a24c47
JB
2600*/
2601
54800acb
MB
2602 /* We don't support standout modes that use `magic cookies', so
2603 turn off any that do. */
fca177d4 2604 if (tty->TS_standout_mode && tgetnum ("sg") >= 0)
54800acb 2605 {
fca177d4
KL
2606 tty->TS_standout_mode = 0;
2607 tty->TS_end_standout_mode = 0;
54800acb 2608 }
fca177d4 2609 if (tty->TS_enter_underline_mode && tgetnum ("ug") >= 0)
54800acb 2610 {
fca177d4
KL
2611 tty->TS_enter_underline_mode = 0;
2612 tty->TS_exit_underline_mode = 0;
54800acb
MB
2613 }
2614
2615 /* If there's no standout mode, try to use underlining instead. */
fca177d4 2616 if (tty->TS_standout_mode == 0)
08a24c47 2617 {
fca177d4
KL
2618 tty->TS_standout_mode = tty->TS_enter_underline_mode;
2619 tty->TS_end_standout_mode = tty->TS_exit_underline_mode;
08a24c47
JB
2620 }
2621
afd359c4
RS
2622 /* If no `se' string, try using a `me' string instead.
2623 If that fails, we can't use standout mode at all. */
fca177d4 2624 if (tty->TS_end_standout_mode == 0)
afd359c4 2625 {
e4bfb3b6 2626 char *s = tgetstr ("me", address);
afd359c4 2627 if (s != 0)
fca177d4 2628 tty->TS_end_standout_mode = s;
afd359c4 2629 else
fca177d4 2630 tty->TS_standout_mode = 0;
afd359c4
RS
2631 }
2632
fca177d4 2633 if (tty->TF_teleray)
08a24c47 2634 {
6548cf00 2635 tty->Wcm->cm_tab = 0;
54800acb 2636 /* We can't support standout mode, because it uses magic cookies. */
fca177d4 2637 tty->TS_standout_mode = 0;
08a24c47 2638 /* But that means we cannot rely on ^M to go to column zero! */
6548cf00 2639 CR (tty) = 0;
08a24c47
JB
2640 /* LF can't be trusted either -- can alter hpos */
2641 /* if move at column 0 thru a line with TS_standout_mode */
6548cf00 2642 Down (tty) = 0;
08a24c47
JB
2643 }
2644
2645 /* Special handling for certain terminal types known to need it */
2646
2647 if (!strcmp (terminal_type, "supdup"))
2648 {
428a555e 2649 display->memory_below_frame = 1;
6548cf00 2650 tty->Wcm->cm_losewrap = 1;
08a24c47
JB
2651 }
2652 if (!strncmp (terminal_type, "c10", 3)
2653 || !strcmp (terminal_type, "perq"))
2654 {
2655 /* Supply a makeshift :wi string.
2656 This string is not valid in general since it works only
2657 for windows starting at the upper left corner;
2658 but that is all Emacs uses.
daf01701 2659
ff11dfa1 2660 This string works only if the frame is using
08a24c47
JB
2661 the top of the video memory, because addressing is memory-relative.
2662 So first check the :ti string to see if that is true.
2663
2664 It would be simpler if the :wi string could go in the termcap
2665 entry, but it can't because it is not fully valid.
2666 If it were in the termcap entry, it would confuse other programs. */
fca177d4 2667 if (!tty->TS_set_window)
08a24c47 2668 {
fca177d4 2669 p = tty->TS_termcap_modes;
08a24c47
JB
2670 while (*p && strcmp (p, "\033v "))
2671 p++;
2672 if (*p)
fca177d4 2673 tty->TS_set_window = "\033v%C %C %C %C ";
08a24c47
JB
2674 }
2675 /* Termcap entry often fails to have :in: flag */
428a555e 2676 display->must_write_spaces = 1;
08a24c47
JB
2677 /* :ti string typically fails to have \E^G! in it */
2678 /* This limits scope of insert-char to one line. */
fca177d4 2679 strcpy (area, tty->TS_termcap_modes);
08a24c47 2680 strcat (area, "\033\007!");
fca177d4 2681 tty->TS_termcap_modes = area;
08a24c47 2682 area += strlen (area) + 1;
6548cf00 2683 p = AbsPosition (tty);
08a24c47 2684 /* Change all %+ parameters to %C, to handle
28d440ab 2685 values above 96 correctly for the C100. */
08a24c47 2686 while (*p)
28d440ab
KL
2687 {
2688 if (p[0] == '%' && p[1] == '+')
2689 p[1] = 'C';
2690 p++;
2691 }
08a24c47
JB
2692 }
2693
0a125897 2694 tty->specified_window = FrameRows (tty);
08a24c47 2695
6548cf00 2696 if (Wcm_init (tty) == -1) /* can't do cursor motion */
3224dac1
KL
2697 {
2698 maybe_fatal (must_succeed, NULL, display,
2699 "Terminal type \"%s\" is not powerful enough to run Emacs",
08a24c47 2700#ifdef VMS
3224dac1 2701 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
08a24c47
JB
2702It lacks the ability to position the cursor.\n\
2703If that is not the actual type of terminal you have, use either the\n\
2704DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
e12c1054 2705or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
37dad45a
RS
2706#else /* not VMS */
2707# ifdef TERMINFO
3224dac1 2708 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
0a125897
KL
2709It lacks the ability to position the cursor.\n\
2710If that is not the actual type of terminal you have,\n\
37dad45a
RS
2711use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2712`setenv TERM ...') to specify the correct type. It may be necessary\n\
e12c1054 2713to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
37dad45a 2714# else /* TERMCAP */
3224dac1 2715 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
0a125897 2716It lacks the ability to position the cursor.\n\
08a24c47 2717If that is not the actual type of terminal you have,\n\
c5a9c3e6
RS
2718use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2719`setenv TERM ...') to specify the correct type. It may be necessary\n\
e12c1054 2720to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
37dad45a
RS
2721# endif /* TERMINFO */
2722#endif /*VMS */
3224dac1 2723 terminal_type);
fca177d4 2724 }
daf01701 2725
0a125897 2726 if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
3224dac1
KL
2727 maybe_fatal (must_succeed, NULL, display,
2728 "Could not determine the frame size",
2729 "Could not determine the frame size");
08a24c47 2730
fca177d4
KL
2731 tty->delete_in_insert_mode
2732 = tty->TS_delete_mode && tty->TS_insert_mode
2733 && !strcmp (tty->TS_delete_mode, tty->TS_insert_mode);
08a24c47 2734
fca177d4
KL
2735 tty->se_is_so = (tty->TS_standout_mode
2736 && tty->TS_end_standout_mode
2737 && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode));
08a24c47 2738
16c290d8 2739 UseTabs (tty) = tabs_safe_p (fileno (TTY_INPUT (tty))) && TabWidth (tty) == 8;
08a24c47 2740
428a555e 2741 display->scroll_region_ok
6548cf00 2742 = (tty->Wcm->cm_abs
fca177d4 2743 && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
08a24c47 2744
428a555e 2745 display->line_ins_del_ok
fca177d4
KL
2746 = (((tty->TS_ins_line || tty->TS_ins_multi_lines)
2747 && (tty->TS_del_line || tty->TS_del_multi_lines))
428a555e 2748 || (display->scroll_region_ok
fca177d4 2749 && tty->TS_fwd_scroll && tty->TS_rev_scroll));
28d440ab 2750
428a555e 2751 display->char_ins_del_ok
fca177d4
KL
2752 = ((tty->TS_ins_char || tty->TS_insert_mode
2753 || tty->TS_pad_inserted_char || tty->TS_ins_multi_chars)
2754 && (tty->TS_del_char || tty->TS_del_multi_chars));
8a56675d 2755
428a555e 2756 display->fast_clear_end_of_line = tty->TS_clr_line != 0;
08a24c47 2757
16c290d8 2758 init_baud_rate (fileno (TTY_INPUT (tty)));
20a558dc 2759
daf01701
KL
2760#ifdef AIXHFT
2761 /* The HFT system on AIX doesn't optimize for scrolling, so it's
2762 really ugly at times. */
428a555e
KL
2763 display->line_ins_del_ok = 0;
2764 display->char_ins_del_ok = 0;
daf01701
KL
2765#endif
2766
7b00d185
KL
2767#ifdef MULTI_KBOARD
2768 tty->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
2769 init_kboard (tty->kboard);
2770 tty->kboard->next_kboard = all_kboards;
2771 all_kboards = tty->kboard;
2772 /* Don't let the initial kboard remain current longer than necessary.
2773 That would cause problems if a file loaded on startup tries to
2774 prompt in the mini-buffer. */
2775 if (current_kboard == initial_kboard)
2776 current_kboard = tty->kboard;
2777 tty->kboard->reference_count++;
2778#endif
2779
0a125897
KL
2780 /* Don't do this. I think termcap may still need the buffer. */
2781 /* xfree (buffer); */
28d440ab 2782
0a125897
KL
2783 /* Init system terminal modes (RAW or CBREAK, etc.). */
2784 init_sys_modes (tty);
daf01701 2785
428a555e 2786 return display;
7b00d185 2787#endif /* not WINDOWSNT */
08a24c47
JB
2788}
2789
3224dac1
KL
2790/* Auxiliary error-handling function for term_init.
2791 Free BUFFER and delete DISPLAY, then call error or fatal
da8e1115
KL
2792 with str1 or str2, respectively, according to MUST_SUCCEED. */
2793
3224dac1
KL
2794static void
2795maybe_fatal (must_succeed, buffer, display, str1, str2, arg1, arg2)
2796 int must_succeed;
2797 char *buffer;
2798 struct display *display;
2799 char *str1, *str2, *arg1, *arg2;
2800{
2801 if (buffer)
2802 xfree (buffer);
2803
2804 if (display)
2805 delete_tty (display);
2806
2807 if (must_succeed)
2808 fatal (str2, arg1, arg2);
2809 else
2810 error (str1, arg1, arg2);
2811
2812 abort ();
2813}
2814
08a24c47 2815/* VARARGS 1 */
dfcf069d 2816void
08a24c47 2817fatal (str, arg1, arg2)
4746118a 2818 char *str, *arg1, *arg2;
08a24c47
JB
2819{
2820 fprintf (stderr, "emacs: ");
2821 fprintf (stderr, str, arg1, arg2);
e12c1054 2822 fprintf (stderr, "\n");
08a24c47
JB
2823 fflush (stderr);
2824 exit (1);
2825}
07c57952 2826
819b8f00
KL
2827\f
2828
2829DEFUN ("delete-tty", Fdelete_tty, Sdelete_tty, 0, 1, 0,
4d553a13
KL
2830 doc: /* Delete all frames on the terminal named TTY, and close the device.
2831If omitted, TTY defaults to the controlling terminal.
2832
2833This function runs `delete-tty-after-functions' after closing the
2834tty. The functions are run with one arg, the frame to be deleted. */)
819b8f00
KL
2835 (tty)
2836 Lisp_Object tty;
07c57952 2837{
428a555e 2838 struct display *d;
819b8f00 2839 char *name = 0;
c291d9ef 2840
819b8f00 2841 CHECK_STRING (tty);
daf01701 2842
819b8f00
KL
2843 if (SBYTES (tty) > 0)
2844 {
2845 name = (char *) alloca (SBYTES (tty) + 1);
2846 strncpy (name, SDATA (tty), SBYTES (tty));
2847 name[SBYTES (tty)] = 0;
2848 }
a168702a 2849
428a555e 2850 d = get_named_tty_display (name);
6548cf00 2851
428a555e
KL
2852 if (! d)
2853 error ("No such terminal device: %s", name);
daf01701 2854
428a555e 2855 delete_tty (d);
0c72d684
KL
2856
2857 return Qnil;
07c57952 2858}
a168702a 2859
0a125897
KL
2860static int deleting_tty = 0;
2861
da8e1115
KL
2862
2863/* Delete the given terminal device, closing all frames on it. */
2864
fca177d4 2865void
428a555e 2866delete_tty (struct display *display)
fca177d4 2867{
428a555e 2868 struct tty_display_info *tty;
fca177d4 2869 Lisp_Object tail, frame;
4d553a13
KL
2870 char *tty_name;
2871
0a125897
KL
2872 if (deleting_tty)
2873 /* We get a recursive call when we delete the last frame on this
428a555e 2874 display. */
0a125897 2875 return;
fca177d4 2876
0a125897 2877 deleting_tty = 1;
daf01701 2878
428a555e
KL
2879 if (display->type != output_termcap)
2880 abort ();
2881
2882 tty = display->display_info.tty;
2883
fca177d4
KL
2884 if (tty == tty_list)
2885 tty_list = tty->next;
2886 else
2887 {
28d7d09f 2888 struct tty_display_info *p;
fca177d4
KL
2889 for (p = tty_list; p && p->next != tty; p = p->next)
2890 ;
2891
2892 if (! p)
2893 /* This should not happen. */
2894 abort ();
2895
0a125897
KL
2896 p->next = tty->next;
2897 tty->next = 0;
fca177d4
KL
2898 }
2899
04c3243c
KL
2900 FOR_EACH_FRAME (tail, frame)
2901 {
2902 struct frame *f = XFRAME (frame);
daf01701 2903 if (FRAME_TERMCAP_P (f) && FRAME_LIVE_P (f) && FRAME_TTY (f) == tty)
04c3243c
KL
2904 {
2905 Fdelete_frame (frame, Qt);
04c3243c
KL
2906 }
2907 }
daf01701 2908
3224dac1
KL
2909 /* reset_sys_modes needs a valid display, so this call needs to be
2910 before delete_display. */
04c3243c 2911 reset_sys_modes (tty);
fca177d4 2912
3224dac1
KL
2913 delete_display (display);
2914
4d553a13 2915 tty_name = tty->name;
fca177d4
KL
2916 if (tty->type)
2917 xfree (tty->type);
daf01701 2918
fca177d4 2919 if (tty->input)
819b8f00
KL
2920 {
2921 delete_keyboard_wait_descriptor (fileno (tty->input));
2922 if (tty->input != stdin)
2923 fclose (tty->input);
2924 }
2925 if (tty->output && tty->output != stdout && tty->output != tty->input)
fca177d4
KL
2926 fclose (tty->output);
2927 if (tty->termscript)
2928 fclose (tty->termscript);
daf01701 2929
fca177d4 2930 if (tty->old_tty)
0a125897 2931 xfree (tty->old_tty);
fca177d4 2932
0a125897 2933 if (tty->Wcm)
daf01701
KL
2934 xfree (tty->Wcm);
2935
7b00d185
KL
2936#ifdef MULTI_KBOARD
2937 if (tty->kboard && --tty->kboard->reference_count > 0)
2938 abort ();
2939 if (tty->kboard)
2940 delete_kboard (tty->kboard);
2941#endif
2942
28d7d09f 2943 bzero (tty, sizeof (struct tty_display_info));
fca177d4 2944 xfree (tty);
0a125897 2945 deleting_tty = 0;
4d553a13
KL
2946
2947 /* Run `delete-tty-after-functions'. */
2948 if (!NILP (Vrun_hooks))
2949 {
2950 Lisp_Object args[2];
2951 args[0] = intern ("delete-tty-after-functions");
2952 if (tty_name)
2953 {
2954 args[1] = build_string (tty_name);
2955 xfree (tty_name);
2956 }
2957 else
2958 args[1] = Qnil;
2959 Frun_hook_with_args (2, args);
2960 }
fca177d4
KL
2961}
2962
428a555e
KL
2963\f
2964
2965/* Initialize the tty-dependent part of frame F. The frame must
2966 already have its display initialized. */
da8e1115 2967
428a555e
KL
2968void
2969create_tty_output (struct frame *f)
2970{
e9cda827
KL
2971 struct tty_output *t;
2972
428a555e
KL
2973 if (! FRAME_TERMCAP_P (f))
2974 abort ();
2975
e9cda827 2976 t = xmalloc (sizeof (struct tty_output));
428a555e
KL
2977 bzero (t, sizeof (struct tty_output));
2978
2979 t->display_info = FRAME_DISPLAY (f)->display_info.tty;
2980
2981 f->output_data.tty = t;
2982}
2983
2984/* Delete the tty-dependent part of frame F. */
da8e1115 2985
428a555e
KL
2986void
2987delete_tty_output (struct frame *f)
2988{
2989 if (! FRAME_TERMCAP_P (f))
2990 abort ();
2991
2992 xfree (f->output_data.tty);
2993}
2994
fca177d4 2995
819b8f00 2996\f
28d440ab 2997
28d7d09f 2998/* Mark the pointers in the tty_display_info objects.
819b8f00 2999 Called by the Fgarbage_collector. */
da8e1115 3000
fca177d4 3001void
819b8f00 3002mark_ttys ()
fca177d4 3003{
28d7d09f 3004 struct tty_display_info *tty;
0c72d684 3005
819b8f00 3006 for (tty = tty_list; tty; tty = tty->next)
fca177d4 3007 {
819b8f00
KL
3008 if (tty->top_frame)
3009 mark_object (tty->top_frame);
fca177d4
KL
3010 }
3011}
3012
428a555e
KL
3013\f
3014
3015/* Create a new display object and add it to the display list. */
da8e1115 3016
428a555e
KL
3017struct display *
3018create_display (void)
3019{
3020 struct display *dev = (struct display *) xmalloc (sizeof (struct display));
3021
3022 bzero (dev, sizeof (struct display));
3023 dev->next_display = display_list;
3024 display_list = dev;
3025
3026 return dev;
3027}
3028
3029/* Remove a display from the display list and free its memory. */
da8e1115 3030
428a555e
KL
3031void
3032delete_display (struct display *dev)
3033{
3034 struct display **dp;
d448e982
KL
3035 Lisp_Object tail, frame;
3036
3037 /* Check for and close live frames that are still on this
3038 display. */
3039 FOR_EACH_FRAME (tail, frame)
3040 {
3041 struct frame *f = XFRAME (frame);
3042 if (FRAME_LIVE_P (f) && f->display == dev)
3043 {
3044 Fdelete_frame (frame, Qt);
3045 }
3046 }
3047
428a555e
KL
3048 for (dp = &display_list; *dp != dev; dp = &(*dp)->next_display)
3049 if (! *dp)
3050 abort ();
3051 *dp = dev->next_display;
3052
3053 bzero (dev, sizeof (struct display));
3054 xfree (dev);
3055}
3056
28d440ab 3057
819b8f00
KL
3058\f
3059void
3060syms_of_term ()
3061{
3062 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
3063 doc: /* Non-nil means the system uses terminfo rather than termcap.
3064This variable can be used by terminal emulator packages. */);
3065#ifdef TERMINFO
3066 system_uses_terminfo = 1;
3067#else
3068 system_uses_terminfo = 0;
3069#endif
3070
3071 DEFVAR_LISP ("ring-bell-function", &Vring_bell_function,
3072 doc: /* Non-nil means call this function to ring the bell.
3073The function should accept no arguments. */);
3074 Vring_bell_function = Qnil;
3075
4d553a13
KL
3076 DEFVAR_LISP ("delete-tty-after-functions", &Vdelete_tty_after_functions,
3077 doc: /* Functions to be run after deleting a tty.
3078The functions are run with one argument, the name of the tty to be deleted.
3079See `delete-tty'. */);
3080 Vdelete_tty_after_functions = Qnil;
3081
819b8f00
KL
3082 Qframe_tty_name = intern ("frame-tty-name");
3083 staticpro (&Qframe_tty_name);
3084
3085 Qframe_tty_type = intern ("frame-tty-type");
3086 staticpro (&Qframe_tty_type);
3087
3088 defsubr (&Stty_display_color_p);
3089 defsubr (&Stty_display_color_cells);
3090 defsubr (&Sframe_tty_name);
3091 defsubr (&Sframe_tty_type);
3092 defsubr (&Sdelete_tty);
daf01701 3093
819b8f00 3094 Fprovide (intern ("multi-tty"), Qnil);
7b00d185 3095
819b8f00
KL
3096}
3097
3098
3099
ab5796a9
MB
3100/* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193
3101 (do not change this comment) */