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