1 /* terminal control module for terminals described by TERMCAP
2 Copyright (C) 1985, 86, 87, 93, 94, 95, 98
3 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
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)
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.
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., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* New redisplay, TTY faces by Gerd Moellmann <gerd@acm.org>. */
36 #include "termhooks.h"
38 #include "dispextern.h"
46 static void turn_on_face
P_ ((struct frame
*, int face_id
));
47 static void turn_off_face
P_ ((struct frame
*, int face_id
));
48 static void tty_show_cursor
P_ ((void));
49 static void tty_hide_cursor
P_ ((void));
51 #define max(a, b) ((a) > (b) ? (a) : (b))
52 #define min(a, b) ((a) < (b) ? (a) : (b))
54 #define OUTPUT(a) tputs (a, (int) (FRAME_HEIGHT (selected_frame) - curY), cmputc)
55 #define OUTPUT1(a) tputs (a, 1, cmputc)
56 #define OUTPUTL(a, lines) tputs (a, lines, cmputc)
58 #define OUTPUT_IF(a) \
60 tputs (a, (int) (FRAME_HEIGHT (selected_frame) - curY), cmputc); \
64 #define OUTPUT1_IF(a) if (a) tputs (a, 1, cmputc); else (void) 0
66 /* Function to use to ring the bell. */
68 Lisp_Object Vring_bell_function
;
70 /* Terminal characteristics that higher levels want to look at.
71 These are all extern'd in termchar.h */
73 int must_write_spaces
; /* Nonzero means spaces in the text
74 must actually be output; can't just skip
75 over some columns to leave them blank. */
76 int min_padding_speed
; /* Speed below which no padding necessary */
78 int line_ins_del_ok
; /* Terminal can insert and delete lines */
79 int char_ins_del_ok
; /* Terminal can insert and delete chars */
80 int scroll_region_ok
; /* Terminal supports setting the
82 int scroll_region_cost
; /* Cost of setting a scroll window,
83 measured in characters */
84 int memory_below_frame
; /* Terminal remembers lines
85 scrolled off bottom */
86 int fast_clear_end_of_line
; /* Terminal has a `ce' string */
88 /* Nonzero means no need to redraw the entire frame on resuming
89 a suspended Emacs. This is useful on terminals with multiple pages,
90 where one page is used for Emacs and another for all else. */
92 int no_redraw_on_reenter
;
94 /* Hook functions that you can set to snap out the functions in this file.
95 These are all extern'd in termhooks.h */
97 void (*cursor_to_hook
) P_ ((int, int));
98 void (*raw_cursor_to_hook
) P_ ((int, int));
99 void (*clear_to_end_hook
) P_ ((void));
100 void (*clear_frame_hook
) P_ ((void));
101 void (*clear_end_of_line_hook
) P_ ((int));
103 void (*ins_del_lines_hook
) P_ ((int, int));
105 void (*change_line_highlight_hook
) P_ ((int, int, int, int));
106 void (*reassert_line_highlight_hook
) P_ ((int, int));
108 void (*delete_glyphs_hook
) P_ ((int));
110 void (*ring_bell_hook
) P_ ((void));
112 void (*reset_terminal_modes_hook
) P_ ((void));
113 void (*set_terminal_modes_hook
) P_ ((void));
114 void (*update_begin_hook
) P_ ((struct frame
*));
115 void (*update_end_hook
) P_ ((struct frame
*));
116 void (*set_terminal_window_hook
) P_ ((int));
117 void (*insert_glyphs_hook
) P_ ((struct glyph
*, int));
118 void (*write_glyphs_hook
) P_ ((struct glyph
*, int));
119 void (*delete_glyphs_hook
) P_ ((int));
121 int (*read_socket_hook
) P_ ((int, struct input_event
*, int, int));
123 void (*frame_up_to_date_hook
) P_ ((struct frame
*));
125 /* Return the current position of the mouse.
127 Set *f to the frame the mouse is in, or zero if the mouse is in no
128 Emacs frame. If it is set to zero, all the other arguments are
131 If the motion started in a scroll bar, set *bar_window to the
132 scroll bar's window, *part to the part the mouse is currently over,
133 *x to the position of the mouse along the scroll bar, and *y to the
134 overall length of the scroll bar.
136 Otherwise, set *bar_window to Qnil, and *x and *y to the column and
137 row of the character cell the mouse is over.
139 Set *time to the time the mouse was at the returned position.
141 This should clear mouse_moved until the next motion
143 void (*mouse_position_hook
) P_ ((FRAME_PTR
*f
, int insist
,
144 Lisp_Object
*bar_window
,
145 enum scroll_bar_part
*part
,
148 unsigned long *time
));
150 /* When reading from a minibuffer in a different frame, Emacs wants
151 to shift the highlight from the selected frame to the mini-buffer's
152 frame; under X, this means it lies about where the focus is.
153 This hook tells the window system code to re-decide where to put
155 void (*frame_rehighlight_hook
) P_ ((FRAME_PTR f
));
157 /* If we're displaying frames using a window system that can stack
158 frames on top of each other, this hook allows you to bring a frame
159 to the front, or bury it behind all the other windows. If this
160 hook is zero, that means the device we're displaying on doesn't
161 support overlapping frames, so there's no need to raise or lower
164 If RAISE is non-zero, F is brought to the front, before all other
165 windows. If RAISE is zero, F is sent to the back, behind all other
167 void (*frame_raise_lower_hook
) P_ ((FRAME_PTR f
, int raise
));
169 /* Set the vertical scroll bar for WINDOW to have its upper left corner
170 at (TOP, LEFT), and be LENGTH rows high. Set its handle to
171 indicate that we are displaying PORTION characters out of a total
172 of WHOLE characters, starting at POSITION. If WINDOW doesn't yet
173 have a scroll bar, create one for it. */
175 void (*set_vertical_scroll_bar_hook
)
176 P_ ((struct window
*window
,
177 int portion
, int whole
, int position
));
180 /* The following three hooks are used when we're doing a thorough
181 redisplay of the frame. We don't explicitly know which scroll bars
182 are going to be deleted, because keeping track of when windows go
183 away is a real pain - can you say set-window-configuration?
184 Instead, we just assert at the beginning of redisplay that *all*
185 scroll bars are to be removed, and then save scroll bars from the
186 fiery pit when we actually redisplay their window. */
188 /* Arrange for all scroll bars on FRAME to be removed at the next call
189 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
190 `*redeem_scroll_bar_hook' is applied to its window before the judgment.
192 This should be applied to each frame each time its window tree is
193 redisplayed, even if it is not displaying scroll bars at the moment;
194 if the HAS_SCROLL_BARS flag has just been turned off, only calling
195 this and the judge_scroll_bars_hook will get rid of them.
197 If non-zero, this hook should be safe to apply to any frame,
198 whether or not it can support scroll bars, and whether or not it is
199 currently displaying them. */
200 void (*condemn_scroll_bars_hook
) P_ ((FRAME_PTR frame
));
202 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
203 Note that it's okay to redeem a scroll bar that is not condemned. */
204 void (*redeem_scroll_bar_hook
) P_ ((struct window
*window
));
206 /* Remove all scroll bars on FRAME that haven't been saved since the
207 last call to `*condemn_scroll_bars_hook'.
209 This should be applied to each frame after each time its window
210 tree is redisplayed, even if it is not displaying scroll bars at the
211 moment; if the HAS_SCROLL_BARS flag has just been turned off, only
212 calling this and condemn_scroll_bars_hook will get rid of them.
214 If non-zero, this hook should be safe to apply to any frame,
215 whether or not it can support scroll bars, and whether or not it is
216 currently displaying them. */
217 void (*judge_scroll_bars_hook
) P_ ((FRAME_PTR FRAME
));
219 /* Hook to call in estimate_mode_line_height, if any. */
221 int (* estimate_mode_line_height_hook
) P_ ((struct frame
*f
, enum face_id
));
224 /* Strings, numbers and flags taken from the termcap entry. */
226 char *TS_ins_line
; /* "al" */
227 char *TS_ins_multi_lines
; /* "AL" (one parameter, # lines to insert) */
228 char *TS_bell
; /* "bl" */
229 char *TS_clr_to_bottom
; /* "cd" */
230 char *TS_clr_line
; /* "ce", clear to end of line */
231 char *TS_clr_frame
; /* "cl" */
232 char *TS_set_scroll_region
; /* "cs" (2 params, first line and last line) */
233 char *TS_set_scroll_region_1
; /* "cS" (4 params: total lines,
234 lines above scroll region, lines below it,
235 total lines again) */
236 char *TS_del_char
; /* "dc" */
237 char *TS_del_multi_chars
; /* "DC" (one parameter, # chars to delete) */
238 char *TS_del_line
; /* "dl" */
239 char *TS_del_multi_lines
; /* "DL" (one parameter, # lines to delete) */
240 char *TS_delete_mode
; /* "dm", enter character-delete mode */
241 char *TS_end_delete_mode
; /* "ed", leave character-delete mode */
242 char *TS_end_insert_mode
; /* "ei", leave character-insert mode */
243 char *TS_ins_char
; /* "ic" */
244 char *TS_ins_multi_chars
; /* "IC" (one parameter, # chars to insert) */
245 char *TS_insert_mode
; /* "im", enter character-insert mode */
246 char *TS_pad_inserted_char
; /* "ip". Just padding, no commands. */
247 char *TS_end_keypad_mode
; /* "ke" */
248 char *TS_keypad_mode
; /* "ks" */
249 char *TS_pad_char
; /* "pc", char to use as padding */
250 char *TS_repeat
; /* "rp" (2 params, # times to repeat
251 and character to be repeated) */
252 char *TS_end_standout_mode
; /* "se" */
253 char *TS_fwd_scroll
; /* "sf" */
254 char *TS_standout_mode
; /* "so" */
255 char *TS_rev_scroll
; /* "sr" */
256 char *TS_end_termcap_modes
; /* "te" */
257 char *TS_termcap_modes
; /* "ti" */
258 char *TS_visible_bell
; /* "vb" */
259 char *TS_cursor_normal
; /* "ve" */
260 char *TS_cursor_visible
; /* "vs" */
261 char *TS_cursor_invisible
; /* "vi" */
262 char *TS_set_window
; /* "wi" (4 params, start and end of window,
263 each as vpos and hpos) */
265 /* "md" -- turn on bold (extra bright mode). */
267 char *TS_enter_bold_mode
;
269 /* "mh" -- turn on half-bright mode. */
271 char *TS_enter_dim_mode
;
273 /* "mb" -- enter blinking mode. */
275 char *TS_enter_blink_mode
;
277 /* "mr" -- enter reverse video mode. */
279 char *TS_enter_reverse_mode
;
281 /* "us"/"ue" -- start/end underlining. */
283 char *TS_exit_underline_mode
, *TS_enter_underline_mode
;
285 /* "ug" -- number of blanks left by underline. */
287 int TN_magic_cookie_glitch_ul
;
289 /* "as"/"ae" -- start/end alternate character set. Not really
292 char *TS_enter_alt_charset_mode
, *TS_exit_alt_charset_mode
;
294 /* "me" -- switch appearances off. */
296 char *TS_exit_attribute_mode
;
298 /* "Co" -- number of colors. */
302 /* "pa" -- max. number of color pairs on screen. Not handled yet.
303 Could be a problem if not equal to TN_max_colors * TN_max_colors. */
307 /* "op" -- SVr4 set default pair to its original value. */
311 /* "AF"/"AB" or "Sf"/"Sb"-- set ANSI or SVr4 foreground/background color.
312 1 param, the color index. */
314 char *TS_set_foreground
, *TS_set_background
;
316 int TF_hazeltine
; /* termcap hz flag. */
317 int TF_insmode_motion
; /* termcap mi flag: can move while in insert mode. */
318 int TF_standout_motion
; /* termcap mi flag: can move while in standout mode. */
319 int TF_underscore
; /* termcap ul flag: _ underlines if over-struck on
320 non-blank position. Must clear before writing _. */
321 int TF_teleray
; /* termcap xt flag: many weird consequences.
324 int TF_xs
; /* Nonzero for "xs". If set together with
325 TN_standout_width == 0, it means don't bother
326 to write any end-standout cookies. */
328 int TN_standout_width
; /* termcap sg number: width occupied by standout
331 static int RPov
; /* # chars to start a TS_repeat */
333 static int delete_in_insert_mode
; /* delete mode == insert mode */
335 static int se_is_so
; /* 1 if same string both enters and leaves
340 /* The largest frame width in any call to calculate_costs. */
344 /* The largest frame height in any call to calculate_costs. */
346 int max_frame_height
;
348 /* Number of chars of space used for standout marker at beginning of line,
349 or'd with 0100. Zero if no standout marker at all.
350 The length of these vectors is max_frame_height.
352 Used IFF TN_standout_width >= 0. */
354 static char *chars_wasted
;
355 static char *copybuf
;
357 /* nonzero means supposed to write text in standout mode. */
359 int standout_requested
;
361 int insert_mode
; /* Nonzero when in insert mode. */
362 int standout_mode
; /* Nonzero when in standout mode. */
364 /* Size of window specified by higher levels.
365 This is the number of lines, from the top of frame downwards,
366 which can participate in insert-line/delete-line operations.
368 Effectively it excludes the bottom frame_height - specified_window_size
369 lines from those operations. */
371 int specified_window
;
373 /* Frame currently being redisplayed; 0 if not currently redisplaying.
374 (Direct output does not count). */
376 FRAME_PTR updating_frame
;
378 /* Provided for lisp packages. */
380 static int system_uses_terminfo
;
384 extern char *tgetstr ();
389 /* We aren't X windows, but we aren't termcap either. This makes me
390 uncertain as to what value to use for frame.output_method. For
391 this file, we'll define FRAME_TERMCAP_P to be zero so that our
392 output hooks get called instead of the termcap functions. Probably
393 the best long-term solution is to define an output_windows_nt... */
395 #undef FRAME_TERMCAP_P
396 #define FRAME_TERMCAP_P(_f_) 0
397 #endif /* WINDOWSNT */
402 if (! NILP (Vring_bell_function
))
404 Lisp_Object function
;
406 /* Temporarily set the global variable to nil
407 so that if we get an error, it stays nil
408 and we don't call it over and over.
410 We don't specbind it, because that would carefully
411 restore the bad value if there's an error
412 and make the loop of errors happen anyway. */
413 function
= Vring_bell_function
;
414 Vring_bell_function
= Qnil
;
418 Vring_bell_function
= function
;
422 if (! FRAME_TERMCAP_P (selected_frame
))
424 (*ring_bell_hook
) ();
427 OUTPUT (TS_visible_bell
&& visible_bell
? TS_visible_bell
: TS_bell
);
431 set_terminal_modes ()
433 if (! FRAME_TERMCAP_P (selected_frame
))
435 (*set_terminal_modes_hook
) ();
438 OUTPUT_IF (TS_termcap_modes
);
439 OUTPUT_IF (TS_cursor_visible
);
440 OUTPUT_IF (TS_keypad_mode
);
445 reset_terminal_modes ()
447 if (! FRAME_TERMCAP_P (selected_frame
))
449 if (reset_terminal_modes_hook
)
450 (*reset_terminal_modes_hook
) ();
453 if (TN_standout_width
< 0)
454 turn_off_highlight ();
456 OUTPUT_IF (TS_end_keypad_mode
);
457 OUTPUT_IF (TS_cursor_normal
);
458 OUTPUT_IF (TS_end_termcap_modes
);
459 OUTPUT_IF (TS_orig_pair
);
460 /* Output raw CR so kernel can track the cursor hpos. */
461 /* But on magic-cookie terminals this can erase an end-standout marker and
462 cause the rest of the frame to be in standout, so move down first. */
463 if (TN_standout_width
>= 0)
473 if (! FRAME_TERMCAP_P (updating_frame
))
474 (*update_begin_hook
) (f
);
483 if (! FRAME_TERMCAP_P (updating_frame
))
485 (*update_end_hook
) (f
);
490 if (!XWINDOW (selected_window
)->cursor_off_p
)
494 background_highlight ();
495 standout_requested
= 0;
500 set_terminal_window (size
)
503 if (! FRAME_TERMCAP_P (updating_frame
))
505 (*set_terminal_window_hook
) (size
);
508 specified_window
= size
? size
: FRAME_HEIGHT (selected_frame
);
509 if (!scroll_region_ok
)
511 set_scroll_region (0, specified_window
);
515 set_scroll_region (start
, stop
)
519 if (TS_set_scroll_region
)
521 buf
= tparam (TS_set_scroll_region
, 0, 0, start
, stop
- 1);
523 else if (TS_set_scroll_region_1
)
525 buf
= tparam (TS_set_scroll_region_1
, 0, 0,
526 FRAME_HEIGHT (selected_frame
), start
,
527 FRAME_HEIGHT (selected_frame
) - stop
,
528 FRAME_HEIGHT (selected_frame
));
532 buf
= tparam (TS_set_window
, 0, 0, start
, 0, stop
, FRAME_WIDTH (selected_frame
));
543 OUTPUT (TS_insert_mode
);
551 OUTPUT (TS_end_insert_mode
);
555 /* Handle highlighting when TN_standout_width (termcap sg) is not specified.
556 In these terminals, output is affected by the value of standout
557 mode when the output is written.
559 These functions are called on all terminals, but do nothing
560 on terminals whose standout mode does not work that way. */
563 turn_off_highlight ()
565 if (TN_standout_width
< 0)
568 OUTPUT_IF (TS_end_standout_mode
);
576 if (TN_standout_width
< 0)
579 OUTPUT_IF (TS_standout_mode
);
585 /* Make cursor invisible. */
590 OUTPUT_IF (TS_cursor_invisible
);
594 /* Ensure that cursor is visible. */
599 OUTPUT_IF (TS_cursor_normal
);
600 OUTPUT_IF (TS_cursor_visible
);
604 /* Set standout mode to the state it should be in for
605 empty space inside windows. What this is,
606 depends on the user option inverse-video. */
609 background_highlight ()
611 if (TN_standout_width
>= 0)
614 turn_on_highlight ();
616 turn_off_highlight ();
619 /* Set standout mode to the mode specified for the text to be output. */
622 highlight_if_desired ()
624 if (TN_standout_width
>= 0)
626 if (!inverse_video
== !standout_requested
)
627 turn_off_highlight ();
629 turn_on_highlight ();
632 /* Handle standout mode for terminals in which TN_standout_width >= 0.
633 On these terminals, standout is controlled by markers that
634 live inside the terminal's memory. TN_standout_width is the width
635 that the marker occupies in memory. Standout runs from the marker
636 to the end of the line on some terminals, or to the next
637 turn-off-standout marker (TS_end_standout_mode) string
638 on other terminals. */
640 /* Write a standout marker or end-standout marker at the front of the line
641 at vertical position vpos. */
644 write_standout_marker (flag
, vpos
)
647 if (flag
|| (TS_end_standout_mode
&& !TF_teleray
&& !se_is_so
648 && !(TF_xs
&& TN_standout_width
== 0)))
651 cmplus (TN_standout_width
);
652 OUTPUT (flag
? TS_standout_mode
: TS_end_standout_mode
);
653 chars_wasted
[curY
] = TN_standout_width
| 0100;
657 /* External interface to control of standout mode.
658 Call this when about to modify line at position VPOS
659 and not change whether it is highlighted. */
662 reassert_line_highlight (highlight
, vpos
)
666 if (! FRAME_TERMCAP_P ((updating_frame
? updating_frame
: selected_frame
)))
668 (*reassert_line_highlight_hook
) (highlight
, vpos
);
671 if (TN_standout_width
< 0)
672 /* Handle terminals where standout takes affect at output time */
673 standout_requested
= highlight
;
674 else if (chars_wasted
&& chars_wasted
[vpos
] == 0)
675 /* For terminals with standout markers, write one on this line
676 if there isn't one already. */
677 write_standout_marker (highlight
, vpos
);
680 /* Call this when about to modify line at position VPOS
681 and change whether it is highlighted. */
684 change_line_highlight (new_highlight
, vpos
, y
, first_unused_hpos
)
685 int new_highlight
, vpos
, y
, first_unused_hpos
;
687 standout_requested
= new_highlight
;
688 if (! FRAME_TERMCAP_P (updating_frame
))
690 (*change_line_highlight_hook
) (new_highlight
, vpos
, y
, first_unused_hpos
);
696 if (TN_standout_width
< 0)
697 background_highlight ();
698 /* If line starts with a marker, delete the marker */
699 else if (TS_clr_line
&& chars_wasted
[curY
])
702 /* On Teleray, make sure to erase the SO marker. */
705 cmgoto (curY
- 1, FRAME_WIDTH (selected_frame
) - 4);
707 curY
++; /* ESC S moves to next line where the TS_standout_mode was */
711 cmgoto (curY
, 0); /* reposition to kill standout marker */
713 clear_end_of_line_raw (first_unused_hpos
);
714 reassert_line_highlight (new_highlight
, curY
);
718 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
719 frame-relative coordinates. */
722 cursor_to (vpos
, hpos
)
725 if (! FRAME_TERMCAP_P ((updating_frame
? updating_frame
: selected_frame
))
728 (*cursor_to_hook
) (vpos
, hpos
);
732 /* Detect the case where we are called from reset_sys_modes
733 and the costs have never been calculated. Do nothing. */
734 if (chars_wasted
== 0)
737 hpos
+= chars_wasted
[vpos
] & 077;
738 if (curY
== vpos
&& curX
== hpos
)
740 if (!TF_standout_motion
)
741 background_highlight ();
742 if (!TF_insmode_motion
)
747 /* Similar but don't take any account of the wasted characters. */
750 raw_cursor_to (row
, col
)
753 if (! FRAME_TERMCAP_P ((updating_frame
? updating_frame
: selected_frame
)))
755 (*raw_cursor_to_hook
) (row
, col
);
758 if (curY
== row
&& curX
== col
)
760 if (!TF_standout_motion
)
761 background_highlight ();
762 if (!TF_insmode_motion
)
767 /* Erase operations */
769 /* clear from cursor to end of frame */
775 if (clear_to_end_hook
&& ! FRAME_TERMCAP_P (updating_frame
))
777 (*clear_to_end_hook
) ();
780 if (TS_clr_to_bottom
)
782 background_highlight ();
783 OUTPUT (TS_clr_to_bottom
);
784 bzero (chars_wasted
+ curY
, FRAME_HEIGHT (selected_frame
) - curY
);
788 for (i
= curY
; i
< FRAME_HEIGHT (selected_frame
); i
++)
791 clear_end_of_line_raw (FRAME_WIDTH (selected_frame
));
796 /* Clear entire frame */
802 && ! FRAME_TERMCAP_P ((updating_frame
? updating_frame
: selected_frame
)))
804 (*clear_frame_hook
) ();
809 background_highlight ();
810 OUTPUT (TS_clr_frame
);
811 bzero (chars_wasted
, FRAME_HEIGHT (selected_frame
));
821 /* Clear to end of line, but do not clear any standout marker.
822 Assumes that the cursor is positioned at a character of real text,
823 which implies it cannot be before a standout marker
824 unless the marker has zero width.
826 Note that the cursor may be moved. */
829 clear_end_of_line (first_unused_hpos
)
830 int first_unused_hpos
;
832 if (FRAME_TERMCAP_P (selected_frame
)
834 && TN_standout_width
== 0 && curX
== 0 && chars_wasted
[curY
] != 0)
835 write_glyphs (&space_glyph
, 1);
836 clear_end_of_line_raw (first_unused_hpos
);
839 /* Clear from cursor to end of line.
840 Assume that the line is already clear starting at column first_unused_hpos.
841 If the cursor is at a standout marker, erase the marker.
843 Note that the cursor may be moved, on terminals lacking a `ce' string. */
846 clear_end_of_line_raw (first_unused_hpos
)
847 int first_unused_hpos
;
851 if (clear_end_of_line_hook
852 && ! FRAME_TERMCAP_P ((updating_frame
856 (*clear_end_of_line_hook
) (first_unused_hpos
);
860 /* Detect the case where we are called from reset_sys_modes
861 and the costs have never been calculated. Do nothing. */
862 if (chars_wasted
== 0)
865 first_unused_hpos
+= chars_wasted
[curY
] & 077;
866 if (curX
>= first_unused_hpos
)
868 /* Notice if we are erasing a magic cookie */
870 chars_wasted
[curY
] = 0;
871 background_highlight ();
874 OUTPUT1 (TS_clr_line
);
877 { /* have to do it the hard way */
880 /* Do not write in last row last col with Auto-wrap on. */
881 if (AutoWrap
&& curY
== FRAME_HEIGHT (selected_frame
) - 1
882 && first_unused_hpos
== FRAME_WIDTH (selected_frame
))
885 for (i
= curX
; i
< first_unused_hpos
; i
++)
888 fputc (' ', termscript
);
891 cmplus (first_unused_hpos
- curX
);
895 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes and
896 store them at DST. Do not write more than DST_LEN bytes. That may
897 require stopping before all SRC_LEN input glyphs have been
900 We store the number of glyphs actually converted in *CONSUMED. The
901 return value is the number of bytes store in DST. */
904 encode_terminal_code (src
, dst
, src_len
, dst_len
, consumed
)
908 int dst_len
, *consumed
;
910 struct glyph
*src_start
= src
, *src_end
= src
+ src_len
;
911 unsigned char *dst_start
= dst
, *dst_end
= dst
+ dst_len
;
914 unsigned char workbuf
[4], *buf
;
916 register int tlen
= GLYPH_TABLE_LENGTH
;
917 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
919 struct coding_system
*coding
;
921 coding
= (CODING_REQUIRE_ENCODING (&terminal_coding
)
923 : &safe_terminal_coding
);
925 while (src
< src_end
)
927 g
= GLYPH_FROM_CHAR_GLYPH (*src
);
929 /* We must skip glyphs to be padded for a wide character. */
930 if (! CHAR_GLYPH_PADDING_P (*src
))
933 if (! GLYPH_CHAR_VALID_P (c
))
936 g
= MAKE_GLYPH (selected_frame
, c
,
937 GLYPH_FACE (selected_frame
, g
));
939 if (COMPOSITE_CHAR_P (c
))
941 /* If C is a composite character, we can display
942 only the first component. */
943 g
= cmpchar_table
[COMPOSITE_CHAR_ID (c
)]->glyph
[0],
944 c
= GLYPH_CHAR (selected_frame
, g
);
948 /* G has an entry in Vglyph_table,
949 so process any alias before testing for simpleness. */
950 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
951 c
= GLYPH_CHAR (selected_frame
, g
);
953 if (GLYPH_SIMPLE_P (tbase
, tlen
, g
))
954 /* We set the multi-byte form of C at BUF. */
955 len
= CHAR_STRING (c
, workbuf
, buf
);
958 /* We have a string in Vglyph_table. */
959 len
= GLYPH_LENGTH (tbase
, g
);
960 buf
= GLYPH_STRING (tbase
, g
);
963 result
= encode_coding (coding
, buf
, dst
, len
, dst_end
- dst
);
964 len
-= coding
->consumed
;
965 dst
+= coding
->produced
;
966 if (result
== CODING_FINISH_INSUFFICIENT_DST
967 || (result
== CODING_FINISH_INSUFFICIENT_SRC
968 && len
> dst_end
- dst
))
969 /* The remaining output buffer is too short. We must
970 break the loop here without increasing SRC so that the
971 next call of this function starts from the same glyph. */
976 /* This is the case that a code of the range 0200..0237
977 exists in buf. We must just write out such a code. */
978 buf
+= coding
->consumed
;
986 *consumed
= src
- src_start
;
987 return (dst
- dst_start
);
992 write_glyphs (string
, len
)
993 register struct glyph
*string
;
996 int produced
, consumed
;
997 struct frame
*f
= updating_frame
? updating_frame
: selected_frame
;
999 if (write_glyphs_hook
1000 && ! FRAME_TERMCAP_P (f
))
1002 (*write_glyphs_hook
) (string
, len
);
1006 highlight_if_desired ();
1009 /* Don't dare write in last column of bottom line, if Auto-Wrap,
1010 since that would scroll the whole frame on some terminals. */
1013 && curY
+ 1 == FRAME_HEIGHT (selected_frame
)
1014 && (curX
+ len
- (chars_wasted
[curY
] & 077)
1015 == FRAME_WIDTH (selected_frame
)))
1022 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
1024 terminal_coding
.mode
&= ~CODING_MODE_LAST_BLOCK
;
1028 /* Identify a run of glyphs with the same face. */
1029 int face_id
= string
->u
.ch
.face_id
;
1032 for (n
= 1; n
< len
; ++n
)
1033 if (string
[n
].u
.ch
.face_id
!= face_id
)
1036 /* Turn appearance modes of the face of the run on. */
1037 turn_on_face (f
, face_id
);
1041 /* We use a shared conversion buffer of the current size
1042 (1024 bytes at least). Usually it is sufficient, but if
1043 not, we just repeat the loop. */
1044 produced
= encode_terminal_code (string
, conversion_buffer
,
1045 n
, conversion_buffer_size
,
1049 fwrite (conversion_buffer
, 1, produced
, stdout
);
1050 if (ferror (stdout
))
1053 fwrite (conversion_buffer
, 1, produced
, termscript
);
1060 /* Turn appearance modes off. */
1061 turn_off_face (f
, face_id
);
1064 /* We may have to output some codes to terminate the writing. */
1065 if (CODING_REQUIRE_FLUSHING (&terminal_coding
))
1067 terminal_coding
.mode
|= CODING_MODE_LAST_BLOCK
;
1068 encode_coding (&terminal_coding
, "", conversion_buffer
,
1069 0, conversion_buffer_size
);
1070 if (terminal_coding
.produced
> 0)
1072 fwrite (conversion_buffer
, 1, terminal_coding
.produced
, stdout
);
1073 if (ferror (stdout
))
1076 fwrite (conversion_buffer
, 1, terminal_coding
.produced
,
1084 /* If start is zero, insert blanks instead of a string at start */
1087 insert_glyphs (start
, len
)
1088 register struct glyph
*start
;
1098 if (insert_glyphs_hook
)
1100 (*insert_glyphs_hook
) (start
, len
);
1104 f
= updating_frame
? updating_frame
: selected_frame
;
1105 highlight_if_desired ();
1107 if (TS_ins_multi_chars
)
1109 buf
= tparam (TS_ins_multi_chars
, 0, 0, len
);
1113 write_glyphs (start
, len
);
1119 /* The bit CODING_MODE_LAST_BLOCK should be set to 1 only at the tail. */
1120 terminal_coding
.mode
&= ~CODING_MODE_LAST_BLOCK
;
1123 int produced
, consumed
;
1126 OUTPUT1_IF (TS_ins_char
);
1131 g
= GLYPH_FROM_CHAR_GLYPH (*start
);
1133 /* We must open sufficient space for a character which
1134 occupies more than one column. */
1135 while (len
&& CHAR_GLYPH_PADDING_P (*start
))
1137 OUTPUT1_IF (TS_ins_char
);
1143 /* This is the last glyph. */
1144 terminal_coding
.mode
|= CODING_MODE_LAST_BLOCK
;
1146 /* We use shared conversion buffer of the current size (1024
1147 bytes at least). It is surely sufficient for just one glyph. */
1148 SET_CHAR_GLYPH_FROM_GLYPH (glyph
, g
);
1149 turn_on_face (f
, glyph
.u
.ch
.face_id
);
1150 produced
= encode_terminal_code (&glyph
, conversion_buffer
,
1151 1, conversion_buffer_size
, &consumed
);
1154 fwrite (conversion_buffer
, 1, produced
, stdout
);
1155 if (ferror (stdout
))
1158 fwrite (conversion_buffer
, 1, produced
, termscript
);
1161 OUTPUT1_IF (TS_pad_inserted_char
);
1162 turn_off_face (f
, glyph
.u
.ch
.face_id
);
1175 if (delete_glyphs_hook
&& ! FRAME_TERMCAP_P (updating_frame
))
1177 (*delete_glyphs_hook
) (n
);
1181 if (delete_in_insert_mode
)
1188 OUTPUT_IF (TS_delete_mode
);
1191 if (TS_del_multi_chars
)
1193 buf
= tparam (TS_del_multi_chars
, 0, 0, n
);
1198 for (i
= 0; i
< n
; i
++)
1199 OUTPUT1 (TS_del_char
);
1200 if (!delete_in_insert_mode
)
1201 OUTPUT_IF (TS_end_delete_mode
);
1204 /* Insert N lines at vpos VPOS. If N is negative, delete -N lines. */
1207 ins_del_lines (vpos
, n
)
1210 char *multi
= n
> 0 ? TS_ins_multi_lines
: TS_del_multi_lines
;
1211 char *single
= n
> 0 ? TS_ins_line
: TS_del_line
;
1212 char *scroll
= n
> 0 ? TS_rev_scroll
: TS_fwd_scroll
;
1214 register int i
= n
> 0 ? n
: -n
;
1217 if (ins_del_lines_hook
&& ! FRAME_TERMCAP_P (updating_frame
))
1219 (*ins_del_lines_hook
) (vpos
, n
);
1223 /* If the lines below the insertion are being pushed
1224 into the end of the window, this is the same as clearing;
1225 and we know the lines are already clear, since the matching
1226 deletion has already been done. So can ignore this. */
1227 /* If the lines below the deletion are blank lines coming
1228 out of the end of the window, don't bother,
1229 as there will be a matching inslines later that will flush them. */
1230 if (scroll_region_ok
&& vpos
+ i
>= specified_window
)
1232 if (!memory_below_frame
&& vpos
+ i
>= FRAME_HEIGHT (selected_frame
))
1237 raw_cursor_to (vpos
, 0);
1238 background_highlight ();
1239 buf
= tparam (multi
, 0, 0, i
);
1245 raw_cursor_to (vpos
, 0);
1246 background_highlight ();
1254 set_scroll_region (vpos
, specified_window
);
1256 raw_cursor_to (specified_window
- 1, 0);
1258 raw_cursor_to (vpos
, 0);
1259 background_highlight ();
1261 OUTPUTL (scroll
, specified_window
- vpos
);
1262 set_scroll_region (0, specified_window
);
1265 if (TN_standout_width
>= 0)
1267 register int lower_limit
1270 : FRAME_HEIGHT (selected_frame
));
1274 bcopy (&chars_wasted
[vpos
- n
], &chars_wasted
[vpos
],
1275 lower_limit
- vpos
+ n
);
1276 bzero (&chars_wasted
[lower_limit
+ n
], - n
);
1280 bcopy (&chars_wasted
[vpos
], ©buf
[vpos
], lower_limit
- vpos
- n
);
1281 bcopy (©buf
[vpos
], &chars_wasted
[vpos
+ n
],
1282 lower_limit
- vpos
- n
);
1283 bzero (&chars_wasted
[vpos
], n
);
1286 if (!scroll_region_ok
&& memory_below_frame
&& n
< 0)
1288 cursor_to (FRAME_HEIGHT (selected_frame
) + n
, 0);
1293 /* Compute cost of sending "str", in characters,
1294 not counting any line-dependent padding. */
1302 tputs (str
, 0, evalcost
);
1306 /* Compute cost of sending "str", in characters,
1307 counting any line-dependent padding at one line. */
1310 string_cost_one_line (str
)
1315 tputs (str
, 1, evalcost
);
1319 /* Compute per line amount of line-dependent padding,
1320 in tenths of characters. */
1328 tputs (str
, 0, evalcost
);
1331 tputs (str
, 10, evalcost
);
1336 /* char_ins_del_cost[n] is cost of inserting N characters.
1337 char_ins_del_cost[-n] is cost of deleting N characters.
1338 The length of this vector is based on max_frame_width. */
1340 int *char_ins_del_vector
;
1342 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WIDTH ((f))])
1347 calculate_ins_del_char_costs (frame
)
1350 int ins_startup_cost
, del_startup_cost
;
1351 int ins_cost_per_char
, del_cost_per_char
;
1355 if (TS_ins_multi_chars
)
1357 ins_cost_per_char
= 0;
1358 ins_startup_cost
= string_cost_one_line (TS_ins_multi_chars
);
1360 else if (TS_ins_char
|| TS_pad_inserted_char
1361 || (TS_insert_mode
&& TS_end_insert_mode
))
1363 ins_startup_cost
= (30 * (string_cost (TS_insert_mode
)
1364 + string_cost (TS_end_insert_mode
))) / 100;
1365 ins_cost_per_char
= (string_cost_one_line (TS_ins_char
)
1366 + string_cost_one_line (TS_pad_inserted_char
));
1370 ins_startup_cost
= 9999;
1371 ins_cost_per_char
= 0;
1374 if (TS_del_multi_chars
)
1376 del_cost_per_char
= 0;
1377 del_startup_cost
= string_cost_one_line (TS_del_multi_chars
);
1379 else if (TS_del_char
)
1381 del_startup_cost
= (string_cost (TS_delete_mode
)
1382 + string_cost (TS_end_delete_mode
));
1383 if (delete_in_insert_mode
)
1384 del_startup_cost
/= 2;
1385 del_cost_per_char
= string_cost_one_line (TS_del_char
);
1389 del_startup_cost
= 9999;
1390 del_cost_per_char
= 0;
1393 /* Delete costs are at negative offsets */
1394 p
= &char_ins_del_cost (frame
)[0];
1395 for (i
= FRAME_WIDTH (frame
); --i
>= 0;)
1396 *--p
= (del_startup_cost
+= del_cost_per_char
);
1398 /* Doing nothing is free */
1399 p
= &char_ins_del_cost (frame
)[0];
1402 /* Insert costs are at positive offsets */
1403 for (i
= FRAME_WIDTH (frame
); --i
>= 0;)
1404 *p
++ = (ins_startup_cost
+= ins_cost_per_char
);
1408 calculate_costs (frame
)
1411 register char *f
= (TS_set_scroll_region
1412 ? TS_set_scroll_region
1413 : TS_set_scroll_region_1
);
1415 FRAME_COST_BAUD_RATE (frame
) = baud_rate
;
1417 scroll_region_cost
= string_cost (f
);
1418 #ifdef HAVE_X_WINDOWS
1419 if (FRAME_X_P (frame
))
1421 do_line_insertion_deletion_costs (frame
, 0, ".5*", 0, ".5*",
1423 x_screen_planes (frame
));
1424 scroll_region_cost
= 0;
1429 /* These variables are only used for terminal stuff. They are allocated
1430 once for the terminal frame of X-windows emacs, but not used afterwards.
1432 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1433 X turns off char_ins_del_ok.
1435 chars_wasted and copybuf are only used here in term.c in cases where
1436 the term hook isn't called. */
1438 max_frame_height
= max (max_frame_height
, FRAME_HEIGHT (frame
));
1439 max_frame_width
= max (max_frame_width
, FRAME_WIDTH (frame
));
1441 if (chars_wasted
!= 0)
1442 chars_wasted
= (char *) xrealloc (chars_wasted
, max_frame_height
);
1444 chars_wasted
= (char *) xmalloc (max_frame_height
);
1447 copybuf
= (char *) xrealloc (copybuf
, max_frame_height
);
1449 copybuf
= (char *) xmalloc (max_frame_height
);
1451 if (char_ins_del_vector
!= 0)
1453 = (int *) xrealloc (char_ins_del_vector
,
1455 + 2 * max_frame_width
* sizeof (int)));
1458 = (int *) xmalloc (sizeof (int)
1459 + 2 * max_frame_width
* sizeof (int));
1461 bzero (chars_wasted
, max_frame_height
);
1462 bzero (copybuf
, max_frame_height
);
1463 bzero (char_ins_del_vector
, (sizeof (int)
1464 + 2 * max_frame_width
* sizeof (int)));
1466 if (f
&& (!TS_ins_line
&& !TS_del_line
))
1467 do_line_insertion_deletion_costs (frame
,
1468 TS_rev_scroll
, TS_ins_multi_lines
,
1469 TS_fwd_scroll
, TS_del_multi_lines
,
1472 do_line_insertion_deletion_costs (frame
,
1473 TS_ins_line
, TS_ins_multi_lines
,
1474 TS_del_line
, TS_del_multi_lines
,
1477 calculate_ins_del_char_costs (frame
);
1479 /* Don't use TS_repeat if its padding is worse than sending the chars */
1480 if (TS_repeat
&& per_line_cost (TS_repeat
) * baud_rate
< 9000)
1481 RPov
= string_cost (TS_repeat
);
1483 RPov
= FRAME_WIDTH (frame
) * 2;
1485 cmcostinit (); /* set up cursor motion costs */
1492 /* Termcap capability names that correspond directly to X keysyms.
1493 Some of these (marked "terminfo") aren't supplied by old-style
1494 (Berkeley) termcap entries. They're listed in X keysym order;
1495 except we put the keypad keys first, so that if they clash with
1496 other keys (as on the IBM PC keyboard) they get overridden.
1499 static struct fkey_table keys
[] =
1501 "kh", "home", /* termcap */
1502 "kl", "left", /* termcap */
1503 "ku", "up", /* termcap */
1504 "kr", "right", /* termcap */
1505 "kd", "down", /* termcap */
1506 "%8", "prior", /* terminfo */
1507 "%5", "next", /* terminfo */
1508 "@7", "end", /* terminfo */
1509 "@1", "begin", /* terminfo */
1510 "*6", "select", /* terminfo */
1511 "%9", "print", /* terminfo */
1512 "@4", "execute", /* terminfo --- actually the `command' key */
1514 * "insert" --- see below
1516 "&8", "undo", /* terminfo */
1517 "%0", "redo", /* terminfo */
1518 "%7", "menu", /* terminfo --- actually the `options' key */
1519 "@0", "find", /* terminfo */
1520 "@2", "cancel", /* terminfo */
1521 "%1", "help", /* terminfo */
1523 * "break" goes here, but can't be reliably intercepted with termcap
1525 "&4", "reset", /* terminfo --- actually `restart' */
1527 * "system" and "user" --- no termcaps
1529 "kE", "clearline", /* terminfo */
1530 "kA", "insertline", /* terminfo */
1531 "kL", "deleteline", /* terminfo */
1532 "kI", "insertchar", /* terminfo */
1533 "kD", "deletechar", /* terminfo */
1534 "kB", "backtab", /* terminfo */
1536 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1538 "@8", "kp-enter", /* terminfo */
1540 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1541 * "kp-multiply", "kp-add", "kp-separator",
1542 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1543 * --- no termcaps for any of these.
1545 "K4", "kp-1", /* terminfo */
1547 * "kp-2" --- no termcap
1549 "K5", "kp-3", /* terminfo */
1551 * "kp-4" --- no termcap
1553 "K2", "kp-5", /* terminfo */
1555 * "kp-6" --- no termcap
1557 "K1", "kp-7", /* terminfo */
1559 * "kp-8" --- no termcap
1561 "K3", "kp-9", /* terminfo */
1563 * "kp-equal" --- no termcap
1576 static char **term_get_fkeys_arg
;
1577 static Lisp_Object
term_get_fkeys_1 ();
1579 /* Find the escape codes sent by the function keys for Vfunction_key_map.
1580 This function scans the termcap function key sequence entries, and
1581 adds entries to Vfunction_key_map for each function key it finds. */
1584 term_get_fkeys (address
)
1587 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1588 errors during the call. The only errors should be from Fdefine_key
1589 when given a key sequence containing an invalid prefix key. If the
1590 termcap defines function keys which use a prefix that is already bound
1591 to a command by the default bindings, we should silently ignore that
1592 function key specification, rather than giving the user an error and
1593 refusing to run at all on such a terminal. */
1595 extern Lisp_Object
Fidentity ();
1596 term_get_fkeys_arg
= address
;
1597 internal_condition_case (term_get_fkeys_1
, Qerror
, Fidentity
);
1605 char **address
= term_get_fkeys_arg
;
1607 /* This can happen if CANNOT_DUMP or with strange options. */
1609 Vfunction_key_map
= Fmake_sparse_keymap (Qnil
);
1611 for (i
= 0; i
< (sizeof (keys
)/sizeof (keys
[0])); i
++)
1613 char *sequence
= tgetstr (keys
[i
].cap
, address
);
1615 Fdefine_key (Vfunction_key_map
, build_string (sequence
),
1616 Fmake_vector (make_number (1),
1617 intern (keys
[i
].name
)));
1620 /* The uses of the "k0" capability are inconsistent; sometimes it
1621 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1622 We will attempt to politely accommodate both systems by testing for
1623 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1626 char *k_semi
= tgetstr ("k;", address
);
1627 char *k0
= tgetstr ("k0", address
);
1628 char *k0_name
= "f10";
1632 Fdefine_key (Vfunction_key_map
, build_string (k_semi
),
1633 Fmake_vector (make_number (1), intern ("f10")));
1638 Fdefine_key (Vfunction_key_map
, build_string (k0
),
1639 Fmake_vector (make_number (1), intern (k0_name
)));
1642 /* Set up cookies for numbered function keys above f10. */
1644 char fcap
[3], fkey
[4];
1646 fcap
[0] = 'F'; fcap
[2] = '\0';
1647 for (i
= 11; i
< 64; i
++)
1650 fcap
[1] = '1' + i
- 11;
1652 fcap
[1] = 'A' + i
- 20;
1654 fcap
[1] = 'a' + i
- 46;
1657 char *sequence
= tgetstr (fcap
, address
);
1660 sprintf (fkey
, "f%d", i
);
1661 Fdefine_key (Vfunction_key_map
, build_string (sequence
),
1662 Fmake_vector (make_number (1),
1670 * Various mappings to try and get a better fit.
1673 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1674 if (!tgetstr (cap1, address)) \
1676 char *sequence = tgetstr (cap2, address); \
1678 Fdefine_key (Vfunction_key_map, build_string (sequence), \
1679 Fmake_vector (make_number (1), \
1683 /* if there's no key_next keycap, map key_npage to `next' keysym */
1684 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1685 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1686 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1687 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1688 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1689 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1690 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1692 /* IBM has their own non-standard dialect of terminfo.
1693 If the standard name isn't found, try the IBM name. */
1694 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1695 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1696 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1697 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1698 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1699 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1700 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1701 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1702 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1703 #undef CONDITIONAL_REASSIGN
1710 /***********************************************************************
1711 Character Display Information
1712 ***********************************************************************/
1714 static void append_glyph
P_ ((struct it
*));
1717 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1718 terminal frames if IT->glyph_row != NULL. IT->c is the character
1719 for which to produce glyphs; IT->face_id contains the character's
1720 face. Padding glyphs are appended if IT->c has a IT->pixel_width >
1727 struct glyph
*glyph
, *end
;
1730 xassert (it
->glyph_row
);
1731 glyph
= (it
->glyph_row
->glyphs
[it
->area
]
1732 + it
->glyph_row
->used
[it
->area
]);
1733 end
= it
->glyph_row
->glyphs
[1 + it
->area
];
1736 i
< it
->pixel_width
&& glyph
< end
;
1739 glyph
->type
= CHAR_GLYPH
;
1740 glyph
->pixel_width
= 1;
1741 glyph
->u
.ch
.code
= it
->c
;
1742 glyph
->u
.ch
.face_id
= it
->face_id
;
1743 glyph
->u
.ch
.padding_p
= i
> 0;
1744 glyph
->charpos
= CHARPOS (it
->position
);
1745 glyph
->object
= it
->object
;
1747 ++it
->glyph_row
->used
[it
->area
];
1753 /* Produce glyphs for the display element described by IT. The
1754 function fills output fields of IT with pixel information like the
1755 pixel width and height of a character, and maybe produces glyphs at
1756 the same time if IT->glyph_row is non-null. See the explanation of
1757 struct display_iterator in dispextern.h for an overview. */
1763 /* If a hook is installed, let it do the work. */
1764 xassert (it
->what
== IT_CHARACTER
1765 || it
->what
== IT_IMAGE
1766 || it
->what
== IT_STRETCH
);
1768 /* Nothing but characters are supported on terminal frames. */
1769 xassert (it
->what
== IT_CHARACTER
);
1771 if (it
->c
>= 040 && it
->c
< 0177)
1773 it
->pixel_width
= it
->nglyphs
= 1;
1777 else if (it
->c
== '\n')
1778 it
->pixel_width
= it
->nglyphs
= 0;
1779 else if (it
->c
== '\t')
1781 int absolute_x
= (it
->current_x
- it
->prompt_width
1782 + it
->continuation_lines_width
);
1784 = (((1 + absolute_x
+ it
->tab_width
- 1)
1789 /* If part of the TAB has been displayed on the previous line
1790 which is continued now, continuation_lines_width will have
1791 been incremented already by the part that fitted on the
1792 continued line. So, we will get the right number of spaces
1794 nspaces
= next_tab_x
- absolute_x
;
1801 it
->pixel_width
= it
->len
= 1;
1809 it
->pixel_width
= nspaces
;
1810 it
->nglyphs
= nspaces
;
1814 /* A multi-byte character. The display width is a per character
1815 value for characters of set CHARSET_COMPOSITION; otherwise
1816 it is fixed for all characters of the set. Some of the
1817 glyphs may have to be ignored because they are already
1818 displayed in a continued line. */
1819 int charset
= CHAR_CHARSET (it
->c
);
1821 if (charset
== CHARSET_COMPOSITION
)
1822 it
->pixel_width
= cmpchar_table
[COMPOSITE_CHAR_ID (it
->c
)]->width
;
1824 it
->pixel_width
= CHARSET_WIDTH (charset
);
1825 it
->nglyphs
= it
->pixel_width
;
1831 /* Advance current_x by the pixel width as a convenience for
1833 if (it
->area
== TEXT_AREA
)
1834 it
->current_x
+= it
->pixel_width
;
1835 it
->ascent
= it
->max_ascent
= 0;
1836 it
->descent
= it
->max_descent
= 1;
1840 /* Get information about special display element WHAT in an
1841 environment described by IT. WHAT is one of IT_TRUNCATION or
1842 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1843 non-null glyph_row member. This function ensures that fields like
1844 face_id, c, len of IT are left untouched. */
1847 produce_special_glyphs (it
, what
)
1849 enum display_element_type what
;
1855 temp_it
.what
= IT_CHARACTER
;
1858 bzero (&temp_it
.current
, sizeof temp_it
.current
);
1860 if (what
== IT_CONTINUATION
)
1862 /* Continuation glyph. */
1864 && INTEGERP (DISP_CONTINUE_GLYPH (it
->dp
))
1865 && GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (it
->dp
))))
1867 temp_it
.c
= FAST_GLYPH_CHAR (XINT (DISP_CONTINUE_GLYPH (it
->dp
)));
1868 temp_it
.len
= CHAR_LEN (temp_it
.c
);
1873 produce_glyphs (&temp_it
);
1874 it
->pixel_width
= temp_it
.pixel_width
;
1875 it
->nglyphs
= temp_it
.pixel_width
;
1877 else if (what
== IT_TRUNCATION
)
1879 /* Truncation glyph. */
1881 && INTEGERP (DISP_TRUNC_GLYPH (it
->dp
))
1882 && GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (it
->dp
))))
1884 temp_it
.c
= FAST_GLYPH_CHAR (XINT (DISP_TRUNC_GLYPH (it
->dp
)));
1885 temp_it
.len
= CHAR_LEN (temp_it
.c
);
1890 produce_glyphs (&temp_it
);
1891 it
->pixel_width
= temp_it
.pixel_width
;
1892 it
->nglyphs
= temp_it
.pixel_width
;
1899 /* Return an estimation of the pixel height of mode or top lines on
1900 frame F. FACE_ID specifies what line's height to estimate. */
1903 estimate_mode_line_height (f
, face_id
)
1905 enum face_id face_id
;
1907 if (estimate_mode_line_height_hook
)
1908 return estimate_mode_line_height_hook (f
, face_id
);
1915 /***********************************************************************
1917 ***********************************************************************/
1920 /* Turn appearances of face FACE_ID on tty frame F on. */
1923 turn_on_face (f
, face_id
)
1927 struct face
*face
= FACE_FROM_ID (f
, face_id
);
1929 xassert (face
!= NULL
);
1931 if (face
->tty_bold_p
)
1932 OUTPUT1_IF (TS_enter_bold_mode
);
1933 else if (face
->tty_dim_p
)
1934 OUTPUT1_IF (TS_enter_dim_mode
);
1936 /* Alternate charset and blinking not yet used. */
1937 if (face
->tty_alt_charset_p
)
1938 OUTPUT1_IF (TS_enter_alt_charset_mode
);
1940 if (face
->tty_blinking_p
)
1941 OUTPUT1_IF (TS_enter_blink_mode
);
1943 if (face
->tty_underline_p
1944 /* Don't underline if that's difficult. */
1945 && TN_magic_cookie_glitch_ul
<= 0)
1946 OUTPUT1_IF (TS_enter_underline_mode
);
1948 if (face
->tty_reverse_p
)
1949 OUTPUT1_IF (TS_enter_reverse_mode
);
1951 if (TN_max_colors
> 0)
1955 if (face
->foreground
!= FACE_TTY_DEFAULT_COLOR
1956 && TS_set_foreground
)
1958 p
= tparam (TS_set_foreground
, NULL
, 0, (int) face
->foreground
);
1963 if (face
->background
!= FACE_TTY_DEFAULT_COLOR
1964 && TS_set_background
)
1966 p
= tparam (TS_set_background
, NULL
, 0, (int) face
->background
);
1974 /* Turn off appearances of face FACE_ID on tty frame F. */
1977 turn_off_face (f
, face_id
)
1981 struct face
*face
= FACE_FROM_ID (f
, face_id
);
1984 xassert (face
!= NULL
);
1986 if (TS_exit_attribute_mode
)
1988 /* Capability "me" will turn off appearance modes double-bright,
1989 half-bright, reverse-video, standout, underline. It may or
1990 may not turn off alt-char-mode. */
1991 if (face
->tty_bold_p
1993 || face
->tty_reverse_p
1994 || face
->tty_alt_charset_p
1995 || face
->tty_blinking_p
1996 || face
->tty_underline_p
)
1997 OUTPUT1_IF (TS_exit_attribute_mode
);
1999 if (face
->tty_alt_charset_p
)
2000 OUTPUT_IF (TS_exit_alt_charset_mode
);
2004 /* If we don't have "me" we can only have those appearances
2005 that have exit sequences defined. */
2006 if (face
->tty_alt_charset_p
)
2007 OUTPUT_IF (TS_exit_alt_charset_mode
);
2009 if (face
->tty_underline_p
2010 /* We don't underline if that's difficult. */
2011 && TN_magic_cookie_glitch_ul
<= 0)
2012 OUTPUT_IF (TS_exit_underline_mode
);
2015 /* Switch back to default colors. */
2016 if (TN_max_colors
> 0
2017 && (face
->foreground
!= FACE_TTY_DEFAULT_COLOR
2018 || face
->background
!= FACE_TTY_DEFAULT_COLOR
))
2019 OUTPUT1_IF (TS_orig_pair
);
2023 /* Return non-zero if the terminal is capable to display colors. */
2025 DEFUN ("tty-display-color-p", Ftty_display_color_p
, Stty_display_color_p
,
2027 "Return non-nil if TTY can display colors.")
2030 return TN_max_colors
> 0 ? Qt
: Qnil
;
2036 /***********************************************************************
2038 ***********************************************************************/
2041 term_init (terminal_type
)
2042 char *terminal_type
;
2045 char **address
= &area
;
2051 initialize_w32_display ();
2055 area
= (char *) xmalloc (2044);
2060 FrameRows
= FRAME_HEIGHT (selected_frame
);
2061 FrameCols
= FRAME_WIDTH (selected_frame
);
2062 specified_window
= FRAME_HEIGHT (selected_frame
);
2064 delete_in_insert_mode
= 1;
2067 scroll_region_ok
= 0;
2069 /* Seems to insert lines when it's not supposed to, messing
2070 up the display. In doing a trace, it didn't seem to be
2071 called much, so I don't think we're losing anything by
2074 line_ins_del_ok
= 0;
2075 char_ins_del_ok
= 1;
2079 FRAME_CAN_HAVE_SCROLL_BARS (selected_frame
) = 0;
2080 FRAME_VERTICAL_SCROLL_BAR_TYPE (selected_frame
) = vertical_scroll_bar_none
;
2083 #else /* not WINDOWSNT */
2087 status
= tgetent (buffer
, terminal_type
);
2091 fatal ("Cannot open terminfo database file");
2093 fatal ("Cannot open termcap database file");
2099 fatal ("Terminal type %s is not defined.\n\
2100 If that is not the actual type of terminal you have,\n\
2101 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2102 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2103 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
2106 fatal ("Terminal type %s is not defined.\n\
2107 If that is not the actual type of terminal you have,\n\
2108 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2109 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2110 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
2115 area
= (char *) xmalloc (2044);
2117 area
= (char *) xmalloc (strlen (buffer
));
2118 #endif /* not TERMINFO */
2122 TS_ins_line
= tgetstr ("al", address
);
2123 TS_ins_multi_lines
= tgetstr ("AL", address
);
2124 TS_bell
= tgetstr ("bl", address
);
2125 BackTab
= tgetstr ("bt", address
);
2126 TS_clr_to_bottom
= tgetstr ("cd", address
);
2127 TS_clr_line
= tgetstr ("ce", address
);
2128 TS_clr_frame
= tgetstr ("cl", address
);
2129 ColPosition
= tgetstr ("ch", address
);
2130 AbsPosition
= tgetstr ("cm", address
);
2131 CR
= tgetstr ("cr", address
);
2132 TS_set_scroll_region
= tgetstr ("cs", address
);
2133 TS_set_scroll_region_1
= tgetstr ("cS", address
);
2134 RowPosition
= tgetstr ("cv", address
);
2135 TS_del_char
= tgetstr ("dc", address
);
2136 TS_del_multi_chars
= tgetstr ("DC", address
);
2137 TS_del_line
= tgetstr ("dl", address
);
2138 TS_del_multi_lines
= tgetstr ("DL", address
);
2139 TS_delete_mode
= tgetstr ("dm", address
);
2140 TS_end_delete_mode
= tgetstr ("ed", address
);
2141 TS_end_insert_mode
= tgetstr ("ei", address
);
2142 Home
= tgetstr ("ho", address
);
2143 TS_ins_char
= tgetstr ("ic", address
);
2144 TS_ins_multi_chars
= tgetstr ("IC", address
);
2145 TS_insert_mode
= tgetstr ("im", address
);
2146 TS_pad_inserted_char
= tgetstr ("ip", address
);
2147 TS_end_keypad_mode
= tgetstr ("ke", address
);
2148 TS_keypad_mode
= tgetstr ("ks", address
);
2149 LastLine
= tgetstr ("ll", address
);
2150 Right
= tgetstr ("nd", address
);
2151 Down
= tgetstr ("do", address
);
2153 Down
= tgetstr ("nl", address
); /* Obsolete name for "do" */
2155 /* VMS puts a carriage return before each linefeed,
2156 so it is not safe to use linefeeds. */
2157 if (Down
&& Down
[0] == '\n' && Down
[1] == '\0')
2160 if (tgetflag ("bs"))
2161 Left
= "\b"; /* can't possibly be longer! */
2162 else /* (Actually, "bs" is obsolete...) */
2163 Left
= tgetstr ("le", address
);
2165 Left
= tgetstr ("bc", address
); /* Obsolete name for "le" */
2166 TS_pad_char
= tgetstr ("pc", address
);
2167 TS_repeat
= tgetstr ("rp", address
);
2168 TS_end_standout_mode
= tgetstr ("se", address
);
2169 TS_fwd_scroll
= tgetstr ("sf", address
);
2170 TS_standout_mode
= tgetstr ("so", address
);
2171 TS_rev_scroll
= tgetstr ("sr", address
);
2172 Wcm
.cm_tab
= tgetstr ("ta", address
);
2173 TS_end_termcap_modes
= tgetstr ("te", address
);
2174 TS_termcap_modes
= tgetstr ("ti", address
);
2175 Up
= tgetstr ("up", address
);
2176 TS_visible_bell
= tgetstr ("vb", address
);
2177 TS_cursor_normal
= tgetstr ("ve", address
);
2178 TS_cursor_visible
= tgetstr ("vs", address
);
2179 TS_cursor_invisible
= tgetstr ("vi", address
);
2180 TS_set_window
= tgetstr ("wi", address
);
2182 TS_enter_underline_mode
= tgetstr ("us", address
);
2183 TS_exit_underline_mode
= tgetstr ("ue", address
);
2184 TN_magic_cookie_glitch_ul
= tgetnum ("ug");
2185 TS_enter_bold_mode
= tgetstr ("md", address
);
2186 TS_enter_dim_mode
= tgetstr ("mh", address
);
2187 TS_enter_blink_mode
= tgetstr ("mb", address
);
2188 TS_enter_reverse_mode
= tgetstr ("mr", address
);
2189 TS_enter_alt_charset_mode
= tgetstr ("as", address
);
2190 TS_exit_alt_charset_mode
= tgetstr ("ae", address
);
2191 TS_exit_attribute_mode
= tgetstr ("me", address
);
2193 MultiUp
= tgetstr ("UP", address
);
2194 MultiDown
= tgetstr ("DO", address
);
2195 MultiLeft
= tgetstr ("LE", address
);
2196 MultiRight
= tgetstr ("RI", address
);
2198 /* SVr4/ANSI color suppert. */
2199 TS_orig_pair
= tgetstr ("op", address
);
2200 TS_set_foreground
= tgetstr ("AF", address
);
2201 TS_set_background
= tgetstr ("AB", address
);
2202 if (!TS_set_foreground
)
2205 TS_set_foreground
= tgetstr ("Sf", address
);
2206 TS_set_background
= tgetstr ("Sb", address
);
2208 TN_max_colors
= tgetnum ("Co");
2209 TN_max_pairs
= tgetnum ("pa");
2211 MagicWrap
= tgetflag ("xn");
2212 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
2213 the former flag imply the latter. */
2214 AutoWrap
= MagicWrap
|| tgetflag ("am");
2215 memory_below_frame
= tgetflag ("db");
2216 TF_hazeltine
= tgetflag ("hz");
2217 must_write_spaces
= tgetflag ("in");
2218 meta_key
= tgetflag ("km") || tgetflag ("MT");
2219 TF_insmode_motion
= tgetflag ("mi");
2220 TF_standout_motion
= tgetflag ("ms");
2221 TF_underscore
= tgetflag ("ul");
2222 TF_xs
= tgetflag ("xs");
2223 TF_teleray
= tgetflag ("xt");
2225 term_get_fkeys (address
);
2227 /* Get frame size from system, or else from termcap. */
2230 get_frame_size (&width
, &height
);
2231 FRAME_WIDTH (selected_frame
) = width
;
2232 FRAME_HEIGHT (selected_frame
) = height
;
2235 if (FRAME_WIDTH (selected_frame
) <= 0)
2236 SET_FRAME_WIDTH (selected_frame
, tgetnum ("co"));
2238 /* Keep width and external_width consistent */
2239 SET_FRAME_WIDTH (selected_frame
, FRAME_WIDTH (selected_frame
));
2240 if (FRAME_HEIGHT (selected_frame
) <= 0)
2241 FRAME_HEIGHT (selected_frame
) = tgetnum ("li");
2243 if (FRAME_HEIGHT (selected_frame
) < 3
2244 || FRAME_WIDTH (selected_frame
) < 3)
2245 fatal ("Screen size %dx%d is too small",
2246 FRAME_HEIGHT (selected_frame
), FRAME_WIDTH (selected_frame
));
2248 min_padding_speed
= tgetnum ("pb");
2249 TN_standout_width
= tgetnum ("sg");
2250 TabWidth
= tgetnum ("tw");
2253 /* These capabilities commonly use ^J.
2254 I don't know why, but sending them on VMS does not work;
2255 it causes following spaces to be lost, sometimes.
2256 For now, the simplest fix is to avoid using these capabilities ever. */
2257 if (Down
&& Down
[0] == '\n')
2265 TS_fwd_scroll
= Down
;
2267 PC
= TS_pad_char
? *TS_pad_char
: 0;
2272 /* Turned off since /etc/termcap seems to have :ta= for most terminals
2273 and newer termcap doc does not seem to say there is a default.
2278 if (TS_standout_mode
== 0)
2280 TN_standout_width
= tgetnum ("ug");
2281 TS_end_standout_mode
= tgetstr ("ue", address
);
2282 TS_standout_mode
= tgetstr ("us", address
);
2285 /* If no `se' string, try using a `me' string instead.
2286 If that fails, we can't use standout mode at all. */
2287 if (TS_end_standout_mode
== 0)
2289 char *s
= tgetstr ("me", address
);
2291 TS_end_standout_mode
= s
;
2293 TS_standout_mode
= 0;
2299 /* Teleray: most programs want a space in front of TS_standout_mode,
2300 but Emacs can do without it (and give one extra column). */
2301 TS_standout_mode
= "\033RD";
2302 TN_standout_width
= 1;
2303 /* But that means we cannot rely on ^M to go to column zero! */
2305 /* LF can't be trusted either -- can alter hpos */
2306 /* if move at column 0 thru a line with TS_standout_mode */
2310 /* Special handling for certain terminal types known to need it */
2312 if (!strcmp (terminal_type
, "supdup"))
2314 memory_below_frame
= 1;
2315 Wcm
.cm_losewrap
= 1;
2317 if (!strncmp (terminal_type
, "c10", 3)
2318 || !strcmp (terminal_type
, "perq"))
2320 /* Supply a makeshift :wi string.
2321 This string is not valid in general since it works only
2322 for windows starting at the upper left corner;
2323 but that is all Emacs uses.
2325 This string works only if the frame is using
2326 the top of the video memory, because addressing is memory-relative.
2327 So first check the :ti string to see if that is true.
2329 It would be simpler if the :wi string could go in the termcap
2330 entry, but it can't because it is not fully valid.
2331 If it were in the termcap entry, it would confuse other programs. */
2334 p
= TS_termcap_modes
;
2335 while (*p
&& strcmp (p
, "\033v "))
2338 TS_set_window
= "\033v%C %C %C %C ";
2340 /* Termcap entry often fails to have :in: flag */
2341 must_write_spaces
= 1;
2342 /* :ti string typically fails to have \E^G! in it */
2343 /* This limits scope of insert-char to one line. */
2344 strcpy (area
, TS_termcap_modes
);
2345 strcat (area
, "\033\007!");
2346 TS_termcap_modes
= area
;
2347 area
+= strlen (area
) + 1;
2349 /* Change all %+ parameters to %C, to handle
2350 values above 96 correctly for the C100. */
2353 if (p
[0] == '%' && p
[1] == '+')
2359 FrameRows
= FRAME_HEIGHT (selected_frame
);
2360 FrameCols
= FRAME_WIDTH (selected_frame
);
2361 specified_window
= FRAME_HEIGHT (selected_frame
);
2363 if (Wcm_init () == -1) /* can't do cursor motion */
2365 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2366 It lacks the ability to position the cursor.\n\
2367 If that is not the actual type of terminal you have, use either the\n\
2368 DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
2369 or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
2373 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2374 It lacks the ability to position the cursor.\n\
2375 If that is not the actual type of terminal you have,\n\
2376 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2377 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2378 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
2380 # else /* TERMCAP */
2381 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2382 It lacks the ability to position the cursor.\n\
2383 If that is not the actual type of terminal you have,\n\
2384 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2385 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2386 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
2388 # endif /* TERMINFO */
2390 if (FRAME_HEIGHT (selected_frame
) <= 0
2391 || FRAME_WIDTH (selected_frame
) <= 0)
2392 fatal ("The frame size has not been specified");
2394 delete_in_insert_mode
2395 = TS_delete_mode
&& TS_insert_mode
2396 && !strcmp (TS_delete_mode
, TS_insert_mode
);
2398 se_is_so
= (TS_standout_mode
2399 && TS_end_standout_mode
2400 && !strcmp (TS_standout_mode
, TS_end_standout_mode
));
2402 /* Remove width of standout marker from usable width of line */
2403 if (TN_standout_width
> 0)
2404 SET_FRAME_WIDTH (selected_frame
,
2405 FRAME_WIDTH (selected_frame
) - TN_standout_width
);
2407 UseTabs
= tabs_safe_p () && TabWidth
== 8;
2411 && (TS_set_window
|| TS_set_scroll_region
|| TS_set_scroll_region_1
));
2413 line_ins_del_ok
= (((TS_ins_line
|| TS_ins_multi_lines
)
2414 && (TS_del_line
|| TS_del_multi_lines
))
2415 || (scroll_region_ok
&& TS_fwd_scroll
&& TS_rev_scroll
));
2417 char_ins_del_ok
= ((TS_ins_char
|| TS_insert_mode
2418 || TS_pad_inserted_char
|| TS_ins_multi_chars
)
2419 && (TS_del_char
|| TS_del_multi_chars
));
2421 fast_clear_end_of_line
= TS_clr_line
!= 0;
2424 if (read_socket_hook
) /* Baudrate is somewhat */
2425 /* meaningless in this case */
2428 FRAME_CAN_HAVE_SCROLL_BARS (selected_frame
) = 0;
2429 FRAME_VERTICAL_SCROLL_BAR_TYPE (selected_frame
) = vertical_scroll_bar_none
;
2430 #endif /* WINDOWSNT */
2435 fatal (str
, arg1
, arg2
)
2436 char *str
, *arg1
, *arg2
;
2438 fprintf (stderr
, "emacs: ");
2439 fprintf (stderr
, str
, arg1
, arg2
);
2440 fprintf (stderr
, "\n");
2448 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo
,
2449 "Non-nil means the system uses terminfo rather than termcap.\n\
2450 This variable can be used by terminal emulator packages.");
2452 system_uses_terminfo
= 1;
2454 system_uses_terminfo
= 0;
2457 DEFVAR_LISP ("ring-bell-function", &Vring_bell_function
,
2458 "Non-nil means call this function to ring the bell.\n\
2459 The function should accept no arguments.");
2460 Vring_bell_function
= Qnil
;
2462 defsubr (&Stty_display_color_p
);