(Ftty_display_color_p): Accept an optional argument FRAME.
[emacs.git] / src / term.c
blobd4ea6a6f2f7d5a03beefb5da7f594e0863437b13
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 #endif
45 #include "cm.h"
46 #ifdef HAVE_X_WINDOWS
47 #include "xterm.h"
48 #endif
50 static void turn_on_face P_ ((struct frame *, int face_id));
51 static void turn_off_face P_ ((struct frame *, int face_id));
52 static void tty_show_cursor P_ ((void));
53 static void tty_hide_cursor P_ ((void));
55 #define max(a, b) ((a) > (b) ? (a) : (b))
56 #define min(a, b) ((a) < (b) ? (a) : (b))
58 #define OUTPUT(a) \
59 tputs (a, (int) (FRAME_HEIGHT (XFRAME (selected_frame)) - curY), cmputc)
60 #define OUTPUT1(a) tputs (a, 1, cmputc)
61 #define OUTPUTL(a, lines) tputs (a, lines, cmputc)
63 #define OUTPUT_IF(a) \
64 do { \
65 if (a) \
66 tputs (a, (int) (FRAME_HEIGHT (XFRAME (selected_frame)) \
67 - curY), cmputc); \
68 } while (0)
70 #define OUTPUT1_IF(a) do { if (a) tputs (a, 1, cmputc); } while (0)
72 /* Function to use to ring the bell. */
74 Lisp_Object Vring_bell_function;
76 /* Terminal characteristics that higher levels want to look at.
77 These are all extern'd in termchar.h */
79 int must_write_spaces; /* Nonzero means spaces in the text
80 must actually be output; can't just skip
81 over some columns to leave them blank. */
82 int min_padding_speed; /* Speed below which no padding necessary */
84 int line_ins_del_ok; /* Terminal can insert and delete lines */
85 int char_ins_del_ok; /* Terminal can insert and delete chars */
86 int scroll_region_ok; /* Terminal supports setting the
87 scroll window */
88 int scroll_region_cost; /* Cost of setting a scroll window,
89 measured in characters */
90 int memory_below_frame; /* Terminal remembers lines
91 scrolled off bottom */
92 int fast_clear_end_of_line; /* Terminal has a `ce' string */
94 /* Nonzero means no need to redraw the entire frame on resuming
95 a suspended Emacs. This is useful on terminals with multiple pages,
96 where one page is used for Emacs and another for all else. */
98 int no_redraw_on_reenter;
100 /* Hook functions that you can set to snap out the functions in this file.
101 These are all extern'd in termhooks.h */
103 void (*cursor_to_hook) P_ ((int, int));
104 void (*raw_cursor_to_hook) P_ ((int, int));
105 void (*clear_to_end_hook) P_ ((void));
106 void (*clear_frame_hook) P_ ((void));
107 void (*clear_end_of_line_hook) P_ ((int));
109 void (*ins_del_lines_hook) P_ ((int, int));
111 void (*change_line_highlight_hook) P_ ((int, int, int, int));
112 void (*reassert_line_highlight_hook) P_ ((int, int));
114 void (*delete_glyphs_hook) P_ ((int));
116 void (*ring_bell_hook) P_ ((void));
118 void (*reset_terminal_modes_hook) P_ ((void));
119 void (*set_terminal_modes_hook) P_ ((void));
120 void (*update_begin_hook) P_ ((struct frame *));
121 void (*update_end_hook) P_ ((struct frame *));
122 void (*set_terminal_window_hook) P_ ((int));
123 void (*insert_glyphs_hook) P_ ((struct glyph *, int));
124 void (*write_glyphs_hook) P_ ((struct glyph *, int));
125 void (*delete_glyphs_hook) P_ ((int));
127 int (*read_socket_hook) P_ ((int, struct input_event *, int, int));
129 void (*frame_up_to_date_hook) P_ ((struct frame *));
131 /* Return the current position of the mouse.
133 Set *f to the frame the mouse is in, or zero if the mouse is in no
134 Emacs frame. If it is set to zero, all the other arguments are
135 garbage.
137 If the motion started in a scroll bar, set *bar_window to the
138 scroll bar's window, *part to the part the mouse is currently over,
139 *x to the position of the mouse along the scroll bar, and *y to the
140 overall length of the scroll bar.
142 Otherwise, set *bar_window to Qnil, and *x and *y to the column and
143 row of the character cell the mouse is over.
145 Set *time to the time the mouse was at the returned position.
147 This should clear mouse_moved until the next motion
148 event arrives. */
149 void (*mouse_position_hook) P_ ((FRAME_PTR *f, int insist,
150 Lisp_Object *bar_window,
151 enum scroll_bar_part *part,
152 Lisp_Object *x,
153 Lisp_Object *y,
154 unsigned long *time));
156 /* When reading from a minibuffer in a different frame, Emacs wants
157 to shift the highlight from the selected frame to the mini-buffer's
158 frame; under X, this means it lies about where the focus is.
159 This hook tells the window system code to re-decide where to put
160 the highlight. */
161 void (*frame_rehighlight_hook) P_ ((FRAME_PTR f));
163 /* If we're displaying frames using a window system that can stack
164 frames on top of each other, this hook allows you to bring a frame
165 to the front, or bury it behind all the other windows. If this
166 hook is zero, that means the device we're displaying on doesn't
167 support overlapping frames, so there's no need to raise or lower
168 anything.
170 If RAISE is non-zero, F is brought to the front, before all other
171 windows. If RAISE is zero, F is sent to the back, behind all other
172 windows. */
173 void (*frame_raise_lower_hook) P_ ((FRAME_PTR f, int raise));
175 /* Set the vertical scroll bar for WINDOW to have its upper left corner
176 at (TOP, LEFT), and be LENGTH rows high. Set its handle to
177 indicate that we are displaying PORTION characters out of a total
178 of WHOLE characters, starting at POSITION. If WINDOW doesn't yet
179 have a scroll bar, create one for it. */
181 void (*set_vertical_scroll_bar_hook)
182 P_ ((struct window *window,
183 int portion, int whole, int position));
186 /* The following three hooks are used when we're doing a thorough
187 redisplay of the frame. We don't explicitly know which scroll bars
188 are going to be deleted, because keeping track of when windows go
189 away is a real pain - can you say set-window-configuration?
190 Instead, we just assert at the beginning of redisplay that *all*
191 scroll bars are to be removed, and then save scroll bars from the
192 fiery pit when we actually redisplay their window. */
194 /* Arrange for all scroll bars on FRAME to be removed at the next call
195 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
196 `*redeem_scroll_bar_hook' is applied to its window before the judgment.
198 This should be applied to each frame each time its window tree is
199 redisplayed, even if it is not displaying scroll bars at the moment;
200 if the HAS_SCROLL_BARS flag has just been turned off, only calling
201 this and the judge_scroll_bars_hook will get rid of them.
203 If non-zero, this hook should be safe to apply to any frame,
204 whether or not it can support scroll bars, and whether or not it is
205 currently displaying them. */
206 void (*condemn_scroll_bars_hook) P_ ((FRAME_PTR frame));
208 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
209 Note that it's okay to redeem a scroll bar that is not condemned. */
210 void (*redeem_scroll_bar_hook) P_ ((struct window *window));
212 /* Remove all scroll bars on FRAME that haven't been saved since the
213 last call to `*condemn_scroll_bars_hook'.
215 This should be applied to each frame after each time its window
216 tree is redisplayed, even if it is not displaying scroll bars at the
217 moment; if the HAS_SCROLL_BARS flag has just been turned off, only
218 calling this and condemn_scroll_bars_hook will get rid of them.
220 If non-zero, this hook should be safe to apply to any frame,
221 whether or not it can support scroll bars, and whether or not it is
222 currently displaying them. */
223 void (*judge_scroll_bars_hook) P_ ((FRAME_PTR FRAME));
225 /* Hook to call in estimate_mode_line_height, if any. */
227 int (* estimate_mode_line_height_hook) P_ ((struct frame *f, enum face_id));
230 /* Strings, numbers and flags taken from the termcap entry. */
232 char *TS_ins_line; /* "al" */
233 char *TS_ins_multi_lines; /* "AL" (one parameter, # lines to insert) */
234 char *TS_bell; /* "bl" */
235 char *TS_clr_to_bottom; /* "cd" */
236 char *TS_clr_line; /* "ce", clear to end of line */
237 char *TS_clr_frame; /* "cl" */
238 char *TS_set_scroll_region; /* "cs" (2 params, first line and last line) */
239 char *TS_set_scroll_region_1; /* "cS" (4 params: total lines,
240 lines above scroll region, lines below it,
241 total lines again) */
242 char *TS_del_char; /* "dc" */
243 char *TS_del_multi_chars; /* "DC" (one parameter, # chars to delete) */
244 char *TS_del_line; /* "dl" */
245 char *TS_del_multi_lines; /* "DL" (one parameter, # lines to delete) */
246 char *TS_delete_mode; /* "dm", enter character-delete mode */
247 char *TS_end_delete_mode; /* "ed", leave character-delete mode */
248 char *TS_end_insert_mode; /* "ei", leave character-insert mode */
249 char *TS_ins_char; /* "ic" */
250 char *TS_ins_multi_chars; /* "IC" (one parameter, # chars to insert) */
251 char *TS_insert_mode; /* "im", enter character-insert mode */
252 char *TS_pad_inserted_char; /* "ip". Just padding, no commands. */
253 char *TS_end_keypad_mode; /* "ke" */
254 char *TS_keypad_mode; /* "ks" */
255 char *TS_pad_char; /* "pc", char to use as padding */
256 char *TS_repeat; /* "rp" (2 params, # times to repeat
257 and character to be repeated) */
258 char *TS_end_standout_mode; /* "se" */
259 char *TS_fwd_scroll; /* "sf" */
260 char *TS_standout_mode; /* "so" */
261 char *TS_rev_scroll; /* "sr" */
262 char *TS_end_termcap_modes; /* "te" */
263 char *TS_termcap_modes; /* "ti" */
264 char *TS_visible_bell; /* "vb" */
265 char *TS_cursor_normal; /* "ve" */
266 char *TS_cursor_visible; /* "vs" */
267 char *TS_cursor_invisible; /* "vi" */
268 char *TS_set_window; /* "wi" (4 params, start and end of window,
269 each as vpos and hpos) */
271 /* "md" -- turn on bold (extra bright mode). */
273 char *TS_enter_bold_mode;
275 /* "mh" -- turn on half-bright mode. */
277 char *TS_enter_dim_mode;
279 /* "mb" -- enter blinking mode. */
281 char *TS_enter_blink_mode;
283 /* "mr" -- enter reverse video mode. */
285 char *TS_enter_reverse_mode;
287 /* "us"/"ue" -- start/end underlining. */
289 char *TS_exit_underline_mode, *TS_enter_underline_mode;
291 /* "ug" -- number of blanks left by underline. */
293 int TN_magic_cookie_glitch_ul;
295 /* "as"/"ae" -- start/end alternate character set. Not really
296 supported, yet. */
298 char *TS_enter_alt_charset_mode, *TS_exit_alt_charset_mode;
300 /* "me" -- switch appearances off. */
302 char *TS_exit_attribute_mode;
304 /* "Co" -- number of colors. */
306 int TN_max_colors;
308 /* "pa" -- max. number of color pairs on screen. Not handled yet.
309 Could be a problem if not equal to TN_max_colors * TN_max_colors. */
311 int TN_max_pairs;
313 /* "op" -- SVr4 set default pair to its original value. */
315 char *TS_orig_pair;
317 /* "AF"/"AB" or "Sf"/"Sb"-- set ANSI or SVr4 foreground/background color.
318 1 param, the color index. */
320 char *TS_set_foreground, *TS_set_background;
322 int TF_hazeltine; /* termcap hz flag. */
323 int TF_insmode_motion; /* termcap mi flag: can move while in insert mode. */
324 int TF_standout_motion; /* termcap mi flag: can move while in standout mode. */
325 int TF_underscore; /* termcap ul flag: _ underlines if over-struck on
326 non-blank position. Must clear before writing _. */
327 int TF_teleray; /* termcap xt flag: many weird consequences.
328 For t1061. */
330 int TF_xs; /* Nonzero for "xs". If set together with
331 TN_standout_width == 0, it means don't bother
332 to write any end-standout cookies. */
334 int TN_standout_width; /* termcap sg number: width occupied by standout
335 markers */
337 static int RPov; /* # chars to start a TS_repeat */
339 static int delete_in_insert_mode; /* delete mode == insert mode */
341 static int se_is_so; /* 1 if same string both enters and leaves
342 standout mode */
344 /* internal state */
346 /* The largest frame width in any call to calculate_costs. */
348 int max_frame_width;
350 /* The largest frame height in any call to calculate_costs. */
352 int max_frame_height;
354 /* Number of chars of space used for standout marker at beginning of line,
355 or'd with 0100. Zero if no standout marker at all.
356 The length of these vectors is max_frame_height.
358 Used IFF TN_standout_width >= 0. */
360 static char *chars_wasted;
361 static char *copybuf;
363 /* nonzero means supposed to write text in standout mode. */
365 int standout_requested;
367 int insert_mode; /* Nonzero when in insert mode. */
368 int standout_mode; /* Nonzero when in standout mode. */
370 /* Size of window specified by higher levels.
371 This is the number of lines, from the top of frame downwards,
372 which can participate in insert-line/delete-line operations.
374 Effectively it excludes the bottom frame_height - specified_window_size
375 lines from those operations. */
377 int specified_window;
379 /* Frame currently being redisplayed; 0 if not currently redisplaying.
380 (Direct output does not count). */
382 FRAME_PTR updating_frame;
384 /* Provided for lisp packages. */
386 static int system_uses_terminfo;
388 char *tparam ();
390 extern char *tgetstr ();
393 #ifdef WINDOWSNT
395 /* We aren't X windows, but we aren't termcap either. This makes me
396 uncertain as to what value to use for frame.output_method. For
397 this file, we'll define FRAME_TERMCAP_P to be zero so that our
398 output hooks get called instead of the termcap functions. Probably
399 the best long-term solution is to define an output_windows_nt... */
401 #undef FRAME_TERMCAP_P
402 #define FRAME_TERMCAP_P(_f_) 0
403 #endif /* WINDOWSNT */
405 void
406 ring_bell ()
408 if (! NILP (Vring_bell_function))
410 Lisp_Object function;
412 /* Temporarily set the global variable to nil
413 so that if we get an error, it stays nil
414 and we don't call it over and over.
416 We don't specbind it, because that would carefully
417 restore the bad value if there's an error
418 and make the loop of errors happen anyway. */
419 function = Vring_bell_function;
420 Vring_bell_function = Qnil;
422 call0 (function);
424 Vring_bell_function = function;
425 return;
428 if (! FRAME_TERMCAP_P (XFRAME (selected_frame)))
430 (*ring_bell_hook) ();
431 return;
433 OUTPUT (TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell);
436 void
437 set_terminal_modes ()
439 if (! FRAME_TERMCAP_P (XFRAME (selected_frame)))
441 (*set_terminal_modes_hook) ();
442 return;
444 OUTPUT_IF (TS_termcap_modes);
445 OUTPUT_IF (TS_cursor_visible);
446 OUTPUT_IF (TS_keypad_mode);
447 losecursor ();
450 void
451 reset_terminal_modes ()
453 if (! FRAME_TERMCAP_P (XFRAME (selected_frame)))
455 if (reset_terminal_modes_hook)
456 (*reset_terminal_modes_hook) ();
457 return;
459 if (TN_standout_width < 0)
460 turn_off_highlight ();
461 turn_off_insert ();
462 OUTPUT_IF (TS_end_keypad_mode);
463 OUTPUT_IF (TS_cursor_normal);
464 OUTPUT_IF (TS_end_termcap_modes);
465 OUTPUT_IF (TS_orig_pair);
466 /* Output raw CR so kernel can track the cursor hpos. */
467 /* But on magic-cookie terminals this can erase an end-standout marker and
468 cause the rest of the frame to be in standout, so move down first. */
469 if (TN_standout_width >= 0)
470 cmputc ('\n');
471 cmputc ('\r');
474 void
475 update_begin (f)
476 FRAME_PTR f;
478 updating_frame = f;
479 if (! FRAME_TERMCAP_P (updating_frame))
480 (*update_begin_hook) (f);
481 else
482 tty_hide_cursor ();
485 void
486 update_end (f)
487 FRAME_PTR f;
489 if (! FRAME_TERMCAP_P (updating_frame))
491 (*update_end_hook) (f);
492 updating_frame = 0;
493 return;
496 if (!XWINDOW (selected_window)->cursor_off_p)
497 tty_show_cursor ();
499 turn_off_insert ();
500 background_highlight ();
501 standout_requested = 0;
502 updating_frame = 0;
505 void
506 set_terminal_window (size)
507 int size;
509 if (! FRAME_TERMCAP_P (updating_frame))
511 (*set_terminal_window_hook) (size);
512 return;
514 specified_window = size ? size : FRAME_HEIGHT (XFRAME (selected_frame));
515 if (!scroll_region_ok)
516 return;
517 set_scroll_region (0, specified_window);
520 void
521 set_scroll_region (start, stop)
522 int start, stop;
524 char *buf;
525 struct frame *sf = XFRAME (selected_frame);
527 if (TS_set_scroll_region)
529 buf = tparam (TS_set_scroll_region, 0, 0, start, stop - 1);
531 else if (TS_set_scroll_region_1)
533 buf = tparam (TS_set_scroll_region_1, 0, 0,
534 FRAME_HEIGHT (sf), start,
535 FRAME_HEIGHT (sf) - stop,
536 FRAME_HEIGHT (sf));
538 else
540 buf = tparam (TS_set_window, 0, 0, start, 0, stop, FRAME_WIDTH (sf));
542 OUTPUT (buf);
543 xfree (buf);
544 losecursor ();
547 void
548 turn_on_insert ()
550 if (!insert_mode)
551 OUTPUT (TS_insert_mode);
552 insert_mode = 1;
555 void
556 turn_off_insert ()
558 if (insert_mode)
559 OUTPUT (TS_end_insert_mode);
560 insert_mode = 0;
563 /* Handle highlighting when TN_standout_width (termcap sg) is not specified.
564 In these terminals, output is affected by the value of standout
565 mode when the output is written.
567 These functions are called on all terminals, but do nothing
568 on terminals whose standout mode does not work that way. */
570 void
571 turn_off_highlight ()
573 if (TN_standout_width < 0)
575 if (standout_mode)
576 OUTPUT_IF (TS_end_standout_mode);
577 standout_mode = 0;
581 void
582 turn_on_highlight ()
584 if (TN_standout_width < 0)
586 if (!standout_mode)
587 OUTPUT_IF (TS_standout_mode);
588 standout_mode = 1;
593 /* Make cursor invisible. */
595 static void
596 tty_hide_cursor ()
598 OUTPUT_IF (TS_cursor_invisible);
602 /* Ensure that cursor is visible. */
604 static void
605 tty_show_cursor ()
607 OUTPUT_IF (TS_cursor_normal);
608 OUTPUT_IF (TS_cursor_visible);
612 /* Set standout mode to the state it should be in for
613 empty space inside windows. What this is,
614 depends on the user option inverse-video. */
616 void
617 background_highlight ()
619 if (TN_standout_width >= 0)
620 return;
621 if (inverse_video)
622 turn_on_highlight ();
623 else
624 turn_off_highlight ();
627 /* Set standout mode to the mode specified for the text to be output. */
629 static void
630 highlight_if_desired ()
632 if (TN_standout_width >= 0)
633 return;
634 if (!inverse_video == !standout_requested)
635 turn_off_highlight ();
636 else
637 turn_on_highlight ();
640 /* Handle standout mode for terminals in which TN_standout_width >= 0.
641 On these terminals, standout is controlled by markers that
642 live inside the terminal's memory. TN_standout_width is the width
643 that the marker occupies in memory. Standout runs from the marker
644 to the end of the line on some terminals, or to the next
645 turn-off-standout marker (TS_end_standout_mode) string
646 on other terminals. */
648 /* Write a standout marker or end-standout marker at the front of the line
649 at vertical position vpos. */
651 void
652 write_standout_marker (flag, vpos)
653 int flag, vpos;
655 if (flag || (TS_end_standout_mode && !TF_teleray && !se_is_so
656 && !(TF_xs && TN_standout_width == 0)))
658 cmgoto (vpos, 0);
659 cmplus (TN_standout_width);
660 OUTPUT (flag ? TS_standout_mode : TS_end_standout_mode);
661 chars_wasted[curY] = TN_standout_width | 0100;
665 /* External interface to control of standout mode.
666 Call this when about to modify line at position VPOS
667 and not change whether it is highlighted. */
669 void
670 reassert_line_highlight (highlight, vpos)
671 int highlight;
672 int vpos;
674 struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
675 if (! FRAME_TERMCAP_P (f))
677 (*reassert_line_highlight_hook) (highlight, vpos);
678 return;
680 if (TN_standout_width < 0)
681 /* Handle terminals where standout takes affect at output time */
682 standout_requested = highlight;
683 else if (chars_wasted && chars_wasted[vpos] == 0)
684 /* For terminals with standout markers, write one on this line
685 if there isn't one already. */
686 write_standout_marker (highlight, vpos);
689 /* Call this when about to modify line at position VPOS
690 and change whether it is highlighted. */
692 void
693 change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
694 int new_highlight, vpos, y, first_unused_hpos;
696 standout_requested = new_highlight;
697 if (! FRAME_TERMCAP_P (updating_frame))
699 (*change_line_highlight_hook) (new_highlight, vpos, y, first_unused_hpos);
700 return;
703 cursor_to (vpos, 0);
705 if (TN_standout_width < 0)
706 background_highlight ();
707 /* If line starts with a marker, delete the marker */
708 else if (TS_clr_line && chars_wasted[curY])
710 turn_off_insert ();
711 /* On Teleray, make sure to erase the SO marker. */
712 if (TF_teleray)
714 cmgoto (curY - 1, FRAME_WIDTH (XFRAME (selected_frame)) - 4);
715 OUTPUT ("\033S");
716 curY++; /* ESC S moves to next line where the TS_standout_mode was */
717 curX = 0;
719 else
720 cmgoto (curY, 0); /* reposition to kill standout marker */
722 clear_end_of_line_raw (first_unused_hpos);
723 reassert_line_highlight (new_highlight, curY);
727 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
728 frame-relative coordinates. */
730 void
731 cursor_to (vpos, hpos)
732 int vpos, hpos;
734 struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
736 if (! FRAME_TERMCAP_P (f) && cursor_to_hook)
738 (*cursor_to_hook) (vpos, hpos);
739 return;
742 /* Detect the case where we are called from reset_sys_modes
743 and the costs have never been calculated. Do nothing. */
744 if (chars_wasted == 0)
745 return;
747 hpos += chars_wasted[vpos] & 077;
748 if (curY == vpos && curX == hpos)
749 return;
750 if (!TF_standout_motion)
751 background_highlight ();
752 if (!TF_insmode_motion)
753 turn_off_insert ();
754 cmgoto (vpos, hpos);
757 /* Similar but don't take any account of the wasted characters. */
759 void
760 raw_cursor_to (row, col)
761 int row, col;
763 struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
764 if (! FRAME_TERMCAP_P (f))
766 (*raw_cursor_to_hook) (row, col);
767 return;
769 if (curY == row && curX == col)
770 return;
771 if (!TF_standout_motion)
772 background_highlight ();
773 if (!TF_insmode_motion)
774 turn_off_insert ();
775 cmgoto (row, col);
778 /* Erase operations */
780 /* clear from cursor to end of frame */
781 void
782 clear_to_end ()
784 register int i;
786 if (clear_to_end_hook && ! FRAME_TERMCAP_P (updating_frame))
788 (*clear_to_end_hook) ();
789 return;
791 if (TS_clr_to_bottom)
793 background_highlight ();
794 OUTPUT (TS_clr_to_bottom);
795 bzero (chars_wasted + curY,
796 FRAME_HEIGHT (XFRAME (selected_frame)) - curY);
798 else
800 for (i = curY; i < FRAME_HEIGHT (XFRAME (selected_frame)); i++)
802 cursor_to (i, 0);
803 clear_end_of_line_raw (FRAME_WIDTH (XFRAME (selected_frame)));
808 /* Clear entire frame */
810 void
811 clear_frame ()
813 struct frame *sf = XFRAME (selected_frame);
815 if (clear_frame_hook
816 && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : sf)))
818 (*clear_frame_hook) ();
819 return;
821 if (TS_clr_frame)
823 background_highlight ();
824 OUTPUT (TS_clr_frame);
825 bzero (chars_wasted, FRAME_HEIGHT (sf));
826 cmat (0, 0);
828 else
830 cursor_to (0, 0);
831 clear_to_end ();
835 /* Clear to end of line, but do not clear any standout marker.
836 Assumes that the cursor is positioned at a character of real text,
837 which implies it cannot be before a standout marker
838 unless the marker has zero width.
840 Note that the cursor may be moved. */
842 void
843 clear_end_of_line (first_unused_hpos)
844 int first_unused_hpos;
846 if (FRAME_TERMCAP_P (XFRAME (selected_frame))
847 && chars_wasted != 0
848 && TN_standout_width == 0 && curX == 0 && chars_wasted[curY] != 0)
849 write_glyphs (&space_glyph, 1);
850 clear_end_of_line_raw (first_unused_hpos);
853 /* Clear from cursor to end of line.
854 Assume that the line is already clear starting at column first_unused_hpos.
855 If the cursor is at a standout marker, erase the marker.
857 Note that the cursor may be moved, on terminals lacking a `ce' string. */
859 void
860 clear_end_of_line_raw (first_unused_hpos)
861 int first_unused_hpos;
863 register int i;
865 if (clear_end_of_line_hook
866 && ! FRAME_TERMCAP_P ((updating_frame
867 ? updating_frame
868 : XFRAME (selected_frame))))
870 (*clear_end_of_line_hook) (first_unused_hpos);
871 return;
874 /* Detect the case where we are called from reset_sys_modes
875 and the costs have never been calculated. Do nothing. */
876 if (chars_wasted == 0)
877 return;
879 first_unused_hpos += chars_wasted[curY] & 077;
880 if (curX >= first_unused_hpos)
881 return;
882 /* Notice if we are erasing a magic cookie */
883 if (curX == 0)
884 chars_wasted[curY] = 0;
885 background_highlight ();
886 if (TS_clr_line)
888 OUTPUT1 (TS_clr_line);
890 else
891 { /* have to do it the hard way */
892 struct frame *sf = XFRAME (selected_frame);
893 turn_off_insert ();
895 /* Do not write in last row last col with Auto-wrap on. */
896 if (AutoWrap && curY == FRAME_HEIGHT (sf) - 1
897 && first_unused_hpos == FRAME_WIDTH (sf))
898 first_unused_hpos--;
900 for (i = curX; i < first_unused_hpos; i++)
902 if (termscript)
903 fputc (' ', termscript);
904 putchar (' ');
906 cmplus (first_unused_hpos - curX);
910 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes and
911 store them at DST. Do not write more than DST_LEN bytes. That may
912 require stopping before all SRC_LEN input glyphs have been
913 converted.
915 We store the number of glyphs actually converted in *CONSUMED. The
916 return value is the number of bytes store in DST. */
919 encode_terminal_code (src, dst, src_len, dst_len, consumed)
920 struct glyph *src;
921 int src_len;
922 unsigned char *dst;
923 int dst_len, *consumed;
925 struct glyph *src_start = src, *src_end = src + src_len;
926 unsigned char *dst_start = dst, *dst_end = dst + dst_len;
927 register GLYPH g;
928 unsigned int c;
929 unsigned char workbuf[MAX_MULTIBYTE_LENGTH], *buf;
930 int len;
931 register int tlen = GLYPH_TABLE_LENGTH;
932 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
933 int result;
934 struct coding_system *coding;
936 coding = (CODING_REQUIRE_ENCODING (&terminal_coding)
937 ? &terminal_coding
938 : &safe_terminal_coding);
940 while (src < src_end)
942 /* We must skip glyphs to be padded for a wide character. */
943 if (! CHAR_GLYPH_PADDING_P (*src))
945 g = GLYPH_FROM_CHAR_GLYPH (src[0]);
947 if (g < 0 || g >= tlen)
949 /* This glyph doesn't has an entry in Vglyph_table. */
950 if (! CHAR_VALID_P (src->u.ch, 0))
952 len = 1;
953 buf = " ";
955 else
957 len = CHAR_STRING (src->u.ch, workbuf);
958 buf = workbuf;
961 else
963 /* This glyph has an entry in Vglyph_table,
964 so process any alias before testing for simpleness. */
965 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
967 if (GLYPH_SIMPLE_P (tbase, tlen, g))
969 /* We set the multi-byte form of C at WORKBUF. */
970 len = CHAR_STRING (src->u.ch, workbuf);
971 buf = workbuf;
973 else
975 /* We have a string in Vglyph_table. */
976 len = GLYPH_LENGTH (tbase, g);
977 buf = GLYPH_STRING (tbase, g);
981 result = encode_coding (coding, buf, dst, len, dst_end - dst);
982 len -= coding->consumed;
983 dst += coding->produced;
984 if (result == CODING_FINISH_INSUFFICIENT_DST
985 || (result == CODING_FINISH_INSUFFICIENT_SRC
986 && len > dst_end - dst))
987 /* The remaining output buffer is too short. We must
988 break the loop here without increasing SRC so that the
989 next call of this function starts from the same glyph. */
990 break;
992 if (len > 0)
994 /* This is the case that a code of the range 0200..0237
995 exists in buf. We must just write out such a code. */
996 buf += coding->consumed;
997 while (len--)
998 *dst++ = *buf++;
1001 src++;
1004 *consumed = src - src_start;
1005 return (dst - dst_start);
1009 void
1010 write_glyphs (string, len)
1011 register struct glyph *string;
1012 register int len;
1014 int produced, consumed;
1015 struct frame *sf = XFRAME (selected_frame);
1016 struct frame *f = updating_frame ? updating_frame : sf;
1018 if (write_glyphs_hook
1019 && ! FRAME_TERMCAP_P (f))
1021 (*write_glyphs_hook) (string, len);
1022 return;
1025 highlight_if_desired ();
1026 turn_off_insert ();
1028 /* Don't dare write in last column of bottom line, if Auto-Wrap,
1029 since that would scroll the whole frame on some terminals. */
1031 if (AutoWrap
1032 && curY + 1 == FRAME_HEIGHT (sf)
1033 && (curX + len - (chars_wasted[curY] & 077) == FRAME_WIDTH (sf)))
1034 len --;
1035 if (len <= 0)
1036 return;
1038 cmplus (len);
1040 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
1041 the tail. */
1042 terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
1044 while (len > 0)
1046 /* Identify a run of glyphs with the same face. */
1047 int face_id = string->face_id;
1048 int n;
1050 for (n = 1; n < len; ++n)
1051 if (string[n].face_id != face_id)
1052 break;
1054 /* Turn appearance modes of the face of the run on. */
1055 turn_on_face (f, face_id);
1057 while (n > 0)
1059 /* We use a shared conversion buffer of the current size
1060 (1024 bytes at least). Usually it is sufficient, but if
1061 not, we just repeat the loop. */
1062 produced = encode_terminal_code (string, conversion_buffer,
1063 n, conversion_buffer_size,
1064 &consumed);
1065 if (produced > 0)
1067 fwrite (conversion_buffer, 1, produced, stdout);
1068 if (ferror (stdout))
1069 clearerr (stdout);
1070 if (termscript)
1071 fwrite (conversion_buffer, 1, produced, termscript);
1073 len -= consumed;
1074 n -= consumed;
1075 string += consumed;
1078 /* Turn appearance modes off. */
1079 turn_off_face (f, face_id);
1082 /* We may have to output some codes to terminate the writing. */
1083 if (CODING_REQUIRE_FLUSHING (&terminal_coding))
1085 terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
1086 encode_coding (&terminal_coding, "", conversion_buffer,
1087 0, conversion_buffer_size);
1088 if (terminal_coding.produced > 0)
1090 fwrite (conversion_buffer, 1, terminal_coding.produced, stdout);
1091 if (ferror (stdout))
1092 clearerr (stdout);
1093 if (termscript)
1094 fwrite (conversion_buffer, 1, terminal_coding.produced,
1095 termscript);
1099 cmcheckmagic ();
1102 /* If start is zero, insert blanks instead of a string at start */
1104 void
1105 insert_glyphs (start, len)
1106 register struct glyph *start;
1107 register int len;
1109 char *buf;
1110 struct glyph *glyph;
1111 struct frame *f, *sf;
1113 if (len <= 0)
1114 return;
1116 if (insert_glyphs_hook)
1118 (*insert_glyphs_hook) (start, len);
1119 return;
1122 sf = XFRAME (selected_frame);
1123 f = updating_frame ? updating_frame : sf;
1124 highlight_if_desired ();
1126 if (TS_ins_multi_chars)
1128 buf = tparam (TS_ins_multi_chars, 0, 0, len);
1129 OUTPUT1 (buf);
1130 xfree (buf);
1131 if (start)
1132 write_glyphs (start, len);
1133 return;
1136 turn_on_insert ();
1137 cmplus (len);
1138 /* The bit CODING_MODE_LAST_BLOCK should be set to 1 only at the tail. */
1139 terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
1140 while (len-- > 0)
1142 int produced, consumed;
1144 OUTPUT1_IF (TS_ins_char);
1145 if (!start)
1147 conversion_buffer[0] = SPACEGLYPH;
1148 produced = 1;
1150 else
1152 turn_on_face (f, start->face_id);
1153 glyph = start;
1154 ++start;
1155 /* We must open sufficient space for a character which
1156 occupies more than one column. */
1157 while (len && CHAR_GLYPH_PADDING_P (*start))
1159 OUTPUT1_IF (TS_ins_char);
1160 start++, len--;
1163 if (len <= 0)
1164 /* This is the last glyph. */
1165 terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
1167 /* We use shared conversion buffer of the current size (1024
1168 bytes at least). It is surely sufficient for just one glyph. */
1169 produced = encode_terminal_code (glyph, conversion_buffer, 1,
1170 conversion_buffer_size, &consumed);
1173 if (produced > 0)
1175 fwrite (conversion_buffer, 1, produced, stdout);
1176 if (ferror (stdout))
1177 clearerr (stdout);
1178 if (termscript)
1179 fwrite (conversion_buffer, 1, produced, termscript);
1182 OUTPUT1_IF (TS_pad_inserted_char);
1183 if (start)
1184 turn_off_face (f, glyph->face_id);
1187 cmcheckmagic ();
1190 void
1191 delete_glyphs (n)
1192 register int n;
1194 char *buf;
1195 register int i;
1197 if (delete_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame))
1199 (*delete_glyphs_hook) (n);
1200 return;
1203 if (delete_in_insert_mode)
1205 turn_on_insert ();
1207 else
1209 turn_off_insert ();
1210 OUTPUT_IF (TS_delete_mode);
1213 if (TS_del_multi_chars)
1215 buf = tparam (TS_del_multi_chars, 0, 0, n);
1216 OUTPUT1 (buf);
1217 xfree (buf);
1219 else
1220 for (i = 0; i < n; i++)
1221 OUTPUT1 (TS_del_char);
1222 if (!delete_in_insert_mode)
1223 OUTPUT_IF (TS_end_delete_mode);
1226 /* Insert N lines at vpos VPOS. If N is negative, delete -N lines. */
1228 void
1229 ins_del_lines (vpos, n)
1230 int vpos, n;
1232 char *multi = n > 0 ? TS_ins_multi_lines : TS_del_multi_lines;
1233 char *single = n > 0 ? TS_ins_line : TS_del_line;
1234 char *scroll = n > 0 ? TS_rev_scroll : TS_fwd_scroll;
1235 struct frame *sf;
1237 register int i = n > 0 ? n : -n;
1238 register char *buf;
1240 if (ins_del_lines_hook && ! FRAME_TERMCAP_P (updating_frame))
1242 (*ins_del_lines_hook) (vpos, n);
1243 return;
1246 sf = XFRAME (selected_frame);
1248 /* If the lines below the insertion are being pushed
1249 into the end of the window, this is the same as clearing;
1250 and we know the lines are already clear, since the matching
1251 deletion has already been done. So can ignore this. */
1252 /* If the lines below the deletion are blank lines coming
1253 out of the end of the window, don't bother,
1254 as there will be a matching inslines later that will flush them. */
1255 if (scroll_region_ok && vpos + i >= specified_window)
1256 return;
1257 if (!memory_below_frame && vpos + i >= FRAME_HEIGHT (sf))
1258 return;
1260 if (multi)
1262 raw_cursor_to (vpos, 0);
1263 background_highlight ();
1264 buf = tparam (multi, 0, 0, i);
1265 OUTPUT (buf);
1266 xfree (buf);
1268 else if (single)
1270 raw_cursor_to (vpos, 0);
1271 background_highlight ();
1272 while (--i >= 0)
1273 OUTPUT (single);
1274 if (TF_teleray)
1275 curX = 0;
1277 else
1279 set_scroll_region (vpos, specified_window);
1280 if (n < 0)
1281 raw_cursor_to (specified_window - 1, 0);
1282 else
1283 raw_cursor_to (vpos, 0);
1284 background_highlight ();
1285 while (--i >= 0)
1286 OUTPUTL (scroll, specified_window - vpos);
1287 set_scroll_region (0, specified_window);
1290 if (TN_standout_width >= 0)
1292 register int lower_limit
1293 = (scroll_region_ok
1294 ? specified_window
1295 : FRAME_HEIGHT (sf));
1297 if (n < 0)
1299 bcopy (&chars_wasted[vpos - n], &chars_wasted[vpos],
1300 lower_limit - vpos + n);
1301 bzero (&chars_wasted[lower_limit + n], - n);
1303 else
1305 bcopy (&chars_wasted[vpos], &copybuf[vpos], lower_limit - vpos - n);
1306 bcopy (&copybuf[vpos], &chars_wasted[vpos + n],
1307 lower_limit - vpos - n);
1308 bzero (&chars_wasted[vpos], n);
1311 if (!scroll_region_ok && memory_below_frame && n < 0)
1313 cursor_to (FRAME_HEIGHT (sf) + n, 0);
1314 clear_to_end ();
1318 /* Compute cost of sending "str", in characters,
1319 not counting any line-dependent padding. */
1322 string_cost (str)
1323 char *str;
1325 cost = 0;
1326 if (str)
1327 tputs (str, 0, evalcost);
1328 return cost;
1331 /* Compute cost of sending "str", in characters,
1332 counting any line-dependent padding at one line. */
1334 static int
1335 string_cost_one_line (str)
1336 char *str;
1338 cost = 0;
1339 if (str)
1340 tputs (str, 1, evalcost);
1341 return cost;
1344 /* Compute per line amount of line-dependent padding,
1345 in tenths of characters. */
1348 per_line_cost (str)
1349 register char *str;
1351 cost = 0;
1352 if (str)
1353 tputs (str, 0, evalcost);
1354 cost = - cost;
1355 if (str)
1356 tputs (str, 10, evalcost);
1357 return cost;
1360 #ifndef old
1361 /* char_ins_del_cost[n] is cost of inserting N characters.
1362 char_ins_del_cost[-n] is cost of deleting N characters.
1363 The length of this vector is based on max_frame_width. */
1365 int *char_ins_del_vector;
1367 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WIDTH ((f))])
1368 #endif
1370 /* ARGSUSED */
1371 static void
1372 calculate_ins_del_char_costs (frame)
1373 FRAME_PTR frame;
1375 int ins_startup_cost, del_startup_cost;
1376 int ins_cost_per_char, del_cost_per_char;
1377 register int i;
1378 register int *p;
1380 if (TS_ins_multi_chars)
1382 ins_cost_per_char = 0;
1383 ins_startup_cost = string_cost_one_line (TS_ins_multi_chars);
1385 else if (TS_ins_char || TS_pad_inserted_char
1386 || (TS_insert_mode && TS_end_insert_mode))
1388 ins_startup_cost = (30 * (string_cost (TS_insert_mode)
1389 + string_cost (TS_end_insert_mode))) / 100;
1390 ins_cost_per_char = (string_cost_one_line (TS_ins_char)
1391 + string_cost_one_line (TS_pad_inserted_char));
1393 else
1395 ins_startup_cost = 9999;
1396 ins_cost_per_char = 0;
1399 if (TS_del_multi_chars)
1401 del_cost_per_char = 0;
1402 del_startup_cost = string_cost_one_line (TS_del_multi_chars);
1404 else if (TS_del_char)
1406 del_startup_cost = (string_cost (TS_delete_mode)
1407 + string_cost (TS_end_delete_mode));
1408 if (delete_in_insert_mode)
1409 del_startup_cost /= 2;
1410 del_cost_per_char = string_cost_one_line (TS_del_char);
1412 else
1414 del_startup_cost = 9999;
1415 del_cost_per_char = 0;
1418 /* Delete costs are at negative offsets */
1419 p = &char_ins_del_cost (frame)[0];
1420 for (i = FRAME_WIDTH (frame); --i >= 0;)
1421 *--p = (del_startup_cost += del_cost_per_char);
1423 /* Doing nothing is free */
1424 p = &char_ins_del_cost (frame)[0];
1425 *p++ = 0;
1427 /* Insert costs are at positive offsets */
1428 for (i = FRAME_WIDTH (frame); --i >= 0;)
1429 *p++ = (ins_startup_cost += ins_cost_per_char);
1432 void
1433 calculate_costs (frame)
1434 FRAME_PTR frame;
1436 register char *f = (TS_set_scroll_region
1437 ? TS_set_scroll_region
1438 : TS_set_scroll_region_1);
1440 FRAME_COST_BAUD_RATE (frame) = baud_rate;
1442 scroll_region_cost = string_cost (f);
1443 #ifdef HAVE_X_WINDOWS
1444 if (FRAME_X_P (frame))
1446 do_line_insertion_deletion_costs (frame, 0, ".5*", 0, ".5*",
1447 0, 0,
1448 x_screen_planes (frame));
1449 scroll_region_cost = 0;
1450 return;
1452 #endif
1454 /* These variables are only used for terminal stuff. They are allocated
1455 once for the terminal frame of X-windows emacs, but not used afterwards.
1457 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1458 X turns off char_ins_del_ok.
1460 chars_wasted and copybuf are only used here in term.c in cases where
1461 the term hook isn't called. */
1463 max_frame_height = max (max_frame_height, FRAME_HEIGHT (frame));
1464 max_frame_width = max (max_frame_width, FRAME_WIDTH (frame));
1466 if (chars_wasted != 0)
1467 chars_wasted = (char *) xrealloc (chars_wasted, max_frame_height);
1468 else
1469 chars_wasted = (char *) xmalloc (max_frame_height);
1471 if (copybuf != 0)
1472 copybuf = (char *) xrealloc (copybuf, max_frame_height);
1473 else
1474 copybuf = (char *) xmalloc (max_frame_height);
1476 if (char_ins_del_vector != 0)
1477 char_ins_del_vector
1478 = (int *) xrealloc (char_ins_del_vector,
1479 (sizeof (int)
1480 + 2 * max_frame_width * sizeof (int)));
1481 else
1482 char_ins_del_vector
1483 = (int *) xmalloc (sizeof (int)
1484 + 2 * max_frame_width * sizeof (int));
1486 bzero (chars_wasted, max_frame_height);
1487 bzero (copybuf, max_frame_height);
1488 bzero (char_ins_del_vector, (sizeof (int)
1489 + 2 * max_frame_width * sizeof (int)));
1491 if (f && (!TS_ins_line && !TS_del_line))
1492 do_line_insertion_deletion_costs (frame,
1493 TS_rev_scroll, TS_ins_multi_lines,
1494 TS_fwd_scroll, TS_del_multi_lines,
1495 f, f, 1);
1496 else
1497 do_line_insertion_deletion_costs (frame,
1498 TS_ins_line, TS_ins_multi_lines,
1499 TS_del_line, TS_del_multi_lines,
1500 0, 0, 1);
1502 calculate_ins_del_char_costs (frame);
1504 /* Don't use TS_repeat if its padding is worse than sending the chars */
1505 if (TS_repeat && per_line_cost (TS_repeat) * baud_rate < 9000)
1506 RPov = string_cost (TS_repeat);
1507 else
1508 RPov = FRAME_WIDTH (frame) * 2;
1510 cmcostinit (); /* set up cursor motion costs */
1513 struct fkey_table {
1514 char *cap, *name;
1517 /* Termcap capability names that correspond directly to X keysyms.
1518 Some of these (marked "terminfo") aren't supplied by old-style
1519 (Berkeley) termcap entries. They're listed in X keysym order;
1520 except we put the keypad keys first, so that if they clash with
1521 other keys (as on the IBM PC keyboard) they get overridden.
1524 static struct fkey_table keys[] =
1526 "kh", "home", /* termcap */
1527 "kl", "left", /* termcap */
1528 "ku", "up", /* termcap */
1529 "kr", "right", /* termcap */
1530 "kd", "down", /* termcap */
1531 "%8", "prior", /* terminfo */
1532 "%5", "next", /* terminfo */
1533 "@7", "end", /* terminfo */
1534 "@1", "begin", /* terminfo */
1535 "*6", "select", /* terminfo */
1536 "%9", "print", /* terminfo */
1537 "@4", "execute", /* terminfo --- actually the `command' key */
1539 * "insert" --- see below
1541 "&8", "undo", /* terminfo */
1542 "%0", "redo", /* terminfo */
1543 "%7", "menu", /* terminfo --- actually the `options' key */
1544 "@0", "find", /* terminfo */
1545 "@2", "cancel", /* terminfo */
1546 "%1", "help", /* terminfo */
1548 * "break" goes here, but can't be reliably intercepted with termcap
1550 "&4", "reset", /* terminfo --- actually `restart' */
1552 * "system" and "user" --- no termcaps
1554 "kE", "clearline", /* terminfo */
1555 "kA", "insertline", /* terminfo */
1556 "kL", "deleteline", /* terminfo */
1557 "kI", "insertchar", /* terminfo */
1558 "kD", "deletechar", /* terminfo */
1559 "kB", "backtab", /* terminfo */
1561 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1563 "@8", "kp-enter", /* terminfo */
1565 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1566 * "kp-multiply", "kp-add", "kp-separator",
1567 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1568 * --- no termcaps for any of these.
1570 "K4", "kp-1", /* terminfo */
1572 * "kp-2" --- no termcap
1574 "K5", "kp-3", /* terminfo */
1576 * "kp-4" --- no termcap
1578 "K2", "kp-5", /* terminfo */
1580 * "kp-6" --- no termcap
1582 "K1", "kp-7", /* terminfo */
1584 * "kp-8" --- no termcap
1586 "K3", "kp-9", /* terminfo */
1588 * "kp-equal" --- no termcap
1590 "k1", "f1",
1591 "k2", "f2",
1592 "k3", "f3",
1593 "k4", "f4",
1594 "k5", "f5",
1595 "k6", "f6",
1596 "k7", "f7",
1597 "k8", "f8",
1598 "k9", "f9",
1601 static char **term_get_fkeys_arg;
1602 static Lisp_Object term_get_fkeys_1 ();
1604 /* Find the escape codes sent by the function keys for Vfunction_key_map.
1605 This function scans the termcap function key sequence entries, and
1606 adds entries to Vfunction_key_map for each function key it finds. */
1608 void
1609 term_get_fkeys (address)
1610 char **address;
1612 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1613 errors during the call. The only errors should be from Fdefine_key
1614 when given a key sequence containing an invalid prefix key. If the
1615 termcap defines function keys which use a prefix that is already bound
1616 to a command by the default bindings, we should silently ignore that
1617 function key specification, rather than giving the user an error and
1618 refusing to run at all on such a terminal. */
1620 extern Lisp_Object Fidentity ();
1621 term_get_fkeys_arg = address;
1622 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1625 static Lisp_Object
1626 term_get_fkeys_1 ()
1628 int i;
1630 char **address = term_get_fkeys_arg;
1632 /* This can happen if CANNOT_DUMP or with strange options. */
1633 if (!initialized)
1634 Vfunction_key_map = Fmake_sparse_keymap (Qnil);
1636 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1638 char *sequence = tgetstr (keys[i].cap, address);
1639 if (sequence)
1640 Fdefine_key (Vfunction_key_map, build_string (sequence),
1641 Fmake_vector (make_number (1),
1642 intern (keys[i].name)));
1645 /* The uses of the "k0" capability are inconsistent; sometimes it
1646 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1647 We will attempt to politely accommodate both systems by testing for
1648 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1651 char *k_semi = tgetstr ("k;", address);
1652 char *k0 = tgetstr ("k0", address);
1653 char *k0_name = "f10";
1655 if (k_semi)
1657 Fdefine_key (Vfunction_key_map, build_string (k_semi),
1658 Fmake_vector (make_number (1), intern ("f10")));
1659 k0_name = "f0";
1662 if (k0)
1663 Fdefine_key (Vfunction_key_map, build_string (k0),
1664 Fmake_vector (make_number (1), intern (k0_name)));
1667 /* Set up cookies for numbered function keys above f10. */
1669 char fcap[3], fkey[4];
1671 fcap[0] = 'F'; fcap[2] = '\0';
1672 for (i = 11; i < 64; i++)
1674 if (i <= 19)
1675 fcap[1] = '1' + i - 11;
1676 else if (i <= 45)
1677 fcap[1] = 'A' + i - 20;
1678 else
1679 fcap[1] = 'a' + i - 46;
1682 char *sequence = tgetstr (fcap, address);
1683 if (sequence)
1685 sprintf (fkey, "f%d", i);
1686 Fdefine_key (Vfunction_key_map, build_string (sequence),
1687 Fmake_vector (make_number (1),
1688 intern (fkey)));
1695 * Various mappings to try and get a better fit.
1698 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1699 if (!tgetstr (cap1, address)) \
1701 char *sequence = tgetstr (cap2, address); \
1702 if (sequence) \
1703 Fdefine_key (Vfunction_key_map, build_string (sequence), \
1704 Fmake_vector (make_number (1), \
1705 intern (sym))); \
1708 /* if there's no key_next keycap, map key_npage to `next' keysym */
1709 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1710 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1711 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1712 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1713 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1714 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1715 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1717 /* IBM has their own non-standard dialect of terminfo.
1718 If the standard name isn't found, try the IBM name. */
1719 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1720 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1721 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1722 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1723 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1724 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1725 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1726 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1727 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1728 #undef CONDITIONAL_REASSIGN
1731 return Qnil;
1735 /***********************************************************************
1736 Character Display Information
1737 ***********************************************************************/
1739 static void append_glyph P_ ((struct it *));
1742 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1743 terminal frames if IT->glyph_row != NULL. IT->c is the character
1744 for which to produce glyphs; IT->face_id contains the character's
1745 face. Padding glyphs are appended if IT->c has a IT->pixel_width >
1746 1. */
1748 static void
1749 append_glyph (it)
1750 struct it *it;
1752 struct glyph *glyph, *end;
1753 int i;
1755 xassert (it->glyph_row);
1756 glyph = (it->glyph_row->glyphs[it->area]
1757 + it->glyph_row->used[it->area]);
1758 end = it->glyph_row->glyphs[1 + it->area];
1760 for (i = 0;
1761 i < it->pixel_width && glyph < end;
1762 ++i)
1764 glyph->type = CHAR_GLYPH;
1765 glyph->pixel_width = 1;
1766 glyph->u.ch = it->c;
1767 glyph->face_id = it->face_id;
1768 glyph->padding_p = i > 0;
1769 glyph->charpos = CHARPOS (it->position);
1770 glyph->object = it->object;
1772 ++it->glyph_row->used[it->area];
1773 ++glyph;
1778 /* Produce glyphs for the display element described by IT. The
1779 function fills output fields of IT with pixel information like the
1780 pixel width and height of a character, and maybe produces glyphs at
1781 the same time if IT->glyph_row is non-null. See the explanation of
1782 struct display_iterator in dispextern.h for an overview. */
1784 void
1785 produce_glyphs (it)
1786 struct it *it;
1788 /* If a hook is installed, let it do the work. */
1789 xassert (it->what == IT_CHARACTER
1790 || it->what == IT_COMPOSITION
1791 || it->what == IT_IMAGE
1792 || it->what == IT_STRETCH);
1794 /* Nothing but characters are supported on terminal frames. For a
1795 composition sequence, it->c is the first character of the
1796 sequence. */
1797 xassert (it->what == IT_CHARACTER
1798 || it->what == IT_COMPOSITION);
1800 if (it->c >= 040 && it->c < 0177)
1802 it->pixel_width = it->nglyphs = 1;
1803 if (it->glyph_row)
1804 append_glyph (it);
1806 else if (it->c == '\n')
1807 it->pixel_width = it->nglyphs = 0;
1808 else if (it->c == '\t')
1810 int absolute_x = (it->current_x - it->prompt_width
1811 + it->continuation_lines_width);
1812 int next_tab_x
1813 = (((1 + absolute_x + it->tab_width - 1)
1814 / it->tab_width)
1815 * it->tab_width);
1816 int nspaces;
1818 /* If part of the TAB has been displayed on the previous line
1819 which is continued now, continuation_lines_width will have
1820 been incremented already by the part that fitted on the
1821 continued line. So, we will get the right number of spaces
1822 here. */
1823 nspaces = next_tab_x - absolute_x;
1825 if (it->glyph_row)
1827 int n = nspaces;
1829 it->c = ' ';
1830 it->pixel_width = it->len = 1;
1832 while (n--)
1833 append_glyph (it);
1835 it->c = '\t';
1838 it->pixel_width = nspaces;
1839 it->nglyphs = nspaces;
1841 else
1843 /* A multi-byte character. The display width is fixed for all
1844 characters of the set. Some of the glyphs may have to be
1845 ignored because they are already displayed in a continued
1846 line. */
1847 int charset = CHAR_CHARSET (it->c);
1849 it->pixel_width = CHARSET_WIDTH (charset);
1850 it->nglyphs = it->pixel_width;
1852 if (it->glyph_row)
1853 append_glyph (it);
1856 /* Advance current_x by the pixel width as a convenience for
1857 the caller. */
1858 if (it->area == TEXT_AREA)
1859 it->current_x += it->pixel_width;
1860 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1861 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
1865 /* Get information about special display element WHAT in an
1866 environment described by IT. WHAT is one of IT_TRUNCATION or
1867 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1868 non-null glyph_row member. This function ensures that fields like
1869 face_id, c, len of IT are left untouched. */
1871 void
1872 produce_special_glyphs (it, what)
1873 struct it *it;
1874 enum display_element_type what;
1876 struct it temp_it;
1878 temp_it = *it;
1879 temp_it.dp = NULL;
1880 temp_it.what = IT_CHARACTER;
1881 temp_it.len = 1;
1882 temp_it.object = 0;
1883 bzero (&temp_it.current, sizeof temp_it.current);
1885 if (what == IT_CONTINUATION)
1887 /* Continuation glyph. */
1888 if (it->dp
1889 && INTEGERP (DISP_CONTINUE_GLYPH (it->dp))
1890 && GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (it->dp))))
1892 temp_it.c = FAST_GLYPH_CHAR (XINT (DISP_CONTINUE_GLYPH (it->dp)));
1893 temp_it.len = CHAR_LEN (temp_it.c);
1895 else
1896 temp_it.c = '\\';
1898 produce_glyphs (&temp_it);
1899 it->pixel_width = temp_it.pixel_width;
1900 it->nglyphs = temp_it.pixel_width;
1902 else if (what == IT_TRUNCATION)
1904 /* Truncation glyph. */
1905 if (it->dp
1906 && INTEGERP (DISP_TRUNC_GLYPH (it->dp))
1907 && GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (it->dp))))
1909 temp_it.c = FAST_GLYPH_CHAR (XINT (DISP_TRUNC_GLYPH (it->dp)));
1910 temp_it.len = CHAR_LEN (temp_it.c);
1912 else
1913 temp_it.c = '$';
1915 produce_glyphs (&temp_it);
1916 it->pixel_width = temp_it.pixel_width;
1917 it->nglyphs = temp_it.pixel_width;
1919 else
1920 abort ();
1924 /* Return an estimation of the pixel height of mode or top lines on
1925 frame F. FACE_ID specifies what line's height to estimate. */
1928 estimate_mode_line_height (f, face_id)
1929 struct frame *f;
1930 enum face_id face_id;
1932 if (estimate_mode_line_height_hook)
1933 return estimate_mode_line_height_hook (f, face_id);
1934 else
1935 return 1;
1940 /***********************************************************************
1941 Faces
1942 ***********************************************************************/
1945 /* Turn appearances of face FACE_ID on tty frame F on. */
1947 static void
1948 turn_on_face (f, face_id)
1949 struct frame *f;
1950 int face_id;
1952 struct face *face = FACE_FROM_ID (f, face_id);
1954 xassert (face != NULL);
1956 if (face->tty_bold_p)
1957 OUTPUT1_IF (TS_enter_bold_mode);
1958 else if (face->tty_dim_p)
1959 OUTPUT1_IF (TS_enter_dim_mode);
1961 /* Alternate charset and blinking not yet used. */
1962 if (face->tty_alt_charset_p)
1963 OUTPUT1_IF (TS_enter_alt_charset_mode);
1965 if (face->tty_blinking_p)
1966 OUTPUT1_IF (TS_enter_blink_mode);
1968 if (face->tty_underline_p
1969 /* Don't underline if that's difficult. */
1970 && TN_magic_cookie_glitch_ul <= 0)
1971 OUTPUT1_IF (TS_enter_underline_mode);
1973 if (face->tty_reverse_p
1974 || face->foreground == FACE_TTY_DEFAULT_BG_COLOR
1975 || face->background == FACE_TTY_DEFAULT_FG_COLOR)
1976 OUTPUT1_IF (TS_enter_reverse_mode);
1978 if (TN_max_colors > 0)
1980 char *p;
1982 if (face->foreground != FACE_TTY_DEFAULT_COLOR
1983 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR
1984 && face->foreground != FACE_TTY_DEFAULT_BG_COLOR
1985 && TS_set_foreground)
1987 p = tparam (TS_set_foreground, NULL, 0, (int) face->foreground);
1988 OUTPUT (p);
1989 xfree (p);
1992 if (face->background != FACE_TTY_DEFAULT_COLOR
1993 && face->background != FACE_TTY_DEFAULT_BG_COLOR
1994 && face->background != FACE_TTY_DEFAULT_FG_COLOR
1995 && TS_set_background)
1997 p = tparam (TS_set_background, NULL, 0, (int) face->background);
1998 OUTPUT (p);
1999 xfree (p);
2005 /* Turn off appearances of face FACE_ID on tty frame F. */
2007 static void
2008 turn_off_face (f, face_id)
2009 struct frame *f;
2010 int face_id;
2012 struct face *face = FACE_FROM_ID (f, face_id);
2014 xassert (face != NULL);
2016 if (TS_exit_attribute_mode)
2018 /* Capability "me" will turn off appearance modes double-bright,
2019 half-bright, reverse-video, standout, underline. It may or
2020 may not turn off alt-char-mode. */
2021 if (face->tty_bold_p
2022 || face->tty_dim_p
2023 || face->tty_reverse_p
2024 || face->tty_alt_charset_p
2025 || face->tty_blinking_p
2026 || face->tty_underline_p)
2027 OUTPUT1_IF (TS_exit_attribute_mode);
2029 if (face->tty_alt_charset_p)
2030 OUTPUT_IF (TS_exit_alt_charset_mode);
2032 else
2034 /* If we don't have "me" we can only have those appearances
2035 that have exit sequences defined. */
2036 if (face->tty_alt_charset_p)
2037 OUTPUT_IF (TS_exit_alt_charset_mode);
2039 if (face->tty_underline_p
2040 /* We don't underline if that's difficult. */
2041 && TN_magic_cookie_glitch_ul <= 0)
2042 OUTPUT_IF (TS_exit_underline_mode);
2045 /* Switch back to default colors. */
2046 if (TN_max_colors > 0
2047 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
2048 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
2049 || (face->background != FACE_TTY_DEFAULT_COLOR
2050 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
2051 OUTPUT1_IF (TS_orig_pair);
2055 /* Return non-zero if the terminal is capable to display colors. */
2057 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
2058 0, 1, 0,
2059 "Return non-nil if TTY can display colors on FRAME.")
2060 (frame)
2061 Lisp_Object frame;
2063 return TN_max_colors > 0 ? Qt : Qnil;
2069 /***********************************************************************
2070 Initialization
2071 ***********************************************************************/
2073 void
2074 term_init (terminal_type)
2075 char *terminal_type;
2077 char *area;
2078 char **address = &area;
2079 char buffer[2044];
2080 register char *p;
2081 int status;
2082 struct frame *sf = XFRAME (selected_frame);
2084 #ifdef WINDOWSNT
2085 initialize_w32_display ();
2087 Wcm_clear ();
2089 area = (char *) xmalloc (2044);
2091 if (area == 0)
2092 abort ();
2094 FrameRows = FRAME_HEIGHT (sf);
2095 FrameCols = FRAME_WIDTH (sf);
2096 specified_window = FRAME_HEIGHT (sf);
2098 delete_in_insert_mode = 1;
2100 UseTabs = 0;
2101 scroll_region_ok = 0;
2103 /* Seems to insert lines when it's not supposed to, messing
2104 up the display. In doing a trace, it didn't seem to be
2105 called much, so I don't think we're losing anything by
2106 turning it off. */
2108 line_ins_del_ok = 0;
2109 char_ins_del_ok = 1;
2111 baud_rate = 19200;
2113 FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0;
2114 FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none;
2116 return;
2117 #else /* not WINDOWSNT */
2119 Wcm_clear ();
2121 status = tgetent (buffer, terminal_type);
2122 if (status < 0)
2124 #ifdef TERMINFO
2125 fatal ("Cannot open terminfo database file");
2126 #else
2127 fatal ("Cannot open termcap database file");
2128 #endif
2130 if (status == 0)
2132 #ifdef TERMINFO
2133 fatal ("Terminal type %s is not defined.\n\
2134 If that is not the actual type of terminal you have,\n\
2135 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2136 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2137 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
2138 terminal_type);
2139 #else
2140 fatal ("Terminal type %s is not defined.\n\
2141 If that is not the actual type of terminal you have,\n\
2142 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2143 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2144 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
2145 terminal_type);
2146 #endif
2148 #ifdef TERMINFO
2149 area = (char *) xmalloc (2044);
2150 #else
2151 area = (char *) xmalloc (strlen (buffer));
2152 #endif /* not TERMINFO */
2153 if (area == 0)
2154 abort ();
2156 TS_ins_line = tgetstr ("al", address);
2157 TS_ins_multi_lines = tgetstr ("AL", address);
2158 TS_bell = tgetstr ("bl", address);
2159 BackTab = tgetstr ("bt", address);
2160 TS_clr_to_bottom = tgetstr ("cd", address);
2161 TS_clr_line = tgetstr ("ce", address);
2162 TS_clr_frame = tgetstr ("cl", address);
2163 ColPosition = tgetstr ("ch", address);
2164 AbsPosition = tgetstr ("cm", address);
2165 CR = tgetstr ("cr", address);
2166 TS_set_scroll_region = tgetstr ("cs", address);
2167 TS_set_scroll_region_1 = tgetstr ("cS", address);
2168 RowPosition = tgetstr ("cv", address);
2169 TS_del_char = tgetstr ("dc", address);
2170 TS_del_multi_chars = tgetstr ("DC", address);
2171 TS_del_line = tgetstr ("dl", address);
2172 TS_del_multi_lines = tgetstr ("DL", address);
2173 TS_delete_mode = tgetstr ("dm", address);
2174 TS_end_delete_mode = tgetstr ("ed", address);
2175 TS_end_insert_mode = tgetstr ("ei", address);
2176 Home = tgetstr ("ho", address);
2177 TS_ins_char = tgetstr ("ic", address);
2178 TS_ins_multi_chars = tgetstr ("IC", address);
2179 TS_insert_mode = tgetstr ("im", address);
2180 TS_pad_inserted_char = tgetstr ("ip", address);
2181 TS_end_keypad_mode = tgetstr ("ke", address);
2182 TS_keypad_mode = tgetstr ("ks", address);
2183 LastLine = tgetstr ("ll", address);
2184 Right = tgetstr ("nd", address);
2185 Down = tgetstr ("do", address);
2186 if (!Down)
2187 Down = tgetstr ("nl", address); /* Obsolete name for "do" */
2188 #ifdef VMS
2189 /* VMS puts a carriage return before each linefeed,
2190 so it is not safe to use linefeeds. */
2191 if (Down && Down[0] == '\n' && Down[1] == '\0')
2192 Down = 0;
2193 #endif /* VMS */
2194 if (tgetflag ("bs"))
2195 Left = "\b"; /* can't possibly be longer! */
2196 else /* (Actually, "bs" is obsolete...) */
2197 Left = tgetstr ("le", address);
2198 if (!Left)
2199 Left = tgetstr ("bc", address); /* Obsolete name for "le" */
2200 TS_pad_char = tgetstr ("pc", address);
2201 TS_repeat = tgetstr ("rp", address);
2202 TS_end_standout_mode = tgetstr ("se", address);
2203 TS_fwd_scroll = tgetstr ("sf", address);
2204 TS_standout_mode = tgetstr ("so", address);
2205 TS_rev_scroll = tgetstr ("sr", address);
2206 Wcm.cm_tab = tgetstr ("ta", address);
2207 TS_end_termcap_modes = tgetstr ("te", address);
2208 TS_termcap_modes = tgetstr ("ti", address);
2209 Up = tgetstr ("up", address);
2210 TS_visible_bell = tgetstr ("vb", address);
2211 TS_cursor_normal = tgetstr ("ve", address);
2212 TS_cursor_visible = tgetstr ("vs", address);
2213 TS_cursor_invisible = tgetstr ("vi", address);
2214 TS_set_window = tgetstr ("wi", address);
2216 TS_enter_underline_mode = tgetstr ("us", address);
2217 TS_exit_underline_mode = tgetstr ("ue", address);
2218 TN_magic_cookie_glitch_ul = tgetnum ("ug");
2219 TS_enter_bold_mode = tgetstr ("md", address);
2220 TS_enter_dim_mode = tgetstr ("mh", address);
2221 TS_enter_blink_mode = tgetstr ("mb", address);
2222 TS_enter_reverse_mode = tgetstr ("mr", address);
2223 TS_enter_alt_charset_mode = tgetstr ("as", address);
2224 TS_exit_alt_charset_mode = tgetstr ("ae", address);
2225 TS_exit_attribute_mode = tgetstr ("me", address);
2227 MultiUp = tgetstr ("UP", address);
2228 MultiDown = tgetstr ("DO", address);
2229 MultiLeft = tgetstr ("LE", address);
2230 MultiRight = tgetstr ("RI", address);
2232 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
2233 color because we can't switch back to the default foreground and
2234 background. */
2235 TS_orig_pair = tgetstr ("op", address);
2236 if (TS_orig_pair)
2238 TS_set_foreground = tgetstr ("AF", address);
2239 TS_set_background = tgetstr ("AB", address);
2240 if (!TS_set_foreground)
2242 /* SVr4. */
2243 TS_set_foreground = tgetstr ("Sf", address);
2244 TS_set_background = tgetstr ("Sb", address);
2246 TN_max_colors = tgetnum ("Co");
2247 TN_max_pairs = tgetnum ("pa");
2250 MagicWrap = tgetflag ("xn");
2251 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
2252 the former flag imply the latter. */
2253 AutoWrap = MagicWrap || tgetflag ("am");
2254 memory_below_frame = tgetflag ("db");
2255 TF_hazeltine = tgetflag ("hz");
2256 must_write_spaces = tgetflag ("in");
2257 meta_key = tgetflag ("km") || tgetflag ("MT");
2258 TF_insmode_motion = tgetflag ("mi");
2259 TF_standout_motion = tgetflag ("ms");
2260 TF_underscore = tgetflag ("ul");
2261 TF_xs = tgetflag ("xs");
2262 TF_teleray = tgetflag ("xt");
2264 term_get_fkeys (address);
2266 /* Get frame size from system, or else from termcap. */
2268 int height, width;
2269 get_frame_size (&width, &height);
2270 FRAME_WIDTH (sf) = width;
2271 FRAME_HEIGHT (sf) = height;
2274 if (FRAME_WIDTH (sf) <= 0)
2275 SET_FRAME_WIDTH (sf, tgetnum ("co"));
2276 else
2277 /* Keep width and external_width consistent */
2278 SET_FRAME_WIDTH (sf, FRAME_WIDTH (sf));
2279 if (FRAME_HEIGHT (sf) <= 0)
2280 FRAME_HEIGHT (sf) = tgetnum ("li");
2282 if (FRAME_HEIGHT (sf) < 3 || FRAME_WIDTH (sf) < 3)
2283 fatal ("Screen size %dx%d is too small",
2284 FRAME_HEIGHT (sf), FRAME_WIDTH (sf));
2286 min_padding_speed = tgetnum ("pb");
2287 TN_standout_width = tgetnum ("sg");
2288 TabWidth = tgetnum ("tw");
2290 #ifdef VMS
2291 /* These capabilities commonly use ^J.
2292 I don't know why, but sending them on VMS does not work;
2293 it causes following spaces to be lost, sometimes.
2294 For now, the simplest fix is to avoid using these capabilities ever. */
2295 if (Down && Down[0] == '\n')
2296 Down = 0;
2297 #endif /* VMS */
2299 if (!TS_bell)
2300 TS_bell = "\07";
2302 if (!TS_fwd_scroll)
2303 TS_fwd_scroll = Down;
2305 PC = TS_pad_char ? *TS_pad_char : 0;
2307 if (TabWidth < 0)
2308 TabWidth = 8;
2310 /* Turned off since /etc/termcap seems to have :ta= for most terminals
2311 and newer termcap doc does not seem to say there is a default.
2312 if (!Wcm.cm_tab)
2313 Wcm.cm_tab = "\t";
2316 if (TS_standout_mode == 0)
2318 TN_standout_width = tgetnum ("ug");
2319 TS_end_standout_mode = tgetstr ("ue", address);
2320 TS_standout_mode = tgetstr ("us", address);
2323 /* If no `se' string, try using a `me' string instead.
2324 If that fails, we can't use standout mode at all. */
2325 if (TS_end_standout_mode == 0)
2327 char *s = tgetstr ("me", address);
2328 if (s != 0)
2329 TS_end_standout_mode = s;
2330 else
2331 TS_standout_mode = 0;
2334 if (TF_teleray)
2336 Wcm.cm_tab = 0;
2337 /* Teleray: most programs want a space in front of TS_standout_mode,
2338 but Emacs can do without it (and give one extra column). */
2339 TS_standout_mode = "\033RD";
2340 TN_standout_width = 1;
2341 /* But that means we cannot rely on ^M to go to column zero! */
2342 CR = 0;
2343 /* LF can't be trusted either -- can alter hpos */
2344 /* if move at column 0 thru a line with TS_standout_mode */
2345 Down = 0;
2348 /* Special handling for certain terminal types known to need it */
2350 if (!strcmp (terminal_type, "supdup"))
2352 memory_below_frame = 1;
2353 Wcm.cm_losewrap = 1;
2355 if (!strncmp (terminal_type, "c10", 3)
2356 || !strcmp (terminal_type, "perq"))
2358 /* Supply a makeshift :wi string.
2359 This string is not valid in general since it works only
2360 for windows starting at the upper left corner;
2361 but that is all Emacs uses.
2363 This string works only if the frame is using
2364 the top of the video memory, because addressing is memory-relative.
2365 So first check the :ti string to see if that is true.
2367 It would be simpler if the :wi string could go in the termcap
2368 entry, but it can't because it is not fully valid.
2369 If it were in the termcap entry, it would confuse other programs. */
2370 if (!TS_set_window)
2372 p = TS_termcap_modes;
2373 while (*p && strcmp (p, "\033v "))
2374 p++;
2375 if (*p)
2376 TS_set_window = "\033v%C %C %C %C ";
2378 /* Termcap entry often fails to have :in: flag */
2379 must_write_spaces = 1;
2380 /* :ti string typically fails to have \E^G! in it */
2381 /* This limits scope of insert-char to one line. */
2382 strcpy (area, TS_termcap_modes);
2383 strcat (area, "\033\007!");
2384 TS_termcap_modes = area;
2385 area += strlen (area) + 1;
2386 p = AbsPosition;
2387 /* Change all %+ parameters to %C, to handle
2388 values above 96 correctly for the C100. */
2389 while (*p)
2391 if (p[0] == '%' && p[1] == '+')
2392 p[1] = 'C';
2393 p++;
2397 FrameRows = FRAME_HEIGHT (sf);
2398 FrameCols = FRAME_WIDTH (sf);
2399 specified_window = FRAME_HEIGHT (sf);
2401 if (Wcm_init () == -1) /* can't do cursor motion */
2402 #ifdef VMS
2403 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2404 It lacks the ability to position the cursor.\n\
2405 If that is not the actual type of terminal you have, use either the\n\
2406 DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
2407 or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
2408 terminal_type);
2409 #else /* not VMS */
2410 # ifdef TERMINFO
2411 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2412 It lacks the ability to position the cursor.\n\
2413 If that is not the actual type of terminal you have,\n\
2414 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2415 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2416 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
2417 terminal_type);
2418 # else /* TERMCAP */
2419 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2420 It lacks the ability to position the cursor.\n\
2421 If that is not the actual type of terminal you have,\n\
2422 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2423 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2424 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
2425 terminal_type);
2426 # endif /* TERMINFO */
2427 #endif /*VMS */
2428 if (FRAME_HEIGHT (sf) <= 0
2429 || FRAME_WIDTH (sf) <= 0)
2430 fatal ("The frame size has not been specified");
2432 delete_in_insert_mode
2433 = TS_delete_mode && TS_insert_mode
2434 && !strcmp (TS_delete_mode, TS_insert_mode);
2436 se_is_so = (TS_standout_mode
2437 && TS_end_standout_mode
2438 && !strcmp (TS_standout_mode, TS_end_standout_mode));
2440 /* Remove width of standout marker from usable width of line */
2441 if (TN_standout_width > 0)
2442 SET_FRAME_WIDTH (sf, FRAME_WIDTH (sf) - TN_standout_width);
2444 UseTabs = tabs_safe_p () && TabWidth == 8;
2446 scroll_region_ok
2447 = (Wcm.cm_abs
2448 && (TS_set_window || TS_set_scroll_region || TS_set_scroll_region_1));
2450 line_ins_del_ok = (((TS_ins_line || TS_ins_multi_lines)
2451 && (TS_del_line || TS_del_multi_lines))
2452 || (scroll_region_ok && TS_fwd_scroll && TS_rev_scroll));
2454 char_ins_del_ok = ((TS_ins_char || TS_insert_mode
2455 || TS_pad_inserted_char || TS_ins_multi_chars)
2456 && (TS_del_char || TS_del_multi_chars));
2458 fast_clear_end_of_line = TS_clr_line != 0;
2460 init_baud_rate ();
2461 if (read_socket_hook) /* Baudrate is somewhat */
2462 /* meaningless in this case */
2463 baud_rate = 9600;
2465 FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0;
2466 FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none;
2467 #endif /* WINDOWSNT */
2470 /* VARARGS 1 */
2471 void
2472 fatal (str, arg1, arg2)
2473 char *str, *arg1, *arg2;
2475 fprintf (stderr, "emacs: ");
2476 fprintf (stderr, str, arg1, arg2);
2477 fprintf (stderr, "\n");
2478 fflush (stderr);
2479 exit (1);
2482 void
2483 syms_of_term ()
2485 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
2486 "Non-nil means the system uses terminfo rather than termcap.\n\
2487 This variable can be used by terminal emulator packages.");
2488 #ifdef TERMINFO
2489 system_uses_terminfo = 1;
2490 #else
2491 system_uses_terminfo = 0;
2492 #endif
2494 DEFVAR_LISP ("ring-bell-function", &Vring_bell_function,
2495 "Non-nil means call this function to ring the bell.\n\
2496 The function should accept no arguments.");
2497 Vring_bell_function = Qnil;
2499 defsubr (&Stty_display_color_p);