*** empty log message ***
[emacs.git] / src / term.c
blob5c439b34c9eea6aa8bb64bd285e2af3c1b1a4e59
1 /* terminal control module for terminals described by TERMCAP
2 Copyright (C) 1985, 86, 87, 93, 94, 95, 98
3 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
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., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* New redisplay, TTY faces by Gerd Moellmann <gerd@acm.org>. */
25 #include <config.h>
26 #include <stdio.h>
27 #include <ctype.h>
28 #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 "frame.h"
35 #include "disptab.h"
36 #include "termhooks.h"
37 #include "keyboard.h"
38 #include "dispextern.h"
39 #include "window.h"
41 #ifdef HAVE_TERMCAP_H
42 #include <termcap.h>
43 #else
44 extern void tputs P_ ((const char *, int, int (*)(int)));
45 extern int tgetent P_ ((char *, const char *));
46 extern int tgetflag P_ ((char *id));
47 extern int tgetnum P_ ((char *id));
48 #endif
50 #include "cm.h"
51 #ifdef HAVE_X_WINDOWS
52 #include "xterm.h"
53 #endif
55 static void turn_on_face P_ ((struct frame *, int face_id));
56 static void turn_off_face P_ ((struct frame *, int face_id));
57 static void tty_show_cursor P_ ((void));
58 static void tty_hide_cursor P_ ((void));
60 #define max(a, b) ((a) > (b) ? (a) : (b))
61 #define min(a, b) ((a) < (b) ? (a) : (b))
63 #define OUTPUT(a) \
64 tputs (a, (int) (FRAME_HEIGHT (XFRAME (selected_frame)) - curY), cmputc)
65 #define OUTPUT1(a) tputs (a, 1, cmputc)
66 #define OUTPUTL(a, lines) tputs (a, lines, cmputc)
68 #define OUTPUT_IF(a) \
69 do { \
70 if (a) \
71 tputs (a, (int) (FRAME_HEIGHT (XFRAME (selected_frame)) \
72 - curY), cmputc); \
73 } while (0)
75 #define OUTPUT1_IF(a) do { if (a) tputs (a, 1, cmputc); } while (0)
77 /* Function to use to ring the bell. */
79 Lisp_Object Vring_bell_function;
81 /* Terminal characteristics that higher levels want to look at.
82 These are all extern'd in termchar.h */
84 int must_write_spaces; /* Nonzero means spaces in the text
85 must actually be output; can't just skip
86 over some columns to leave them blank. */
87 int min_padding_speed; /* Speed below which no padding necessary */
89 int line_ins_del_ok; /* Terminal can insert and delete lines */
90 int char_ins_del_ok; /* Terminal can insert and delete chars */
91 int scroll_region_ok; /* Terminal supports setting the
92 scroll window */
93 int scroll_region_cost; /* Cost of setting a scroll window,
94 measured in characters */
95 int memory_below_frame; /* Terminal remembers lines
96 scrolled off bottom */
97 int fast_clear_end_of_line; /* Terminal has a `ce' string */
99 /* Nonzero means no need to redraw the entire frame on resuming
100 a suspended Emacs. This is useful on terminals with multiple pages,
101 where one page is used for Emacs and another for all else. */
103 int no_redraw_on_reenter;
105 /* Hook functions that you can set to snap out the functions in this file.
106 These are all extern'd in termhooks.h */
108 void (*cursor_to_hook) P_ ((int, int));
109 void (*raw_cursor_to_hook) P_ ((int, int));
110 void (*clear_to_end_hook) P_ ((void));
111 void (*clear_frame_hook) P_ ((void));
112 void (*clear_end_of_line_hook) P_ ((int));
114 void (*ins_del_lines_hook) P_ ((int, int));
116 void (*change_line_highlight_hook) P_ ((int, int, int, int));
117 void (*reassert_line_highlight_hook) P_ ((int, int));
119 void (*delete_glyphs_hook) P_ ((int));
121 void (*ring_bell_hook) P_ ((void));
123 void (*reset_terminal_modes_hook) P_ ((void));
124 void (*set_terminal_modes_hook) P_ ((void));
125 void (*update_begin_hook) P_ ((struct frame *));
126 void (*update_end_hook) P_ ((struct frame *));
127 void (*set_terminal_window_hook) P_ ((int));
128 void (*insert_glyphs_hook) P_ ((struct glyph *, int));
129 void (*write_glyphs_hook) P_ ((struct glyph *, int));
130 void (*delete_glyphs_hook) P_ ((int));
132 int (*read_socket_hook) P_ ((int, struct input_event *, int, int));
134 void (*frame_up_to_date_hook) P_ ((struct frame *));
136 /* Return the current position of the mouse.
138 Set *f to the frame the mouse is in, or zero if the mouse is in no
139 Emacs frame. If it is set to zero, all the other arguments are
140 garbage.
142 If the motion started in a scroll bar, set *bar_window to the
143 scroll bar's window, *part to the part the mouse is currently over,
144 *x to the position of the mouse along the scroll bar, and *y to the
145 overall length of the scroll bar.
147 Otherwise, set *bar_window to Qnil, and *x and *y to the column and
148 row of the character cell the mouse is over.
150 Set *time to the time the mouse was at the returned position.
152 This should clear mouse_moved until the next motion
153 event arrives. */
154 void (*mouse_position_hook) P_ ((FRAME_PTR *f, int insist,
155 Lisp_Object *bar_window,
156 enum scroll_bar_part *part,
157 Lisp_Object *x,
158 Lisp_Object *y,
159 unsigned long *time));
161 /* When reading from a minibuffer in a different frame, Emacs wants
162 to shift the highlight from the selected frame to the mini-buffer's
163 frame; under X, this means it lies about where the focus is.
164 This hook tells the window system code to re-decide where to put
165 the highlight. */
166 void (*frame_rehighlight_hook) P_ ((FRAME_PTR f));
168 /* If we're displaying frames using a window system that can stack
169 frames on top of each other, this hook allows you to bring a frame
170 to the front, or bury it behind all the other windows. If this
171 hook is zero, that means the device we're displaying on doesn't
172 support overlapping frames, so there's no need to raise or lower
173 anything.
175 If RAISE is non-zero, F is brought to the front, before all other
176 windows. If RAISE is zero, F is sent to the back, behind all other
177 windows. */
178 void (*frame_raise_lower_hook) P_ ((FRAME_PTR f, int raise));
180 /* Set the vertical scroll bar for WINDOW to have its upper left corner
181 at (TOP, LEFT), and be LENGTH rows high. Set its handle to
182 indicate that we are displaying PORTION characters out of a total
183 of WHOLE characters, starting at POSITION. If WINDOW doesn't yet
184 have a scroll bar, create one for it. */
186 void (*set_vertical_scroll_bar_hook)
187 P_ ((struct window *window,
188 int portion, int whole, int position));
191 /* The following three hooks are used when we're doing a thorough
192 redisplay of the frame. We don't explicitly know which scroll bars
193 are going to be deleted, because keeping track of when windows go
194 away is a real pain - can you say set-window-configuration?
195 Instead, we just assert at the beginning of redisplay that *all*
196 scroll bars are to be removed, and then save scroll bars from the
197 fiery pit when we actually redisplay their window. */
199 /* Arrange for all scroll bars on FRAME to be removed at the next call
200 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
201 `*redeem_scroll_bar_hook' is applied to its window before the judgment.
203 This should be applied to each frame each time its window tree is
204 redisplayed, even if it is not displaying scroll bars at the moment;
205 if the HAS_SCROLL_BARS flag has just been turned off, only calling
206 this and the judge_scroll_bars_hook will get rid of them.
208 If non-zero, this hook should be safe to apply to any frame,
209 whether or not it can support scroll bars, and whether or not it is
210 currently displaying them. */
211 void (*condemn_scroll_bars_hook) P_ ((FRAME_PTR frame));
213 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
214 Note that it's okay to redeem a scroll bar that is not condemned. */
215 void (*redeem_scroll_bar_hook) P_ ((struct window *window));
217 /* Remove all scroll bars on FRAME that haven't been saved since the
218 last call to `*condemn_scroll_bars_hook'.
220 This should be applied to each frame after each time its window
221 tree is redisplayed, even if it is not displaying scroll bars at the
222 moment; if the HAS_SCROLL_BARS flag has just been turned off, only
223 calling this and condemn_scroll_bars_hook will get rid of them.
225 If non-zero, this hook should be safe to apply to any frame,
226 whether or not it can support scroll bars, and whether or not it is
227 currently displaying them. */
228 void (*judge_scroll_bars_hook) P_ ((FRAME_PTR FRAME));
230 /* Hook to call in estimate_mode_line_height, if any. */
232 int (* estimate_mode_line_height_hook) P_ ((struct frame *f, enum face_id));
235 /* Strings, numbers and flags taken from the termcap entry. */
237 char *TS_ins_line; /* "al" */
238 char *TS_ins_multi_lines; /* "AL" (one parameter, # lines to insert) */
239 char *TS_bell; /* "bl" */
240 char *TS_clr_to_bottom; /* "cd" */
241 char *TS_clr_line; /* "ce", clear to end of line */
242 char *TS_clr_frame; /* "cl" */
243 char *TS_set_scroll_region; /* "cs" (2 params, first line and last line) */
244 char *TS_set_scroll_region_1; /* "cS" (4 params: total lines,
245 lines above scroll region, lines below it,
246 total lines again) */
247 char *TS_del_char; /* "dc" */
248 char *TS_del_multi_chars; /* "DC" (one parameter, # chars to delete) */
249 char *TS_del_line; /* "dl" */
250 char *TS_del_multi_lines; /* "DL" (one parameter, # lines to delete) */
251 char *TS_delete_mode; /* "dm", enter character-delete mode */
252 char *TS_end_delete_mode; /* "ed", leave character-delete mode */
253 char *TS_end_insert_mode; /* "ei", leave character-insert mode */
254 char *TS_ins_char; /* "ic" */
255 char *TS_ins_multi_chars; /* "IC" (one parameter, # chars to insert) */
256 char *TS_insert_mode; /* "im", enter character-insert mode */
257 char *TS_pad_inserted_char; /* "ip". Just padding, no commands. */
258 char *TS_end_keypad_mode; /* "ke" */
259 char *TS_keypad_mode; /* "ks" */
260 char *TS_pad_char; /* "pc", char to use as padding */
261 char *TS_repeat; /* "rp" (2 params, # times to repeat
262 and character to be repeated) */
263 char *TS_end_standout_mode; /* "se" */
264 char *TS_fwd_scroll; /* "sf" */
265 char *TS_standout_mode; /* "so" */
266 char *TS_rev_scroll; /* "sr" */
267 char *TS_end_termcap_modes; /* "te" */
268 char *TS_termcap_modes; /* "ti" */
269 char *TS_visible_bell; /* "vb" */
270 char *TS_cursor_normal; /* "ve" */
271 char *TS_cursor_visible; /* "vs" */
272 char *TS_cursor_invisible; /* "vi" */
273 char *TS_set_window; /* "wi" (4 params, start and end of window,
274 each as vpos and hpos) */
276 /* Value of the "NC" (no_color_video) capability, or 0 if not
277 present. */
279 static int TN_no_color_video;
281 /* Meaning of bits in no_color_video. Each bit set means that the
282 corresponding attribute cannot be combined with colors. */
284 enum no_color_bit
286 NC_STANDOUT = 1 << 0,
287 NC_UNDERLINE = 1 << 1,
288 NC_REVERSE = 1 << 2,
289 NC_BLINK = 1 << 3,
290 NC_DIM = 1 << 4,
291 NC_BOLD = 1 << 5,
292 NC_INVIS = 1 << 6,
293 NC_PROTECT = 1 << 7,
294 NC_ALT_CHARSET = 1 << 8
297 /* "md" -- turn on bold (extra bright mode). */
299 char *TS_enter_bold_mode;
301 /* "mh" -- turn on half-bright mode. */
303 char *TS_enter_dim_mode;
305 /* "mb" -- enter blinking mode. */
307 char *TS_enter_blink_mode;
309 /* "mr" -- enter reverse video mode. */
311 char *TS_enter_reverse_mode;
313 /* "us"/"ue" -- start/end underlining. */
315 char *TS_exit_underline_mode, *TS_enter_underline_mode;
317 /* "ug" -- number of blanks left by underline. */
319 int TN_magic_cookie_glitch_ul;
321 /* "as"/"ae" -- start/end alternate character set. Not really
322 supported, yet. */
324 char *TS_enter_alt_charset_mode, *TS_exit_alt_charset_mode;
326 /* "me" -- switch appearances off. */
328 char *TS_exit_attribute_mode;
330 /* "Co" -- number of colors. */
332 int TN_max_colors;
334 /* "pa" -- max. number of color pairs on screen. Not handled yet.
335 Could be a problem if not equal to TN_max_colors * TN_max_colors. */
337 int TN_max_pairs;
339 /* "op" -- SVr4 set default pair to its original value. */
341 char *TS_orig_pair;
343 /* "AF"/"AB" or "Sf"/"Sb"-- set ANSI or SVr4 foreground/background color.
344 1 param, the color index. */
346 char *TS_set_foreground, *TS_set_background;
348 int TF_hazeltine; /* termcap hz flag. */
349 int TF_insmode_motion; /* termcap mi flag: can move while in insert mode. */
350 int TF_standout_motion; /* termcap mi flag: can move while in standout mode. */
351 int TF_underscore; /* termcap ul flag: _ underlines if over-struck on
352 non-blank position. Must clear before writing _. */
353 int TF_teleray; /* termcap xt flag: many weird consequences.
354 For t1061. */
356 int TF_xs; /* Nonzero for "xs". If set together with
357 TN_standout_width == 0, it means don't bother
358 to write any end-standout cookies. */
360 int TN_standout_width; /* termcap sg number: width occupied by standout
361 markers */
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_width;
376 /* The largest frame height in any call to calculate_costs. */
378 int max_frame_height;
380 /* Number of chars of space used for standout marker at beginning of line,
381 or'd with 0100. Zero if no standout marker at all.
382 The length of these vectors is max_frame_height.
384 Used IFF TN_standout_width >= 0. */
386 static char *chars_wasted;
387 static char *copybuf;
389 /* nonzero means supposed to write text in standout mode. */
391 int standout_requested;
393 int insert_mode; /* Nonzero when in insert mode. */
394 int standout_mode; /* Nonzero when in standout mode. */
396 /* Size of window specified by higher levels.
397 This is the number of lines, from the top of frame downwards,
398 which can participate in insert-line/delete-line operations.
400 Effectively it excludes the bottom frame_height - specified_window_size
401 lines from those operations. */
403 int specified_window;
405 /* Frame currently being redisplayed; 0 if not currently redisplaying.
406 (Direct output does not count). */
408 FRAME_PTR updating_frame;
410 /* Provided for lisp packages. */
412 static int system_uses_terminfo;
414 char *tparam ();
416 extern char *tgetstr ();
419 #ifdef WINDOWSNT
421 /* We aren't X windows, but we aren't termcap either. This makes me
422 uncertain as to what value to use for frame.output_method. For
423 this file, we'll define FRAME_TERMCAP_P to be zero so that our
424 output hooks get called instead of the termcap functions. Probably
425 the best long-term solution is to define an output_windows_nt... */
427 #undef FRAME_TERMCAP_P
428 #define FRAME_TERMCAP_P(_f_) 0
429 #endif /* WINDOWSNT */
431 void
432 ring_bell ()
434 if (! NILP (Vring_bell_function))
436 Lisp_Object function;
438 /* Temporarily set the global variable to nil
439 so that if we get an error, it stays nil
440 and we don't call it over and over.
442 We don't specbind it, because that would carefully
443 restore the bad value if there's an error
444 and make the loop of errors happen anyway. */
445 function = Vring_bell_function;
446 Vring_bell_function = Qnil;
448 call0 (function);
450 Vring_bell_function = function;
451 return;
454 if (! FRAME_TERMCAP_P (XFRAME (selected_frame)))
456 (*ring_bell_hook) ();
457 return;
459 OUTPUT (TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell);
462 void
463 set_terminal_modes ()
465 if (! FRAME_TERMCAP_P (XFRAME (selected_frame)))
467 (*set_terminal_modes_hook) ();
468 return;
470 OUTPUT_IF (TS_termcap_modes);
471 OUTPUT_IF (TS_cursor_visible);
472 OUTPUT_IF (TS_keypad_mode);
473 losecursor ();
476 void
477 reset_terminal_modes ()
479 if (! FRAME_TERMCAP_P (XFRAME (selected_frame)))
481 if (reset_terminal_modes_hook)
482 (*reset_terminal_modes_hook) ();
483 return;
485 if (TN_standout_width < 0)
486 turn_off_highlight ();
487 turn_off_insert ();
488 OUTPUT_IF (TS_end_keypad_mode);
489 OUTPUT_IF (TS_cursor_normal);
490 OUTPUT_IF (TS_end_termcap_modes);
491 OUTPUT_IF (TS_orig_pair);
492 /* Output raw CR so kernel can track the cursor hpos. */
493 /* But on magic-cookie terminals this can erase an end-standout marker and
494 cause the rest of the frame to be in standout, so move down first. */
495 if (TN_standout_width >= 0)
496 cmputc ('\n');
497 cmputc ('\r');
500 void
501 update_begin (f)
502 FRAME_PTR f;
504 updating_frame = f;
505 if (! FRAME_TERMCAP_P (updating_frame))
506 (*update_begin_hook) (f);
507 else
508 tty_hide_cursor ();
511 void
512 update_end (f)
513 FRAME_PTR f;
515 if (! FRAME_TERMCAP_P (updating_frame))
517 (*update_end_hook) (f);
518 updating_frame = 0;
519 return;
522 if (!XWINDOW (selected_window)->cursor_off_p)
523 tty_show_cursor ();
525 turn_off_insert ();
526 background_highlight ();
527 standout_requested = 0;
528 updating_frame = 0;
531 void
532 set_terminal_window (size)
533 int size;
535 if (! FRAME_TERMCAP_P (updating_frame))
537 (*set_terminal_window_hook) (size);
538 return;
540 specified_window = size ? size : FRAME_HEIGHT (XFRAME (selected_frame));
541 if (!scroll_region_ok)
542 return;
543 set_scroll_region (0, specified_window);
546 void
547 set_scroll_region (start, stop)
548 int start, stop;
550 char *buf;
551 struct frame *sf = XFRAME (selected_frame);
553 if (TS_set_scroll_region)
555 buf = tparam (TS_set_scroll_region, 0, 0, start, stop - 1);
557 else if (TS_set_scroll_region_1)
559 buf = tparam (TS_set_scroll_region_1, 0, 0,
560 FRAME_HEIGHT (sf), start,
561 FRAME_HEIGHT (sf) - stop,
562 FRAME_HEIGHT (sf));
564 else
566 buf = tparam (TS_set_window, 0, 0, start, 0, stop, FRAME_WIDTH (sf));
568 OUTPUT (buf);
569 xfree (buf);
570 losecursor ();
573 void
574 turn_on_insert ()
576 if (!insert_mode)
577 OUTPUT (TS_insert_mode);
578 insert_mode = 1;
581 void
582 turn_off_insert ()
584 if (insert_mode)
585 OUTPUT (TS_end_insert_mode);
586 insert_mode = 0;
589 /* Handle highlighting when TN_standout_width (termcap sg) is not specified.
590 In these terminals, output is affected by the value of standout
591 mode when the output is written.
593 These functions are called on all terminals, but do nothing
594 on terminals whose standout mode does not work that way. */
596 void
597 turn_off_highlight ()
599 if (TN_standout_width < 0)
601 if (standout_mode)
602 OUTPUT_IF (TS_end_standout_mode);
603 standout_mode = 0;
607 void
608 turn_on_highlight ()
610 if (TN_standout_width < 0)
612 if (!standout_mode)
613 OUTPUT_IF (TS_standout_mode);
614 standout_mode = 1;
619 /* Make cursor invisible. */
621 static void
622 tty_hide_cursor ()
624 OUTPUT_IF (TS_cursor_invisible);
628 /* Ensure that cursor is visible. */
630 static void
631 tty_show_cursor ()
633 OUTPUT_IF (TS_cursor_normal);
634 OUTPUT_IF (TS_cursor_visible);
638 /* Set standout mode to the state it should be in for
639 empty space inside windows. What this is,
640 depends on the user option inverse-video. */
642 void
643 background_highlight ()
645 if (TN_standout_width >= 0)
646 return;
647 if (inverse_video)
648 turn_on_highlight ();
649 else
650 turn_off_highlight ();
653 /* Set standout mode to the mode specified for the text to be output. */
655 static void
656 highlight_if_desired ()
658 if (TN_standout_width >= 0)
659 return;
660 if (!inverse_video == !standout_requested)
661 turn_off_highlight ();
662 else
663 turn_on_highlight ();
666 /* Handle standout mode for terminals in which TN_standout_width >= 0.
667 On these terminals, standout is controlled by markers that
668 live inside the terminal's memory. TN_standout_width is the width
669 that the marker occupies in memory. Standout runs from the marker
670 to the end of the line on some terminals, or to the next
671 turn-off-standout marker (TS_end_standout_mode) string
672 on other terminals. */
674 /* Write a standout marker or end-standout marker at the front of the line
675 at vertical position vpos. */
677 void
678 write_standout_marker (flag, vpos)
679 int flag, vpos;
681 if (flag || (TS_end_standout_mode && !TF_teleray && !se_is_so
682 && !(TF_xs && TN_standout_width == 0)))
684 cmgoto (vpos, 0);
685 cmplus (TN_standout_width);
686 OUTPUT (flag ? TS_standout_mode : TS_end_standout_mode);
687 chars_wasted[curY] = TN_standout_width | 0100;
691 /* External interface to control of standout mode.
692 Call this when about to modify line at position VPOS
693 and not change whether it is highlighted. */
695 void
696 reassert_line_highlight (highlight, vpos)
697 int highlight;
698 int vpos;
700 struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
701 if (! FRAME_TERMCAP_P (f))
703 (*reassert_line_highlight_hook) (highlight, vpos);
704 return;
706 if (TN_standout_width < 0)
707 /* Handle terminals where standout takes affect at output time */
708 standout_requested = highlight;
709 else if (chars_wasted && chars_wasted[vpos] == 0)
710 /* For terminals with standout markers, write one on this line
711 if there isn't one already. */
712 write_standout_marker (highlight, vpos);
715 /* Call this when about to modify line at position VPOS
716 and change whether it is highlighted. */
718 void
719 change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
720 int new_highlight, vpos, y, first_unused_hpos;
722 standout_requested = new_highlight;
723 if (! FRAME_TERMCAP_P (updating_frame))
725 (*change_line_highlight_hook) (new_highlight, vpos, y, first_unused_hpos);
726 return;
729 cursor_to (vpos, 0);
731 if (TN_standout_width < 0)
732 background_highlight ();
733 /* If line starts with a marker, delete the marker */
734 else if (TS_clr_line && chars_wasted[curY])
736 turn_off_insert ();
737 /* On Teleray, make sure to erase the SO marker. */
738 if (TF_teleray)
740 cmgoto (curY - 1, FRAME_WIDTH (XFRAME (selected_frame)) - 4);
741 OUTPUT ("\033S");
742 curY++; /* ESC S moves to next line where the TS_standout_mode was */
743 curX = 0;
745 else
746 cmgoto (curY, 0); /* reposition to kill standout marker */
748 clear_end_of_line_raw (first_unused_hpos);
749 reassert_line_highlight (new_highlight, curY);
753 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
754 frame-relative coordinates. */
756 void
757 cursor_to (vpos, hpos)
758 int vpos, hpos;
760 struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
762 if (! FRAME_TERMCAP_P (f) && cursor_to_hook)
764 (*cursor_to_hook) (vpos, hpos);
765 return;
768 /* Detect the case where we are called from reset_sys_modes
769 and the costs have never been calculated. Do nothing. */
770 if (chars_wasted == 0)
771 return;
773 hpos += chars_wasted[vpos] & 077;
774 if (curY == vpos && curX == hpos)
775 return;
776 if (!TF_standout_motion)
777 background_highlight ();
778 if (!TF_insmode_motion)
779 turn_off_insert ();
780 cmgoto (vpos, hpos);
783 /* Similar but don't take any account of the wasted characters. */
785 void
786 raw_cursor_to (row, col)
787 int row, col;
789 struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
790 if (! FRAME_TERMCAP_P (f))
792 (*raw_cursor_to_hook) (row, col);
793 return;
795 if (curY == row && curX == col)
796 return;
797 if (!TF_standout_motion)
798 background_highlight ();
799 if (!TF_insmode_motion)
800 turn_off_insert ();
801 cmgoto (row, col);
804 /* Erase operations */
806 /* clear from cursor to end of frame */
807 void
808 clear_to_end ()
810 register int i;
812 if (clear_to_end_hook && ! FRAME_TERMCAP_P (updating_frame))
814 (*clear_to_end_hook) ();
815 return;
817 if (TS_clr_to_bottom)
819 background_highlight ();
820 OUTPUT (TS_clr_to_bottom);
821 bzero (chars_wasted + curY,
822 FRAME_HEIGHT (XFRAME (selected_frame)) - curY);
824 else
826 for (i = curY; i < FRAME_HEIGHT (XFRAME (selected_frame)); i++)
828 cursor_to (i, 0);
829 clear_end_of_line_raw (FRAME_WIDTH (XFRAME (selected_frame)));
834 /* Clear entire frame */
836 void
837 clear_frame ()
839 struct frame *sf = XFRAME (selected_frame);
841 if (clear_frame_hook
842 && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : sf)))
844 (*clear_frame_hook) ();
845 return;
847 if (TS_clr_frame)
849 background_highlight ();
850 OUTPUT (TS_clr_frame);
851 bzero (chars_wasted, FRAME_HEIGHT (sf));
852 cmat (0, 0);
854 else
856 cursor_to (0, 0);
857 clear_to_end ();
861 /* Clear to end of line, but do not clear any standout marker.
862 Assumes that the cursor is positioned at a character of real text,
863 which implies it cannot be before a standout marker
864 unless the marker has zero width.
866 Note that the cursor may be moved. */
868 void
869 clear_end_of_line (first_unused_hpos)
870 int first_unused_hpos;
872 if (FRAME_TERMCAP_P (XFRAME (selected_frame))
873 && chars_wasted != 0
874 && TN_standout_width == 0 && curX == 0 && chars_wasted[curY] != 0)
875 write_glyphs (&space_glyph, 1);
876 clear_end_of_line_raw (first_unused_hpos);
879 /* Clear from cursor to end of line.
880 Assume that the line is already clear starting at column first_unused_hpos.
881 If the cursor is at a standout marker, erase the marker.
883 Note that the cursor may be moved, on terminals lacking a `ce' string. */
885 void
886 clear_end_of_line_raw (first_unused_hpos)
887 int first_unused_hpos;
889 register int i;
891 if (clear_end_of_line_hook
892 && ! FRAME_TERMCAP_P ((updating_frame
893 ? updating_frame
894 : XFRAME (selected_frame))))
896 (*clear_end_of_line_hook) (first_unused_hpos);
897 return;
900 /* Detect the case where we are called from reset_sys_modes
901 and the costs have never been calculated. Do nothing. */
902 if (chars_wasted == 0)
903 return;
905 first_unused_hpos += chars_wasted[curY] & 077;
906 if (curX >= first_unused_hpos)
907 return;
908 /* Notice if we are erasing a magic cookie */
909 if (curX == 0)
910 chars_wasted[curY] = 0;
911 background_highlight ();
912 if (TS_clr_line)
914 OUTPUT1 (TS_clr_line);
916 else
917 { /* have to do it the hard way */
918 struct frame *sf = XFRAME (selected_frame);
919 turn_off_insert ();
921 /* Do not write in last row last col with Auto-wrap on. */
922 if (AutoWrap && curY == FRAME_HEIGHT (sf) - 1
923 && first_unused_hpos == FRAME_WIDTH (sf))
924 first_unused_hpos--;
926 for (i = curX; i < first_unused_hpos; i++)
928 if (termscript)
929 fputc (' ', termscript);
930 putchar (' ');
932 cmplus (first_unused_hpos - curX);
936 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes and
937 store them at DST. Do not write more than DST_LEN bytes. That may
938 require stopping before all SRC_LEN input glyphs have been
939 converted.
941 We store the number of glyphs actually converted in *CONSUMED. The
942 return value is the number of bytes store in DST. */
945 encode_terminal_code (src, dst, src_len, dst_len, consumed)
946 struct glyph *src;
947 int src_len;
948 unsigned char *dst;
949 int dst_len, *consumed;
951 struct glyph *src_start = src, *src_end = src + src_len;
952 unsigned char *dst_start = dst, *dst_end = dst + dst_len;
953 register GLYPH g;
954 unsigned int c;
955 unsigned char workbuf[MAX_MULTIBYTE_LENGTH], *buf;
956 int len;
957 register int tlen = GLYPH_TABLE_LENGTH;
958 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
959 int result;
960 struct coding_system *coding;
962 /* If terminal_coding does any conversion, use it, otherwise use
963 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
964 because it always return 1 if the member src_multibyte is 1. */
965 coding = (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK
966 ? &terminal_coding
967 : &safe_terminal_coding);
969 while (src < src_end)
971 /* We must skip glyphs to be padded for a wide character. */
972 if (! CHAR_GLYPH_PADDING_P (*src))
974 g = GLYPH_FROM_CHAR_GLYPH (src[0]);
976 if (g < 0 || g >= tlen)
978 /* This glyph doesn't has an entry in Vglyph_table. */
979 if (! CHAR_VALID_P (src->u.ch, 0))
981 len = 1;
982 buf = " ";
983 coding->src_multibyte = 0;
985 else
987 len = CHAR_STRING (src->u.ch, workbuf);
988 buf = workbuf;
989 coding->src_multibyte = 1;
992 else
994 /* This glyph has an entry in Vglyph_table,
995 so process any alias before testing for simpleness. */
996 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
998 if (GLYPH_SIMPLE_P (tbase, tlen, g))
1000 /* We set the multi-byte form of a character in G
1001 (that should be an ASCII character) at
1002 WORKBUF. */
1003 workbuf[0] = FAST_GLYPH_CHAR (g);
1004 len = 1;
1005 buf = workbuf;
1006 coding->src_multibyte = 0;
1008 else
1010 /* We have a string in Vglyph_table. */
1011 len = GLYPH_LENGTH (tbase, g);
1012 buf = GLYPH_STRING (tbase, g);
1013 coding->src_multibyte = STRING_MULTIBYTE (tbase[g]);
1017 result = encode_coding (coding, buf, dst, len, dst_end - dst);
1018 len -= coding->consumed;
1019 dst += coding->produced;
1020 if (result == CODING_FINISH_INSUFFICIENT_DST
1021 || (result == CODING_FINISH_INSUFFICIENT_SRC
1022 && len > dst_end - dst))
1023 /* The remaining output buffer is too short. We must
1024 break the loop here without increasing SRC so that the
1025 next call of this function starts from the same glyph. */
1026 break;
1028 if (len > 0)
1030 /* This is the case that a code of the range 0200..0237
1031 exists in buf. We must just write out such a code. */
1032 buf += coding->consumed;
1033 while (len--)
1034 *dst++ = *buf++;
1037 src++;
1040 *consumed = src - src_start;
1041 return (dst - dst_start);
1045 void
1046 write_glyphs (string, len)
1047 register struct glyph *string;
1048 register int len;
1050 int produced, consumed;
1051 struct frame *sf = XFRAME (selected_frame);
1052 struct frame *f = updating_frame ? updating_frame : sf;
1054 if (write_glyphs_hook
1055 && ! FRAME_TERMCAP_P (f))
1057 (*write_glyphs_hook) (string, len);
1058 return;
1061 highlight_if_desired ();
1062 turn_off_insert ();
1064 /* Don't dare write in last column of bottom line, if Auto-Wrap,
1065 since that would scroll the whole frame on some terminals. */
1067 if (AutoWrap
1068 && curY + 1 == FRAME_HEIGHT (sf)
1069 && (curX + len - (chars_wasted[curY] & 077) == FRAME_WIDTH (sf)))
1070 len --;
1071 if (len <= 0)
1072 return;
1074 cmplus (len);
1076 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
1077 the tail. */
1078 terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
1080 while (len > 0)
1082 /* Identify a run of glyphs with the same face. */
1083 int face_id = string->face_id;
1084 int n;
1086 for (n = 1; n < len; ++n)
1087 if (string[n].face_id != face_id)
1088 break;
1090 /* Turn appearance modes of the face of the run on. */
1091 turn_on_face (f, face_id);
1093 while (n > 0)
1095 /* We use a shared conversion buffer of the current size
1096 (1024 bytes at least). Usually it is sufficient, but if
1097 not, we just repeat the loop. */
1098 produced = encode_terminal_code (string, conversion_buffer,
1099 n, conversion_buffer_size,
1100 &consumed);
1101 if (produced > 0)
1103 fwrite (conversion_buffer, 1, produced, stdout);
1104 if (ferror (stdout))
1105 clearerr (stdout);
1106 if (termscript)
1107 fwrite (conversion_buffer, 1, produced, termscript);
1109 len -= consumed;
1110 n -= consumed;
1111 string += consumed;
1114 /* Turn appearance modes off. */
1115 turn_off_face (f, face_id);
1118 /* We may have to output some codes to terminate the writing. */
1119 if (CODING_REQUIRE_FLUSHING (&terminal_coding))
1121 terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
1122 encode_coding (&terminal_coding, "", conversion_buffer,
1123 0, conversion_buffer_size);
1124 if (terminal_coding.produced > 0)
1126 fwrite (conversion_buffer, 1, terminal_coding.produced, stdout);
1127 if (ferror (stdout))
1128 clearerr (stdout);
1129 if (termscript)
1130 fwrite (conversion_buffer, 1, terminal_coding.produced,
1131 termscript);
1135 cmcheckmagic ();
1138 /* If start is zero, insert blanks instead of a string at start */
1140 void
1141 insert_glyphs (start, len)
1142 register struct glyph *start;
1143 register int len;
1145 char *buf;
1146 struct glyph *glyph;
1147 struct frame *f, *sf;
1149 if (len <= 0)
1150 return;
1152 if (insert_glyphs_hook)
1154 (*insert_glyphs_hook) (start, len);
1155 return;
1158 sf = XFRAME (selected_frame);
1159 f = updating_frame ? updating_frame : sf;
1160 highlight_if_desired ();
1162 if (TS_ins_multi_chars)
1164 buf = tparam (TS_ins_multi_chars, 0, 0, len);
1165 OUTPUT1 (buf);
1166 xfree (buf);
1167 if (start)
1168 write_glyphs (start, len);
1169 return;
1172 turn_on_insert ();
1173 cmplus (len);
1174 /* The bit CODING_MODE_LAST_BLOCK should be set to 1 only at the tail. */
1175 terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
1176 while (len-- > 0)
1178 int produced, consumed;
1180 OUTPUT1_IF (TS_ins_char);
1181 if (!start)
1183 conversion_buffer[0] = SPACEGLYPH;
1184 produced = 1;
1186 else
1188 turn_on_face (f, start->face_id);
1189 glyph = start;
1190 ++start;
1191 /* We must open sufficient space for a character which
1192 occupies more than one column. */
1193 while (len && CHAR_GLYPH_PADDING_P (*start))
1195 OUTPUT1_IF (TS_ins_char);
1196 start++, len--;
1199 if (len <= 0)
1200 /* This is the last glyph. */
1201 terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
1203 /* We use shared conversion buffer of the current size (1024
1204 bytes at least). It is surely sufficient for just one glyph. */
1205 produced = encode_terminal_code (glyph, conversion_buffer, 1,
1206 conversion_buffer_size, &consumed);
1209 if (produced > 0)
1211 fwrite (conversion_buffer, 1, produced, stdout);
1212 if (ferror (stdout))
1213 clearerr (stdout);
1214 if (termscript)
1215 fwrite (conversion_buffer, 1, produced, termscript);
1218 OUTPUT1_IF (TS_pad_inserted_char);
1219 if (start)
1220 turn_off_face (f, glyph->face_id);
1223 cmcheckmagic ();
1226 void
1227 delete_glyphs (n)
1228 register int n;
1230 char *buf;
1231 register int i;
1233 if (delete_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame))
1235 (*delete_glyphs_hook) (n);
1236 return;
1239 if (delete_in_insert_mode)
1241 turn_on_insert ();
1243 else
1245 turn_off_insert ();
1246 OUTPUT_IF (TS_delete_mode);
1249 if (TS_del_multi_chars)
1251 buf = tparam (TS_del_multi_chars, 0, 0, n);
1252 OUTPUT1 (buf);
1253 xfree (buf);
1255 else
1256 for (i = 0; i < n; i++)
1257 OUTPUT1 (TS_del_char);
1258 if (!delete_in_insert_mode)
1259 OUTPUT_IF (TS_end_delete_mode);
1262 /* Insert N lines at vpos VPOS. If N is negative, delete -N lines. */
1264 void
1265 ins_del_lines (vpos, n)
1266 int vpos, n;
1268 char *multi = n > 0 ? TS_ins_multi_lines : TS_del_multi_lines;
1269 char *single = n > 0 ? TS_ins_line : TS_del_line;
1270 char *scroll = n > 0 ? TS_rev_scroll : TS_fwd_scroll;
1271 struct frame *sf;
1273 register int i = n > 0 ? n : -n;
1274 register char *buf;
1276 if (ins_del_lines_hook && ! FRAME_TERMCAP_P (updating_frame))
1278 (*ins_del_lines_hook) (vpos, n);
1279 return;
1282 sf = XFRAME (selected_frame);
1284 /* If the lines below the insertion are being pushed
1285 into the end of the window, this is the same as clearing;
1286 and we know the lines are already clear, since the matching
1287 deletion has already been done. So can ignore this. */
1288 /* If the lines below the deletion are blank lines coming
1289 out of the end of the window, don't bother,
1290 as there will be a matching inslines later that will flush them. */
1291 if (scroll_region_ok && vpos + i >= specified_window)
1292 return;
1293 if (!memory_below_frame && vpos + i >= FRAME_HEIGHT (sf))
1294 return;
1296 if (multi)
1298 raw_cursor_to (vpos, 0);
1299 background_highlight ();
1300 buf = tparam (multi, 0, 0, i);
1301 OUTPUT (buf);
1302 xfree (buf);
1304 else if (single)
1306 raw_cursor_to (vpos, 0);
1307 background_highlight ();
1308 while (--i >= 0)
1309 OUTPUT (single);
1310 if (TF_teleray)
1311 curX = 0;
1313 else
1315 set_scroll_region (vpos, specified_window);
1316 if (n < 0)
1317 raw_cursor_to (specified_window - 1, 0);
1318 else
1319 raw_cursor_to (vpos, 0);
1320 background_highlight ();
1321 while (--i >= 0)
1322 OUTPUTL (scroll, specified_window - vpos);
1323 set_scroll_region (0, specified_window);
1326 if (TN_standout_width >= 0)
1328 register int lower_limit
1329 = (scroll_region_ok
1330 ? specified_window
1331 : FRAME_HEIGHT (sf));
1333 if (n < 0)
1335 bcopy (&chars_wasted[vpos - n], &chars_wasted[vpos],
1336 lower_limit - vpos + n);
1337 bzero (&chars_wasted[lower_limit + n], - n);
1339 else
1341 bcopy (&chars_wasted[vpos], &copybuf[vpos], lower_limit - vpos - n);
1342 bcopy (&copybuf[vpos], &chars_wasted[vpos + n],
1343 lower_limit - vpos - n);
1344 bzero (&chars_wasted[vpos], n);
1347 if (!scroll_region_ok && memory_below_frame && n < 0)
1349 cursor_to (FRAME_HEIGHT (sf) + n, 0);
1350 clear_to_end ();
1354 /* Compute cost of sending "str", in characters,
1355 not counting any line-dependent padding. */
1358 string_cost (str)
1359 char *str;
1361 cost = 0;
1362 if (str)
1363 tputs (str, 0, evalcost);
1364 return cost;
1367 /* Compute cost of sending "str", in characters,
1368 counting any line-dependent padding at one line. */
1370 static int
1371 string_cost_one_line (str)
1372 char *str;
1374 cost = 0;
1375 if (str)
1376 tputs (str, 1, evalcost);
1377 return cost;
1380 /* Compute per line amount of line-dependent padding,
1381 in tenths of characters. */
1384 per_line_cost (str)
1385 register char *str;
1387 cost = 0;
1388 if (str)
1389 tputs (str, 0, evalcost);
1390 cost = - cost;
1391 if (str)
1392 tputs (str, 10, evalcost);
1393 return cost;
1396 #ifndef old
1397 /* char_ins_del_cost[n] is cost of inserting N characters.
1398 char_ins_del_cost[-n] is cost of deleting N characters.
1399 The length of this vector is based on max_frame_width. */
1401 int *char_ins_del_vector;
1403 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WIDTH ((f))])
1404 #endif
1406 /* ARGSUSED */
1407 static void
1408 calculate_ins_del_char_costs (frame)
1409 FRAME_PTR frame;
1411 int ins_startup_cost, del_startup_cost;
1412 int ins_cost_per_char, del_cost_per_char;
1413 register int i;
1414 register int *p;
1416 if (TS_ins_multi_chars)
1418 ins_cost_per_char = 0;
1419 ins_startup_cost = string_cost_one_line (TS_ins_multi_chars);
1421 else if (TS_ins_char || TS_pad_inserted_char
1422 || (TS_insert_mode && TS_end_insert_mode))
1424 ins_startup_cost = (30 * (string_cost (TS_insert_mode)
1425 + string_cost (TS_end_insert_mode))) / 100;
1426 ins_cost_per_char = (string_cost_one_line (TS_ins_char)
1427 + string_cost_one_line (TS_pad_inserted_char));
1429 else
1431 ins_startup_cost = 9999;
1432 ins_cost_per_char = 0;
1435 if (TS_del_multi_chars)
1437 del_cost_per_char = 0;
1438 del_startup_cost = string_cost_one_line (TS_del_multi_chars);
1440 else if (TS_del_char)
1442 del_startup_cost = (string_cost (TS_delete_mode)
1443 + string_cost (TS_end_delete_mode));
1444 if (delete_in_insert_mode)
1445 del_startup_cost /= 2;
1446 del_cost_per_char = string_cost_one_line (TS_del_char);
1448 else
1450 del_startup_cost = 9999;
1451 del_cost_per_char = 0;
1454 /* Delete costs are at negative offsets */
1455 p = &char_ins_del_cost (frame)[0];
1456 for (i = FRAME_WIDTH (frame); --i >= 0;)
1457 *--p = (del_startup_cost += del_cost_per_char);
1459 /* Doing nothing is free */
1460 p = &char_ins_del_cost (frame)[0];
1461 *p++ = 0;
1463 /* Insert costs are at positive offsets */
1464 for (i = FRAME_WIDTH (frame); --i >= 0;)
1465 *p++ = (ins_startup_cost += ins_cost_per_char);
1468 void
1469 calculate_costs (frame)
1470 FRAME_PTR frame;
1472 register char *f = (TS_set_scroll_region
1473 ? TS_set_scroll_region
1474 : TS_set_scroll_region_1);
1476 FRAME_COST_BAUD_RATE (frame) = baud_rate;
1478 scroll_region_cost = string_cost (f);
1480 /* These variables are only used for terminal stuff. They are allocated
1481 once for the terminal frame of X-windows emacs, but not used afterwards.
1483 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1484 X turns off char_ins_del_ok.
1486 chars_wasted and copybuf are only used here in term.c in cases where
1487 the term hook isn't called. */
1489 max_frame_height = max (max_frame_height, FRAME_HEIGHT (frame));
1490 max_frame_width = max (max_frame_width, FRAME_WIDTH (frame));
1492 if (chars_wasted != 0)
1493 chars_wasted = (char *) xrealloc (chars_wasted, max_frame_height);
1494 else
1495 chars_wasted = (char *) xmalloc (max_frame_height);
1497 if (copybuf != 0)
1498 copybuf = (char *) xrealloc (copybuf, max_frame_height);
1499 else
1500 copybuf = (char *) xmalloc (max_frame_height);
1502 if (char_ins_del_vector != 0)
1503 char_ins_del_vector
1504 = (int *) xrealloc (char_ins_del_vector,
1505 (sizeof (int)
1506 + 2 * max_frame_width * sizeof (int)));
1507 else
1508 char_ins_del_vector
1509 = (int *) xmalloc (sizeof (int)
1510 + 2 * max_frame_width * sizeof (int));
1512 bzero (chars_wasted, max_frame_height);
1513 bzero (copybuf, max_frame_height);
1514 bzero (char_ins_del_vector, (sizeof (int)
1515 + 2 * max_frame_width * sizeof (int)));
1517 if (f && (!TS_ins_line && !TS_del_line))
1518 do_line_insertion_deletion_costs (frame,
1519 TS_rev_scroll, TS_ins_multi_lines,
1520 TS_fwd_scroll, TS_del_multi_lines,
1521 f, f, 1);
1522 else
1523 do_line_insertion_deletion_costs (frame,
1524 TS_ins_line, TS_ins_multi_lines,
1525 TS_del_line, TS_del_multi_lines,
1526 0, 0, 1);
1528 calculate_ins_del_char_costs (frame);
1530 /* Don't use TS_repeat if its padding is worse than sending the chars */
1531 if (TS_repeat && per_line_cost (TS_repeat) * baud_rate < 9000)
1532 RPov = string_cost (TS_repeat);
1533 else
1534 RPov = FRAME_WIDTH (frame) * 2;
1536 cmcostinit (); /* set up cursor motion costs */
1539 struct fkey_table {
1540 char *cap, *name;
1543 /* Termcap capability names that correspond directly to X keysyms.
1544 Some of these (marked "terminfo") aren't supplied by old-style
1545 (Berkeley) termcap entries. They're listed in X keysym order;
1546 except we put the keypad keys first, so that if they clash with
1547 other keys (as on the IBM PC keyboard) they get overridden.
1550 static struct fkey_table keys[] =
1552 "kh", "home", /* termcap */
1553 "kl", "left", /* termcap */
1554 "ku", "up", /* termcap */
1555 "kr", "right", /* termcap */
1556 "kd", "down", /* termcap */
1557 "%8", "prior", /* terminfo */
1558 "%5", "next", /* terminfo */
1559 "@7", "end", /* terminfo */
1560 "@1", "begin", /* terminfo */
1561 "*6", "select", /* terminfo */
1562 "%9", "print", /* terminfo */
1563 "@4", "execute", /* terminfo --- actually the `command' key */
1565 * "insert" --- see below
1567 "&8", "undo", /* terminfo */
1568 "%0", "redo", /* terminfo */
1569 "%7", "menu", /* terminfo --- actually the `options' key */
1570 "@0", "find", /* terminfo */
1571 "@2", "cancel", /* terminfo */
1572 "%1", "help", /* terminfo */
1574 * "break" goes here, but can't be reliably intercepted with termcap
1576 "&4", "reset", /* terminfo --- actually `restart' */
1578 * "system" and "user" --- no termcaps
1580 "kE", "clearline", /* terminfo */
1581 "kA", "insertline", /* terminfo */
1582 "kL", "deleteline", /* terminfo */
1583 "kI", "insertchar", /* terminfo */
1584 "kD", "deletechar", /* terminfo */
1585 "kB", "backtab", /* terminfo */
1587 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1589 "@8", "kp-enter", /* terminfo */
1591 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1592 * "kp-multiply", "kp-add", "kp-separator",
1593 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1594 * --- no termcaps for any of these.
1596 "K4", "kp-1", /* terminfo */
1598 * "kp-2" --- no termcap
1600 "K5", "kp-3", /* terminfo */
1602 * "kp-4" --- no termcap
1604 "K2", "kp-5", /* terminfo */
1606 * "kp-6" --- no termcap
1608 "K1", "kp-7", /* terminfo */
1610 * "kp-8" --- no termcap
1612 "K3", "kp-9", /* terminfo */
1614 * "kp-equal" --- no termcap
1616 "k1", "f1",
1617 "k2", "f2",
1618 "k3", "f3",
1619 "k4", "f4",
1620 "k5", "f5",
1621 "k6", "f6",
1622 "k7", "f7",
1623 "k8", "f8",
1624 "k9", "f9",
1627 static char **term_get_fkeys_arg;
1628 static Lisp_Object term_get_fkeys_1 ();
1630 /* Find the escape codes sent by the function keys for Vfunction_key_map.
1631 This function scans the termcap function key sequence entries, and
1632 adds entries to Vfunction_key_map for each function key it finds. */
1634 void
1635 term_get_fkeys (address)
1636 char **address;
1638 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1639 errors during the call. The only errors should be from Fdefine_key
1640 when given a key sequence containing an invalid prefix key. If the
1641 termcap defines function keys which use a prefix that is already bound
1642 to a command by the default bindings, we should silently ignore that
1643 function key specification, rather than giving the user an error and
1644 refusing to run at all on such a terminal. */
1646 extern Lisp_Object Fidentity ();
1647 term_get_fkeys_arg = address;
1648 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1651 static Lisp_Object
1652 term_get_fkeys_1 ()
1654 int i;
1656 char **address = term_get_fkeys_arg;
1658 /* This can happen if CANNOT_DUMP or with strange options. */
1659 if (!initialized)
1660 Vfunction_key_map = Fmake_sparse_keymap (Qnil);
1662 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1664 char *sequence = tgetstr (keys[i].cap, address);
1665 if (sequence)
1666 Fdefine_key (Vfunction_key_map, build_string (sequence),
1667 Fmake_vector (make_number (1),
1668 intern (keys[i].name)));
1671 /* The uses of the "k0" capability are inconsistent; sometimes it
1672 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1673 We will attempt to politely accommodate both systems by testing for
1674 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1677 char *k_semi = tgetstr ("k;", address);
1678 char *k0 = tgetstr ("k0", address);
1679 char *k0_name = "f10";
1681 if (k_semi)
1683 Fdefine_key (Vfunction_key_map, build_string (k_semi),
1684 Fmake_vector (make_number (1), intern ("f10")));
1685 k0_name = "f0";
1688 if (k0)
1689 Fdefine_key (Vfunction_key_map, build_string (k0),
1690 Fmake_vector (make_number (1), intern (k0_name)));
1693 /* Set up cookies for numbered function keys above f10. */
1695 char fcap[3], fkey[4];
1697 fcap[0] = 'F'; fcap[2] = '\0';
1698 for (i = 11; i < 64; i++)
1700 if (i <= 19)
1701 fcap[1] = '1' + i - 11;
1702 else if (i <= 45)
1703 fcap[1] = 'A' + i - 20;
1704 else
1705 fcap[1] = 'a' + i - 46;
1708 char *sequence = tgetstr (fcap, address);
1709 if (sequence)
1711 sprintf (fkey, "f%d", i);
1712 Fdefine_key (Vfunction_key_map, build_string (sequence),
1713 Fmake_vector (make_number (1),
1714 intern (fkey)));
1721 * Various mappings to try and get a better fit.
1724 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1725 if (!tgetstr (cap1, address)) \
1727 char *sequence = tgetstr (cap2, address); \
1728 if (sequence) \
1729 Fdefine_key (Vfunction_key_map, build_string (sequence), \
1730 Fmake_vector (make_number (1), \
1731 intern (sym))); \
1734 /* if there's no key_next keycap, map key_npage to `next' keysym */
1735 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1736 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1737 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1738 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1739 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1740 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1741 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1743 /* IBM has their own non-standard dialect of terminfo.
1744 If the standard name isn't found, try the IBM name. */
1745 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1746 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1747 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1748 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1749 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1750 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1751 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1752 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1753 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1754 #undef CONDITIONAL_REASSIGN
1757 return Qnil;
1761 /***********************************************************************
1762 Character Display Information
1763 ***********************************************************************/
1765 static void append_glyph P_ ((struct it *));
1768 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1769 terminal frames if IT->glyph_row != NULL. IT->c is the character
1770 for which to produce glyphs; IT->face_id contains the character's
1771 face. Padding glyphs are appended if IT->c has a IT->pixel_width >
1772 1. */
1774 static void
1775 append_glyph (it)
1776 struct it *it;
1778 struct glyph *glyph, *end;
1779 int i;
1781 xassert (it->glyph_row);
1782 glyph = (it->glyph_row->glyphs[it->area]
1783 + it->glyph_row->used[it->area]);
1784 end = it->glyph_row->glyphs[1 + it->area];
1786 for (i = 0;
1787 i < it->pixel_width && glyph < end;
1788 ++i)
1790 glyph->type = CHAR_GLYPH;
1791 glyph->pixel_width = 1;
1792 glyph->u.ch = it->c;
1793 glyph->face_id = it->face_id;
1794 glyph->padding_p = i > 0;
1795 glyph->charpos = CHARPOS (it->position);
1796 glyph->object = it->object;
1798 ++it->glyph_row->used[it->area];
1799 ++glyph;
1804 /* Produce glyphs for the display element described by IT. The
1805 function fills output fields of IT with pixel information like the
1806 pixel width and height of a character, and maybe produces glyphs at
1807 the same time if IT->glyph_row is non-null. See the explanation of
1808 struct display_iterator in dispextern.h for an overview. */
1810 void
1811 produce_glyphs (it)
1812 struct it *it;
1814 /* If a hook is installed, let it do the work. */
1815 xassert (it->what == IT_CHARACTER
1816 || it->what == IT_COMPOSITION
1817 || it->what == IT_IMAGE
1818 || it->what == IT_STRETCH);
1820 /* Nothing but characters are supported on terminal frames. For a
1821 composition sequence, it->c is the first character of the
1822 sequence. */
1823 xassert (it->what == IT_CHARACTER
1824 || it->what == IT_COMPOSITION);
1826 if (it->c >= 040 && it->c < 0177)
1828 it->pixel_width = it->nglyphs = 1;
1829 if (it->glyph_row)
1830 append_glyph (it);
1832 else if (it->c == '\n')
1833 it->pixel_width = it->nglyphs = 0;
1834 else if (it->c == '\t')
1836 int absolute_x = (it->current_x
1837 + it->continuation_lines_width);
1838 int next_tab_x
1839 = (((1 + absolute_x + it->tab_width - 1)
1840 / it->tab_width)
1841 * it->tab_width);
1842 int nspaces;
1844 /* If part of the TAB has been displayed on the previous line
1845 which is continued now, continuation_lines_width will have
1846 been incremented already by the part that fitted on the
1847 continued line. So, we will get the right number of spaces
1848 here. */
1849 nspaces = next_tab_x - absolute_x;
1851 if (it->glyph_row)
1853 int n = nspaces;
1855 it->c = ' ';
1856 it->pixel_width = it->len = 1;
1858 while (n--)
1859 append_glyph (it);
1861 it->c = '\t';
1864 it->pixel_width = nspaces;
1865 it->nglyphs = nspaces;
1867 else if (SINGLE_BYTE_CHAR_P (it->c))
1869 /* Coming here means that it->c is from display table, thus we
1870 must send the code as is to the terminal. Although there's
1871 no way to know how many columns it occupies on a screen, it
1872 is a good assumption that a single byte code has 1-column
1873 width. */
1874 it->pixel_width = it->nglyphs = 1;
1875 if (it->glyph_row)
1876 append_glyph (it);
1878 else
1880 /* A multi-byte character. The display width is fixed for all
1881 characters of the set. Some of the glyphs may have to be
1882 ignored because they are already displayed in a continued
1883 line. */
1884 int charset = CHAR_CHARSET (it->c);
1886 it->pixel_width = CHARSET_WIDTH (charset);
1887 it->nglyphs = it->pixel_width;
1889 if (it->glyph_row)
1890 append_glyph (it);
1893 /* Advance current_x by the pixel width as a convenience for
1894 the caller. */
1895 if (it->area == TEXT_AREA)
1896 it->current_x += it->pixel_width;
1897 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1898 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
1902 /* Get information about special display element WHAT in an
1903 environment described by IT. WHAT is one of IT_TRUNCATION or
1904 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1905 non-null glyph_row member. This function ensures that fields like
1906 face_id, c, len of IT are left untouched. */
1908 void
1909 produce_special_glyphs (it, what)
1910 struct it *it;
1911 enum display_element_type what;
1913 struct it temp_it;
1915 temp_it = *it;
1916 temp_it.dp = NULL;
1917 temp_it.what = IT_CHARACTER;
1918 temp_it.len = 1;
1919 temp_it.object = make_number (0);
1920 bzero (&temp_it.current, sizeof temp_it.current);
1922 if (what == IT_CONTINUATION)
1924 /* Continuation glyph. */
1925 if (it->dp
1926 && INTEGERP (DISP_CONTINUE_GLYPH (it->dp))
1927 && GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (it->dp))))
1929 temp_it.c = FAST_GLYPH_CHAR (XINT (DISP_CONTINUE_GLYPH (it->dp)));
1930 temp_it.len = CHAR_BYTES (temp_it.c);
1932 else
1933 temp_it.c = '\\';
1935 produce_glyphs (&temp_it);
1936 it->pixel_width = temp_it.pixel_width;
1937 it->nglyphs = temp_it.pixel_width;
1939 else if (what == IT_TRUNCATION)
1941 /* Truncation glyph. */
1942 if (it->dp
1943 && INTEGERP (DISP_TRUNC_GLYPH (it->dp))
1944 && GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (it->dp))))
1946 temp_it.c = FAST_GLYPH_CHAR (XINT (DISP_TRUNC_GLYPH (it->dp)));
1947 temp_it.len = CHAR_BYTES (temp_it.c);
1949 else
1950 temp_it.c = '$';
1952 produce_glyphs (&temp_it);
1953 it->pixel_width = temp_it.pixel_width;
1954 it->nglyphs = temp_it.pixel_width;
1956 else
1957 abort ();
1961 /* Return an estimation of the pixel height of mode or top lines on
1962 frame F. FACE_ID specifies what line's height to estimate. */
1965 estimate_mode_line_height (f, face_id)
1966 struct frame *f;
1967 enum face_id face_id;
1969 if (estimate_mode_line_height_hook)
1970 return estimate_mode_line_height_hook (f, face_id);
1971 else
1972 return 1;
1977 /***********************************************************************
1978 Faces
1979 ***********************************************************************/
1981 /* Value is non-zero if attribute ATTR may be used. ATTR should be
1982 one of the enumerators from enum no_color_bit, or a bit set built
1983 from them. Some display attributes may not be used together with
1984 color; the termcap capability `NC' specifies which ones. */
1986 #define MAY_USE_WITH_COLORS_P(ATTR) \
1987 (TN_max_colors > 0 \
1988 ? (TN_no_color_video & (ATTR)) == 0 \
1989 : 1)
1991 /* Turn appearances of face FACE_ID on tty frame F on. */
1993 static void
1994 turn_on_face (f, face_id)
1995 struct frame *f;
1996 int face_id;
1998 struct face *face = FACE_FROM_ID (f, face_id);
2000 xassert (face != NULL);
2002 if (face->tty_bold_p)
2004 if (MAY_USE_WITH_COLORS_P (NC_BOLD))
2005 OUTPUT1_IF (TS_enter_bold_mode);
2007 else if (face->tty_dim_p)
2008 if (MAY_USE_WITH_COLORS_P (NC_DIM))
2009 OUTPUT1_IF (TS_enter_dim_mode);
2011 /* Alternate charset and blinking not yet used. */
2012 if (face->tty_alt_charset_p
2013 && MAY_USE_WITH_COLORS_P (NC_ALT_CHARSET))
2014 OUTPUT1_IF (TS_enter_alt_charset_mode);
2016 if (face->tty_blinking_p
2017 && MAY_USE_WITH_COLORS_P (NC_BLINK))
2018 OUTPUT1_IF (TS_enter_blink_mode);
2020 if (face->tty_underline_p
2021 /* Don't underline if that's difficult. */
2022 && TN_magic_cookie_glitch_ul <= 0
2023 && MAY_USE_WITH_COLORS_P (NC_UNDERLINE))
2024 OUTPUT1_IF (TS_enter_underline_mode);
2026 if (MAY_USE_WITH_COLORS_P (NC_REVERSE))
2027 if (face->tty_reverse_p
2028 || face->foreground == FACE_TTY_DEFAULT_BG_COLOR
2029 || face->background == FACE_TTY_DEFAULT_FG_COLOR)
2030 OUTPUT1_IF (TS_enter_reverse_mode);
2032 if (TN_max_colors > 0)
2034 char *p;
2036 if (face->foreground != FACE_TTY_DEFAULT_COLOR
2037 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR
2038 && face->foreground != FACE_TTY_DEFAULT_BG_COLOR
2039 && TS_set_foreground)
2041 p = tparam (TS_set_foreground, NULL, 0, (int) face->foreground);
2042 OUTPUT (p);
2043 xfree (p);
2046 if (face->background != FACE_TTY_DEFAULT_COLOR
2047 && face->background != FACE_TTY_DEFAULT_BG_COLOR
2048 && face->background != FACE_TTY_DEFAULT_FG_COLOR
2049 && TS_set_background)
2051 p = tparam (TS_set_background, NULL, 0, (int) face->background);
2052 OUTPUT (p);
2053 xfree (p);
2059 /* Turn off appearances of face FACE_ID on tty frame F. */
2061 static void
2062 turn_off_face (f, face_id)
2063 struct frame *f;
2064 int face_id;
2066 struct face *face = FACE_FROM_ID (f, face_id);
2068 xassert (face != NULL);
2070 if (TS_exit_attribute_mode)
2072 /* Capability "me" will turn off appearance modes double-bright,
2073 half-bright, reverse-video, standout, underline. It may or
2074 may not turn off alt-char-mode. */
2075 if (face->tty_bold_p
2076 || face->tty_dim_p
2077 || face->tty_reverse_p
2078 || face->tty_alt_charset_p
2079 || face->tty_blinking_p
2080 || face->tty_underline_p)
2081 OUTPUT1_IF (TS_exit_attribute_mode);
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 /* We don't underline if that's difficult. */
2095 && TN_magic_cookie_glitch_ul <= 0)
2096 OUTPUT_IF (TS_exit_underline_mode);
2099 /* Switch back to default colors. */
2100 if (TN_max_colors > 0
2101 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
2102 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
2103 || (face->background != FACE_TTY_DEFAULT_COLOR
2104 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
2105 OUTPUT1_IF (TS_orig_pair);
2109 /* Return non-zero if the terminal is capable to display colors. */
2111 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
2112 0, 1, 0,
2113 "Return non-nil if TTY can display colors on FRAME.")
2114 (frame)
2115 Lisp_Object frame;
2117 return TN_max_colors > 0 ? Qt : Qnil;
2123 /***********************************************************************
2124 Initialization
2125 ***********************************************************************/
2127 void
2128 term_init (terminal_type)
2129 char *terminal_type;
2131 char *area;
2132 char **address = &area;
2133 char buffer[2044];
2134 register char *p;
2135 int status;
2136 struct frame *sf = XFRAME (selected_frame);
2138 #ifdef WINDOWSNT
2139 initialize_w32_display ();
2141 Wcm_clear ();
2143 area = (char *) xmalloc (2044);
2145 if (area == 0)
2146 abort ();
2148 FrameRows = FRAME_HEIGHT (sf);
2149 FrameCols = FRAME_WIDTH (sf);
2150 specified_window = FRAME_HEIGHT (sf);
2152 delete_in_insert_mode = 1;
2154 UseTabs = 0;
2155 scroll_region_ok = 0;
2157 /* Seems to insert lines when it's not supposed to, messing
2158 up the display. In doing a trace, it didn't seem to be
2159 called much, so I don't think we're losing anything by
2160 turning it off. */
2162 line_ins_del_ok = 0;
2163 char_ins_del_ok = 1;
2165 baud_rate = 19200;
2167 FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0;
2168 FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none;
2169 TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
2171 return;
2172 #else /* not WINDOWSNT */
2174 Wcm_clear ();
2176 status = tgetent (buffer, terminal_type);
2177 if (status < 0)
2179 #ifdef TERMINFO
2180 fatal ("Cannot open terminfo database file");
2181 #else
2182 fatal ("Cannot open termcap database file");
2183 #endif
2185 if (status == 0)
2187 #ifdef TERMINFO
2188 fatal ("Terminal type %s is not defined.\n\
2189 If that is not the actual type of terminal you have,\n\
2190 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2191 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2192 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
2193 terminal_type);
2194 #else
2195 fatal ("Terminal type %s is not defined.\n\
2196 If that is not the actual type of terminal you have,\n\
2197 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2198 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2199 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
2200 terminal_type);
2201 #endif
2203 #ifdef TERMINFO
2204 area = (char *) xmalloc (2044);
2205 #else
2206 area = (char *) xmalloc (strlen (buffer));
2207 #endif /* not TERMINFO */
2208 if (area == 0)
2209 abort ();
2211 TS_ins_line = tgetstr ("al", address);
2212 TS_ins_multi_lines = tgetstr ("AL", address);
2213 TS_bell = tgetstr ("bl", address);
2214 BackTab = tgetstr ("bt", address);
2215 TS_clr_to_bottom = tgetstr ("cd", address);
2216 TS_clr_line = tgetstr ("ce", address);
2217 TS_clr_frame = tgetstr ("cl", address);
2218 ColPosition = NULL; /* tgetstr ("ch", address); */
2219 AbsPosition = tgetstr ("cm", address);
2220 CR = tgetstr ("cr", address);
2221 TS_set_scroll_region = tgetstr ("cs", address);
2222 TS_set_scroll_region_1 = tgetstr ("cS", address);
2223 RowPosition = tgetstr ("cv", address);
2224 TS_del_char = tgetstr ("dc", address);
2225 TS_del_multi_chars = tgetstr ("DC", address);
2226 TS_del_line = tgetstr ("dl", address);
2227 TS_del_multi_lines = tgetstr ("DL", address);
2228 TS_delete_mode = tgetstr ("dm", address);
2229 TS_end_delete_mode = tgetstr ("ed", address);
2230 TS_end_insert_mode = tgetstr ("ei", address);
2231 Home = tgetstr ("ho", address);
2232 TS_ins_char = tgetstr ("ic", address);
2233 TS_ins_multi_chars = tgetstr ("IC", address);
2234 TS_insert_mode = tgetstr ("im", address);
2235 TS_pad_inserted_char = tgetstr ("ip", address);
2236 TS_end_keypad_mode = tgetstr ("ke", address);
2237 TS_keypad_mode = tgetstr ("ks", address);
2238 LastLine = tgetstr ("ll", address);
2239 Right = tgetstr ("nd", address);
2240 Down = tgetstr ("do", address);
2241 if (!Down)
2242 Down = tgetstr ("nl", address); /* Obsolete name for "do" */
2243 #ifdef VMS
2244 /* VMS puts a carriage return before each linefeed,
2245 so it is not safe to use linefeeds. */
2246 if (Down && Down[0] == '\n' && Down[1] == '\0')
2247 Down = 0;
2248 #endif /* VMS */
2249 if (tgetflag ("bs"))
2250 Left = "\b"; /* can't possibly be longer! */
2251 else /* (Actually, "bs" is obsolete...) */
2252 Left = tgetstr ("le", address);
2253 if (!Left)
2254 Left = tgetstr ("bc", address); /* Obsolete name for "le" */
2255 TS_pad_char = tgetstr ("pc", address);
2256 TS_repeat = tgetstr ("rp", address);
2257 TS_end_standout_mode = tgetstr ("se", address);
2258 TS_fwd_scroll = tgetstr ("sf", address);
2259 TS_standout_mode = tgetstr ("so", address);
2260 TS_rev_scroll = tgetstr ("sr", address);
2261 Wcm.cm_tab = tgetstr ("ta", address);
2262 TS_end_termcap_modes = tgetstr ("te", address);
2263 TS_termcap_modes = tgetstr ("ti", address);
2264 Up = tgetstr ("up", address);
2265 TS_visible_bell = tgetstr ("vb", address);
2266 TS_cursor_normal = tgetstr ("ve", address);
2267 TS_cursor_visible = tgetstr ("vs", address);
2268 TS_cursor_invisible = tgetstr ("vi", address);
2269 TS_set_window = tgetstr ("wi", address);
2271 TS_enter_underline_mode = tgetstr ("us", address);
2272 TS_exit_underline_mode = tgetstr ("ue", address);
2273 TN_magic_cookie_glitch_ul = tgetnum ("ug");
2274 TS_enter_bold_mode = tgetstr ("md", address);
2275 TS_enter_dim_mode = tgetstr ("mh", address);
2276 TS_enter_blink_mode = tgetstr ("mb", address);
2277 TS_enter_reverse_mode = tgetstr ("mr", address);
2278 TS_enter_alt_charset_mode = tgetstr ("as", address);
2279 TS_exit_alt_charset_mode = tgetstr ("ae", address);
2280 TS_exit_attribute_mode = tgetstr ("me", address);
2282 MultiUp = tgetstr ("UP", address);
2283 MultiDown = tgetstr ("DO", address);
2284 MultiLeft = tgetstr ("LE", address);
2285 MultiRight = tgetstr ("RI", address);
2287 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
2288 color because we can't switch back to the default foreground and
2289 background. */
2290 TS_orig_pair = tgetstr ("op", address);
2291 if (TS_orig_pair)
2293 TS_set_foreground = tgetstr ("AF", address);
2294 TS_set_background = tgetstr ("AB", address);
2295 if (!TS_set_foreground)
2297 /* SVr4. */
2298 TS_set_foreground = tgetstr ("Sf", address);
2299 TS_set_background = tgetstr ("Sb", address);
2302 TN_max_colors = tgetnum ("Co");
2303 TN_max_pairs = tgetnum ("pa");
2305 TN_no_color_video = tgetnum ("NC");
2306 if (TN_no_color_video == -1)
2307 TN_no_color_video = 0;
2310 MagicWrap = tgetflag ("xn");
2311 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
2312 the former flag imply the latter. */
2313 AutoWrap = MagicWrap || tgetflag ("am");
2314 memory_below_frame = tgetflag ("db");
2315 TF_hazeltine = tgetflag ("hz");
2316 must_write_spaces = tgetflag ("in");
2317 meta_key = tgetflag ("km") || tgetflag ("MT");
2318 TF_insmode_motion = tgetflag ("mi");
2319 TF_standout_motion = tgetflag ("ms");
2320 TF_underscore = tgetflag ("ul");
2321 TF_xs = tgetflag ("xs");
2322 TF_teleray = tgetflag ("xt");
2324 term_get_fkeys (address);
2326 /* Get frame size from system, or else from termcap. */
2328 int height, width;
2329 get_frame_size (&width, &height);
2330 FRAME_WIDTH (sf) = width;
2331 FRAME_HEIGHT (sf) = height;
2334 if (FRAME_WIDTH (sf) <= 0)
2335 SET_FRAME_WIDTH (sf, tgetnum ("co"));
2336 else
2337 /* Keep width and external_width consistent */
2338 SET_FRAME_WIDTH (sf, FRAME_WIDTH (sf));
2339 if (FRAME_HEIGHT (sf) <= 0)
2340 FRAME_HEIGHT (sf) = tgetnum ("li");
2342 if (FRAME_HEIGHT (sf) < 3 || FRAME_WIDTH (sf) < 3)
2343 fatal ("Screen size %dx%d is too small",
2344 FRAME_HEIGHT (sf), FRAME_WIDTH (sf));
2346 min_padding_speed = tgetnum ("pb");
2347 TN_standout_width = tgetnum ("sg");
2348 TabWidth = tgetnum ("tw");
2350 #ifdef VMS
2351 /* These capabilities commonly use ^J.
2352 I don't know why, but sending them on VMS does not work;
2353 it causes following spaces to be lost, sometimes.
2354 For now, the simplest fix is to avoid using these capabilities ever. */
2355 if (Down && Down[0] == '\n')
2356 Down = 0;
2357 #endif /* VMS */
2359 if (!TS_bell)
2360 TS_bell = "\07";
2362 if (!TS_fwd_scroll)
2363 TS_fwd_scroll = Down;
2365 PC = TS_pad_char ? *TS_pad_char : 0;
2367 if (TabWidth < 0)
2368 TabWidth = 8;
2370 /* Turned off since /etc/termcap seems to have :ta= for most terminals
2371 and newer termcap doc does not seem to say there is a default.
2372 if (!Wcm.cm_tab)
2373 Wcm.cm_tab = "\t";
2376 if (TS_standout_mode == 0)
2378 TN_standout_width = tgetnum ("ug");
2379 TS_end_standout_mode = tgetstr ("ue", address);
2380 TS_standout_mode = tgetstr ("us", address);
2383 /* If no `se' string, try using a `me' string instead.
2384 If that fails, we can't use standout mode at all. */
2385 if (TS_end_standout_mode == 0)
2387 char *s = tgetstr ("me", address);
2388 if (s != 0)
2389 TS_end_standout_mode = s;
2390 else
2391 TS_standout_mode = 0;
2394 if (TF_teleray)
2396 Wcm.cm_tab = 0;
2397 /* Teleray: most programs want a space in front of TS_standout_mode,
2398 but Emacs can do without it (and give one extra column). */
2399 TS_standout_mode = "\033RD";
2400 TN_standout_width = 1;
2401 /* But that means we cannot rely on ^M to go to column zero! */
2402 CR = 0;
2403 /* LF can't be trusted either -- can alter hpos */
2404 /* if move at column 0 thru a line with TS_standout_mode */
2405 Down = 0;
2408 /* Special handling for certain terminal types known to need it */
2410 if (!strcmp (terminal_type, "supdup"))
2412 memory_below_frame = 1;
2413 Wcm.cm_losewrap = 1;
2415 if (!strncmp (terminal_type, "c10", 3)
2416 || !strcmp (terminal_type, "perq"))
2418 /* Supply a makeshift :wi string.
2419 This string is not valid in general since it works only
2420 for windows starting at the upper left corner;
2421 but that is all Emacs uses.
2423 This string works only if the frame is using
2424 the top of the video memory, because addressing is memory-relative.
2425 So first check the :ti string to see if that is true.
2427 It would be simpler if the :wi string could go in the termcap
2428 entry, but it can't because it is not fully valid.
2429 If it were in the termcap entry, it would confuse other programs. */
2430 if (!TS_set_window)
2432 p = TS_termcap_modes;
2433 while (*p && strcmp (p, "\033v "))
2434 p++;
2435 if (*p)
2436 TS_set_window = "\033v%C %C %C %C ";
2438 /* Termcap entry often fails to have :in: flag */
2439 must_write_spaces = 1;
2440 /* :ti string typically fails to have \E^G! in it */
2441 /* This limits scope of insert-char to one line. */
2442 strcpy (area, TS_termcap_modes);
2443 strcat (area, "\033\007!");
2444 TS_termcap_modes = area;
2445 area += strlen (area) + 1;
2446 p = AbsPosition;
2447 /* Change all %+ parameters to %C, to handle
2448 values above 96 correctly for the C100. */
2449 while (*p)
2451 if (p[0] == '%' && p[1] == '+')
2452 p[1] = 'C';
2453 p++;
2457 FrameRows = FRAME_HEIGHT (sf);
2458 FrameCols = FRAME_WIDTH (sf);
2459 specified_window = FRAME_HEIGHT (sf);
2461 if (Wcm_init () == -1) /* can't do cursor motion */
2462 #ifdef VMS
2463 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2464 It lacks the ability to position the cursor.\n\
2465 If that is not the actual type of terminal you have, use either the\n\
2466 DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
2467 or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
2468 terminal_type);
2469 #else /* not VMS */
2470 # ifdef TERMINFO
2471 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2472 It lacks the ability to position the cursor.\n\
2473 If that is not the actual type of terminal you have,\n\
2474 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2475 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2476 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
2477 terminal_type);
2478 # else /* TERMCAP */
2479 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2480 It lacks the ability to position the cursor.\n\
2481 If that is not the actual type of terminal you have,\n\
2482 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2483 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2484 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
2485 terminal_type);
2486 # endif /* TERMINFO */
2487 #endif /*VMS */
2488 if (FRAME_HEIGHT (sf) <= 0
2489 || FRAME_WIDTH (sf) <= 0)
2490 fatal ("The frame size has not been specified");
2492 delete_in_insert_mode
2493 = TS_delete_mode && TS_insert_mode
2494 && !strcmp (TS_delete_mode, TS_insert_mode);
2496 se_is_so = (TS_standout_mode
2497 && TS_end_standout_mode
2498 && !strcmp (TS_standout_mode, TS_end_standout_mode));
2500 /* Remove width of standout marker from usable width of line */
2501 if (TN_standout_width > 0)
2502 SET_FRAME_WIDTH (sf, FRAME_WIDTH (sf) - TN_standout_width);
2504 UseTabs = tabs_safe_p () && TabWidth == 8;
2506 scroll_region_ok
2507 = (Wcm.cm_abs
2508 && (TS_set_window || TS_set_scroll_region || TS_set_scroll_region_1));
2510 line_ins_del_ok = (((TS_ins_line || TS_ins_multi_lines)
2511 && (TS_del_line || TS_del_multi_lines))
2512 || (scroll_region_ok && TS_fwd_scroll && TS_rev_scroll));
2514 char_ins_del_ok = ((TS_ins_char || TS_insert_mode
2515 || TS_pad_inserted_char || TS_ins_multi_chars)
2516 && (TS_del_char || TS_del_multi_chars));
2518 fast_clear_end_of_line = TS_clr_line != 0;
2520 init_baud_rate ();
2521 if (read_socket_hook) /* Baudrate is somewhat */
2522 /* meaningless in this case */
2523 baud_rate = 9600;
2525 FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0;
2526 FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none;
2527 #endif /* WINDOWSNT */
2530 /* VARARGS 1 */
2531 void
2532 fatal (str, arg1, arg2)
2533 char *str, *arg1, *arg2;
2535 fprintf (stderr, "emacs: ");
2536 fprintf (stderr, str, arg1, arg2);
2537 fprintf (stderr, "\n");
2538 fflush (stderr);
2539 exit (1);
2542 void
2543 syms_of_term ()
2545 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
2546 "Non-nil means the system uses terminfo rather than termcap.\n\
2547 This variable can be used by terminal emulator packages.");
2548 #ifdef TERMINFO
2549 system_uses_terminfo = 1;
2550 #else
2551 system_uses_terminfo = 0;
2552 #endif
2554 DEFVAR_LISP ("ring-bell-function", &Vring_bell_function,
2555 "Non-nil means call this function to ring the bell.\n\
2556 The function should accept no arguments.");
2557 Vring_bell_function = Qnil;
2559 defsubr (&Stty_display_color_p);