1/* Terminal control module for terminals described by TERMCAP
2   Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1998, 2000, 2001,
3                 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
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
9the Free Software Foundation; either version 2, or (at your option)
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
19the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20Boston, MA 02110-1301, USA.  */
21
22/* New redisplay, TTY faces by Gerd Moellmann <gerd@gnu.org>.  */
23
24#include <config.h>
25#include <stdio.h>
26#include <ctype.h>
27#include <string.h>
28
29#include "termchar.h"
30#include "termopts.h"
31#include "lisp.h"
32#include "charset.h"
33#include "coding.h"
34#include "keyboard.h"
35#include "frame.h"
36#include "disptab.h"
37#include "termhooks.h"
38#include "dispextern.h"
39#include "window.h"
40#include "keymap.h"
41#include "blockinput.h"
42
43/* For now, don't try to include termcap.h.  On some systems,
44   configure finds a non-standard termcap.h that the main build
45   won't find.  */
46
47#if defined HAVE_TERMCAP_H && 0
48#include <termcap.h>
49#else
50extern void tputs P_ ((const char *, int, int (*)(int)));
51extern int tgetent P_ ((char *, const char *));
52extern int tgetflag P_ ((char *id));
53extern int tgetnum P_ ((char *id));
54#endif
55
56#include "cm.h"
57#ifdef HAVE_X_WINDOWS
58#include "xterm.h"
59#endif
60#ifdef MAC_OS
61#include "macterm.h"
62#endif
63
64static void turn_on_face P_ ((struct frame *, int face_id));
65static void turn_off_face P_ ((struct frame *, int face_id));
66static void tty_show_cursor P_ ((void));
67static void tty_hide_cursor P_ ((void));
68
69#define OUTPUT(a) \
70     tputs (a, (int) (FRAME_LINES (XFRAME (selected_frame)) - curY), cmputc)
71#define OUTPUT1(a) tputs (a, 1, cmputc)
72#define OUTPUTL(a, lines) tputs (a, lines, cmputc)
73
74#define OUTPUT_IF(a)							\
75     do {								\
76       if (a)								\
77         tputs (a, (int) (FRAME_LINES (XFRAME (selected_frame))	\
78			  - curY), cmputc);				\
79     } while (0)
80
81#define OUTPUT1_IF(a) do { if (a) tputs (a, 1, cmputc); } while (0)
82
83/* Display space properties */
84
85extern Lisp_Object Qspace, QCalign_to, QCwidth;
86
87/* Function to use to ring the bell.  */
88
89Lisp_Object Vring_bell_function;
90
91/* If true, use "vs", otherwise use "ve" to make the cursor visible.  */
92
93static int visible_cursor;
94
95/* Terminal characteristics that higher levels want to look at.
96   These are all extern'd in termchar.h */
97
98int must_write_spaces;		/* Nonzero means spaces in the text
99				   must actually be output; can't just skip
100				   over some columns to leave them blank.  */
101int min_padding_speed;		/* Speed below which no padding necessary */
102
103int line_ins_del_ok;		/* Terminal can insert and delete lines */
104int char_ins_del_ok;		/* Terminal can insert and delete chars */
105int scroll_region_ok;		/* Terminal supports setting the
106				   scroll window */
107int scroll_region_cost;		/* Cost of setting a scroll window,
108				   measured in characters */
109int memory_below_frame;		/* Terminal remembers lines
110				   scrolled off bottom */
111int fast_clear_end_of_line;	/* Terminal has a `ce' string */
112
113/* Nonzero means no need to redraw the entire frame on resuming
114   a suspended Emacs.  This is useful on terminals with multiple pages,
115   where one page is used for Emacs and another for all else. */
116
117int no_redraw_on_reenter;
118
119/* Hook functions that you can set to snap out the functions in this file.
120   These are all extern'd in termhooks.h  */
121
122void (*cursor_to_hook) P_ ((int, int));
123void (*raw_cursor_to_hook) P_ ((int, int));
124void (*clear_to_end_hook) P_ ((void));
125void (*clear_frame_hook) P_ ((void));
126void (*clear_end_of_line_hook) P_ ((int));
127
128void (*ins_del_lines_hook) P_ ((int, int));
129
130void (*delete_glyphs_hook) P_ ((int));
131
132void (*ring_bell_hook) P_ ((void));
133
134void (*reset_terminal_modes_hook) P_ ((void));
135void (*set_terminal_modes_hook) P_ ((void));
136void (*update_begin_hook) P_ ((struct frame *));
137void (*update_end_hook) P_ ((struct frame *));
138void (*set_terminal_window_hook) P_ ((int));
139void (*insert_glyphs_hook) P_ ((struct glyph *, int));
140void (*write_glyphs_hook) P_ ((struct glyph *, int));
141void (*delete_glyphs_hook) P_ ((int));
142
143int (*read_socket_hook) P_ ((int, int, struct input_event *));
144
145void (*frame_up_to_date_hook) P_ ((struct frame *));
146
147/* Return the current position of the mouse.
148
149   Set *f to the frame the mouse is in, or zero if the mouse is in no
150   Emacs frame.  If it is set to zero, all the other arguments are
151   garbage.
152
153   If the motion started in a scroll bar, set *bar_window to the
154   scroll bar's window, *part to the part the mouse is currently over,
155   *x to the position of the mouse along the scroll bar, and *y to the
156   overall length of the scroll bar.
157
158   Otherwise, set *bar_window to Qnil, and *x and *y to the column and
159   row of the character cell the mouse is over.
160
161   Set *time to the time the mouse was at the returned position.
162
163   This should clear mouse_moved until the next motion
164   event arrives.  */
165
166void (*mouse_position_hook) P_ ((FRAME_PTR *f, int insist,
167				 Lisp_Object *bar_window,
168				 enum scroll_bar_part *part,
169				 Lisp_Object *x,
170				 Lisp_Object *y,
171				 unsigned long *time));
172
173/* When reading from a minibuffer in a different frame, Emacs wants
174   to shift the highlight from the selected frame to the mini-buffer's
175   frame; under X, this means it lies about where the focus is.
176   This hook tells the window system code to re-decide where to put
177   the highlight.  */
178
179void (*frame_rehighlight_hook) P_ ((FRAME_PTR f));
180
181/* If we're displaying frames using a window system that can stack
182   frames on top of each other, this hook allows you to bring a frame
183   to the front, or bury it behind all the other windows.  If this
184   hook is zero, that means the device we're displaying on doesn't
185   support overlapping frames, so there's no need to raise or lower
186   anything.
187
188   If RAISE is non-zero, F is brought to the front, before all other
189   windows.  If RAISE is zero, F is sent to the back, behind all other
190   windows.  */
191
192void (*frame_raise_lower_hook) P_ ((FRAME_PTR f, int raise));
193
194/* If the value of the frame parameter changed, whis hook is called.
195   For example, if going from fullscreen to not fullscreen this hook
196   may do something OS dependent, like extended window manager hints on X11.  */
197void (*fullscreen_hook) P_ ((struct frame *f));
198
199/* Set the vertical scroll bar for WINDOW to have its upper left corner
200   at (TOP, LEFT), and be LENGTH rows high.  Set its handle to
201   indicate that we are displaying PORTION characters out of a total
202   of WHOLE characters, starting at POSITION.  If WINDOW doesn't yet
203   have a scroll bar, create one for it.  */
204
205void (*set_vertical_scroll_bar_hook)
206     P_ ((struct window *window,
207	  int portion, int whole, int position));
208
209
210/* The following three hooks are used when we're doing a thorough
211   redisplay of the frame.  We don't explicitly know which scroll bars
212   are going to be deleted, because keeping track of when windows go
213   away is a real pain - can you say set-window-configuration?
214   Instead, we just assert at the beginning of redisplay that *all*
215   scroll bars are to be removed, and then save scroll bars from the
216   fiery pit when we actually redisplay their window.  */
217
218/* Arrange for all scroll bars on FRAME to be removed at the next call
219   to `*judge_scroll_bars_hook'.  A scroll bar may be spared if
220   `*redeem_scroll_bar_hook' is applied to its window before the judgment.
221
222   This should be applied to each frame each time its window tree is
223   redisplayed, even if it is not displaying scroll bars at the moment;
224   if the HAS_SCROLL_BARS flag has just been turned off, only calling
225   this and the judge_scroll_bars_hook will get rid of them.
226
227   If non-zero, this hook should be safe to apply to any frame,
228   whether or not it can support scroll bars, and whether or not it is
229   currently displaying them.  */
230
231void (*condemn_scroll_bars_hook) P_ ((FRAME_PTR frame));
232
233/* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
234   Note that it's okay to redeem a scroll bar that is not condemned.  */
235
236void (*redeem_scroll_bar_hook) P_ ((struct window *window));
237
238/* Remove all scroll bars on FRAME that haven't been saved since the
239   last call to `*condemn_scroll_bars_hook'.
240
241   This should be applied to each frame after each time its window
242   tree is redisplayed, even if it is not displaying scroll bars at the
243   moment; if the HAS_SCROLL_BARS flag has just been turned off, only
244   calling this and condemn_scroll_bars_hook will get rid of them.
245
246   If non-zero, this hook should be safe to apply to any frame,
247   whether or not it can support scroll bars, and whether or not it is
248   currently displaying them.  */
249
250void (*judge_scroll_bars_hook) P_ ((FRAME_PTR FRAME));
251
252/* Strings, numbers and flags taken from the termcap entry.  */
253
254char *TS_ins_line;		/* "al" */
255char *TS_ins_multi_lines;	/* "AL" (one parameter, # lines to insert) */
256char *TS_bell;			/* "bl" */
257char *TS_clr_to_bottom;		/* "cd" */
258char *TS_clr_line;		/* "ce", clear to end of line */
259char *TS_clr_frame;		/* "cl" */
260char *TS_set_scroll_region;	/* "cs" (2 params, first line and last line) */
261char *TS_set_scroll_region_1;   /* "cS" (4 params: total lines,
262				   lines above scroll region, lines below it,
263				   total lines again) */
264char *TS_del_char;		/* "dc" */
265char *TS_del_multi_chars;	/* "DC" (one parameter, # chars to delete) */
266char *TS_del_line;		/* "dl" */
267char *TS_del_multi_lines;	/* "DL" (one parameter, # lines to delete) */
268char *TS_delete_mode;		/* "dm", enter character-delete mode */
269char *TS_end_delete_mode;	/* "ed", leave character-delete mode */
270char *TS_end_insert_mode;	/* "ei", leave character-insert mode */
271char *TS_ins_char;		/* "ic" */
272char *TS_ins_multi_chars;	/* "IC" (one parameter, # chars to insert) */
273char *TS_insert_mode;		/* "im", enter character-insert mode */
274char *TS_pad_inserted_char;	/* "ip".  Just padding, no commands.  */
275char *TS_end_keypad_mode;	/* "ke" */
276char *TS_keypad_mode;		/* "ks" */
277char *TS_pad_char;		/* "pc", char to use as padding */
278char *TS_repeat;		/* "rp" (2 params, # times to repeat
279				   and character to be repeated) */
280char *TS_end_standout_mode;	/* "se" */
281char *TS_fwd_scroll;		/* "sf" */
282char *TS_standout_mode;		/* "so" */
283char *TS_rev_scroll;		/* "sr" */
284char *TS_end_termcap_modes;	/* "te" */
285char *TS_termcap_modes;		/* "ti" */
286char *TS_visible_bell;		/* "vb" */
287char *TS_cursor_normal;		/* "ve" */
288char *TS_cursor_visible;	/* "vs" */
289char *TS_cursor_invisible;	/* "vi" */
290char *TS_set_window;		/* "wi" (4 params, start and end of window,
291				   each as vpos and hpos) */
292
293/* Value of the "NC" (no_color_video) capability, or 0 if not
294   present.  */
295
296static int TN_no_color_video;
297
298/* Meaning of bits in no_color_video.  Each bit set means that the
299   corresponding attribute cannot be combined with colors.  */
300
301enum no_color_bit
302{
303  NC_STANDOUT	 = 1 << 0,
304  NC_UNDERLINE	 = 1 << 1,
305  NC_REVERSE	 = 1 << 2,
306  NC_BLINK	 = 1 << 3,
307  NC_DIM	 = 1 << 4,
308  NC_BOLD	 = 1 << 5,
309  NC_INVIS	 = 1 << 6,
310  NC_PROTECT	 = 1 << 7,
311  NC_ALT_CHARSET = 1 << 8
312};
313
314/* "md" -- turn on bold (extra bright mode).  */
315
316char *TS_enter_bold_mode;
317
318/* "mh" -- turn on half-bright mode.  */
319
320char *TS_enter_dim_mode;
321
322/* "mb" -- enter blinking mode.  */
323
324char *TS_enter_blink_mode;
325
326/* "mr" -- enter reverse video mode.  */
327
328char *TS_enter_reverse_mode;
329
330/* "us"/"ue" -- start/end underlining.  */
331
332char *TS_exit_underline_mode, *TS_enter_underline_mode;
333
334/* "as"/"ae" -- start/end alternate character set.  Not really
335   supported, yet.  */
336
337char *TS_enter_alt_charset_mode, *TS_exit_alt_charset_mode;
338
339/* "me" -- switch appearances off.  */
340
341char *TS_exit_attribute_mode;
342
343/* "Co" -- number of colors.  */
344
345int TN_max_colors;
346
347/* "pa" -- max. number of color pairs on screen.  Not handled yet.
348   Could be a problem if not equal to TN_max_colors * TN_max_colors.  */
349
350int TN_max_pairs;
351
352/* "op" -- SVr4 set default pair to its original value.  */
353
354char *TS_orig_pair;
355
356/* "AF"/"AB" or "Sf"/"Sb"-- set ANSI or SVr4 foreground/background color.
357   1 param, the color index.  */
358
359char *TS_set_foreground, *TS_set_background;
360
361int TF_hazeltine;	/* termcap hz flag. */
362int TF_insmode_motion;	/* termcap mi flag: can move while in insert mode. */
363int TF_standout_motion;	/* termcap mi flag: can move while in standout mode. */
364int TF_underscore;	/* termcap ul flag: _ underlines if over-struck on
365			   non-blank position.  Must clear before writing _.  */
366int TF_teleray;		/* termcap xt flag: many weird consequences.
367			   For t1061. */
368
369static int RPov;	/* # chars to start a TS_repeat */
370
371static int delete_in_insert_mode;	/* delete mode == insert mode */
372
373static int se_is_so;	/* 1 if same string both enters and leaves
374			   standout mode */
375
376/* internal state */
377
378/* The largest frame width in any call to calculate_costs.  */
379
380int max_frame_cols;
381
382/* The largest frame height in any call to calculate_costs.  */
383
384int max_frame_lines;
385
386static int costs_set;	  /* Nonzero if costs have been calculated. */
387
388int insert_mode;			/* Nonzero when in insert mode.  */
389int standout_mode;			/* Nonzero when in standout mode.  */
390
391/* Size of window specified by higher levels.
392   This is the number of lines, from the top of frame downwards,
393   which can participate in insert-line/delete-line operations.
394
395   Effectively it excludes the bottom frame_lines - specified_window_size
396   lines from those operations.  */
397
398int specified_window;
399
400/* Frame currently being redisplayed; 0 if not currently redisplaying.
401   (Direct output does not count).  */
402
403FRAME_PTR updating_frame;
404
405/* Provided for lisp packages.  */
406
407static int system_uses_terminfo;
408
409/* Flag used in tty_show/hide_cursor.  */
410
411static int tty_cursor_hidden;
412
413char *tparam ();
414
415extern char *tgetstr ();
416
417
418#ifdef WINDOWSNT
419/* We aren't X windows, but we aren't termcap either.  This makes me
420   uncertain as to what value to use for frame.output_method.  For
421   this file, we'll define FRAME_TERMCAP_P to be zero so that our
422   output hooks get called instead of the termcap functions.  Probably
423   the best long-term solution is to define an output_windows_nt...  */
424
425#undef FRAME_TERMCAP_P
426#define FRAME_TERMCAP_P(_f_) 0
427#endif /* WINDOWSNT */
428
429void
430ring_bell ()
431{
432  if (!NILP (Vring_bell_function))
433    {
434      Lisp_Object function;
435
436      /* Temporarily set the global variable to nil
437	 so that if we get an error, it stays nil
438	 and we don't call it over and over.
439
440	 We don't specbind it, because that would carefully
441	 restore the bad value if there's an error
442	 and make the loop of errors happen anyway.  */
443
444      function = Vring_bell_function;
445      Vring_bell_function = Qnil;
446
447      call0 (function);
448
449      Vring_bell_function = function;
450    }
451  else if (!FRAME_TERMCAP_P (XFRAME (selected_frame)))
452    (*ring_bell_hook) ();
453  else
454    OUTPUT (TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell);
455}
456
457void
458set_terminal_modes ()
459{
460  if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
461    {
462      if (TS_termcap_modes)
463	OUTPUT (TS_termcap_modes);
464      else
465	{
466	  /* Output enough newlines to scroll all the old screen contents
467	     off the screen, so it won't be overwritten and lost.  */
468	  int i;
469	  for (i = 0; i < FRAME_LINES (XFRAME (selected_frame)); i++)
470	    putchar ('\n');
471	}
472
473      OUTPUT_IF (visible_cursor ? TS_cursor_visible : TS_cursor_normal);
474      OUTPUT_IF (TS_keypad_mode);
475      losecursor ();
476    }
477  else
478    (*set_terminal_modes_hook) ();
479}
480
481void
482reset_terminal_modes ()
483{
484  if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
485    {
486      turn_off_highlight ();
487      turn_off_insert ();
488      OUTPUT_IF (TS_end_keypad_mode);
489      OUTPUT_IF (TS_cursor_normal);
490      OUTPUT_IF (TS_end_termcap_modes);
491      OUTPUT_IF (TS_orig_pair);
492      /* Output raw CR so kernel can track the cursor hpos.  */
493      cmputc ('\r');
494    }
495  else if (reset_terminal_modes_hook)
496    (*reset_terminal_modes_hook) ();
497}
498
499void
500update_begin (f)
501     struct frame *f;
502{
503  updating_frame = f;
504  if (!FRAME_TERMCAP_P (f))
505    update_begin_hook (f);
506}
507
508void
509update_end (f)
510     struct frame *f;
511{
512  if (FRAME_TERMCAP_P (f))
513    {
514      if (!XWINDOW (selected_window)->cursor_off_p)
515	tty_show_cursor ();
516      turn_off_insert ();
517      background_highlight ();
518    }
519  else
520    update_end_hook (f);
521
522  updating_frame = NULL;
523}
524
525void
526set_terminal_window (size)
527     int size;
528{
529  if (FRAME_TERMCAP_P (updating_frame))
530    {
531      specified_window = size ? size : FRAME_LINES (updating_frame);
532      if (scroll_region_ok)
533	set_scroll_region (0, specified_window);
534    }
535  else
536    set_terminal_window_hook (size);
537}
538
539void
540set_scroll_region (start, stop)
541     int start, stop;
542{
543  char *buf;
544  struct frame *sf = XFRAME (selected_frame);
545
546  if (TS_set_scroll_region)
547    buf = tparam (TS_set_scroll_region, 0, 0, start, stop - 1);
548  else if (TS_set_scroll_region_1)
549    buf = tparam (TS_set_scroll_region_1, 0, 0,
550		  FRAME_LINES (sf), start,
551		  FRAME_LINES (sf) - stop,
552		  FRAME_LINES (sf));
553  else
554    buf = tparam (TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (sf));
555
556  OUTPUT (buf);
557  xfree (buf);
558  losecursor ();
559}
560
561
562static void
563turn_on_insert ()
564{
565  if (!insert_mode)
566    OUTPUT (TS_insert_mode);
567  insert_mode = 1;
568}
569
570void
571turn_off_insert ()
572{
573  if (insert_mode)
574    OUTPUT (TS_end_insert_mode);
575  insert_mode = 0;
576}
577
578/* Handle highlighting.  */
579
580void
581turn_off_highlight ()
582{
583  if (standout_mode)
584    OUTPUT_IF (TS_end_standout_mode);
585  standout_mode = 0;
586}
587
588static void
589turn_on_highlight ()
590{
591  if (!standout_mode)
592    OUTPUT_IF (TS_standout_mode);
593  standout_mode = 1;
594}
595
596static void
597toggle_highlight ()
598{
599  if (standout_mode)
600    turn_off_highlight ();
601  else
602    turn_on_highlight ();
603}
604
605
606/* Make cursor invisible.  */
607
608static void
609tty_hide_cursor ()
610{
611  if (tty_cursor_hidden == 0)
612    {
613      tty_cursor_hidden = 1;
614      OUTPUT_IF (TS_cursor_invisible);
615    }
616}
617
618
619/* Ensure that cursor is visible.  */
620
621static void
622tty_show_cursor ()
623{
624  if (tty_cursor_hidden)
625    {
626      tty_cursor_hidden = 0;
627      OUTPUT_IF (TS_cursor_normal);
628      if (visible_cursor)
629	OUTPUT_IF (TS_cursor_visible);
630    }
631}
632
633
634/* Set standout mode to the state it should be in for
635   empty space inside windows.  What this is,
636   depends on the user option inverse-video.  */
637
638void
639background_highlight ()
640{
641  if (inverse_video)
642    turn_on_highlight ();
643  else
644    turn_off_highlight ();
645}
646
647/* Set standout mode to the mode specified for the text to be output.  */
648
649static void
650highlight_if_desired ()
651{
652  if (inverse_video)
653    turn_on_highlight ();
654  else
655    turn_off_highlight ();
656}
657
658
659/* Move cursor to row/column position VPOS/HPOS.  HPOS/VPOS are
660   frame-relative coordinates.  */
661
662void
663cursor_to (vpos, hpos)
664     int vpos, hpos;
665{
666  struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
667
668  if (! FRAME_TERMCAP_P (f) && cursor_to_hook)
669    {
670      (*cursor_to_hook) (vpos, hpos);
671      return;
672    }
673
674  /* Detect the case where we are called from reset_sys_modes
675     and the costs have never been calculated.  Do nothing.  */
676  if (! costs_set)
677    return;
678
679  if (curY == vpos && curX == hpos)
680    return;
681  if (!TF_standout_motion)
682    background_highlight ();
683  if (!TF_insmode_motion)
684    turn_off_insert ();
685  cmgoto (vpos, hpos);
686}
687
688/* Similar but don't take any account of the wasted characters.  */
689
690void
691raw_cursor_to (row, col)
692     int row, col;
693{
694  struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
695  if (! FRAME_TERMCAP_P (f))
696    {
697      (*raw_cursor_to_hook) (row, col);
698      return;
699    }
700  if (curY == row && curX == col)
701    return;
702  if (!TF_standout_motion)
703    background_highlight ();
704  if (!TF_insmode_motion)
705    turn_off_insert ();
706  cmgoto (row, col);
707}
708
709/* Erase operations */
710
711/* clear from cursor to end of frame */
712void
713clear_to_end ()
714{
715  register int i;
716
717  if (clear_to_end_hook && ! FRAME_TERMCAP_P (updating_frame))
718    {
719      (*clear_to_end_hook) ();
720      return;
721    }
722  if (TS_clr_to_bottom)
723    {
724      background_highlight ();
725      OUTPUT (TS_clr_to_bottom);
726    }
727  else
728    {
729      for (i = curY; i < FRAME_LINES (XFRAME (selected_frame)); i++)
730	{
731	  cursor_to (i, 0);
732	  clear_end_of_line (FRAME_COLS (XFRAME (selected_frame)));
733	}
734    }
735}
736
737/* Clear entire frame */
738
739void
740clear_frame ()
741{
742  struct frame *sf = XFRAME (selected_frame);
743
744  if (clear_frame_hook
745      && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : sf)))
746    {
747      (*clear_frame_hook) ();
748      return;
749    }
750  if (TS_clr_frame)
751    {
752      background_highlight ();
753      OUTPUT (TS_clr_frame);
754      cmat (0, 0);
755    }
756  else
757    {
758      cursor_to (0, 0);
759      clear_to_end ();
760    }
761}
762
763/* Clear from cursor to end of line.
764   Assume that the line is already clear starting at column first_unused_hpos.
765
766   Note that the cursor may be moved, on terminals lacking a `ce' string.  */
767
768void
769clear_end_of_line (first_unused_hpos)
770     int first_unused_hpos;
771{
772  register int i;
773
774  if (clear_end_of_line_hook
775      && ! FRAME_TERMCAP_P ((updating_frame
776			       ? updating_frame
777			     : XFRAME (selected_frame))))
778    {
779      (*clear_end_of_line_hook) (first_unused_hpos);
780      return;
781    }
782
783  /* Detect the case where we are called from reset_sys_modes
784     and the costs have never been calculated.  Do nothing.  */
785  if (! costs_set)
786    return;
787
788  if (curX >= first_unused_hpos)
789    return;
790  background_highlight ();
791  if (TS_clr_line)
792    {
793      OUTPUT1 (TS_clr_line);
794    }
795  else
796    {			/* have to do it the hard way */
797      struct frame *sf = XFRAME (selected_frame);
798      turn_off_insert ();
799
800      /* Do not write in last row last col with Auto-wrap on. */
801      if (AutoWrap && curY == FRAME_LINES (sf) - 1
802	  && first_unused_hpos == FRAME_COLS (sf))
803	first_unused_hpos--;
804
805      for (i = curX; i < first_unused_hpos; i++)
806	{
807	  if (termscript)
808	    fputc (' ', termscript);
809	  putchar (' ');
810	}
811      cmplus (first_unused_hpos - curX);
812    }
813}
814
815/* Buffer to store the source and result of code conversion for terminal.  */
816static unsigned char *encode_terminal_buf;
817/* Allocated size of the above buffer.  */
818static int encode_terminal_bufsize;
819
820/* Encode SRC_LEN glyphs starting at SRC to terminal output codes.
821   Set CODING->produced to the byte-length of the resulting byte
822   sequence, and return a pointer to that byte sequence.  */
823
824unsigned char *
825encode_terminal_code (src, src_len, coding)
826     struct glyph *src;
827     int src_len;
828     struct coding_system *coding;
829{
830  struct glyph *src_end = src + src_len;
831  register GLYPH g;
832  unsigned char *buf;
833  int nchars, nbytes, required;
834  register int tlen = GLYPH_TABLE_LENGTH;
835  register Lisp_Object *tbase = GLYPH_TABLE_BASE;
836
837  /* Allocate sufficient size of buffer to store all characters in
838     multibyte-form.  But, it may be enlarged on demand if
839     Vglyph_table contains a string.  */
840  required = MAX_MULTIBYTE_LENGTH * src_len;
841  if (encode_terminal_bufsize < required)
842    {
843      if (encode_terminal_bufsize == 0)
844	encode_terminal_buf = xmalloc (required);
845      else
846	encode_terminal_buf = xrealloc (encode_terminal_buf, required);
847      encode_terminal_bufsize = required;
848    }
849
850  buf = encode_terminal_buf;
851  nchars = 0;
852  while (src < src_end)
853    {
854      /* We must skip glyphs to be padded for a wide character.  */
855      if (! CHAR_GLYPH_PADDING_P (*src))
856	{
857	  g = GLYPH_FROM_CHAR_GLYPH (src[0]);
858
859	  if (g < 0 || g >= tlen)
860	    {
861	      /* This glyph doesn't has an entry in Vglyph_table.  */
862	      if (CHAR_VALID_P (src->u.ch, 0))
863		buf += CHAR_STRING (src->u.ch, buf);
864	      else
865		*buf++ = SPACEGLYPH;
866	      nchars++;
867	    }
868	  else
869	    {
870	      /* This glyph has an entry in Vglyph_table,
871		 so process any alias before testing for simpleness.  */
872	      GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
873
874	      if (GLYPH_SIMPLE_P (tbase, tlen, g))
875		{
876		  int c = FAST_GLYPH_CHAR (g);
877
878		  if (CHAR_VALID_P (c, 0))
879		    buf += CHAR_STRING (c, buf);
880		  else
881		    *buf++ = SPACEGLYPH;
882		  nchars++;
883		}
884	      else
885		{
886		  /* We have a string in Vglyph_table.  */
887		  Lisp_Object string;
888
889		  string = tbase[g];
890		  if (! STRING_MULTIBYTE (string))
891		    string = string_to_multibyte (string);
892		  nbytes = buf - encode_terminal_buf;
893		  if (encode_terminal_bufsize < nbytes + SBYTES (string))
894		    {
895		      encode_terminal_bufsize = nbytes + SBYTES (string);
896		      encode_terminal_buf = xrealloc (encode_terminal_buf,
897						      encode_terminal_bufsize);
898		      buf = encode_terminal_buf + nbytes;
899		    }
900		  bcopy (SDATA (string), buf, SBYTES (string));
901		  buf += SBYTES (string);
902		  nchars += SCHARS (string);
903		}
904	    }
905	}
906      src++;
907    }
908
909  nbytes = buf - encode_terminal_buf;
910  coding->src_multibyte = 1;
911  coding->dst_multibyte = 0;
912  if (SYMBOLP (coding->pre_write_conversion)
913      && ! NILP (Ffboundp (coding->pre_write_conversion)))
914    {
915      run_pre_write_conversin_on_c_str (&encode_terminal_buf,
916					&encode_terminal_bufsize,
917					nchars, nbytes, coding);
918      nchars = coding->produced_char;
919      nbytes = coding->produced;
920    }
921  required = nbytes + encoding_buffer_size (coding, nbytes);
922  if (encode_terminal_bufsize < required)
923    {
924      encode_terminal_bufsize = required;
925      encode_terminal_buf = xrealloc (encode_terminal_buf, required);
926    }
927
928  encode_coding (coding, encode_terminal_buf, encode_terminal_buf + nbytes,
929		 nbytes, encode_terminal_bufsize - nbytes);
930  return encode_terminal_buf + nbytes;
931}
932
933void
934write_glyphs (string, len)
935     register struct glyph *string;
936     register int len;
937{
938  struct frame *sf = XFRAME (selected_frame);
939  struct frame *f = updating_frame ? updating_frame : sf;
940  unsigned char *conversion_buffer;
941  struct coding_system *coding;
942
943  if (write_glyphs_hook
944      && ! FRAME_TERMCAP_P (f))
945    {
946      (*write_glyphs_hook) (string, len);
947      return;
948    }
949
950  turn_off_insert ();
951  tty_hide_cursor ();
952
953  /* Don't dare write in last column of bottom line, if Auto-Wrap,
954     since that would scroll the whole frame on some terminals.  */
955
956  if (AutoWrap
957      && curY + 1 == FRAME_LINES (sf)
958      && (curX + len) == FRAME_COLS (sf))
959    len --;
960  if (len <= 0)
961    return;
962
963  cmplus (len);
964
965  /* If terminal_coding does any conversion, use it, otherwise use
966     safe_terminal_coding.  We can't use CODING_REQUIRE_ENCODING here
967     because it always return 1 if the member src_multibyte is 1.  */
968  coding = (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK
969	    ? &terminal_coding : &safe_terminal_coding);
970  /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
971     the tail.  */
972  coding->mode &= ~CODING_MODE_LAST_BLOCK;
973
974  while (len > 0)
975    {
976      /* Identify a run of glyphs with the same face.  */
977      int face_id = string->face_id;
978      int n;
979
980      for (n = 1; n < len; ++n)
981	if (string[n].face_id != face_id)
982	  break;
983
984      /* Turn appearance modes of the face of the run on.  */
985      highlight_if_desired ();
986      turn_on_face (f, face_id);
987
988      if (n == len)
989	/* This is the last run.  */
990	coding->mode |= CODING_MODE_LAST_BLOCK;
991      conversion_buffer = encode_terminal_code (string, n, coding);
992      if (coding->produced > 0)
993	{
994	  BLOCK_INPUT;
995	  fwrite (conversion_buffer, 1, coding->produced, stdout);
996	  if (ferror (stdout))
997	    clearerr (stdout);
998	  if (termscript)
999	    fwrite (conversion_buffer, 1, coding->produced, termscript);
1000	  UNBLOCK_INPUT;
1001	}
1002      len -= n;
1003      string += n;
1004
1005      /* Turn appearance modes off.  */
1006      turn_off_face (f, face_id);
1007      turn_off_highlight ();
1008    }
1009
1010  cmcheckmagic ();
1011}
1012
1013/* If start is zero, insert blanks instead of a string at start */
1014
1015void
1016insert_glyphs (start, len)
1017     register struct glyph *start;
1018     register int len;
1019{
1020  char *buf;
1021  struct glyph *glyph = NULL;
1022  struct frame *f, *sf;
1023  unsigned char *conversion_buffer;
1024  unsigned char space[1];
1025  struct coding_system *coding;
1026
1027  if (len <= 0)
1028    return;
1029
1030  if (insert_glyphs_hook)
1031    {
1032      (*insert_glyphs_hook) (start, len);
1033      return;
1034    }
1035
1036  sf = XFRAME (selected_frame);
1037  f = updating_frame ? updating_frame : sf;
1038
1039  if (TS_ins_multi_chars)
1040    {
1041      buf = tparam (TS_ins_multi_chars, 0, 0, len);
1042      OUTPUT1 (buf);
1043      xfree (buf);
1044      if (start)
1045	write_glyphs (start, len);
1046      return;
1047    }
1048
1049  turn_on_insert ();
1050  cmplus (len);
1051
1052  if (! start)
1053    space[0] = SPACEGLYPH;
1054
1055  /* If terminal_coding does any conversion, use it, otherwise use
1056     safe_terminal_coding.  We can't use CODING_REQUIRE_ENCODING here
1057     because it always return 1 if the member src_multibyte is 1.  */
1058  coding = (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK
1059	    ? &terminal_coding : &safe_terminal_coding);
1060  /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
1061     the tail.  */
1062  coding->mode &= ~CODING_MODE_LAST_BLOCK;
1063
1064  while (len-- > 0)
1065    {
1066      OUTPUT1_IF (TS_ins_char);
1067      if (!start)
1068	{
1069	  conversion_buffer = space;
1070	  coding->produced = 1;
1071	}
1072      else
1073	{
1074	  highlight_if_desired ();
1075	  turn_on_face (f, start->face_id);
1076	  glyph = start;
1077	  ++start;
1078	  /* We must open sufficient space for a character which
1079	     occupies more than one column.  */
1080	  while (len && CHAR_GLYPH_PADDING_P (*start))
1081	    {
1082	      OUTPUT1_IF (TS_ins_char);
1083	      start++, len--;
1084	    }
1085
1086	  if (len <= 0)
1087	    /* This is the last glyph.  */
1088	    coding->mode |= CODING_MODE_LAST_BLOCK;
1089
1090	  conversion_buffer = encode_terminal_code (glyph, 1, coding);
1091	}
1092
1093      if (coding->produced > 0)
1094	{
1095	  BLOCK_INPUT;
1096	  fwrite (conversion_buffer, 1, coding->produced, stdout);
1097	  if (ferror (stdout))
1098	    clearerr (stdout);
1099	  if (termscript)
1100	    fwrite (conversion_buffer, 1, coding->produced, termscript);
1101	  UNBLOCK_INPUT;
1102	}
1103
1104      OUTPUT1_IF (TS_pad_inserted_char);
1105      if (start)
1106	{
1107	  turn_off_face (f, glyph->face_id);
1108	  turn_off_highlight ();
1109	}
1110    }
1111
1112  cmcheckmagic ();
1113}
1114
1115void
1116delete_glyphs (n)
1117     register int n;
1118{
1119  char *buf;
1120  register int i;
1121
1122  if (delete_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame))
1123    {
1124      (*delete_glyphs_hook) (n);
1125      return;
1126    }
1127
1128  if (delete_in_insert_mode)
1129    {
1130      turn_on_insert ();
1131    }
1132  else
1133    {
1134      turn_off_insert ();
1135      OUTPUT_IF (TS_delete_mode);
1136    }
1137
1138  if (TS_del_multi_chars)
1139    {
1140      buf = tparam (TS_del_multi_chars, 0, 0, n);
1141      OUTPUT1 (buf);
1142      xfree (buf);
1143    }
1144  else
1145    for (i = 0; i < n; i++)
1146      OUTPUT1 (TS_del_char);
1147  if (!delete_in_insert_mode)
1148    OUTPUT_IF (TS_end_delete_mode);
1149}
1150
1151/* Insert N lines at vpos VPOS.  If N is negative, delete -N lines.  */
1152
1153void
1154ins_del_lines (vpos, n)
1155     int vpos, n;
1156{
1157  char *multi = n > 0 ? TS_ins_multi_lines : TS_del_multi_lines;
1158  char *single = n > 0 ? TS_ins_line : TS_del_line;
1159  char *scroll = n > 0 ? TS_rev_scroll : TS_fwd_scroll;
1160  struct frame *sf;
1161
1162  register int i = n > 0 ? n : -n;
1163  register char *buf;
1164
1165  if (ins_del_lines_hook && ! FRAME_TERMCAP_P (updating_frame))
1166    {
1167      (*ins_del_lines_hook) (vpos, n);
1168      return;
1169    }
1170
1171  sf = XFRAME (selected_frame);
1172
1173  /* If the lines below the insertion are being pushed
1174     into the end of the window, this is the same as clearing;
1175     and we know the lines are already clear, since the matching
1176     deletion has already been done.  So can ignore this.  */
1177  /* If the lines below the deletion are blank lines coming
1178     out of the end of the window, don't bother,
1179     as there will be a matching inslines later that will flush them. */
1180  if (scroll_region_ok && vpos + i >= specified_window)
1181    return;
1182  if (!memory_below_frame && vpos + i >= FRAME_LINES (sf))
1183    return;
1184
1185  if (multi)
1186    {
1187      raw_cursor_to (vpos, 0);
1188      background_highlight ();
1189      buf = tparam (multi, 0, 0, i);
1190      OUTPUT (buf);
1191      xfree (buf);
1192    }
1193  else if (single)
1194    {
1195      raw_cursor_to (vpos, 0);
1196      background_highlight ();
1197      while (--i >= 0)
1198	OUTPUT (single);
1199      if (TF_teleray)
1200	curX = 0;
1201    }
1202  else
1203    {
1204      set_scroll_region (vpos, specified_window);
1205      if (n < 0)
1206	raw_cursor_to (specified_window - 1, 0);
1207      else
1208	raw_cursor_to (vpos, 0);
1209      background_highlight ();
1210      while (--i >= 0)
1211	OUTPUTL (scroll, specified_window - vpos);
1212      set_scroll_region (0, specified_window);
1213    }
1214
1215  if (!scroll_region_ok && memory_below_frame && n < 0)
1216    {
1217      cursor_to (FRAME_LINES (sf) + n, 0);
1218      clear_to_end ();
1219    }
1220}
1221
1222/* Compute cost of sending "str", in characters,
1223   not counting any line-dependent padding.  */
1224
1225int
1226string_cost (str)
1227     char *str;
1228{
1229  cost = 0;
1230  if (str)
1231    tputs (str, 0, evalcost);
1232  return cost;
1233}
1234
1235/* Compute cost of sending "str", in characters,
1236   counting any line-dependent padding at one line.  */
1237
1238static int
1239string_cost_one_line (str)
1240     char *str;
1241{
1242  cost = 0;
1243  if (str)
1244    tputs (str, 1, evalcost);
1245  return cost;
1246}
1247
1248/* Compute per line amount of line-dependent padding,
1249   in tenths of characters.  */
1250
1251int
1252per_line_cost (str)
1253     register char *str;
1254{
1255  cost = 0;
1256  if (str)
1257    tputs (str, 0, evalcost);
1258  cost = - cost;
1259  if (str)
1260    tputs (str, 10, evalcost);
1261  return cost;
1262}
1263
1264#ifndef old
1265/* char_ins_del_cost[n] is cost of inserting N characters.
1266   char_ins_del_cost[-n] is cost of deleting N characters.
1267   The length of this vector is based on max_frame_cols.  */
1268
1269int *char_ins_del_vector;
1270
1271#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
1272#endif
1273
1274/* ARGSUSED */
1275static void
1276calculate_ins_del_char_costs (frame)
1277     FRAME_PTR frame;
1278{
1279  int ins_startup_cost, del_startup_cost;
1280  int ins_cost_per_char, del_cost_per_char;
1281  register int i;
1282  register int *p;
1283
1284  if (TS_ins_multi_chars)
1285    {
1286      ins_cost_per_char = 0;
1287      ins_startup_cost = string_cost_one_line (TS_ins_multi_chars);
1288    }
1289  else if (TS_ins_char || TS_pad_inserted_char
1290	   || (TS_insert_mode && TS_end_insert_mode))
1291    {
1292      ins_startup_cost = (30 * (string_cost (TS_insert_mode)
1293				+ string_cost (TS_end_insert_mode))) / 100;
1294      ins_cost_per_char = (string_cost_one_line (TS_ins_char)
1295			   + string_cost_one_line (TS_pad_inserted_char));
1296    }
1297  else
1298    {
1299      ins_startup_cost = 9999;
1300      ins_cost_per_char = 0;
1301    }
1302
1303  if (TS_del_multi_chars)
1304    {
1305      del_cost_per_char = 0;
1306      del_startup_cost = string_cost_one_line (TS_del_multi_chars);
1307    }
1308  else if (TS_del_char)
1309    {
1310      del_startup_cost = (string_cost (TS_delete_mode)
1311			  + string_cost (TS_end_delete_mode));
1312      if (delete_in_insert_mode)
1313	del_startup_cost /= 2;
1314      del_cost_per_char = string_cost_one_line (TS_del_char);
1315    }
1316  else
1317    {
1318      del_startup_cost = 9999;
1319      del_cost_per_char = 0;
1320    }
1321
1322  /* Delete costs are at negative offsets */
1323  p = &char_ins_del_cost (frame)[0];
1324  for (i = FRAME_COLS (frame); --i >= 0;)
1325    *--p = (del_startup_cost += del_cost_per_char);
1326
1327  /* Doing nothing is free */
1328  p = &char_ins_del_cost (frame)[0];
1329  *p++ = 0;
1330
1331  /* Insert costs are at positive offsets */
1332  for (i = FRAME_COLS (frame); --i >= 0;)
1333    *p++ = (ins_startup_cost += ins_cost_per_char);
1334}
1335
1336void
1337calculate_costs (frame)
1338     FRAME_PTR frame;
1339{
1340  register char *f = (TS_set_scroll_region
1341		      ? TS_set_scroll_region
1342		      : TS_set_scroll_region_1);
1343
1344  FRAME_COST_BAUD_RATE (frame) = baud_rate;
1345
1346  scroll_region_cost = string_cost (f);
1347
1348  /* These variables are only used for terminal stuff.  They are allocated
1349     once for the terminal frame of X-windows emacs, but not used afterwards.
1350
1351     char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1352     X turns off char_ins_del_ok. */
1353
1354  max_frame_lines = max (max_frame_lines, FRAME_LINES (frame));
1355  max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
1356
1357  costs_set = 1;
1358
1359  if (char_ins_del_vector != 0)
1360    char_ins_del_vector
1361      = (int *) xrealloc (char_ins_del_vector,
1362			  (sizeof (int)
1363			   + 2 * max_frame_cols * sizeof (int)));
1364  else
1365    char_ins_del_vector
1366      = (int *) xmalloc (sizeof (int)
1367			 + 2 * max_frame_cols * sizeof (int));
1368
1369  bzero (char_ins_del_vector, (sizeof (int)
1370			       + 2 * max_frame_cols * sizeof (int)));
1371
1372  if (f && (!TS_ins_line && !TS_del_line))
1373    do_line_insertion_deletion_costs (frame,
1374				      TS_rev_scroll, TS_ins_multi_lines,
1375				      TS_fwd_scroll, TS_del_multi_lines,
1376				      f, f, 1);
1377  else
1378    do_line_insertion_deletion_costs (frame,
1379				      TS_ins_line, TS_ins_multi_lines,
1380				      TS_del_line, TS_del_multi_lines,
1381				      0, 0, 1);
1382
1383  calculate_ins_del_char_costs (frame);
1384
1385  /* Don't use TS_repeat if its padding is worse than sending the chars */
1386  if (TS_repeat && per_line_cost (TS_repeat) * baud_rate < 9000)
1387    RPov = string_cost (TS_repeat);
1388  else
1389    RPov = FRAME_COLS (frame) * 2;
1390
1391  cmcostinit ();		/* set up cursor motion costs */
1392}
1393
1394struct fkey_table {
1395  char *cap, *name;
1396};
1397
1398  /* Termcap capability names that correspond directly to X keysyms.
1399     Some of these (marked "terminfo") aren't supplied by old-style
1400     (Berkeley) termcap entries.  They're listed in X keysym order;
1401     except we put the keypad keys first, so that if they clash with
1402     other keys (as on the IBM PC keyboard) they get overridden.
1403  */
1404
1405static struct fkey_table keys[] =
1406{
1407  {"kh", "home"},	/* termcap */
1408  {"kl", "left"},	/* termcap */
1409  {"ku", "up"},		/* termcap */
1410  {"kr", "right"},	/* termcap */
1411  {"kd", "down"},	/* termcap */
1412  {"%8", "prior"},	/* terminfo */
1413  {"%5", "next"},	/* terminfo */
1414  {"@7", "end"},	/* terminfo */
1415  {"@1", "begin"},	/* terminfo */
1416  {"*6", "select"},	/* terminfo */
1417  {"%9", "print"},	/* terminfo */
1418  {"@4", "execute"},	/* terminfo --- actually the `command' key */
1419  /*
1420   * "insert" --- see below
1421   */
1422  {"&8", "undo"},	/* terminfo */
1423  {"%0", "redo"},	/* terminfo */
1424  {"%7", "menu"},	/* terminfo --- actually the `options' key */
1425  {"@0", "find"},	/* terminfo */
1426  {"@2", "cancel"},	/* terminfo */
1427  {"%1", "help"},	/* terminfo */
1428  /*
1429   * "break" goes here, but can't be reliably intercepted with termcap
1430   */
1431  {"&4", "reset"},	/* terminfo --- actually `restart' */
1432  /*
1433   * "system" and "user" --- no termcaps
1434   */
1435  {"kE", "clearline"},	/* terminfo */
1436  {"kA", "insertline"},	/* terminfo */
1437  {"kL", "deleteline"},	/* terminfo */
1438  {"kI", "insertchar"},	/* terminfo */
1439  {"kD", "deletechar"},	/* terminfo */
1440  {"kB", "backtab"},	/* terminfo */
1441  /*
1442   * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1443   */
1444  {"@8", "kp-enter"},	/* terminfo */
1445  /*
1446   * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1447   * "kp-multiply", "kp-add", "kp-separator",
1448   * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1449   * --- no termcaps for any of these.
1450   */
1451  {"K4", "kp-1"},	/* terminfo */
1452  /*
1453   * "kp-2" --- no termcap
1454   */
1455  {"K5", "kp-3"},	/* terminfo */
1456  /*
1457   * "kp-4" --- no termcap
1458   */
1459  {"K2", "kp-5"},	/* terminfo */
1460  /*
1461   * "kp-6" --- no termcap
1462   */
1463  {"K1", "kp-7"},	/* terminfo */
1464  /*
1465   * "kp-8" --- no termcap
1466   */
1467  {"K3", "kp-9"},	/* terminfo */
1468  /*
1469   * "kp-equal" --- no termcap
1470   */
1471  {"k1", "f1"},
1472  {"k2", "f2"},
1473  {"k3", "f3"},
1474  {"k4", "f4"},
1475  {"k5", "f5"},
1476  {"k6", "f6"},
1477  {"k7", "f7"},
1478  {"k8", "f8"},
1479  {"k9", "f9"},
1480
1481  {"&0", "S-cancel"},    /*shifted cancel key*/
1482  {"&9", "S-begin"},     /*shifted begin key*/
1483  {"*0", "S-find"},      /*shifted find key*/
1484  {"*1", "S-execute"},   /*shifted execute? actually shifted command key*/
1485  {"*4", "S-delete"},    /*shifted delete-character key*/
1486  {"*7", "S-end"},       /*shifted end key*/
1487  {"*8", "S-clearline"}, /*shifted clear-to end-of-line key*/
1488  {"#1", "S-help"},      /*shifted help key*/
1489  {"#2", "S-home"},      /*shifted home key*/
1490  {"#3", "S-insert"},    /*shifted insert-character key*/
1491  {"#4", "S-left"},      /*shifted left-arrow key*/
1492  {"%d", "S-menu"},      /*shifted menu? actually shifted options key*/
1493  {"%c", "S-next"},      /*shifted next key*/
1494  {"%e", "S-prior"},     /*shifted previous key*/
1495  {"%f", "S-print"},     /*shifted print key*/
1496  {"%g", "S-redo"},      /*shifted redo key*/
1497  {"%i", "S-right"},     /*shifted right-arrow key*/
1498  {"!3", "S-undo"}       /*shifted undo key*/
1499  };
1500
1501static char **term_get_fkeys_arg;
1502static Lisp_Object term_get_fkeys_1 ();
1503
1504/* Find the escape codes sent by the function keys for Vfunction_key_map.
1505   This function scans the termcap function key sequence entries, and
1506   adds entries to Vfunction_key_map for each function key it finds.  */
1507
1508void
1509term_get_fkeys (address)
1510     char **address;
1511{
1512  /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1513     errors during the call.  The only errors should be from Fdefine_key
1514     when given a key sequence containing an invalid prefix key.  If the
1515     termcap defines function keys which use a prefix that is already bound
1516     to a command by the default bindings, we should silently ignore that
1517     function key specification, rather than giving the user an error and
1518     refusing to run at all on such a terminal.  */
1519
1520  extern Lisp_Object Fidentity ();
1521  term_get_fkeys_arg = address;
1522  internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1523}
1524
1525static Lisp_Object
1526term_get_fkeys_1 ()
1527{
1528  int i;
1529
1530  char **address = term_get_fkeys_arg;
1531
1532  /* This can happen if CANNOT_DUMP or with strange options.  */
1533  if (!initialized)
1534    Vfunction_key_map = Fmake_sparse_keymap (Qnil);
1535
1536  for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1537    {
1538      char *sequence = tgetstr (keys[i].cap, address);
1539      if (sequence)
1540	Fdefine_key (Vfunction_key_map, build_string (sequence),
1541		     Fmake_vector (make_number (1),
1542				   intern (keys[i].name)));
1543    }
1544
1545  /* The uses of the "k0" capability are inconsistent; sometimes it
1546     describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1547     We will attempt to politely accommodate both systems by testing for
1548     "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1549     */
1550  {
1551    char *k_semi  = tgetstr ("k;", address);
1552    char *k0      = tgetstr ("k0", address);
1553    char *k0_name = "f10";
1554
1555    if (k_semi)
1556      {
1557	if (k0)
1558	  /* Define f0 first, so that f10 takes precedence in case the
1559	     key sequences happens to be the same.  */
1560	  Fdefine_key (Vfunction_key_map, build_string (k0),
1561		       Fmake_vector (make_number (1), intern ("f0")));
1562	Fdefine_key (Vfunction_key_map, build_string (k_semi),
1563		     Fmake_vector (make_number (1), intern ("f10")));
1564      }
1565    else if (k0)
1566      Fdefine_key (Vfunction_key_map, build_string (k0),
1567		   Fmake_vector (make_number (1), intern (k0_name)));
1568  }
1569
1570  /* Set up cookies for numbered function keys above f10. */
1571  {
1572    char fcap[3], fkey[4];
1573
1574    fcap[0] = 'F'; fcap[2] = '\0';
1575    for (i = 11; i < 64; i++)
1576      {
1577	if (i <= 19)
1578	  fcap[1] = '1' + i - 11;
1579	else if (i <= 45)
1580	  fcap[1] = 'A' + i - 20;
1581	else
1582	  fcap[1] = 'a' + i - 46;
1583
1584	{
1585	  char *sequence = tgetstr (fcap, address);
1586	  if (sequence)
1587	    {
1588	      sprintf (fkey, "f%d", i);
1589	      Fdefine_key (Vfunction_key_map, build_string (sequence),
1590			   Fmake_vector (make_number (1),
1591					 intern (fkey)));
1592	    }
1593	}
1594      }
1595   }
1596
1597  /*
1598   * Various mappings to try and get a better fit.
1599   */
1600  {
1601#define CONDITIONAL_REASSIGN(cap1, cap2, sym)				\
1602      if (!tgetstr (cap1, address))					\
1603	{								\
1604	  char *sequence = tgetstr (cap2, address);			\
1605	  if (sequence)							\
1606	    Fdefine_key (Vfunction_key_map, build_string (sequence),	\
1607			 Fmake_vector (make_number (1),	\
1608				       intern (sym)));	\
1609	}
1610
1611      /* if there's no key_next keycap, map key_npage to `next' keysym */
1612      CONDITIONAL_REASSIGN ("%5", "kN", "next");
1613      /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1614      CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1615      /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1616      CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1617      /* if there's no key_end keycap, map key_ll to 'end' keysym */
1618      CONDITIONAL_REASSIGN ("@7", "kH", "end");
1619
1620      /* IBM has their own non-standard dialect of terminfo.
1621	 If the standard name isn't found, try the IBM name.  */
1622      CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1623      CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1624      CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1625      CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1626      CONDITIONAL_REASSIGN ("@7", "kw", "end");
1627      CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1628      CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1629      CONDITIONAL_REASSIGN ("%1", "kq", "help");
1630      CONDITIONAL_REASSIGN ("*6", "kU", "select");
1631#undef CONDITIONAL_REASSIGN
1632  }
1633
1634  return Qnil;
1635}
1636
1637
1638/***********************************************************************
1639		       Character Display Information
1640 ***********************************************************************/
1641
1642/* Avoid name clash with functions defined in xterm.c */
1643#ifdef static
1644#define append_glyph append_glyph_term
1645#define produce_stretch_glyph produce_stretch_glyph_term
1646#endif
1647
1648static void append_glyph P_ ((struct it *));
1649static void produce_stretch_glyph P_ ((struct it *));
1650
1651
1652/* Append glyphs to IT's glyph_row.  Called from produce_glyphs for
1653   terminal frames if IT->glyph_row != NULL.  IT->char_to_display is
1654   the character for which to produce glyphs; IT->face_id contains the
1655   character's face.  Padding glyphs are appended if IT->c has a
1656   IT->pixel_width > 1.  */
1657
1658static void
1659append_glyph (it)
1660     struct it *it;
1661{
1662  struct glyph *glyph, *end;
1663  int i;
1664
1665  xassert (it->glyph_row);
1666  glyph = (it->glyph_row->glyphs[it->area]
1667	   + it->glyph_row->used[it->area]);
1668  end = it->glyph_row->glyphs[1 + it->area];
1669
1670  for (i = 0;
1671       i < it->pixel_width && glyph < end;
1672       ++i)
1673    {
1674      glyph->type = CHAR_GLYPH;
1675      glyph->pixel_width = 1;
1676      glyph->u.ch = it->char_to_display;
1677      glyph->face_id = it->face_id;
1678      glyph->padding_p = i > 0;
1679      glyph->charpos = CHARPOS (it->position);
1680      glyph->object = it->object;
1681
1682      ++it->glyph_row->used[it->area];
1683      ++glyph;
1684    }
1685}
1686
1687
1688/* Produce glyphs for the display element described by IT.  *IT
1689   specifies what we want to produce a glyph for (character, image, ...),
1690   and where in the glyph matrix we currently are (glyph row and hpos).
1691   produce_glyphs fills in output fields of *IT with information such as the
1692   pixel width and height of a character, and maybe output actual glyphs at
1693   the same time if IT->glyph_row is non-null.  See the explanation of
1694   struct display_iterator in dispextern.h for an overview.
1695
1696   produce_glyphs also stores the result of glyph width, ascent
1697   etc. computations in *IT.
1698
1699   IT->glyph_row may be null, in which case produce_glyphs does not
1700   actually fill in the glyphs.  This is used in the move_* functions
1701   in xdisp.c for text width and height computations.
1702
1703   Callers usually don't call produce_glyphs directly;
1704   instead they use the macro PRODUCE_GLYPHS.  */
1705
1706void
1707produce_glyphs (it)
1708     struct it *it;
1709{
1710  /* If a hook is installed, let it do the work.  */
1711  xassert (it->what == IT_CHARACTER
1712	   || it->what == IT_COMPOSITION
1713	   || it->what == IT_STRETCH);
1714
1715  if (it->what == IT_STRETCH)
1716    {
1717      produce_stretch_glyph (it);
1718      goto done;
1719    }
1720
1721  /* Nothing but characters are supported on terminal frames.  For a
1722     composition sequence, it->c is the first character of the
1723     sequence.  */
1724  xassert (it->what == IT_CHARACTER
1725	   || it->what == IT_COMPOSITION);
1726
1727  /* Maybe translate single-byte characters to multibyte.  */
1728  it->char_to_display = it->c;
1729
1730  if (it->c >= 040 && it->c < 0177)
1731    {
1732      it->pixel_width = it->nglyphs = 1;
1733      if (it->glyph_row)
1734	append_glyph (it);
1735    }
1736  else if (it->c == '\n')
1737    it->pixel_width = it->nglyphs = 0;
1738  else if (it->c == '\t')
1739    {
1740      int absolute_x = (it->current_x
1741			+ it->continuation_lines_width);
1742      int next_tab_x
1743	= (((1 + absolute_x + it->tab_width - 1)
1744	    / it->tab_width)
1745	   * it->tab_width);
1746      int nspaces;
1747
1748      /* If part of the TAB has been displayed on the previous line
1749	 which is continued now, continuation_lines_width will have
1750	 been incremented already by the part that fitted on the
1751	 continued line.  So, we will get the right number of spaces
1752	 here.  */
1753      nspaces = next_tab_x - absolute_x;
1754
1755      if (it->glyph_row)
1756	{
1757	  int n = nspaces;
1758
1759	  it->char_to_display = ' ';
1760	  it->pixel_width = it->len = 1;
1761
1762	  while (n--)
1763	    append_glyph (it);
1764	}
1765
1766      it->pixel_width = nspaces;
1767      it->nglyphs = nspaces;
1768    }
1769  else if (SINGLE_BYTE_CHAR_P (it->c))
1770    {
1771      if (unibyte_display_via_language_environment
1772	  && (it->c >= 0240
1773	      || !NILP (Vnonascii_translation_table)))
1774	{
1775	  int charset;
1776
1777	  it->char_to_display = unibyte_char_to_multibyte (it->c);
1778	  charset = CHAR_CHARSET (it->char_to_display);
1779	  it->pixel_width = CHARSET_WIDTH (charset);
1780	  it->nglyphs = it->pixel_width;
1781	  if (it->glyph_row)
1782	    append_glyph (it);
1783	}
1784      else
1785	{
1786	  /* Coming here means that it->c is from display table, thus we
1787	     must send the code as is to the terminal.  Although there's
1788	     no way to know how many columns it occupies on a screen, it
1789	     is a good assumption that a single byte code has 1-column
1790	     width.  */
1791	  it->pixel_width = it->nglyphs = 1;
1792	  if (it->glyph_row)
1793	    append_glyph (it);
1794	}
1795    }
1796  else
1797    {
1798      /* A multi-byte character.  The display width is fixed for all
1799	 characters of the set.  Some of the glyphs may have to be
1800	 ignored because they are already displayed in a continued
1801	 line.  */
1802      int charset = CHAR_CHARSET (it->c);
1803
1804      it->pixel_width = CHARSET_WIDTH (charset);
1805      it->nglyphs = it->pixel_width;
1806
1807      if (it->glyph_row)
1808	append_glyph (it);
1809    }
1810
1811 done:
1812  /* Advance current_x by the pixel width as a convenience for
1813     the caller.  */
1814  if (it->area == TEXT_AREA)
1815    it->current_x += it->pixel_width;
1816  it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1817  it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
1818}
1819
1820
1821/* Produce a stretch glyph for iterator IT.  IT->object is the value
1822   of the glyph property displayed.  The value must be a list
1823   `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1824   being recognized:
1825
1826   1. `:width WIDTH' specifies that the space should be WIDTH *
1827   canonical char width wide.  WIDTH may be an integer or floating
1828   point number.
1829
1830   2. `:align-to HPOS' specifies that the space should be wide enough
1831   to reach HPOS, a value in canonical character units.  */
1832
1833static void
1834produce_stretch_glyph (it)
1835     struct it *it;
1836{
1837  /* (space :width WIDTH ...)  */
1838  Lisp_Object prop, plist;
1839  int width = 0, align_to = -1;
1840  int zero_width_ok_p = 0;
1841  double tem;
1842
1843  /* List should start with `space'.  */
1844  xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1845  plist = XCDR (it->object);
1846
1847  /* Compute the width of the stretch.  */
1848  if ((prop = Fplist_get (plist, QCwidth), !NILP (prop))
1849      && calc_pixel_width_or_height (&tem, it, prop, 0, 1, 0))
1850    {
1851      /* Absolute width `:width WIDTH' specified and valid.  */
1852      zero_width_ok_p = 1;
1853      width = (int)(tem + 0.5);
1854    }
1855  else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
1856	   && calc_pixel_width_or_height (&tem, it, prop, 0, 1, &align_to))
1857    {
1858      if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
1859	align_to = (align_to < 0
1860		    ? 0
1861		    : align_to - window_box_left_offset (it->w, TEXT_AREA));
1862      else if (align_to < 0)
1863	align_to = window_box_left_offset (it->w, TEXT_AREA);
1864      width = max (0, (int)(tem + 0.5) + align_to - it->current_x);
1865      zero_width_ok_p = 1;
1866    }
1867  else
1868    /* Nothing specified -> width defaults to canonical char width.  */
1869    width = FRAME_COLUMN_WIDTH (it->f);
1870
1871  if (width <= 0 && (width < 0 || !zero_width_ok_p))
1872    width = 1;
1873
1874  if (width > 0 && it->glyph_row)
1875    {
1876      Lisp_Object o_object = it->object;
1877      Lisp_Object object = it->stack[it->sp - 1].string;
1878      int n = width;
1879
1880      if (!STRINGP (object))
1881	object = it->w->buffer;
1882      it->object = object;
1883      it->char_to_display = ' ';
1884      it->pixel_width = it->len = 1;
1885      while (n--)
1886	append_glyph (it);
1887      it->object = o_object;
1888    }
1889  it->pixel_width = width;
1890  it->nglyphs = width;
1891}
1892
1893
1894/* Get information about special display element WHAT in an
1895   environment described by IT.  WHAT is one of IT_TRUNCATION or
1896   IT_CONTINUATION.  Maybe produce glyphs for WHAT if IT has a
1897   non-null glyph_row member.  This function ensures that fields like
1898   face_id, c, len of IT are left untouched.  */
1899
1900void
1901produce_special_glyphs (it, what)
1902     struct it *it;
1903     enum display_element_type what;
1904{
1905  struct it temp_it;
1906  GLYPH glyph;
1907
1908  temp_it = *it;
1909  temp_it.dp = NULL;
1910  temp_it.what = IT_CHARACTER;
1911  temp_it.len = 1;
1912  temp_it.object = make_number (0);
1913  bzero (&temp_it.current, sizeof temp_it.current);
1914
1915  if (what == IT_CONTINUATION)
1916    {
1917      /* Continuation glyph.  */
1918      if (it->dp
1919	  && INTEGERP (DISP_CONTINUE_GLYPH (it->dp))
1920	  && GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (it->dp))))
1921	{
1922	  glyph = XINT (DISP_CONTINUE_GLYPH (it->dp));
1923	  glyph = spec_glyph_lookup_face (XWINDOW (it->window), glyph);
1924	}
1925      else
1926	glyph = '\\';
1927    }
1928  else if (what == IT_TRUNCATION)
1929    {
1930      /* Truncation glyph.  */
1931      if (it->dp
1932	  && INTEGERP (DISP_TRUNC_GLYPH (it->dp))
1933	  && GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (it->dp))))
1934	{
1935	  glyph = XINT (DISP_TRUNC_GLYPH (it->dp));
1936	  glyph = spec_glyph_lookup_face (XWINDOW (it->window), glyph);
1937	}
1938      else
1939	glyph = '$';
1940    }
1941  else
1942    abort ();
1943
1944  temp_it.c = FAST_GLYPH_CHAR (glyph);
1945  temp_it.face_id = FAST_GLYPH_FACE (glyph);
1946  temp_it.len = CHAR_BYTES (temp_it.c);
1947
1948  produce_glyphs (&temp_it);
1949  it->pixel_width = temp_it.pixel_width;
1950  it->nglyphs = temp_it.pixel_width;
1951}
1952
1953
1954
1955/***********************************************************************
1956				Faces
1957 ***********************************************************************/
1958
1959/* Value is non-zero if attribute ATTR may be used.  ATTR should be
1960   one of the enumerators from enum no_color_bit, or a bit set built
1961   from them.  Some display attributes may not be used together with
1962   color; the termcap capability `NC' specifies which ones.  */
1963
1964#define MAY_USE_WITH_COLORS_P(ATTR)		\
1965     (TN_max_colors > 0				\
1966      ? (TN_no_color_video & (ATTR)) == 0	\
1967      : 1)
1968
1969/* Turn appearances of face FACE_ID on tty frame F on.
1970   FACE_ID is a realized face ID number, in the face cache.  */
1971
1972static void
1973turn_on_face (f, face_id)
1974     struct frame *f;
1975     int face_id;
1976{
1977  struct face *face = FACE_FROM_ID (f, face_id);
1978  long fg = face->foreground;
1979  long bg = face->background;
1980
1981  /* Do this first because TS_end_standout_mode may be the same
1982     as TS_exit_attribute_mode, which turns all appearances off. */
1983  if (MAY_USE_WITH_COLORS_P (NC_REVERSE))
1984    {
1985      if (TN_max_colors > 0)
1986	{
1987	  if (fg >= 0 && bg >= 0)
1988	    {
1989	      /* If the terminal supports colors, we can set them
1990		 below without using reverse video.  The face's fg
1991		 and bg colors are set as they should appear on
1992		 the screen, i.e. they take the inverse-video'ness
1993		 of the face already into account.  */
1994	    }
1995	  else if (inverse_video)
1996	    {
1997	      if (fg == FACE_TTY_DEFAULT_FG_COLOR
1998		  || bg == FACE_TTY_DEFAULT_BG_COLOR)
1999		toggle_highlight ();
2000	    }
2001	  else
2002	    {
2003	      if (fg == FACE_TTY_DEFAULT_BG_COLOR
2004		  || bg == FACE_TTY_DEFAULT_FG_COLOR)
2005		toggle_highlight ();
2006	    }
2007	}
2008      else
2009	{
2010	  /* If we can't display colors, use reverse video
2011	     if the face specifies that.  */
2012	  if (inverse_video)
2013	    {
2014	      if (fg == FACE_TTY_DEFAULT_FG_COLOR
2015		  || bg == FACE_TTY_DEFAULT_BG_COLOR)
2016		toggle_highlight ();
2017	    }
2018	  else
2019	    {
2020	      if (fg == FACE_TTY_DEFAULT_BG_COLOR
2021		  || bg == FACE_TTY_DEFAULT_FG_COLOR)
2022		toggle_highlight ();
2023	    }
2024	}
2025    }
2026
2027  if (face->tty_bold_p)
2028    {
2029      if (MAY_USE_WITH_COLORS_P (NC_BOLD))
2030	OUTPUT1_IF (TS_enter_bold_mode);
2031    }
2032  else if (face->tty_dim_p)
2033    if (MAY_USE_WITH_COLORS_P (NC_DIM))
2034      OUTPUT1_IF (TS_enter_dim_mode);
2035
2036  /* Alternate charset and blinking not yet used.  */
2037  if (face->tty_alt_charset_p
2038      && MAY_USE_WITH_COLORS_P (NC_ALT_CHARSET))
2039    OUTPUT1_IF (TS_enter_alt_charset_mode);
2040
2041  if (face->tty_blinking_p
2042      && MAY_USE_WITH_COLORS_P (NC_BLINK))
2043    OUTPUT1_IF (TS_enter_blink_mode);
2044
2045  if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (NC_UNDERLINE))
2046    OUTPUT1_IF (TS_enter_underline_mode);
2047
2048  if (TN_max_colors > 0)
2049    {
2050      char *ts, *p;
2051
2052      ts = standout_mode ? TS_set_background : TS_set_foreground;
2053      if (fg >= 0 && ts)
2054	{
2055	  p = tparam (ts, NULL, 0, (int) fg);
2056	  OUTPUT (p);
2057	  xfree (p);
2058	}
2059
2060      ts = standout_mode ? TS_set_foreground : TS_set_background;
2061      if (bg >= 0 && ts)
2062	{
2063	  p = tparam (ts, NULL, 0, (int) bg);
2064	  OUTPUT (p);
2065	  xfree (p);
2066	}
2067    }
2068}
2069
2070
2071/* Turn off appearances of face FACE_ID on tty frame F.  */
2072
2073static void
2074turn_off_face (f, face_id)
2075     struct frame *f;
2076     int face_id;
2077{
2078  struct face *face = FACE_FROM_ID (f, face_id);
2079
2080  xassert (face != NULL);
2081
2082  if (TS_exit_attribute_mode)
2083    {
2084      /* Capability "me" will turn off appearance modes double-bright,
2085	 half-bright, reverse-video, standout, underline.  It may or
2086	 may not turn off alt-char-mode.  */
2087      if (face->tty_bold_p
2088	  || face->tty_dim_p
2089	  || face->tty_reverse_p
2090	  || face->tty_alt_charset_p
2091	  || face->tty_blinking_p
2092	  || face->tty_underline_p)
2093	{
2094	  OUTPUT1_IF (TS_exit_attribute_mode);
2095	  if (strcmp (TS_exit_attribute_mode, TS_end_standout_mode) == 0)
2096	    standout_mode = 0;
2097	}
2098
2099      if (face->tty_alt_charset_p)
2100	OUTPUT_IF (TS_exit_alt_charset_mode);
2101    }
2102  else
2103    {
2104      /* If we don't have "me" we can only have those appearances
2105	 that have exit sequences defined.  */
2106      if (face->tty_alt_charset_p)
2107	OUTPUT_IF (TS_exit_alt_charset_mode);
2108
2109      if (face->tty_underline_p)
2110	OUTPUT_IF (TS_exit_underline_mode);
2111    }
2112
2113  /* Switch back to default colors.  */
2114  if (TN_max_colors > 0
2115      && ((face->foreground != FACE_TTY_DEFAULT_COLOR
2116	   && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
2117	  || (face->background != FACE_TTY_DEFAULT_COLOR
2118	      && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
2119    OUTPUT1_IF (TS_orig_pair);
2120}
2121
2122
2123/* Return non-zero if the terminal on frame F supports all of the
2124   capabilities in CAPS simultaneously, with foreground and background
2125   colors FG and BG.  */
2126
2127int
2128tty_capable_p (f, caps, fg, bg)
2129     struct frame *f;
2130     unsigned caps;
2131     unsigned long fg, bg;
2132{
2133#define TTY_CAPABLE_P_TRY(cap, TS, NC_bit)				\
2134  if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(NC_bit)))	\
2135    return 0;
2136
2137  TTY_CAPABLE_P_TRY (TTY_CAP_INVERSE,	TS_standout_mode, 	 NC_REVERSE);
2138  TTY_CAPABLE_P_TRY (TTY_CAP_UNDERLINE, TS_enter_underline_mode, NC_UNDERLINE);
2139  TTY_CAPABLE_P_TRY (TTY_CAP_BOLD, 	TS_enter_bold_mode, 	 NC_BOLD);
2140  TTY_CAPABLE_P_TRY (TTY_CAP_DIM, 	TS_enter_dim_mode, 	 NC_DIM);
2141  TTY_CAPABLE_P_TRY (TTY_CAP_BLINK, 	TS_enter_blink_mode, 	 NC_BLINK);
2142  TTY_CAPABLE_P_TRY (TTY_CAP_ALT_CHARSET, TS_enter_alt_charset_mode, NC_ALT_CHARSET);
2143
2144  /* We can do it!  */
2145  return 1;
2146}
2147
2148
2149/* Return non-zero if the terminal is capable to display colors.  */
2150
2151DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
2152       0, 1, 0,
2153       doc: /* Return non-nil if TTY can display colors on DISPLAY.  */)
2154     (display)
2155     Lisp_Object display;
2156{
2157  return TN_max_colors > 0 ? Qt : Qnil;
2158}
2159
2160/* Return the number of supported colors.  */
2161DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
2162       Stty_display_color_cells, 0, 1, 0,
2163       doc: /* Return the number of colors supported by TTY on DISPLAY.  */)
2164     (display)
2165     Lisp_Object display;
2166{
2167  return make_number (TN_max_colors);
2168}
2169
2170#ifndef WINDOWSNT
2171
2172/* Save or restore the default color-related capabilities of this
2173   terminal.  */
2174static void
2175tty_default_color_capabilities (save)
2176     int save;
2177{
2178  static char
2179    *default_orig_pair, *default_set_foreground, *default_set_background;
2180  static int default_max_colors, default_max_pairs, default_no_color_video;
2181
2182  if (save)
2183    {
2184      if (default_orig_pair)
2185	xfree (default_orig_pair);
2186      default_orig_pair = TS_orig_pair ? xstrdup (TS_orig_pair) : NULL;
2187
2188      if (default_set_foreground)
2189	xfree (default_set_foreground);
2190      default_set_foreground = TS_set_foreground ? xstrdup (TS_set_foreground)
2191			       : NULL;
2192
2193      if (default_set_background)
2194	xfree (default_set_background);
2195      default_set_background = TS_set_background ? xstrdup (TS_set_background)
2196			       : NULL;
2197
2198      default_max_colors = TN_max_colors;
2199      default_max_pairs = TN_max_pairs;
2200      default_no_color_video = TN_no_color_video;
2201    }
2202  else
2203    {
2204      TS_orig_pair = default_orig_pair;
2205      TS_set_foreground = default_set_foreground;
2206      TS_set_background = default_set_background;
2207      TN_max_colors = default_max_colors;
2208      TN_max_pairs = default_max_pairs;
2209      TN_no_color_video = default_no_color_video;
2210    }
2211}
2212
2213/* Setup one of the standard tty color schemes according to MODE.
2214   MODE's value is generally the number of colors which we want to
2215   support; zero means set up for the default capabilities, the ones
2216   we saw at term_init time; -1 means turn off color support.  */
2217void
2218tty_setup_colors (mode)
2219     int mode;
2220{
2221  /* Canonicalize all negative values of MODE.  */
2222  if (mode < -1)
2223    mode = -1;
2224
2225  switch (mode)
2226    {
2227      case -1:	 /* no colors at all */
2228	TN_max_colors = 0;
2229	TN_max_pairs = 0;
2230	TN_no_color_video = 0;
2231	TS_set_foreground = TS_set_background = TS_orig_pair = NULL;
2232	break;
2233      case 0:	 /* default colors, if any */
2234      default:
2235	tty_default_color_capabilities (0);
2236	break;
2237      case 8:	/* 8 standard ANSI colors */
2238	TS_orig_pair = "\033[0m";
2239#ifdef TERMINFO
2240	TS_set_foreground = "\033[3%p1%dm";
2241	TS_set_background = "\033[4%p1%dm";
2242#else
2243	TS_set_foreground = "\033[3%dm";
2244	TS_set_background = "\033[4%dm";
2245#endif
2246	TN_max_colors = 8;
2247	TN_max_pairs = 64;
2248	TN_no_color_video = 0;
2249	break;
2250    }
2251}
2252
2253void
2254set_tty_color_mode (f, val)
2255     struct frame *f;
2256     Lisp_Object val;
2257{
2258  Lisp_Object color_mode_spec, current_mode_spec;
2259  Lisp_Object color_mode, current_mode;
2260  int mode, old_mode;
2261  extern Lisp_Object Qtty_color_mode;
2262  Lisp_Object tty_color_mode_alist;
2263
2264  tty_color_mode_alist = Fintern_soft (build_string ("tty-color-mode-alist"),
2265				       Qnil);
2266
2267  if (INTEGERP (val))
2268    color_mode = val;
2269  else
2270    {
2271      if (NILP (tty_color_mode_alist))
2272	color_mode_spec = Qnil;
2273      else
2274	color_mode_spec = Fassq (val, XSYMBOL (tty_color_mode_alist)->value);
2275
2276      if (CONSP (color_mode_spec))
2277	color_mode = XCDR (color_mode_spec);
2278      else
2279	color_mode = Qnil;
2280    }
2281
2282  current_mode_spec = assq_no_quit (Qtty_color_mode, f->param_alist);
2283
2284  if (CONSP (current_mode_spec))
2285    current_mode = XCDR (current_mode_spec);
2286  else
2287    current_mode = Qnil;
2288  if (INTEGERP (color_mode))
2289    mode = XINT (color_mode);
2290  else
2291    mode = 0;	/* meaning default */
2292  if (INTEGERP (current_mode))
2293    old_mode = XINT (current_mode);
2294  else
2295    old_mode = 0;
2296
2297  if (mode != old_mode)
2298    {
2299      tty_setup_colors (mode);
2300      /*  This recomputes all the faces given the new color
2301	  definitions.  */
2302      call0 (intern ("tty-set-up-initial-frame-faces"));
2303      redraw_frame (f);
2304    }
2305}
2306
2307#endif /* !WINDOWSNT */
2308
2309
2310/***********************************************************************
2311			    Initialization
2312 ***********************************************************************/
2313
2314void
2315term_init (terminal_type)
2316     char *terminal_type;
2317{
2318  char *area;
2319  char **address = &area;
2320  char *buffer = NULL;
2321  int buffer_size = 4096;
2322  register char *p;
2323  int status;
2324  struct frame *sf = XFRAME (selected_frame);
2325
2326  encode_terminal_bufsize = 0;
2327
2328#ifdef WINDOWSNT
2329  initialize_w32_display ();
2330
2331  Wcm_clear ();
2332
2333  area = (char *) xmalloc (2044);
2334
2335  FrameRows = FRAME_LINES (sf);
2336  FrameCols = FRAME_COLS (sf);
2337  specified_window = FRAME_LINES (sf);
2338
2339  delete_in_insert_mode = 1;
2340
2341  UseTabs = 0;
2342  scroll_region_ok = 0;
2343
2344  /* Seems to insert lines when it's not supposed to, messing
2345     up the display.  In doing a trace, it didn't seem to be
2346     called much, so I don't think we're losing anything by
2347     turning it off.  */
2348
2349  line_ins_del_ok = 0;
2350  char_ins_del_ok = 1;
2351
2352  baud_rate = 19200;
2353
2354  FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0;
2355  FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none;
2356  TN_max_colors = 16;  /* Required to be non-zero for tty-display-color-p */
2357
2358  return;
2359#else  /* not WINDOWSNT */
2360
2361  Wcm_clear ();
2362
2363  buffer = (char *) xmalloc (buffer_size);
2364  status = tgetent (buffer, terminal_type);
2365  if (status < 0)
2366    {
2367#ifdef TERMINFO
2368      fatal ("Cannot open terminfo database file");
2369#else
2370      fatal ("Cannot open termcap database file");
2371#endif
2372    }
2373  if (status == 0)
2374    {
2375#ifdef TERMINFO
2376      fatal ("Terminal type %s is not defined.\n\
2377If that is not the actual type of terminal you have,\n\
2378use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2379`setenv TERM ...') to specify the correct type.  It may be necessary\n\
2380to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
2381	     terminal_type);
2382#else
2383      fatal ("Terminal type %s is not defined.\n\
2384If that is not the actual type of terminal you have,\n\
2385use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2386`setenv TERM ...') to specify the correct type.  It may be necessary\n\
2387to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
2388	     terminal_type);
2389#endif
2390    }
2391
2392#ifndef TERMINFO
2393  if (strlen (buffer) >= buffer_size)
2394    abort ();
2395  buffer_size = strlen (buffer);
2396#endif
2397  area = (char *) xmalloc (buffer_size);
2398
2399  TS_ins_line = tgetstr ("al", address);
2400  TS_ins_multi_lines = tgetstr ("AL", address);
2401  TS_bell = tgetstr ("bl", address);
2402  BackTab = tgetstr ("bt", address);
2403  TS_clr_to_bottom = tgetstr ("cd", address);
2404  TS_clr_line = tgetstr ("ce", address);
2405  TS_clr_frame = tgetstr ("cl", address);
2406  ColPosition = NULL; /* tgetstr ("ch", address); */
2407  AbsPosition = tgetstr ("cm", address);
2408  CR = tgetstr ("cr", address);
2409  TS_set_scroll_region = tgetstr ("cs", address);
2410  TS_set_scroll_region_1 = tgetstr ("cS", address);
2411  RowPosition = tgetstr ("cv", address);
2412  TS_del_char = tgetstr ("dc", address);
2413  TS_del_multi_chars = tgetstr ("DC", address);
2414  TS_del_line = tgetstr ("dl", address);
2415  TS_del_multi_lines = tgetstr ("DL", address);
2416  TS_delete_mode = tgetstr ("dm", address);
2417  TS_end_delete_mode = tgetstr ("ed", address);
2418  TS_end_insert_mode = tgetstr ("ei", address);
2419  Home = tgetstr ("ho", address);
2420  TS_ins_char = tgetstr ("ic", address);
2421  TS_ins_multi_chars = tgetstr ("IC", address);
2422  TS_insert_mode = tgetstr ("im", address);
2423  TS_pad_inserted_char = tgetstr ("ip", address);
2424  TS_end_keypad_mode = tgetstr ("ke", address);
2425  TS_keypad_mode = tgetstr ("ks", address);
2426  LastLine = tgetstr ("ll", address);
2427  Right = tgetstr ("nd", address);
2428  Down = tgetstr ("do", address);
2429  if (!Down)
2430    Down = tgetstr ("nl", address); /* Obsolete name for "do" */
2431#ifdef VMS
2432  /* VMS puts a carriage return before each linefeed,
2433     so it is not safe to use linefeeds.  */
2434  if (Down && Down[0] == '\n' && Down[1] == '\0')
2435    Down = 0;
2436#endif /* VMS */
2437  if (tgetflag ("bs"))
2438    Left = "\b";		  /* can't possibly be longer! */
2439  else				  /* (Actually, "bs" is obsolete...) */
2440    Left = tgetstr ("le", address);
2441  if (!Left)
2442    Left = tgetstr ("bc", address); /* Obsolete name for "le" */
2443  TS_pad_char = tgetstr ("pc", address);
2444  TS_repeat = tgetstr ("rp", address);
2445  TS_end_standout_mode = tgetstr ("se", address);
2446  TS_fwd_scroll = tgetstr ("sf", address);
2447  TS_standout_mode = tgetstr ("so", address);
2448  TS_rev_scroll = tgetstr ("sr", address);
2449  Wcm.cm_tab = tgetstr ("ta", address);
2450  TS_end_termcap_modes = tgetstr ("te", address);
2451  TS_termcap_modes = tgetstr ("ti", address);
2452  Up = tgetstr ("up", address);
2453  TS_visible_bell = tgetstr ("vb", address);
2454  TS_cursor_normal = tgetstr ("ve", address);
2455  TS_cursor_visible = tgetstr ("vs", address);
2456  TS_cursor_invisible = tgetstr ("vi", address);
2457  TS_set_window = tgetstr ("wi", address);
2458
2459  TS_enter_underline_mode = tgetstr ("us", address);
2460  TS_exit_underline_mode = tgetstr ("ue", address);
2461  TS_enter_bold_mode = tgetstr ("md", address);
2462  TS_enter_dim_mode = tgetstr ("mh", address);
2463  TS_enter_blink_mode = tgetstr ("mb", address);
2464  TS_enter_reverse_mode = tgetstr ("mr", address);
2465  TS_enter_alt_charset_mode = tgetstr ("as", address);
2466  TS_exit_alt_charset_mode = tgetstr ("ae", address);
2467  TS_exit_attribute_mode = tgetstr ("me", address);
2468
2469  MultiUp = tgetstr ("UP", address);
2470  MultiDown = tgetstr ("DO", address);
2471  MultiLeft = tgetstr ("LE", address);
2472  MultiRight = tgetstr ("RI", address);
2473
2474  /* SVr4/ANSI color suppert.  If "op" isn't available, don't support
2475     color because we can't switch back to the default foreground and
2476     background.  */
2477  TS_orig_pair = tgetstr ("op", address);
2478  if (TS_orig_pair)
2479    {
2480      TS_set_foreground = tgetstr ("AF", address);
2481      TS_set_background = tgetstr ("AB", address);
2482      if (!TS_set_foreground)
2483	{
2484	  /* SVr4.  */
2485	  TS_set_foreground = tgetstr ("Sf", address);
2486	  TS_set_background = tgetstr ("Sb", address);
2487	}
2488
2489      TN_max_colors = tgetnum ("Co");
2490      TN_max_pairs = tgetnum ("pa");
2491
2492      TN_no_color_video = tgetnum ("NC");
2493      if (TN_no_color_video == -1)
2494	TN_no_color_video = 0;
2495    }
2496
2497  tty_default_color_capabilities (1);
2498
2499  MagicWrap = tgetflag ("xn");
2500  /* Since we make MagicWrap terminals look like AutoWrap, we need to have
2501     the former flag imply the latter.  */
2502  AutoWrap = MagicWrap || tgetflag ("am");
2503  memory_below_frame = tgetflag ("db");
2504  TF_hazeltine = tgetflag ("hz");
2505  must_write_spaces = tgetflag ("in");
2506  meta_key = tgetflag ("km") || tgetflag ("MT");
2507  TF_insmode_motion = tgetflag ("mi");
2508  TF_standout_motion = tgetflag ("ms");
2509  TF_underscore = tgetflag ("ul");
2510  TF_teleray = tgetflag ("xt");
2511
2512  term_get_fkeys (address);
2513
2514  /* Get frame size from system, or else from termcap.  */
2515  {
2516    int height, width;
2517    get_frame_size (&width, &height);
2518    FRAME_COLS (sf) = width;
2519    FRAME_LINES (sf) = height;
2520  }
2521
2522  if (FRAME_COLS (sf) <= 0)
2523    SET_FRAME_COLS (sf, tgetnum ("co"));
2524  else
2525    /* Keep width and external_width consistent */
2526    SET_FRAME_COLS (sf, FRAME_COLS (sf));
2527  if (FRAME_LINES (sf) <= 0)
2528    FRAME_LINES (sf) = tgetnum ("li");
2529
2530  if (FRAME_LINES (sf) < 3 || FRAME_COLS (sf) < 3)
2531    fatal ("Screen size %dx%d is too small",
2532	   FRAME_LINES (sf), FRAME_COLS (sf));
2533
2534  min_padding_speed = tgetnum ("pb");
2535  TabWidth = tgetnum ("tw");
2536
2537#ifdef VMS
2538  /* These capabilities commonly use ^J.
2539     I don't know why, but sending them on VMS does not work;
2540     it causes following spaces to be lost, sometimes.
2541     For now, the simplest fix is to avoid using these capabilities ever.  */
2542  if (Down && Down[0] == '\n')
2543    Down = 0;
2544#endif /* VMS */
2545
2546  if (!TS_bell)
2547    TS_bell = "\07";
2548
2549  if (!TS_fwd_scroll)
2550    TS_fwd_scroll = Down;
2551
2552  PC = TS_pad_char ? *TS_pad_char : 0;
2553
2554  if (TabWidth < 0)
2555    TabWidth = 8;
2556
2557/* Turned off since /etc/termcap seems to have :ta= for most terminals
2558   and newer termcap doc does not seem to say there is a default.
2559  if (!Wcm.cm_tab)
2560    Wcm.cm_tab = "\t";
2561*/
2562
2563  /* We don't support standout modes that use `magic cookies', so
2564     turn off any that do.  */
2565  if (TS_standout_mode && tgetnum ("sg") >= 0)
2566    {
2567      TS_standout_mode = 0;
2568      TS_end_standout_mode = 0;
2569    }
2570  if (TS_enter_underline_mode && tgetnum ("ug") >= 0)
2571    {
2572      TS_enter_underline_mode = 0;
2573      TS_exit_underline_mode = 0;
2574    }
2575
2576  /* If there's no standout mode, try to use underlining instead.  */
2577  if (TS_standout_mode == 0)
2578    {
2579      TS_standout_mode = TS_enter_underline_mode;
2580      TS_end_standout_mode = TS_exit_underline_mode;
2581    }
2582
2583  /* If no `se' string, try using a `me' string instead.
2584     If that fails, we can't use standout mode at all.  */
2585  if (TS_end_standout_mode == 0)
2586    {
2587      char *s = tgetstr ("me", address);
2588      if (s != 0)
2589	TS_end_standout_mode = s;
2590      else
2591	TS_standout_mode = 0;
2592    }
2593
2594  if (TF_teleray)
2595    {
2596      Wcm.cm_tab = 0;
2597      /* We can't support standout mode, because it uses magic cookies.  */
2598      TS_standout_mode = 0;
2599      /* But that means we cannot rely on ^M to go to column zero! */
2600      CR = 0;
2601      /* LF can't be trusted either -- can alter hpos */
2602      /* if move at column 0 thru a line with TS_standout_mode */
2603      Down = 0;
2604    }
2605
2606  /* Special handling for certain terminal types known to need it */
2607
2608  if (!strcmp (terminal_type, "supdup"))
2609    {
2610      memory_below_frame = 1;
2611      Wcm.cm_losewrap = 1;
2612    }
2613  if (!strncmp (terminal_type, "c10", 3)
2614      || !strcmp (terminal_type, "perq"))
2615    {
2616      /* Supply a makeshift :wi string.
2617	 This string is not valid in general since it works only
2618	 for windows starting at the upper left corner;
2619	 but that is all Emacs uses.
2620
2621	 This string works only if the frame is using
2622	 the top of the video memory, because addressing is memory-relative.
2623	 So first check the :ti string to see if that is true.
2624
2625	 It would be simpler if the :wi string could go in the termcap
2626	 entry, but it can't because it is not fully valid.
2627	 If it were in the termcap entry, it would confuse other programs.  */
2628      if (!TS_set_window)
2629	{
2630	  p = TS_termcap_modes;
2631	  while (*p && strcmp (p, "\033v  "))
2632	    p++;
2633	  if (*p)
2634	    TS_set_window = "\033v%C %C %C %C ";
2635	}
2636      /* Termcap entry often fails to have :in: flag */
2637      must_write_spaces = 1;
2638      /* :ti string typically fails to have \E^G! in it */
2639      /* This limits scope of insert-char to one line.  */
2640      strcpy (area, TS_termcap_modes);
2641      strcat (area, "\033\007!");
2642      TS_termcap_modes = area;
2643      area += strlen (area) + 1;
2644      p = AbsPosition;
2645      /* Change all %+ parameters to %C, to handle
2646	 values above 96 correctly for the C100.  */
2647      while (*p)
2648	{
2649	  if (p[0] == '%' && p[1] == '+')
2650	    p[1] = 'C';
2651	  p++;
2652	}
2653    }
2654
2655  FrameRows = FRAME_LINES (sf);
2656  FrameCols = FRAME_COLS (sf);
2657  specified_window = FRAME_LINES (sf);
2658
2659  if (Wcm_init () == -1)	/* can't do cursor motion */
2660#ifdef VMS
2661    fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2662It lacks the ability to position the cursor.\n\
2663If that is not the actual type of terminal you have, use either the\n\
2664DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
2665or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
2666           terminal_type);
2667#else /* not VMS */
2668# ifdef TERMINFO
2669    fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2670It lacks the ability to position the cursor.\n\
2671If that is not the actual type of terminal you have,\n\
2672use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2673`setenv TERM ...') to specify the correct type.  It may be necessary\n\
2674to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
2675	   terminal_type);
2676# else /* TERMCAP */
2677    fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2678It lacks the ability to position the cursor.\n\
2679If that is not the actual type of terminal you have,\n\
2680use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2681`setenv TERM ...') to specify the correct type.  It may be necessary\n\
2682to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
2683	   terminal_type);
2684# endif /* TERMINFO */
2685#endif /*VMS */
2686  if (FRAME_LINES (sf) <= 0
2687      || FRAME_COLS (sf) <= 0)
2688    fatal ("The frame size has not been specified");
2689
2690  delete_in_insert_mode
2691    = TS_delete_mode && TS_insert_mode
2692      && !strcmp (TS_delete_mode, TS_insert_mode);
2693
2694  se_is_so = (TS_standout_mode
2695	      && TS_end_standout_mode
2696	      && !strcmp (TS_standout_mode, TS_end_standout_mode));
2697
2698  UseTabs = tabs_safe_p () && TabWidth == 8;
2699
2700  scroll_region_ok
2701    = (Wcm.cm_abs
2702       && (TS_set_window || TS_set_scroll_region || TS_set_scroll_region_1));
2703
2704  line_ins_del_ok = (((TS_ins_line || TS_ins_multi_lines)
2705		      && (TS_del_line || TS_del_multi_lines))
2706		     || (scroll_region_ok && TS_fwd_scroll && TS_rev_scroll));
2707
2708  char_ins_del_ok = ((TS_ins_char || TS_insert_mode
2709		      || TS_pad_inserted_char || TS_ins_multi_chars)
2710		     && (TS_del_char || TS_del_multi_chars));
2711
2712  fast_clear_end_of_line = TS_clr_line != 0;
2713
2714  init_baud_rate ();
2715  if (read_socket_hook)		/* Baudrate is somewhat */
2716				/* meaningless in this case */
2717    baud_rate = 9600;
2718
2719  FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0;
2720  FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none;
2721#endif /* WINDOWSNT */
2722
2723  xfree (buffer);
2724}
2725
2726/* VARARGS 1 */
2727void
2728fatal (str, arg1, arg2)
2729     char *str, *arg1, *arg2;
2730{
2731  fprintf (stderr, "emacs: ");
2732  fprintf (stderr, str, arg1, arg2);
2733  fprintf (stderr, "\n");
2734  fflush (stderr);
2735  exit (1);
2736}
2737
2738DEFUN ("tty-no-underline", Ftty_no_underline, Stty_no_underline, 0, 0, 0,
2739       doc: /* Declare that this terminal does not handle underlining.
2740This is used to override the terminfo data, for certain terminals that
2741do not really do underlining, but say that they do.  */)
2742  ()
2743{
2744  TS_enter_underline_mode = 0;
2745  return Qnil;
2746}
2747
2748void
2749syms_of_term ()
2750{
2751  DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
2752    doc: /* Non-nil means the system uses terminfo rather than termcap.
2753This variable can be used by terminal emulator packages.  */);
2754#ifdef TERMINFO
2755  system_uses_terminfo = 1;
2756#else
2757  system_uses_terminfo = 0;
2758#endif
2759
2760  DEFVAR_LISP ("ring-bell-function", &Vring_bell_function,
2761    doc: /* Non-nil means call this function to ring the bell.
2762The function should accept no arguments.  */);
2763  Vring_bell_function = Qnil;
2764
2765  DEFVAR_BOOL ("visible-cursor", &visible_cursor,
2766	       doc: /* Non-nil means to make the cursor very visible.
2767This only has an effect when running in a text terminal.
2768What means \"very visible\" is up to your terminal.  It may make the cursor
2769bigger, or it may make it blink, or it may do nothing at all.  */);
2770  visible_cursor = 1;
2771
2772  defsubr (&Stty_display_color_p);
2773  defsubr (&Stty_display_color_cells);
2774  defsubr (&Stty_no_underline);
2775
2776  fullscreen_hook = NULL;
2777}
2778
2779/* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193
2780   (do not change this comment) */
2781