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