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