Various cleanups.
[emacs.git] / src / term.c
blob2b44653b961ec4cf92ac9d8fbf6311cf0f92cda4
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.
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)
10 any later version.
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., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 /* New redisplay, TTY faces by Gerd Moellmann <gerd@gnu.org>. */
24 #include <config.h>
25 #include <stdio.h>
26 #include <ctype.h>
27 #include <string.h>
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"
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. */
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
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
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));
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)
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)
80 #define OUTPUT1_IF(a) do { if (a) tputs (a, 1, cmputc); } while (0)
82 /* Display space properties */
84 extern Lisp_Object Qspace, QCalign_to, QCwidth;
86 /* Function to use to ring the bell. */
88 Lisp_Object Vring_bell_function;
90 /* If true, use "vs", otherwise use "ve" to make the cursor visible. */
92 static int visible_cursor;
94 /* Terminal characteristics that higher levels want to look at.
95 These are all extern'd in termchar.h */
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 */
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 */
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. */
116 int no_redraw_on_reenter;
118 /* Hook functions that you can set to snap out the functions in this file.
119 These are all extern'd in termhooks.h */
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));
127 void (*ins_del_lines_hook) P_ ((int, int));
129 void (*delete_glyphs_hook) P_ ((int));
131 void (*ring_bell_hook) P_ ((void));
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));
142 int (*read_socket_hook) P_ ((int, int, struct input_event *));
144 void (*frame_up_to_date_hook) P_ ((struct frame *));
146 /* Return the current position of the mouse.
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.
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.
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.
160 Set *time to the time the mouse was at the returned position.
162 This should clear mouse_moved until the next motion
163 event arrives. */
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));
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. */
178 void (*frame_rehighlight_hook) P_ ((FRAME_PTR f));
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.
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. */
191 void (*frame_raise_lower_hook) P_ ((FRAME_PTR f, int raise));
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. */
199 void (*set_vertical_scroll_bar_hook)
200 P_ ((struct window *window,
201 int portion, int whole, int position));
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. */
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.
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.
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. */
225 void (*condemn_scroll_bars_hook) P_ ((FRAME_PTR frame));
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. */
230 void (*redeem_scroll_bar_hook) P_ ((struct window *window));
232 /* Remove all scroll bars on FRAME that haven't been saved since the
233 last call to `*condemn_scroll_bars_hook'.
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.
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. */
244 void (*judge_scroll_bars_hook) P_ ((FRAME_PTR FRAME));
246 /* Strings, numbers and flags taken from the termcap entry. */
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) */
287 /* Value of the "NC" (no_color_video) capability, or 0 if not
288 present. */
290 static int TN_no_color_video;
292 /* Meaning of bits in no_color_video. Each bit set means that the
293 corresponding attribute cannot be combined with colors. */
295 enum no_color_bit
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
308 /* "md" -- turn on bold (extra bright mode). */
310 char *TS_enter_bold_mode;
312 /* "mh" -- turn on half-bright mode. */
314 char *TS_enter_dim_mode;
316 /* "mb" -- enter blinking mode. */
318 char *TS_enter_blink_mode;
320 /* "mr" -- enter reverse video mode. */
322 char *TS_enter_reverse_mode;
324 /* "us"/"ue" -- start/end underlining. */
326 char *TS_exit_underline_mode, *TS_enter_underline_mode;
328 /* "as"/"ae" -- start/end alternate character set. Not really
329 supported, yet. */
331 char *TS_enter_alt_charset_mode, *TS_exit_alt_charset_mode;
333 /* "me" -- switch appearances off. */
335 char *TS_exit_attribute_mode;
337 /* "Co" -- number of colors. */
339 int TN_max_colors;
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. */
344 int TN_max_pairs;
346 /* "op" -- SVr4 set default pair to its original value. */
348 char *TS_orig_pair;
350 /* "AF"/"AB" or "Sf"/"Sb"-- set ANSI or SVr4 foreground/background color.
351 1 param, the color index. */
353 char *TS_set_foreground, *TS_set_background;
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. */
363 static int RPov; /* # chars to start a TS_repeat */
365 static int delete_in_insert_mode; /* delete mode == insert mode */
367 static int se_is_so; /* 1 if same string both enters and leaves
368 standout mode */
370 /* internal state */
372 /* The largest frame width in any call to calculate_costs. */
374 int max_frame_cols;
376 /* The largest frame height in any call to calculate_costs. */
378 int max_frame_lines;
380 static int costs_set; /* Nonzero if costs have been calculated. */
382 int insert_mode; /* Nonzero when in insert mode. */
383 int standout_mode; /* Nonzero when in standout mode. */
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.
389 Effectively it excludes the bottom frame_lines - specified_window_size
390 lines from those operations. */
392 int specified_window;
394 /* Frame currently being redisplayed; 0 if not currently redisplaying.
395 (Direct output does not count). */
397 FRAME_PTR updating_frame;
399 /* Provided for lisp packages. */
401 static int system_uses_terminfo;
403 /* Flag used in tty_show/hide_cursor. */
405 static int tty_cursor_hidden;
407 char *tparam ();
409 extern char *tgetstr ();
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... */
419 #undef FRAME_TERMCAP_P
420 #define FRAME_TERMCAP_P(_f_) 0
421 #endif /* WINDOWSNT */
423 void
424 ring_bell ()
426 if (!NILP (Vring_bell_function))
428 Lisp_Object function;
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.
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. */
438 function = Vring_bell_function;
439 Vring_bell_function = Qnil;
441 call0 (function);
443 Vring_bell_function = function;
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);
451 void
452 set_terminal_modes ()
454 if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
456 if (TS_termcap_modes)
457 OUTPUT (TS_termcap_modes);
458 else
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');
467 OUTPUT_IF (visible_cursor ? TS_cursor_visible : TS_cursor_normal);
468 OUTPUT_IF (TS_keypad_mode);
469 losecursor ();
471 else
472 (*set_terminal_modes_hook) ();
475 void
476 reset_terminal_modes ()
478 if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
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');
489 else if (reset_terminal_modes_hook)
490 (*reset_terminal_modes_hook) ();
493 void
494 update_begin (f)
495 struct frame *f;
497 updating_frame = f;
498 if (!FRAME_TERMCAP_P (f))
499 update_begin_hook (f);
502 void
503 update_end (f)
504 struct frame *f;
506 if (FRAME_TERMCAP_P (f))
508 if (!XWINDOW (selected_window)->cursor_off_p)
509 tty_show_cursor ();
510 turn_off_insert ();
511 background_highlight ();
513 else
514 update_end_hook (f);
516 updating_frame = NULL;
519 void
520 set_terminal_window (size)
521 int size;
523 if (FRAME_TERMCAP_P (updating_frame))
525 specified_window = size ? size : FRAME_LINES (updating_frame);
526 if (scroll_region_ok)
527 set_scroll_region (0, specified_window);
529 else
530 set_terminal_window_hook (size);
533 void
534 set_scroll_region (start, stop)
535 int start, stop;
537 char *buf;
538 struct frame *sf = XFRAME (selected_frame);
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));
550 OUTPUT (buf);
551 xfree (buf);
552 losecursor ();
556 static void
557 turn_on_insert ()
559 if (!insert_mode)
560 OUTPUT (TS_insert_mode);
561 insert_mode = 1;
564 void
565 turn_off_insert ()
567 if (insert_mode)
568 OUTPUT (TS_end_insert_mode);
569 insert_mode = 0;
572 /* Handle highlighting. */
574 void
575 turn_off_highlight ()
577 if (standout_mode)
578 OUTPUT_IF (TS_end_standout_mode);
579 standout_mode = 0;
582 static void
583 turn_on_highlight ()
585 if (!standout_mode)
586 OUTPUT_IF (TS_standout_mode);
587 standout_mode = 1;
590 static void
591 toggle_highlight ()
593 if (standout_mode)
594 turn_off_highlight ();
595 else
596 turn_on_highlight ();
600 /* Make cursor invisible. */
602 static void
603 tty_hide_cursor ()
605 if (tty_cursor_hidden == 0)
607 tty_cursor_hidden = 1;
608 OUTPUT_IF (TS_cursor_invisible);
613 /* Ensure that cursor is visible. */
615 static void
616 tty_show_cursor ()
618 if (tty_cursor_hidden)
620 tty_cursor_hidden = 0;
621 OUTPUT_IF (TS_cursor_normal);
622 if (visible_cursor)
623 OUTPUT_IF (TS_cursor_visible);
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. */
632 void
633 background_highlight ()
635 if (inverse_video)
636 turn_on_highlight ();
637 else
638 turn_off_highlight ();
641 /* Set standout mode to the mode specified for the text to be output. */
643 static void
644 highlight_if_desired ()
646 if (inverse_video)
647 turn_on_highlight ();
648 else
649 turn_off_highlight ();
653 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
654 frame-relative coordinates. */
656 void
657 cursor_to (vpos, hpos)
658 int vpos, hpos;
660 struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
662 if (! FRAME_TERMCAP_P (f) && cursor_to_hook)
664 (*cursor_to_hook) (vpos, hpos);
665 return;
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;
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);
682 /* Similar but don't take any account of the wasted characters. */
684 void
685 raw_cursor_to (row, col)
686 int row, col;
688 struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
689 if (! FRAME_TERMCAP_P (f))
691 (*raw_cursor_to_hook) (row, col);
692 return;
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);
703 /* Erase operations */
705 /* clear from cursor to end of frame */
706 void
707 clear_to_end ()
709 register int i;
711 if (clear_to_end_hook && ! FRAME_TERMCAP_P (updating_frame))
713 (*clear_to_end_hook) ();
714 return;
716 if (TS_clr_to_bottom)
718 background_highlight ();
719 OUTPUT (TS_clr_to_bottom);
721 else
723 for (i = curY; i < FRAME_LINES (XFRAME (selected_frame)); i++)
725 cursor_to (i, 0);
726 clear_end_of_line (FRAME_COLS (XFRAME (selected_frame)));
731 /* Clear entire frame */
733 void
734 clear_frame ()
736 struct frame *sf = XFRAME (selected_frame);
738 if (clear_frame_hook
739 && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : sf)))
741 (*clear_frame_hook) ();
742 return;
744 if (TS_clr_frame)
746 background_highlight ();
747 OUTPUT (TS_clr_frame);
748 cmat (0, 0);
750 else
752 cursor_to (0, 0);
753 clear_to_end ();
757 /* Clear from cursor to end of line.
758 Assume that the line is already clear starting at column first_unused_hpos.
760 Note that the cursor may be moved, on terminals lacking a `ce' string. */
762 void
763 clear_end_of_line (first_unused_hpos)
764 int first_unused_hpos;
766 register int i;
768 if (clear_end_of_line_hook
769 && ! FRAME_TERMCAP_P ((updating_frame
770 ? updating_frame
771 : XFRAME (selected_frame))))
773 (*clear_end_of_line_hook) (first_unused_hpos);
774 return;
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;
782 if (curX >= first_unused_hpos)
783 return;
784 background_highlight ();
785 if (TS_clr_line)
787 OUTPUT1 (TS_clr_line);
789 else
790 { /* have to do it the hard way */
791 struct frame *sf = XFRAME (selected_frame);
792 turn_off_insert ();
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--;
799 for (i = curX; i < first_unused_hpos; i++)
801 if (termscript)
802 fputc (' ', termscript);
803 putchar (' ');
805 cmplus (first_unused_hpos - curX);
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;
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. */
818 unsigned char *
819 encode_terminal_code (src, src_len, coding)
820 struct glyph *src;
821 int src_len;
822 struct coding_system *coding;
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;
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)
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;
844 buf = encode_terminal_buf;
845 nchars = 0;
846 while (src < src_end)
848 /* We must skip glyphs to be padded for a wide character. */
849 if (! CHAR_GLYPH_PADDING_P (*src))
851 g = GLYPH_FROM_CHAR_GLYPH (src[0]);
853 if (g < 0 || g >= tlen)
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++;
862 else
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);
868 if (GLYPH_SIMPLE_P (tbase, tlen, g))
870 int c = FAST_GLYPH_CHAR (g);
872 if (CHAR_VALID_P (c, 0))
873 buf += CHAR_STRING (c, buf);
874 else
875 *buf++ = SPACEGLYPH;
876 nchars++;
878 else
880 /* We have a string in Vglyph_table. */
881 Lisp_Object string;
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))
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;
894 bcopy (SDATA (string), buf, SBYTES (string));
895 buf += SBYTES (string);
896 nchars += SCHARS (string);
900 src++;
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)))
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;
915 required = nbytes + encoding_buffer_size (coding, nbytes);
916 if (encode_terminal_bufsize < required)
918 encode_terminal_bufsize = required;
919 encode_terminal_buf = xrealloc (encode_terminal_buf, required);
922 encode_coding (coding, encode_terminal_buf, encode_terminal_buf + nbytes,
923 nbytes, encode_terminal_bufsize - nbytes);
924 return encode_terminal_buf + nbytes;
927 void
928 write_glyphs (string, len)
929 register struct glyph *string;
930 register int len;
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;
937 if (write_glyphs_hook
938 && ! FRAME_TERMCAP_P (f))
940 (*write_glyphs_hook) (string, len);
941 return;
944 turn_off_insert ();
945 tty_hide_cursor ();
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. */
950 if (AutoWrap
951 && curY + 1 == FRAME_LINES (sf)
952 && (curX + len) == FRAME_COLS (sf))
953 len --;
954 if (len <= 0)
955 return;
957 cmplus (len);
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;
968 while (len > 0)
970 /* Identify a run of glyphs with the same face. */
971 int face_id = string->face_id;
972 int n;
974 for (n = 1; n < len; ++n)
975 if (string[n].face_id != face_id)
976 break;
978 /* Turn appearance modes of the face of the run on. */
979 highlight_if_desired ();
980 turn_on_face (f, face_id);
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)
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);
994 len -= n;
995 string += n;
997 /* Turn appearance modes off. */
998 turn_off_face (f, face_id);
999 turn_off_highlight ();
1002 cmcheckmagic ();
1005 /* If start is zero, insert blanks instead of a string at start */
1007 void
1008 insert_glyphs (start, len)
1009 register struct glyph *start;
1010 register int len;
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;
1019 if (len <= 0)
1020 return;
1022 if (insert_glyphs_hook)
1024 (*insert_glyphs_hook) (start, len);
1025 return;
1028 sf = XFRAME (selected_frame);
1029 f = updating_frame ? updating_frame : sf;
1031 if (TS_ins_multi_chars)
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;
1041 turn_on_insert ();
1042 cmplus (len);
1044 if (! start)
1045 space[0] = SPACEGLYPH;
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;
1056 while (len-- > 0)
1058 OUTPUT1_IF (TS_ins_char);
1059 if (!start)
1061 conversion_buffer = space;
1062 coding->produced = 1;
1064 else
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))
1074 OUTPUT1_IF (TS_ins_char);
1075 start++, len--;
1078 if (len <= 0)
1079 /* This is the last glyph. */
1080 coding->mode |= CODING_MODE_LAST_BLOCK;
1082 conversion_buffer = encode_terminal_code (glyph, 1, coding);
1085 if (coding->produced > 0)
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);
1094 OUTPUT1_IF (TS_pad_inserted_char);
1095 if (start)
1097 turn_off_face (f, glyph->face_id);
1098 turn_off_highlight ();
1102 cmcheckmagic ();
1105 void
1106 delete_glyphs (n)
1107 register int n;
1109 char *buf;
1110 register int i;
1112 if (delete_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame))
1114 (*delete_glyphs_hook) (n);
1115 return;
1118 if (delete_in_insert_mode)
1120 turn_on_insert ();
1122 else
1124 turn_off_insert ();
1125 OUTPUT_IF (TS_delete_mode);
1128 if (TS_del_multi_chars)
1130 buf = tparam (TS_del_multi_chars, 0, 0, n);
1131 OUTPUT1 (buf);
1132 xfree (buf);
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);
1141 /* Insert N lines at vpos VPOS. If N is negative, delete -N lines. */
1143 void
1144 ins_del_lines (vpos, n)
1145 int vpos, n;
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;
1152 register int i = n > 0 ? n : -n;
1153 register char *buf;
1155 if (ins_del_lines_hook && ! FRAME_TERMCAP_P (updating_frame))
1157 (*ins_del_lines_hook) (vpos, n);
1158 return;
1161 sf = XFRAME (selected_frame);
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;
1175 if (multi)
1177 raw_cursor_to (vpos, 0);
1178 background_highlight ();
1179 buf = tparam (multi, 0, 0, i);
1180 OUTPUT (buf);
1181 xfree (buf);
1183 else if (single)
1185 raw_cursor_to (vpos, 0);
1186 background_highlight ();
1187 while (--i >= 0)
1188 OUTPUT (single);
1189 if (TF_teleray)
1190 curX = 0;
1192 else
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);
1205 if (!scroll_region_ok && memory_below_frame && n < 0)
1207 cursor_to (FRAME_LINES (sf) + n, 0);
1208 clear_to_end ();
1212 /* Compute cost of sending "str", in characters,
1213 not counting any line-dependent padding. */
1216 string_cost (str)
1217 char *str;
1219 cost = 0;
1220 if (str)
1221 tputs (str, 0, evalcost);
1222 return cost;
1225 /* Compute cost of sending "str", in characters,
1226 counting any line-dependent padding at one line. */
1228 static int
1229 string_cost_one_line (str)
1230 char *str;
1232 cost = 0;
1233 if (str)
1234 tputs (str, 1, evalcost);
1235 return cost;
1238 /* Compute per line amount of line-dependent padding,
1239 in tenths of characters. */
1242 per_line_cost (str)
1243 register char *str;
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;
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. */
1259 int *char_ins_del_vector;
1261 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
1262 #endif
1264 /* ARGSUSED */
1265 static void
1266 calculate_ins_del_char_costs (frame)
1267 FRAME_PTR frame;
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;
1274 if (TS_ins_multi_chars)
1276 ins_cost_per_char = 0;
1277 ins_startup_cost = string_cost_one_line (TS_ins_multi_chars);
1279 else if (TS_ins_char || TS_pad_inserted_char
1280 || (TS_insert_mode && TS_end_insert_mode))
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));
1287 else
1289 ins_startup_cost = 9999;
1290 ins_cost_per_char = 0;
1293 if (TS_del_multi_chars)
1295 del_cost_per_char = 0;
1296 del_startup_cost = string_cost_one_line (TS_del_multi_chars);
1298 else if (TS_del_char)
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);
1306 else
1308 del_startup_cost = 9999;
1309 del_cost_per_char = 0;
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);
1317 /* Doing nothing is free */
1318 p = &char_ins_del_cost (frame)[0];
1319 *p++ = 0;
1321 /* Insert costs are at positive offsets */
1322 for (i = FRAME_COLS (frame); --i >= 0;)
1323 *p++ = (ins_startup_cost += ins_cost_per_char);
1326 void
1327 calculate_costs (frame)
1328 FRAME_PTR frame;
1330 register char *f = (TS_set_scroll_region
1331 ? TS_set_scroll_region
1332 : TS_set_scroll_region_1);
1334 FRAME_COST_BAUD_RATE (frame) = baud_rate;
1336 scroll_region_cost = string_cost (f);
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.
1341 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1342 X turns off char_ins_del_ok. */
1344 max_frame_lines = max (max_frame_lines, FRAME_LINES (frame));
1345 max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
1347 costs_set = 1;
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));
1359 bzero (char_ins_del_vector, (sizeof (int)
1360 + 2 * max_frame_cols * sizeof (int)));
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);
1373 calculate_ins_del_char_costs (frame);
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;
1381 cmcostinit (); /* set up cursor motion costs */
1384 struct fkey_table {
1385 char *cap, *name;
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.
1395 static struct fkey_table keys[] =
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 */
1410 * "insert" --- see below
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 */
1419 * "break" goes here, but can't be reliably intercepted with termcap
1421 {"&4", "reset"}, /* terminfo --- actually `restart' */
1423 * "system" and "user" --- no termcaps
1425 {"kE", "clearline"}, /* terminfo */
1426 {"kA", "insertline"}, /* terminfo */
1427 {"kL", "deleteline"}, /* terminfo */
1428 {"kI", "insertchar"}, /* terminfo */
1429 {"kD", "deletechar"}, /* terminfo */
1430 {"kB", "backtab"}, /* terminfo */
1432 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1434 {"@8", "kp-enter"}, /* terminfo */
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.
1441 {"K4", "kp-1"}, /* terminfo */
1443 * "kp-2" --- no termcap
1445 {"K5", "kp-3"}, /* terminfo */
1447 * "kp-4" --- no termcap
1449 {"K2", "kp-5"}, /* terminfo */
1451 * "kp-6" --- no termcap
1453 {"K1", "kp-7"}, /* terminfo */
1455 * "kp-8" --- no termcap
1457 {"K3", "kp-9"}, /* terminfo */
1459 * "kp-equal" --- no termcap
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"},
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*/
1491 static char **term_get_fkeys_arg;
1492 static Lisp_Object term_get_fkeys_1 ();
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. */
1498 void
1499 term_get_fkeys (address)
1500 char **address;
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. */
1510 extern Lisp_Object Fidentity ();
1511 term_get_fkeys_arg = address;
1512 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1515 static Lisp_Object
1516 term_get_fkeys_1 ()
1518 int i;
1520 char **address = term_get_fkeys_arg;
1522 /* This can happen if CANNOT_DUMP or with strange options. */
1523 if (!initialized)
1524 Vfunction_key_map = Fmake_sparse_keymap (Qnil);
1526 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
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)));
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.
1541 char *k_semi = tgetstr ("k;", address);
1542 char *k0 = tgetstr ("k0", address);
1543 char *k0_name = "f10";
1545 if (k_semi)
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")));
1555 else if (k0)
1556 Fdefine_key (Vfunction_key_map, build_string (k0),
1557 Fmake_vector (make_number (1), intern (k0_name)));
1560 /* Set up cookies for numbered function keys above f10. */
1562 char fcap[3], fkey[4];
1564 fcap[0] = 'F'; fcap[2] = '\0';
1565 for (i = 11; i < 64; i++)
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;
1575 char *sequence = tgetstr (fcap, address);
1576 if (sequence)
1578 sprintf (fkey, "f%d", i);
1579 Fdefine_key (Vfunction_key_map, build_string (sequence),
1580 Fmake_vector (make_number (1),
1581 intern (fkey)));
1588 * Various mappings to try and get a better fit.
1591 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1592 if (!tgetstr (cap1, address)) \
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))); \
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");
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
1624 return Qnil;
1628 /***********************************************************************
1629 Character Display Information
1630 ***********************************************************************/
1632 static void append_glyph P_ ((struct it *));
1633 static void produce_stretch_glyph P_ ((struct it *));
1636 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1637 terminal frames if IT->glyph_row != NULL. IT->char_to_display is
1638 the character for which to produce glyphs; IT->face_id contains the
1639 character's face. Padding glyphs are appended if IT->c has a
1640 IT->pixel_width > 1. */
1642 static void
1643 append_glyph (it)
1644 struct it *it;
1646 struct glyph *glyph, *end;
1647 int i;
1649 xassert (it->glyph_row);
1650 glyph = (it->glyph_row->glyphs[it->area]
1651 + it->glyph_row->used[it->area]);
1652 end = it->glyph_row->glyphs[1 + it->area];
1654 for (i = 0;
1655 i < it->pixel_width && glyph < end;
1656 ++i)
1658 glyph->type = CHAR_GLYPH;
1659 glyph->pixel_width = 1;
1660 glyph->u.ch = it->char_to_display;
1661 glyph->face_id = it->face_id;
1662 glyph->padding_p = i > 0;
1663 glyph->charpos = CHARPOS (it->position);
1664 glyph->object = it->object;
1666 ++it->glyph_row->used[it->area];
1667 ++glyph;
1672 /* Produce glyphs for the display element described by IT. *IT
1673 specifies what we want to produce a glyph for (character, image, ...),
1674 and where in the glyph matrix we currently are (glyph row and hpos).
1675 produce_glyphs fills in output fields of *IT with information such as the
1676 pixel width and height of a character, and maybe output actual glyphs at
1677 the same time if IT->glyph_row is non-null. See the explanation of
1678 struct display_iterator in dispextern.h for an overview.
1680 produce_glyphs also stores the result of glyph width, ascent
1681 etc. computations in *IT.
1683 IT->glyph_row may be null, in which case produce_glyphs does not
1684 actually fill in the glyphs. This is used in the move_* functions
1685 in xdisp.c for text width and height computations.
1687 Callers usually don't call produce_glyphs directly;
1688 instead they use the macro PRODUCE_GLYPHS. */
1690 void
1691 produce_glyphs (it)
1692 struct it *it;
1694 /* If a hook is installed, let it do the work. */
1695 xassert (it->what == IT_CHARACTER
1696 || it->what == IT_COMPOSITION
1697 || it->what == IT_STRETCH);
1699 if (it->what == IT_STRETCH)
1701 produce_stretch_glyph (it);
1702 goto done;
1705 /* Nothing but characters are supported on terminal frames. For a
1706 composition sequence, it->c is the first character of the
1707 sequence. */
1708 xassert (it->what == IT_CHARACTER
1709 || it->what == IT_COMPOSITION);
1711 /* Maybe translate single-byte characters to multibyte. */
1712 it->char_to_display = it->c;
1714 if (it->c >= 040 && it->c < 0177)
1716 it->pixel_width = it->nglyphs = 1;
1717 if (it->glyph_row)
1718 append_glyph (it);
1720 else if (it->c == '\n')
1721 it->pixel_width = it->nglyphs = 0;
1722 else if (it->c == '\t')
1724 int absolute_x = (it->current_x
1725 + it->continuation_lines_width);
1726 int next_tab_x
1727 = (((1 + absolute_x + it->tab_width - 1)
1728 / it->tab_width)
1729 * it->tab_width);
1730 int nspaces;
1732 /* If part of the TAB has been displayed on the previous line
1733 which is continued now, continuation_lines_width will have
1734 been incremented already by the part that fitted on the
1735 continued line. So, we will get the right number of spaces
1736 here. */
1737 nspaces = next_tab_x - absolute_x;
1739 if (it->glyph_row)
1741 int n = nspaces;
1743 it->char_to_display = ' ';
1744 it->pixel_width = it->len = 1;
1746 while (n--)
1747 append_glyph (it);
1750 it->pixel_width = nspaces;
1751 it->nglyphs = nspaces;
1753 else if (SINGLE_BYTE_CHAR_P (it->c))
1755 if (unibyte_display_via_language_environment
1756 && (it->c >= 0240
1757 || !NILP (Vnonascii_translation_table)))
1759 int charset;
1761 it->char_to_display = unibyte_char_to_multibyte (it->c);
1762 charset = CHAR_CHARSET (it->char_to_display);
1763 it->pixel_width = CHARSET_WIDTH (charset);
1764 it->nglyphs = it->pixel_width;
1765 if (it->glyph_row)
1766 append_glyph (it);
1768 else
1770 /* Coming here means that it->c is from display table, thus we
1771 must send the code as is to the terminal. Although there's
1772 no way to know how many columns it occupies on a screen, it
1773 is a good assumption that a single byte code has 1-column
1774 width. */
1775 it->pixel_width = it->nglyphs = 1;
1776 if (it->glyph_row)
1777 append_glyph (it);
1780 else
1782 /* A multi-byte character. The display width is fixed for all
1783 characters of the set. Some of the glyphs may have to be
1784 ignored because they are already displayed in a continued
1785 line. */
1786 int charset = CHAR_CHARSET (it->c);
1788 it->pixel_width = CHARSET_WIDTH (charset);
1789 it->nglyphs = it->pixel_width;
1791 if (it->glyph_row)
1792 append_glyph (it);
1795 done:
1796 /* Advance current_x by the pixel width as a convenience for
1797 the caller. */
1798 if (it->area == TEXT_AREA)
1799 it->current_x += it->pixel_width;
1800 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1801 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
1805 /* Produce a stretch glyph for iterator IT. IT->object is the value
1806 of the glyph property displayed. The value must be a list
1807 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1808 being recognized:
1810 1. `:width WIDTH' specifies that the space should be WIDTH *
1811 canonical char width wide. WIDTH may be an integer or floating
1812 point number.
1814 2. `:align-to HPOS' specifies that the space should be wide enough
1815 to reach HPOS, a value in canonical character units. */
1817 static void
1818 produce_stretch_glyph (it)
1819 struct it *it;
1821 /* (space :width WIDTH ...) */
1822 Lisp_Object prop, plist;
1823 int width = 0, align_to = -1;
1824 int zero_width_ok_p = 0;
1825 double tem;
1827 /* List should start with `space'. */
1828 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1829 plist = XCDR (it->object);
1831 /* Compute the width of the stretch. */
1832 if ((prop = Fplist_get (plist, QCwidth), !NILP (prop))
1833 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, 0))
1835 /* Absolute width `:width WIDTH' specified and valid. */
1836 zero_width_ok_p = 1;
1837 width = (int)(tem + 0.5);
1839 else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
1840 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, &align_to))
1842 if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
1843 align_to = (align_to < 0
1845 : align_to - window_box_left_offset (it->w, TEXT_AREA));
1846 else if (align_to < 0)
1847 align_to = window_box_left_offset (it->w, TEXT_AREA);
1848 width = max (0, (int)(tem + 0.5) + align_to - it->current_x);
1849 zero_width_ok_p = 1;
1851 else
1852 /* Nothing specified -> width defaults to canonical char width. */
1853 width = FRAME_COLUMN_WIDTH (it->f);
1855 if (width <= 0 && (width < 0 || !zero_width_ok_p))
1856 width = 1;
1858 if (width > 0 && it->glyph_row)
1860 Lisp_Object o_object = it->object;
1861 Lisp_Object object = it->stack[it->sp - 1].string;
1862 int n = width;
1864 if (!STRINGP (object))
1865 object = it->w->buffer;
1866 it->object = object;
1867 it->char_to_display = ' ';
1868 it->pixel_width = it->len = 1;
1869 while (n--)
1870 append_glyph (it);
1871 it->object = o_object;
1873 it->pixel_width = width;
1874 it->nglyphs = width;
1878 /* Get information about special display element WHAT in an
1879 environment described by IT. WHAT is one of IT_TRUNCATION or
1880 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1881 non-null glyph_row member. This function ensures that fields like
1882 face_id, c, len of IT are left untouched. */
1884 void
1885 produce_special_glyphs (it, what)
1886 struct it *it;
1887 enum display_element_type what;
1889 struct it temp_it;
1890 GLYPH glyph;
1892 temp_it = *it;
1893 temp_it.dp = NULL;
1894 temp_it.what = IT_CHARACTER;
1895 temp_it.len = 1;
1896 temp_it.object = make_number (0);
1897 bzero (&temp_it.current, sizeof temp_it.current);
1899 if (what == IT_CONTINUATION)
1901 /* Continuation glyph. */
1902 if (it->dp
1903 && INTEGERP (DISP_CONTINUE_GLYPH (it->dp))
1904 && GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (it->dp))))
1906 glyph = XINT (DISP_CONTINUE_GLYPH (it->dp));
1907 glyph = spec_glyph_lookup_face (XWINDOW (it->window), glyph);
1909 else
1910 glyph = '\\';
1912 else if (what == IT_TRUNCATION)
1914 /* Truncation glyph. */
1915 if (it->dp
1916 && INTEGERP (DISP_TRUNC_GLYPH (it->dp))
1917 && GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (it->dp))))
1919 glyph = XINT (DISP_TRUNC_GLYPH (it->dp));
1920 glyph = spec_glyph_lookup_face (XWINDOW (it->window), glyph);
1922 else
1923 glyph = '$';
1925 else
1926 abort ();
1928 temp_it.c = FAST_GLYPH_CHAR (glyph);
1929 temp_it.face_id = FAST_GLYPH_FACE (glyph);
1930 temp_it.len = CHAR_BYTES (temp_it.c);
1932 produce_glyphs (&temp_it);
1933 it->pixel_width = temp_it.pixel_width;
1934 it->nglyphs = temp_it.pixel_width;
1939 /***********************************************************************
1940 Faces
1941 ***********************************************************************/
1943 /* Value is non-zero if attribute ATTR may be used. ATTR should be
1944 one of the enumerators from enum no_color_bit, or a bit set built
1945 from them. Some display attributes may not be used together with
1946 color; the termcap capability `NC' specifies which ones. */
1948 #define MAY_USE_WITH_COLORS_P(ATTR) \
1949 (TN_max_colors > 0 \
1950 ? (TN_no_color_video & (ATTR)) == 0 \
1951 : 1)
1953 /* Turn appearances of face FACE_ID on tty frame F on.
1954 FACE_ID is a realized face ID number, in the face cache. */
1956 static void
1957 turn_on_face (f, face_id)
1958 struct frame *f;
1959 int face_id;
1961 struct face *face = FACE_FROM_ID (f, face_id);
1962 long fg = face->foreground;
1963 long bg = face->background;
1965 /* Do this first because TS_end_standout_mode may be the same
1966 as TS_exit_attribute_mode, which turns all appearances off. */
1967 if (MAY_USE_WITH_COLORS_P (NC_REVERSE))
1969 if (TN_max_colors > 0)
1971 if (fg >= 0 && bg >= 0)
1973 /* If the terminal supports colors, we can set them
1974 below without using reverse video. The face's fg
1975 and bg colors are set as they should appear on
1976 the screen, i.e. they take the inverse-video'ness
1977 of the face already into account. */
1979 else if (inverse_video)
1981 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1982 || bg == FACE_TTY_DEFAULT_BG_COLOR)
1983 toggle_highlight ();
1985 else
1987 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1988 || bg == FACE_TTY_DEFAULT_FG_COLOR)
1989 toggle_highlight ();
1992 else
1994 /* If we can't display colors, use reverse video
1995 if the face specifies that. */
1996 if (inverse_video)
1998 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1999 || bg == FACE_TTY_DEFAULT_BG_COLOR)
2000 toggle_highlight ();
2002 else
2004 if (fg == FACE_TTY_DEFAULT_BG_COLOR
2005 || bg == FACE_TTY_DEFAULT_FG_COLOR)
2006 toggle_highlight ();
2011 if (face->tty_bold_p)
2013 if (MAY_USE_WITH_COLORS_P (NC_BOLD))
2014 OUTPUT1_IF (TS_enter_bold_mode);
2016 else if (face->tty_dim_p)
2017 if (MAY_USE_WITH_COLORS_P (NC_DIM))
2018 OUTPUT1_IF (TS_enter_dim_mode);
2020 /* Alternate charset and blinking not yet used. */
2021 if (face->tty_alt_charset_p
2022 && MAY_USE_WITH_COLORS_P (NC_ALT_CHARSET))
2023 OUTPUT1_IF (TS_enter_alt_charset_mode);
2025 if (face->tty_blinking_p
2026 && MAY_USE_WITH_COLORS_P (NC_BLINK))
2027 OUTPUT1_IF (TS_enter_blink_mode);
2029 if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (NC_UNDERLINE))
2030 OUTPUT1_IF (TS_enter_underline_mode);
2032 if (TN_max_colors > 0)
2034 char *ts, *p;
2036 ts = standout_mode ? TS_set_background : TS_set_foreground;
2037 if (fg >= 0 && ts)
2039 p = tparam (ts, NULL, 0, (int) fg);
2040 OUTPUT (p);
2041 xfree (p);
2044 ts = standout_mode ? TS_set_foreground : TS_set_background;
2045 if (bg >= 0 && ts)
2047 p = tparam (ts, NULL, 0, (int) bg);
2048 OUTPUT (p);
2049 xfree (p);
2055 /* Turn off appearances of face FACE_ID on tty frame F. */
2057 static void
2058 turn_off_face (f, face_id)
2059 struct frame *f;
2060 int face_id;
2062 struct face *face = FACE_FROM_ID (f, face_id);
2064 xassert (face != NULL);
2066 if (TS_exit_attribute_mode)
2068 /* Capability "me" will turn off appearance modes double-bright,
2069 half-bright, reverse-video, standout, underline. It may or
2070 may not turn off alt-char-mode. */
2071 if (face->tty_bold_p
2072 || face->tty_dim_p
2073 || face->tty_reverse_p
2074 || face->tty_alt_charset_p
2075 || face->tty_blinking_p
2076 || face->tty_underline_p)
2078 OUTPUT1_IF (TS_exit_attribute_mode);
2079 if (strcmp (TS_exit_attribute_mode, TS_end_standout_mode) == 0)
2080 standout_mode = 0;
2083 if (face->tty_alt_charset_p)
2084 OUTPUT_IF (TS_exit_alt_charset_mode);
2086 else
2088 /* If we don't have "me" we can only have those appearances
2089 that have exit sequences defined. */
2090 if (face->tty_alt_charset_p)
2091 OUTPUT_IF (TS_exit_alt_charset_mode);
2093 if (face->tty_underline_p)
2094 OUTPUT_IF (TS_exit_underline_mode);
2097 /* Switch back to default colors. */
2098 if (TN_max_colors > 0
2099 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
2100 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
2101 || (face->background != FACE_TTY_DEFAULT_COLOR
2102 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
2103 OUTPUT1_IF (TS_orig_pair);
2107 /* Return non-zero if the terminal on frame F supports all of the
2108 capabilities in CAPS simultaneously, with foreground and background
2109 colors FG and BG. */
2112 tty_capable_p (f, caps, fg, bg)
2113 struct frame *f;
2114 unsigned caps;
2115 unsigned long fg, bg;
2117 #define TTY_CAPABLE_P_TRY(cap, TS, NC_bit) \
2118 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(NC_bit))) \
2119 return 0;
2121 TTY_CAPABLE_P_TRY (TTY_CAP_INVERSE, TS_standout_mode, NC_REVERSE);
2122 TTY_CAPABLE_P_TRY (TTY_CAP_UNDERLINE, TS_enter_underline_mode, NC_UNDERLINE);
2123 TTY_CAPABLE_P_TRY (TTY_CAP_BOLD, TS_enter_bold_mode, NC_BOLD);
2124 TTY_CAPABLE_P_TRY (TTY_CAP_DIM, TS_enter_dim_mode, NC_DIM);
2125 TTY_CAPABLE_P_TRY (TTY_CAP_BLINK, TS_enter_blink_mode, NC_BLINK);
2126 TTY_CAPABLE_P_TRY (TTY_CAP_ALT_CHARSET, TS_enter_alt_charset_mode, NC_ALT_CHARSET);
2128 /* We can do it! */
2129 return 1;
2133 /* Return non-zero if the terminal is capable to display colors. */
2135 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
2136 0, 1, 0,
2137 doc: /* Return non-nil if TTY can display colors on DISPLAY. */)
2138 (display)
2139 Lisp_Object display;
2141 return TN_max_colors > 0 ? Qt : Qnil;
2144 /* Return the number of supported colors. */
2145 DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
2146 Stty_display_color_cells, 0, 1, 0,
2147 doc: /* Return the number of colors supported by TTY on DISPLAY. */)
2148 (display)
2149 Lisp_Object display;
2151 return make_number (TN_max_colors);
2154 #ifndef WINDOWSNT
2156 /* Save or restore the default color-related capabilities of this
2157 terminal. */
2158 static void
2159 tty_default_color_capabilities (save)
2160 int save;
2162 static char
2163 *default_orig_pair, *default_set_foreground, *default_set_background;
2164 static int default_max_colors, default_max_pairs, default_no_color_video;
2166 if (save)
2168 if (default_orig_pair)
2169 xfree (default_orig_pair);
2170 default_orig_pair = TS_orig_pair ? xstrdup (TS_orig_pair) : NULL;
2172 if (default_set_foreground)
2173 xfree (default_set_foreground);
2174 default_set_foreground = TS_set_foreground ? xstrdup (TS_set_foreground)
2175 : NULL;
2177 if (default_set_background)
2178 xfree (default_set_background);
2179 default_set_background = TS_set_background ? xstrdup (TS_set_background)
2180 : NULL;
2182 default_max_colors = TN_max_colors;
2183 default_max_pairs = TN_max_pairs;
2184 default_no_color_video = TN_no_color_video;
2186 else
2188 TS_orig_pair = default_orig_pair;
2189 TS_set_foreground = default_set_foreground;
2190 TS_set_background = default_set_background;
2191 TN_max_colors = default_max_colors;
2192 TN_max_pairs = default_max_pairs;
2193 TN_no_color_video = default_no_color_video;
2197 /* Setup one of the standard tty color schemes according to MODE.
2198 MODE's value is generally the number of colors which we want to
2199 support; zero means set up for the default capabilities, the ones
2200 we saw at term_init time; -1 means turn off color support. */
2201 void
2202 tty_setup_colors (mode)
2203 int mode;
2205 /* Canonicalize all negative values of MODE. */
2206 if (mode < -1)
2207 mode = -1;
2209 switch (mode)
2211 case -1: /* no colors at all */
2212 TN_max_colors = 0;
2213 TN_max_pairs = 0;
2214 TN_no_color_video = 0;
2215 TS_set_foreground = TS_set_background = TS_orig_pair = NULL;
2216 break;
2217 case 0: /* default colors, if any */
2218 default:
2219 tty_default_color_capabilities (0);
2220 break;
2221 case 8: /* 8 standard ANSI colors */
2222 TS_orig_pair = "\033[0m";
2223 #ifdef TERMINFO
2224 TS_set_foreground = "\033[3%p1%dm";
2225 TS_set_background = "\033[4%p1%dm";
2226 #else
2227 TS_set_foreground = "\033[3%dm";
2228 TS_set_background = "\033[4%dm";
2229 #endif
2230 TN_max_colors = 8;
2231 TN_max_pairs = 64;
2232 TN_no_color_video = 0;
2233 break;
2237 void
2238 set_tty_color_mode (f, val)
2239 struct frame *f;
2240 Lisp_Object val;
2242 Lisp_Object color_mode_spec, current_mode_spec;
2243 Lisp_Object color_mode, current_mode;
2244 int mode, old_mode;
2245 extern Lisp_Object Qtty_color_mode;
2246 Lisp_Object tty_color_mode_alist;
2248 tty_color_mode_alist = Fintern_soft (build_string ("tty-color-mode-alist"),
2249 Qnil);
2251 if (INTEGERP (val))
2252 color_mode = val;
2253 else
2255 if (NILP (tty_color_mode_alist))
2256 color_mode_spec = Qnil;
2257 else
2258 color_mode_spec = Fassq (val, XSYMBOL (tty_color_mode_alist)->value);
2260 if (CONSP (color_mode_spec))
2261 color_mode = XCDR (color_mode_spec);
2262 else
2263 color_mode = Qnil;
2266 current_mode_spec = assq_no_quit (Qtty_color_mode, f->param_alist);
2268 if (CONSP (current_mode_spec))
2269 current_mode = XCDR (current_mode_spec);
2270 else
2271 current_mode = Qnil;
2272 if (INTEGERP (color_mode))
2273 mode = XINT (color_mode);
2274 else
2275 mode = 0; /* meaning default */
2276 if (INTEGERP (current_mode))
2277 old_mode = XINT (current_mode);
2278 else
2279 old_mode = 0;
2281 if (mode != old_mode)
2283 tty_setup_colors (mode);
2284 /* This recomputes all the faces given the new color
2285 definitions. */
2286 call0 (intern ("tty-set-up-initial-frame-faces"));
2287 redraw_frame (f);
2291 #endif /* !WINDOWSNT */
2294 /***********************************************************************
2295 Initialization
2296 ***********************************************************************/
2298 void
2299 term_init (terminal_type)
2300 char *terminal_type;
2302 char *area;
2303 char **address = &area;
2304 char *buffer = NULL;
2305 int buffer_size = 4096;
2306 register char *p;
2307 int status;
2308 struct frame *sf = XFRAME (selected_frame);
2310 encode_terminal_bufsize = 0;
2312 #ifdef WINDOWSNT
2313 initialize_w32_display ();
2315 Wcm_clear ();
2317 area = (char *) xmalloc (2044);
2319 FrameRows = FRAME_LINES (sf);
2320 FrameCols = FRAME_COLS (sf);
2321 specified_window = FRAME_LINES (sf);
2323 delete_in_insert_mode = 1;
2325 UseTabs = 0;
2326 scroll_region_ok = 0;
2328 /* Seems to insert lines when it's not supposed to, messing
2329 up the display. In doing a trace, it didn't seem to be
2330 called much, so I don't think we're losing anything by
2331 turning it off. */
2333 line_ins_del_ok = 0;
2334 char_ins_del_ok = 1;
2336 baud_rate = 19200;
2338 FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0;
2339 FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none;
2340 TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
2342 return;
2343 #else /* not WINDOWSNT */
2345 Wcm_clear ();
2347 buffer = (char *) xmalloc (buffer_size);
2348 status = tgetent (buffer, terminal_type);
2349 if (status < 0)
2351 #ifdef TERMINFO
2352 fatal ("Cannot open terminfo database file");
2353 #else
2354 fatal ("Cannot open termcap database file");
2355 #endif
2357 if (status == 0)
2359 #ifdef TERMINFO
2360 fatal ("Terminal type %s is not defined.\n\
2361 If that is not the actual type of terminal you have,\n\
2362 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2363 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2364 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
2365 terminal_type);
2366 #else
2367 fatal ("Terminal type %s is not defined.\n\
2368 If that is not the actual type of terminal you have,\n\
2369 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2370 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2371 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
2372 terminal_type);
2373 #endif
2376 #ifndef TERMINFO
2377 if (strlen (buffer) >= buffer_size)
2378 abort ();
2379 buffer_size = strlen (buffer);
2380 #endif
2381 area = (char *) xmalloc (buffer_size);
2383 TS_ins_line = tgetstr ("al", address);
2384 TS_ins_multi_lines = tgetstr ("AL", address);
2385 TS_bell = tgetstr ("bl", address);
2386 BackTab = tgetstr ("bt", address);
2387 TS_clr_to_bottom = tgetstr ("cd", address);
2388 TS_clr_line = tgetstr ("ce", address);
2389 TS_clr_frame = tgetstr ("cl", address);
2390 ColPosition = NULL; /* tgetstr ("ch", address); */
2391 AbsPosition = tgetstr ("cm", address);
2392 CR = tgetstr ("cr", address);
2393 TS_set_scroll_region = tgetstr ("cs", address);
2394 TS_set_scroll_region_1 = tgetstr ("cS", address);
2395 RowPosition = tgetstr ("cv", address);
2396 TS_del_char = tgetstr ("dc", address);
2397 TS_del_multi_chars = tgetstr ("DC", address);
2398 TS_del_line = tgetstr ("dl", address);
2399 TS_del_multi_lines = tgetstr ("DL", address);
2400 TS_delete_mode = tgetstr ("dm", address);
2401 TS_end_delete_mode = tgetstr ("ed", address);
2402 TS_end_insert_mode = tgetstr ("ei", address);
2403 Home = tgetstr ("ho", address);
2404 TS_ins_char = tgetstr ("ic", address);
2405 TS_ins_multi_chars = tgetstr ("IC", address);
2406 TS_insert_mode = tgetstr ("im", address);
2407 TS_pad_inserted_char = tgetstr ("ip", address);
2408 TS_end_keypad_mode = tgetstr ("ke", address);
2409 TS_keypad_mode = tgetstr ("ks", address);
2410 LastLine = tgetstr ("ll", address);
2411 Right = tgetstr ("nd", address);
2412 Down = tgetstr ("do", address);
2413 if (!Down)
2414 Down = tgetstr ("nl", address); /* Obsolete name for "do" */
2415 #ifdef VMS
2416 /* VMS puts a carriage return before each linefeed,
2417 so it is not safe to use linefeeds. */
2418 if (Down && Down[0] == '\n' && Down[1] == '\0')
2419 Down = 0;
2420 #endif /* VMS */
2421 if (tgetflag ("bs"))
2422 Left = "\b"; /* can't possibly be longer! */
2423 else /* (Actually, "bs" is obsolete...) */
2424 Left = tgetstr ("le", address);
2425 if (!Left)
2426 Left = tgetstr ("bc", address); /* Obsolete name for "le" */
2427 TS_pad_char = tgetstr ("pc", address);
2428 TS_repeat = tgetstr ("rp", address);
2429 TS_end_standout_mode = tgetstr ("se", address);
2430 TS_fwd_scroll = tgetstr ("sf", address);
2431 TS_standout_mode = tgetstr ("so", address);
2432 TS_rev_scroll = tgetstr ("sr", address);
2433 Wcm.cm_tab = tgetstr ("ta", address);
2434 TS_end_termcap_modes = tgetstr ("te", address);
2435 TS_termcap_modes = tgetstr ("ti", address);
2436 Up = tgetstr ("up", address);
2437 TS_visible_bell = tgetstr ("vb", address);
2438 TS_cursor_normal = tgetstr ("ve", address);
2439 TS_cursor_visible = tgetstr ("vs", address);
2440 TS_cursor_invisible = tgetstr ("vi", address);
2441 TS_set_window = tgetstr ("wi", address);
2443 TS_enter_underline_mode = tgetstr ("us", address);
2444 TS_exit_underline_mode = tgetstr ("ue", address);
2445 TS_enter_bold_mode = tgetstr ("md", address);
2446 TS_enter_dim_mode = tgetstr ("mh", address);
2447 TS_enter_blink_mode = tgetstr ("mb", address);
2448 TS_enter_reverse_mode = tgetstr ("mr", address);
2449 TS_enter_alt_charset_mode = tgetstr ("as", address);
2450 TS_exit_alt_charset_mode = tgetstr ("ae", address);
2451 TS_exit_attribute_mode = tgetstr ("me", address);
2453 MultiUp = tgetstr ("UP", address);
2454 MultiDown = tgetstr ("DO", address);
2455 MultiLeft = tgetstr ("LE", address);
2456 MultiRight = tgetstr ("RI", address);
2458 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
2459 color because we can't switch back to the default foreground and
2460 background. */
2461 TS_orig_pair = tgetstr ("op", address);
2462 if (TS_orig_pair)
2464 TS_set_foreground = tgetstr ("AF", address);
2465 TS_set_background = tgetstr ("AB", address);
2466 if (!TS_set_foreground)
2468 /* SVr4. */
2469 TS_set_foreground = tgetstr ("Sf", address);
2470 TS_set_background = tgetstr ("Sb", address);
2473 TN_max_colors = tgetnum ("Co");
2474 TN_max_pairs = tgetnum ("pa");
2476 TN_no_color_video = tgetnum ("NC");
2477 if (TN_no_color_video == -1)
2478 TN_no_color_video = 0;
2481 tty_default_color_capabilities (1);
2483 MagicWrap = tgetflag ("xn");
2484 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
2485 the former flag imply the latter. */
2486 AutoWrap = MagicWrap || tgetflag ("am");
2487 memory_below_frame = tgetflag ("db");
2488 TF_hazeltine = tgetflag ("hz");
2489 must_write_spaces = tgetflag ("in");
2490 meta_key = tgetflag ("km") || tgetflag ("MT");
2491 TF_insmode_motion = tgetflag ("mi");
2492 TF_standout_motion = tgetflag ("ms");
2493 TF_underscore = tgetflag ("ul");
2494 TF_teleray = tgetflag ("xt");
2496 term_get_fkeys (address);
2498 /* Get frame size from system, or else from termcap. */
2500 int height, width;
2501 get_frame_size (&width, &height);
2502 FRAME_COLS (sf) = width;
2503 FRAME_LINES (sf) = height;
2506 if (FRAME_COLS (sf) <= 0)
2507 SET_FRAME_COLS (sf, tgetnum ("co"));
2508 else
2509 /* Keep width and external_width consistent */
2510 SET_FRAME_COLS (sf, FRAME_COLS (sf));
2511 if (FRAME_LINES (sf) <= 0)
2512 FRAME_LINES (sf) = tgetnum ("li");
2514 if (FRAME_LINES (sf) < 3 || FRAME_COLS (sf) < 3)
2515 fatal ("Screen size %dx%d is too small",
2516 FRAME_LINES (sf), FRAME_COLS (sf));
2518 min_padding_speed = tgetnum ("pb");
2519 TabWidth = tgetnum ("tw");
2521 #ifdef VMS
2522 /* These capabilities commonly use ^J.
2523 I don't know why, but sending them on VMS does not work;
2524 it causes following spaces to be lost, sometimes.
2525 For now, the simplest fix is to avoid using these capabilities ever. */
2526 if (Down && Down[0] == '\n')
2527 Down = 0;
2528 #endif /* VMS */
2530 if (!TS_bell)
2531 TS_bell = "\07";
2533 if (!TS_fwd_scroll)
2534 TS_fwd_scroll = Down;
2536 PC = TS_pad_char ? *TS_pad_char : 0;
2538 if (TabWidth < 0)
2539 TabWidth = 8;
2541 /* Turned off since /etc/termcap seems to have :ta= for most terminals
2542 and newer termcap doc does not seem to say there is a default.
2543 if (!Wcm.cm_tab)
2544 Wcm.cm_tab = "\t";
2547 /* We don't support standout modes that use `magic cookies', so
2548 turn off any that do. */
2549 if (TS_standout_mode && tgetnum ("sg") >= 0)
2551 TS_standout_mode = 0;
2552 TS_end_standout_mode = 0;
2554 if (TS_enter_underline_mode && tgetnum ("ug") >= 0)
2556 TS_enter_underline_mode = 0;
2557 TS_exit_underline_mode = 0;
2560 /* If there's no standout mode, try to use underlining instead. */
2561 if (TS_standout_mode == 0)
2563 TS_standout_mode = TS_enter_underline_mode;
2564 TS_end_standout_mode = TS_exit_underline_mode;
2567 /* If no `se' string, try using a `me' string instead.
2568 If that fails, we can't use standout mode at all. */
2569 if (TS_end_standout_mode == 0)
2571 char *s = tgetstr ("me", address);
2572 if (s != 0)
2573 TS_end_standout_mode = s;
2574 else
2575 TS_standout_mode = 0;
2578 if (TF_teleray)
2580 Wcm.cm_tab = 0;
2581 /* We can't support standout mode, because it uses magic cookies. */
2582 TS_standout_mode = 0;
2583 /* But that means we cannot rely on ^M to go to column zero! */
2584 CR = 0;
2585 /* LF can't be trusted either -- can alter hpos */
2586 /* if move at column 0 thru a line with TS_standout_mode */
2587 Down = 0;
2590 /* Special handling for certain terminal types known to need it */
2592 if (!strcmp (terminal_type, "supdup"))
2594 memory_below_frame = 1;
2595 Wcm.cm_losewrap = 1;
2597 if (!strncmp (terminal_type, "c10", 3)
2598 || !strcmp (terminal_type, "perq"))
2600 /* Supply a makeshift :wi string.
2601 This string is not valid in general since it works only
2602 for windows starting at the upper left corner;
2603 but that is all Emacs uses.
2605 This string works only if the frame is using
2606 the top of the video memory, because addressing is memory-relative.
2607 So first check the :ti string to see if that is true.
2609 It would be simpler if the :wi string could go in the termcap
2610 entry, but it can't because it is not fully valid.
2611 If it were in the termcap entry, it would confuse other programs. */
2612 if (!TS_set_window)
2614 p = TS_termcap_modes;
2615 while (*p && strcmp (p, "\033v "))
2616 p++;
2617 if (*p)
2618 TS_set_window = "\033v%C %C %C %C ";
2620 /* Termcap entry often fails to have :in: flag */
2621 must_write_spaces = 1;
2622 /* :ti string typically fails to have \E^G! in it */
2623 /* This limits scope of insert-char to one line. */
2624 strcpy (area, TS_termcap_modes);
2625 strcat (area, "\033\007!");
2626 TS_termcap_modes = area;
2627 area += strlen (area) + 1;
2628 p = AbsPosition;
2629 /* Change all %+ parameters to %C, to handle
2630 values above 96 correctly for the C100. */
2631 while (*p)
2633 if (p[0] == '%' && p[1] == '+')
2634 p[1] = 'C';
2635 p++;
2639 FrameRows = FRAME_LINES (sf);
2640 FrameCols = FRAME_COLS (sf);
2641 specified_window = FRAME_LINES (sf);
2643 if (Wcm_init () == -1) /* can't do cursor motion */
2644 #ifdef VMS
2645 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2646 It lacks the ability to position the cursor.\n\
2647 If that is not the actual type of terminal you have, use either the\n\
2648 DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
2649 or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
2650 terminal_type);
2651 #else /* not VMS */
2652 # ifdef TERMINFO
2653 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2654 It lacks the ability to position the cursor.\n\
2655 If that is not the actual type of terminal you have,\n\
2656 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2657 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2658 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
2659 terminal_type);
2660 # else /* TERMCAP */
2661 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2662 It lacks the ability to position the cursor.\n\
2663 If that is not the actual type of terminal you have,\n\
2664 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2665 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2666 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
2667 terminal_type);
2668 # endif /* TERMINFO */
2669 #endif /*VMS */
2670 if (FRAME_LINES (sf) <= 0
2671 || FRAME_COLS (sf) <= 0)
2672 fatal ("The frame size has not been specified");
2674 delete_in_insert_mode
2675 = TS_delete_mode && TS_insert_mode
2676 && !strcmp (TS_delete_mode, TS_insert_mode);
2678 se_is_so = (TS_standout_mode
2679 && TS_end_standout_mode
2680 && !strcmp (TS_standout_mode, TS_end_standout_mode));
2682 UseTabs = tabs_safe_p () && TabWidth == 8;
2684 scroll_region_ok
2685 = (Wcm.cm_abs
2686 && (TS_set_window || TS_set_scroll_region || TS_set_scroll_region_1));
2688 line_ins_del_ok = (((TS_ins_line || TS_ins_multi_lines)
2689 && (TS_del_line || TS_del_multi_lines))
2690 || (scroll_region_ok && TS_fwd_scroll && TS_rev_scroll));
2692 char_ins_del_ok = ((TS_ins_char || TS_insert_mode
2693 || TS_pad_inserted_char || TS_ins_multi_chars)
2694 && (TS_del_char || TS_del_multi_chars));
2696 fast_clear_end_of_line = TS_clr_line != 0;
2698 init_baud_rate ();
2699 if (read_socket_hook) /* Baudrate is somewhat */
2700 /* meaningless in this case */
2701 baud_rate = 9600;
2703 FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0;
2704 FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none;
2705 #endif /* WINDOWSNT */
2707 xfree (buffer);
2710 /* VARARGS 1 */
2711 void
2712 fatal (str, arg1, arg2)
2713 char *str, *arg1, *arg2;
2715 fprintf (stderr, "emacs: ");
2716 fprintf (stderr, str, arg1, arg2);
2717 fprintf (stderr, "\n");
2718 fflush (stderr);
2719 exit (1);
2722 DEFUN ("tty-no-underline", Ftty_no_underline, Stty_no_underline, 0, 0, 0,
2723 doc: /* Declare that this terminal does not handle underlining.
2724 This is used to override the terminfo data, for certain terminals that
2725 do not really do underlining, but say that they do. */)
2728 TS_enter_underline_mode = 0;
2729 return Qnil;
2732 void
2733 syms_of_term ()
2735 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
2736 doc: /* Non-nil means the system uses terminfo rather than termcap.
2737 This variable can be used by terminal emulator packages. */);
2738 #ifdef TERMINFO
2739 system_uses_terminfo = 1;
2740 #else
2741 system_uses_terminfo = 0;
2742 #endif
2744 DEFVAR_LISP ("ring-bell-function", &Vring_bell_function,
2745 doc: /* Non-nil means call this function to ring the bell.
2746 The function should accept no arguments. */);
2747 Vring_bell_function = Qnil;
2749 DEFVAR_BOOL ("visible-cursor", &visible_cursor,
2750 doc: /* Non-nil means to make the cursor very visible.
2751 This only has an effect when running in a text terminal.
2752 What means \"very visible\" is up to your terminal. It may make the cursor
2753 bigger, or it may make it blink, or it may do nothing at all. */);
2754 visible_cursor = 1;
2756 defsubr (&Stty_display_color_p);
2757 defsubr (&Stty_display_color_cells);
2758 defsubr (&Stty_no_underline);
2761 /* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193
2762 (do not change this comment) */