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