* dired.el: (dired-mode): Set font-lock-defaults.
[emacs.git] / src / term.c
blob5b1d8118cae9773d969fb9ad3c29a892183962ac
1 /* terminal control module for terminals described by TERMCAP
2 Copyright (C) 1985, 1986, 1987, 1993, 1994 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21 #include <config.h>
22 #include <stdio.h>
23 #include <ctype.h>
24 #include "termchar.h"
25 #include "termopts.h"
26 #include "cm.h"
27 #undef NULL
28 #include "lisp.h"
29 #include "frame.h"
30 #include "disptab.h"
31 #include "termhooks.h"
32 #include "keyboard.h"
34 extern Lisp_Object Fmake_sparse_keymap ();
36 #define max(a, b) ((a) > (b) ? (a) : (b))
37 #define min(a, b) ((a) < (b) ? (a) : (b))
39 #define OUTPUT(a) tputs (a, FRAME_HEIGHT (selected_frame) - curY, cmputc)
40 #define OUTPUT1(a) tputs (a, 1, cmputc)
41 #define OUTPUTL(a, lines) tputs (a, lines, cmputc)
42 #define OUTPUT_IF(a) { if (a) tputs (a, FRAME_HEIGHT (selected_frame) - curY, cmputc); }
43 #define OUTPUT1_IF(a) { if (a) tputs (a, 1, cmputc); }
45 /* Terminal characteristics that higher levels want to look at.
46 These are all extern'd in termchar.h */
48 int must_write_spaces; /* Nonzero means spaces in the text
49 must actually be output; can't just skip
50 over some columns to leave them blank. */
51 int min_padding_speed; /* Speed below which no padding necessary */
53 int line_ins_del_ok; /* Terminal can insert and delete lines */
54 int char_ins_del_ok; /* Terminal can insert and delete chars */
55 int scroll_region_ok; /* Terminal supports setting the
56 scroll window */
57 int memory_below_frame; /* Terminal remembers lines
58 scrolled off bottom */
59 int fast_clear_end_of_line; /* Terminal has a `ce' string */
61 int dont_calculate_costs; /* Nonzero means don't bother computing */
62 /* various cost tables; we won't use them. */
64 /* Nonzero means no need to redraw the entire frame on resuming
65 a suspended Emacs. This is useful on terminals with multiple pages,
66 where one page is used for Emacs and another for all else. */
67 int no_redraw_on_reenter;
69 /* Hook functions that you can set to snap out the functions in this file.
70 These are all extern'd in termhooks.h */
72 int (*cursor_to_hook) ();
73 int (*raw_cursor_to_hook) ();
75 int (*clear_to_end_hook) ();
76 int (*clear_frame_hook) ();
77 int (*clear_end_of_line_hook) ();
79 int (*ins_del_lines_hook) ();
81 int (*change_line_highlight_hook) ();
82 int (*reassert_line_highlight_hook) ();
84 int (*insert_glyphs_hook) ();
85 int (*write_glyphs_hook) ();
86 int (*delete_glyphs_hook) ();
88 int (*ring_bell_hook) ();
90 int (*reset_terminal_modes_hook) ();
91 int (*set_terminal_modes_hook) ();
92 int (*update_begin_hook) ();
93 int (*update_end_hook) ();
94 int (*set_terminal_window_hook) ();
96 int (*read_socket_hook) ();
98 int (*frame_up_to_date_hook) ();
100 /* Return the current position of the mouse.
102 Set *f to the frame the mouse is in, or zero if the mouse is in no
103 Emacs frame. If it is set to zero, all the other arguments are
104 garbage.
106 If the motion started in a scroll bar, set *bar_window to the
107 scroll bar's window, *part to the part the mouse is currently over,
108 *x to the position of the mouse along the scroll bar, and *y to the
109 overall length of the scroll bar.
111 Otherwise, set *bar_window to Qnil, and *x and *y to the column and
112 row of the character cell the mouse is over.
114 Set *time to the time the mouse was at the returned position.
116 This should clear mouse_moved until the next motion
117 event arrives. */
118 void (*mouse_position_hook) ( /* FRAME_PTR *f,
119 Lisp_Object *bar_window,
120 enum scroll_bar_part *part,
121 Lisp_Object *x,
122 Lisp_Object *y,
123 unsigned long *time */ );
125 /* When reading from a minibuffer in a different frame, Emacs wants
126 to shift the highlight from the selected frame to the minibuffer's
127 frame; under X, this means it lies about where the focus is.
128 This hook tells the window system code to re-decide where to put
129 the highlight. */
130 void (*frame_rehighlight_hook) ( /* FRAME_PTR f */ );
132 /* If we're displaying frames using a window system that can stack
133 frames on top of each other, this hook allows you to bring a frame
134 to the front, or bury it behind all the other windows. If this
135 hook is zero, that means the device we're displaying on doesn't
136 support overlapping frames, so there's no need to raise or lower
137 anything.
139 If RAISE is non-zero, F is brought to the front, before all other
140 windows. If RAISE is zero, F is sent to the back, behind all other
141 windows. */
142 void (*frame_raise_lower_hook) ( /* FRAME_PTR f, int raise */ );
144 /* Set the vertical scroll bar for WINDOW to have its upper left corner
145 at (TOP, LEFT), and be LENGTH rows high. Set its handle to
146 indicate that we are displaying PORTION characters out of a total
147 of WHOLE characters, starting at POSITION. If WINDOW doesn't yet
148 have a scroll bar, create one for it. */
149 void (*set_vertical_scroll_bar_hook)
150 ( /* struct window *window,
151 int portion, int whole, int position */ );
154 /* The following three hooks are used when we're doing a thorough
155 redisplay of the frame. We don't explicitly know which scroll bars
156 are going to be deleted, because keeping track of when windows go
157 away is a real pain - can you say set-window-configuration?
158 Instead, we just assert at the beginning of redisplay that *all*
159 scroll bars are to be removed, and then save scroll bars from the
160 firey pit when we actually redisplay their window. */
162 /* Arrange for all scroll bars on FRAME to be removed at the next call
163 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
164 `*redeem_scroll_bar_hook' is applied to its window before the judgement.
166 This should be applied to each frame each time its window tree is
167 redisplayed, even if it is not displaying scroll bars at the moment;
168 if the HAS_SCROLL_BARS flag has just been turned off, only calling
169 this and the judge_scroll_bars_hook will get rid of them.
171 If non-zero, this hook should be safe to apply to any frame,
172 whether or not it can support scroll bars, and whether or not it is
173 currently displaying them. */
174 void (*condemn_scroll_bars_hook)( /* FRAME_PTR *frame */ );
176 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
177 Note that it's okay to redeem a scroll bar that is not condemned. */
178 void (*redeem_scroll_bar_hook)( /* struct window *window */ );
180 /* Remove all scroll bars on FRAME that haven't been saved since the
181 last call to `*condemn_scroll_bars_hook'.
183 This should be applied to each frame after each time its window
184 tree is redisplayed, even if it is not displaying scroll bars at the
185 moment; if the HAS_SCROLL_BARS flag has just been turned off, only
186 calling this and condemn_scroll_bars_hook will get rid of them.
188 If non-zero, this hook should be safe to apply to any frame,
189 whether or not it can support scroll bars, and whether or not it is
190 currently displaying them. */
191 void (*judge_scroll_bars_hook)( /* FRAME_PTR *FRAME */ );
194 /* Strings, numbers and flags taken from the termcap entry. */
196 char *TS_ins_line; /* termcap "al" */
197 char *TS_ins_multi_lines; /* "AL" (one parameter, # lines to insert) */
198 char *TS_bell; /* "bl" */
199 char *TS_clr_to_bottom; /* "cd" */
200 char *TS_clr_line; /* "ce", clear to end of line */
201 char *TS_clr_frame; /* "cl" */
202 char *TS_set_scroll_region; /* "cs" (2 params, first line and last line) */
203 char *TS_set_scroll_region_1; /* "cS" (4 params: total lines,
204 lines above scroll region, lines below it,
205 total lines again) */
206 char *TS_del_char; /* "dc" */
207 char *TS_del_multi_chars; /* "DC" (one parameter, # chars to delete) */
208 char *TS_del_line; /* "dl" */
209 char *TS_del_multi_lines; /* "DL" (one parameter, # lines to delete) */
210 char *TS_delete_mode; /* "dm", enter character-delete mode */
211 char *TS_end_delete_mode; /* "ed", leave character-delete mode */
212 char *TS_end_insert_mode; /* "ei", leave character-insert mode */
213 char *TS_ins_char; /* "ic" */
214 char *TS_ins_multi_chars; /* "IC" (one parameter, # chars to insert) */
215 char *TS_insert_mode; /* "im", enter character-insert mode */
216 char *TS_pad_inserted_char; /* "ip". Just padding, no commands. */
217 char *TS_end_keypad_mode; /* "ke" */
218 char *TS_keypad_mode; /* "ks" */
219 char *TS_pad_char; /* "pc", char to use as padding */
220 char *TS_repeat; /* "rp" (2 params, # times to repeat
221 and character to be repeated) */
222 char *TS_end_standout_mode; /* "se" */
223 char *TS_fwd_scroll; /* "sf" */
224 char *TS_standout_mode; /* "so" */
225 char *TS_rev_scroll; /* "sr" */
226 char *TS_end_termcap_modes; /* "te" */
227 char *TS_termcap_modes; /* "ti" */
228 char *TS_visible_bell; /* "vb" */
229 char *TS_end_visual_mode; /* "ve" */
230 char *TS_visual_mode; /* "vi" */
231 char *TS_set_window; /* "wi" (4 params, start and end of window,
232 each as vpos and hpos) */
234 int TF_hazeltine; /* termcap hz flag. */
235 int TF_insmode_motion; /* termcap mi flag: can move while in insert mode. */
236 int TF_standout_motion; /* termcap mi flag: can move while in standout mode. */
237 int TF_underscore; /* termcap ul flag: _ underlines if overstruck on
238 nonblank position. Must clear before writing _. */
239 int TF_teleray; /* termcap xt flag: many weird consequences.
240 For t1061. */
242 int TF_xs; /* Nonzero for "xs". If set together with
243 TN_standout_width == 0, it means don't bother
244 to write any end-standout cookies. */
246 int TN_standout_width; /* termcap sg number: width occupied by standout
247 markers */
249 static int RPov; /* # chars to start a TS_repeat */
251 static int delete_in_insert_mode; /* delete mode == insert mode */
253 static int se_is_so; /* 1 if same string both enters and leaves
254 standout mode */
256 /* internal state */
258 /* Number of chars of space used for standout marker at beginning of line,
259 or'd with 0100. Zero if no standout marker at all.
261 Used IFF TN_standout_width >= 0. */
263 static char *chars_wasted;
264 static char *copybuf;
266 /* nonzero means supposed to write text in standout mode. */
267 int standout_requested;
269 int insert_mode; /* Nonzero when in insert mode. */
270 int standout_mode; /* Nonzero when in standout mode. */
272 /* Size of window specified by higher levels.
273 This is the number of lines, from the top of frame downwards,
274 which can participate in insert-line/delete-line operations.
276 Effectively it excludes the bottom frame_height - specified_window_size
277 lines from those operations. */
279 int specified_window;
281 /* Frame currently being redisplayed; 0 if not currently redisplaying.
282 (Direct output does not count). */
284 FRAME_PTR updating_frame;
286 /* Provided for lisp packages. */
287 static int system_uses_terminfo;
289 char *tparam ();
291 extern char *tgetstr ();
293 ring_bell ()
295 if (! FRAME_TERMCAP_P (selected_frame))
297 (*ring_bell_hook) ();
298 return;
300 OUTPUT (TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell);
303 set_terminal_modes ()
305 if (! FRAME_TERMCAP_P (selected_frame))
307 (*set_terminal_modes_hook) ();
308 return;
310 OUTPUT_IF (TS_termcap_modes);
311 OUTPUT_IF (TS_visual_mode);
312 OUTPUT_IF (TS_keypad_mode);
313 losecursor ();
316 reset_terminal_modes ()
318 if (! FRAME_TERMCAP_P (selected_frame))
320 (*reset_terminal_modes_hook) ();
321 return;
323 if (TN_standout_width < 0)
324 turn_off_highlight ();
325 turn_off_insert ();
326 OUTPUT_IF (TS_end_keypad_mode);
327 OUTPUT_IF (TS_end_visual_mode);
328 OUTPUT_IF (TS_end_termcap_modes);
329 /* Output raw CR so kernel can track the cursor hpos. */
330 /* But on magic-cookie terminals this can erase an end-standout marker and
331 cause the rest of the frame to be in standout, so move down first. */
332 if (TN_standout_width >= 0)
333 cmputc ('\n');
334 cmputc ('\r');
337 update_begin (f)
338 FRAME_PTR f;
340 updating_frame = f;
341 if (! FRAME_TERMCAP_P (updating_frame))
342 (*update_begin_hook) (f);
345 update_end (f)
346 FRAME_PTR f;
348 if (! FRAME_TERMCAP_P (updating_frame))
350 (*update_end_hook) (f);
351 updating_frame = 0;
352 return;
354 turn_off_insert ();
355 background_highlight ();
356 standout_requested = 0;
357 updating_frame = 0;
360 set_terminal_window (size)
361 int size;
363 if (! FRAME_TERMCAP_P (updating_frame))
365 (*set_terminal_window_hook) (size);
366 return;
368 specified_window = size ? size : FRAME_HEIGHT (selected_frame);
369 if (!scroll_region_ok)
370 return;
371 set_scroll_region (0, specified_window);
374 set_scroll_region (start, stop)
375 int start, stop;
377 char *buf;
378 if (TS_set_scroll_region)
380 buf = tparam (TS_set_scroll_region, 0, 0, start, stop - 1);
382 else if (TS_set_scroll_region_1)
384 buf = tparam (TS_set_scroll_region_1, 0, 0,
385 FRAME_HEIGHT (selected_frame), start,
386 FRAME_HEIGHT (selected_frame) - stop,
387 FRAME_HEIGHT (selected_frame));
389 else
391 buf = tparam (TS_set_window, 0, 0, start, 0, stop, FRAME_WIDTH (selected_frame));
393 OUTPUT (buf);
394 xfree (buf);
395 losecursor ();
398 turn_on_insert ()
400 if (!insert_mode)
401 OUTPUT (TS_insert_mode);
402 insert_mode = 1;
405 turn_off_insert ()
407 if (insert_mode)
408 OUTPUT (TS_end_insert_mode);
409 insert_mode = 0;
412 /* Handle highlighting when TN_standout_width (termcap sg) is not specified.
413 In these terminals, output is affected by the value of standout
414 mode when the output is written.
416 These functions are called on all terminals, but do nothing
417 on terminals whose standout mode does not work that way. */
419 turn_off_highlight ()
421 if (TN_standout_width < 0)
423 if (standout_mode)
424 OUTPUT_IF (TS_end_standout_mode);
425 standout_mode = 0;
429 turn_on_highlight ()
431 if (TN_standout_width < 0)
433 if (!standout_mode)
434 OUTPUT_IF (TS_standout_mode);
435 standout_mode = 1;
439 /* Set standout mode to the state it should be in for
440 empty space inside windows. What this is,
441 depends on the user option inverse-video. */
443 background_highlight ()
445 if (TN_standout_width >= 0)
446 return;
447 if (inverse_video)
448 turn_on_highlight ();
449 else
450 turn_off_highlight ();
453 /* Set standout mode to the mode specified for the text to be output. */
455 static
456 highlight_if_desired ()
458 if (TN_standout_width >= 0)
459 return;
460 if (!inverse_video == !standout_requested)
461 turn_off_highlight ();
462 else
463 turn_on_highlight ();
466 /* Handle standout mode for terminals in which TN_standout_width >= 0.
467 On these terminals, standout is controlled by markers that
468 live inside the terminal's memory. TN_standout_width is the width
469 that the marker occupies in memory. Standout runs from the marker
470 to the end of the line on some terminals, or to the next
471 turn-off-standout marker (TS_end_standout_mode) string
472 on other terminals. */
474 /* Write a standout marker or end-standout marker at the front of the line
475 at vertical position vpos. */
477 write_standout_marker (flag, vpos)
478 int flag, vpos;
480 if (flag || (TS_end_standout_mode && !TF_teleray && !se_is_so
481 && !(TF_xs && TN_standout_width == 0)))
483 cmgoto (vpos, 0);
484 cmplus (TN_standout_width);
485 OUTPUT (flag ? TS_standout_mode : TS_end_standout_mode);
486 chars_wasted[curY] = TN_standout_width | 0100;
490 /* External interface to control of standout mode.
491 Call this when about to modify line at position VPOS
492 and not change whether it is highlighted. */
494 reassert_line_highlight (highlight, vpos)
495 int highlight;
496 int vpos;
498 if (! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
500 (*reassert_line_highlight_hook) (highlight, vpos);
501 return;
503 if (TN_standout_width < 0)
504 /* Handle terminals where standout takes affect at output time */
505 standout_requested = highlight;
506 else if (chars_wasted[vpos] == 0)
507 /* For terminals with standout markers, write one on this line
508 if there isn't one already. */
509 write_standout_marker (highlight, vpos);
512 /* Call this when about to modify line at position VPOS
513 and change whether it is highlighted. */
515 change_line_highlight (new_highlight, vpos, first_unused_hpos)
516 int new_highlight, vpos, first_unused_hpos;
518 standout_requested = new_highlight;
519 if (! FRAME_TERMCAP_P (updating_frame))
521 (*change_line_highlight_hook) (new_highlight, vpos, first_unused_hpos);
522 return;
525 cursor_to (vpos, 0);
527 if (TN_standout_width < 0)
528 background_highlight ();
529 /* If line starts with a marker, delete the marker */
530 else if (TS_clr_line && chars_wasted[curY])
532 turn_off_insert ();
533 /* On Teleray, make sure to erase the SO marker. */
534 if (TF_teleray)
536 cmgoto (curY - 1, FRAME_WIDTH (selected_frame) - 4);
537 OUTPUT ("\033S");
538 curY++; /* ESC S moves to next line where the TS_standout_mode was */
539 curX = 0;
541 else
542 cmgoto (curY, 0); /* reposition to kill standout marker */
544 clear_end_of_line_raw (first_unused_hpos);
545 reassert_line_highlight (new_highlight, curY);
549 /* Move to absolute position, specified origin 0 */
551 cursor_to (row, col)
552 int row, col;
554 if (! FRAME_TERMCAP_P ((updating_frame
555 ? updating_frame
556 : selected_frame))
557 && cursor_to_hook)
559 (*cursor_to_hook) (row, col);
560 return;
563 col += chars_wasted[row] & 077;
564 if (curY == row && curX == col)
565 return;
566 if (!TF_standout_motion)
567 background_highlight ();
568 if (!TF_insmode_motion)
569 turn_off_insert ();
570 cmgoto (row, col);
573 /* Similar but don't take any account of the wasted characters. */
575 raw_cursor_to (row, col)
576 int row, col;
578 if (! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
580 (*raw_cursor_to_hook) (row, col);
581 return;
583 if (curY == row && curX == col)
584 return;
585 if (!TF_standout_motion)
586 background_highlight ();
587 if (!TF_insmode_motion)
588 turn_off_insert ();
589 cmgoto (row, col);
592 /* Erase operations */
594 /* clear from cursor to end of frame */
595 clear_to_end ()
597 register int i;
599 if (clear_to_end_hook && ! FRAME_TERMCAP_P (updating_frame))
601 (*clear_to_end_hook) ();
602 return;
604 if (TS_clr_to_bottom)
606 background_highlight ();
607 OUTPUT (TS_clr_to_bottom);
608 bzero (chars_wasted + curY, FRAME_HEIGHT (selected_frame) - curY);
610 else
612 for (i = curY; i < FRAME_HEIGHT (selected_frame); i++)
614 cursor_to (i, 0);
615 clear_end_of_line_raw (FRAME_WIDTH (selected_frame));
620 /* Clear entire frame */
622 clear_frame ()
624 if (clear_frame_hook
625 && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
627 (*clear_frame_hook) ();
628 return;
630 if (TS_clr_frame)
632 background_highlight ();
633 OUTPUT (TS_clr_frame);
634 bzero (chars_wasted, FRAME_HEIGHT (selected_frame));
635 cmat (0, 0);
637 else
639 cursor_to (0, 0);
640 clear_to_end ();
644 /* Clear to end of line, but do not clear any standout marker.
645 Assumes that the cursor is positioned at a character of real text,
646 which implies it cannot be before a standout marker
647 unless the marker has zero width.
649 Note that the cursor may be moved. */
651 clear_end_of_line (first_unused_hpos)
652 int first_unused_hpos;
654 static GLYPH buf = SPACEGLYPH;
655 if (FRAME_TERMCAP_P (selected_frame)
656 && TN_standout_width == 0 && curX == 0 && chars_wasted[curY] != 0)
657 write_glyphs (&buf, 1);
658 clear_end_of_line_raw (first_unused_hpos);
661 /* Clear from cursor to end of line.
662 Assume that the line is already clear starting at column first_unused_hpos.
663 If the cursor is at a standout marker, erase the marker.
665 Note that the cursor may be moved, on terminals lacking a `ce' string. */
667 clear_end_of_line_raw (first_unused_hpos)
668 int first_unused_hpos;
670 register int i;
672 if (clear_end_of_line_hook
673 && ! FRAME_TERMCAP_P ((updating_frame
674 ? updating_frame
675 : selected_frame)))
677 (*clear_end_of_line_hook) (first_unused_hpos);
678 return;
681 first_unused_hpos += chars_wasted[curY] & 077;
682 if (curX >= first_unused_hpos)
683 return;
684 /* Notice if we are erasing a magic cookie */
685 if (curX == 0)
686 chars_wasted[curY] = 0;
687 background_highlight ();
688 if (TS_clr_line)
690 OUTPUT1 (TS_clr_line);
692 else
693 { /* have to do it the hard way */
694 turn_off_insert ();
696 /* Do not write in last row last col with Autowrap on. */
697 if (AutoWrap && curY == FRAME_HEIGHT (selected_frame) - 1
698 && first_unused_hpos == FRAME_WIDTH (selected_frame))
699 first_unused_hpos--;
701 for (i = curX; i < first_unused_hpos; i++)
703 if (termscript)
704 fputc (' ', termscript);
705 putchar (' ');
707 cmplus (first_unused_hpos - curX);
712 write_glyphs (string, len)
713 register GLYPH *string;
714 register int len;
716 register GLYPH g;
717 register int tlen = GLYPH_TABLE_LENGTH;
718 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
720 if (write_glyphs_hook
721 && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
723 (*write_glyphs_hook) (string, len);
724 return;
727 highlight_if_desired ();
728 turn_off_insert ();
730 /* Don't dare write in last column of bottom line, if AutoWrap,
731 since that would scroll the whole frame on some terminals. */
733 if (AutoWrap
734 && curY + 1 == FRAME_HEIGHT (selected_frame)
735 && (curX + len - (chars_wasted[curY] & 077)
736 == FRAME_WIDTH (selected_frame)))
737 len --;
739 cmplus (len);
740 while (--len >= 0)
742 g = *string++;
743 /* Check quickly for G beyond length of table.
744 That implies it isn't an alias and is simple. */
745 if (g >= tlen)
747 simple:
748 putc (g & 0xff, stdout);
749 if (ferror (stdout))
750 clearerr (stdout);
751 if (termscript)
752 putc (g & 0xff, termscript);
754 else
756 /* G has an entry in Vglyph_table,
757 so process any alias and then test for simpleness. */
758 while (GLYPH_ALIAS_P (tbase, tlen, g))
759 g = GLYPH_ALIAS (tbase, g);
760 if (GLYPH_SIMPLE_P (tbase, tlen, g))
761 goto simple;
762 else
764 /* Here if G (or its definition as an alias) is not simple. */
765 fwrite (GLYPH_STRING (tbase, g), 1, GLYPH_LENGTH (tbase, g),
766 stdout);
767 if (ferror (stdout))
768 clearerr (stdout);
769 if (termscript)
770 fwrite (GLYPH_STRING (tbase, g), 1, GLYPH_LENGTH (tbase, g),
771 termscript);
777 /* If start is zero, insert blanks instead of a string at start */
779 insert_glyphs (start, len)
780 register GLYPH *start;
781 register int len;
783 char *buf;
784 register GLYPH g;
785 register int tlen = GLYPH_TABLE_LENGTH;
786 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
788 if (insert_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame))
790 (*insert_glyphs_hook) (start, len);
791 return;
793 highlight_if_desired ();
795 if (TS_ins_multi_chars)
797 buf = tparam (TS_ins_multi_chars, 0, 0, len);
798 OUTPUT1 (buf);
799 xfree (buf);
800 if (start)
801 write_glyphs (start, len);
802 return;
805 turn_on_insert ();
806 cmplus (len);
807 while (--len >= 0)
809 OUTPUT1_IF (TS_ins_char);
810 if (!start)
811 g = SPACEGLYPH;
812 else
813 g = *start++;
815 if (GLYPH_SIMPLE_P (tbase, tlen, g))
817 putc (g & 0xff, stdout);
818 if (ferror (stdout))
819 clearerr (stdout);
820 if (termscript)
821 putc (g & 0xff, termscript);
823 else
825 fwrite (GLYPH_STRING (tbase, g), 1, GLYPH_LENGTH (tbase, g), stdout);
826 if (ferror (stdout))
827 clearerr (stdout);
828 if (termscript)
829 fwrite (GLYPH_STRING (tbase, g), 1, GLYPH_LENGTH (tbase, g),
830 termscript);
833 OUTPUT1_IF (TS_pad_inserted_char);
837 delete_glyphs (n)
838 register int n;
840 char *buf;
841 register int i;
843 if (delete_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame))
845 (*delete_glyphs_hook) (n);
846 return;
849 if (delete_in_insert_mode)
851 turn_on_insert ();
853 else
855 turn_off_insert ();
856 OUTPUT_IF (TS_delete_mode);
859 if (TS_del_multi_chars)
861 buf = tparam (TS_del_multi_chars, 0, 0, n);
862 OUTPUT1 (buf);
863 xfree (buf);
865 else
866 for (i = 0; i < n; i++)
867 OUTPUT1 (TS_del_char);
868 if (!delete_in_insert_mode)
869 OUTPUT_IF (TS_end_delete_mode);
872 /* Insert N lines at vpos VPOS. If N is negative, delete -N lines. */
874 ins_del_lines (vpos, n)
875 int vpos, n;
877 char *multi = n > 0 ? TS_ins_multi_lines : TS_del_multi_lines;
878 char *single = n > 0 ? TS_ins_line : TS_del_line;
879 char *scroll = n > 0 ? TS_rev_scroll : TS_fwd_scroll;
881 register int i = n > 0 ? n : -n;
882 register char *buf;
884 if (ins_del_lines_hook && ! FRAME_TERMCAP_P (updating_frame))
886 (*ins_del_lines_hook) (vpos, n);
887 return;
890 /* If the lines below the insertion are being pushed
891 into the end of the window, this is the same as clearing;
892 and we know the lines are already clear, since the matching
893 deletion has already been done. So can ignore this. */
894 /* If the lines below the deletion are blank lines coming
895 out of the end of the window, don't bother,
896 as there will be a matching inslines later that will flush them. */
897 if (scroll_region_ok && vpos + i >= specified_window)
898 return;
899 if (!memory_below_frame && vpos + i >= FRAME_HEIGHT (selected_frame))
900 return;
902 if (multi)
904 raw_cursor_to (vpos, 0);
905 background_highlight ();
906 buf = tparam (multi, 0, 0, i);
907 OUTPUT (buf);
908 xfree (buf);
910 else if (single)
912 raw_cursor_to (vpos, 0);
913 background_highlight ();
914 while (--i >= 0)
915 OUTPUT (single);
916 if (TF_teleray)
917 curX = 0;
919 else
921 set_scroll_region (vpos, specified_window);
922 if (n < 0)
923 raw_cursor_to (specified_window - 1, 0);
924 else
925 raw_cursor_to (vpos, 0);
926 background_highlight ();
927 while (--i >= 0)
928 OUTPUTL (scroll, specified_window - vpos);
929 set_scroll_region (0, specified_window);
932 if (TN_standout_width >= 0)
934 register lower_limit
935 = (scroll_region_ok
936 ? specified_window
937 : FRAME_HEIGHT (selected_frame));
939 if (n < 0)
941 bcopy (&chars_wasted[vpos - n], &chars_wasted[vpos],
942 lower_limit - vpos + n);
943 bzero (&chars_wasted[lower_limit + n], - n);
945 else
947 bcopy (&chars_wasted[vpos], &copybuf[vpos], lower_limit - vpos - n);
948 bcopy (&copybuf[vpos], &chars_wasted[vpos + n],
949 lower_limit - vpos - n);
950 bzero (&chars_wasted[vpos], n);
953 if (!scroll_region_ok && memory_below_frame && n < 0)
955 cursor_to (FRAME_HEIGHT (selected_frame) + n, 0);
956 clear_to_end ();
960 /* Compute cost of sending "str", in characters,
961 not counting any line-dependent padding. */
964 string_cost (str)
965 char *str;
967 cost = 0;
968 if (str)
969 tputs (str, 0, evalcost);
970 return cost;
973 /* Compute cost of sending "str", in characters,
974 counting any line-dependent padding at one line. */
976 static int
977 string_cost_one_line (str)
978 char *str;
980 cost = 0;
981 if (str)
982 tputs (str, 1, evalcost);
983 return cost;
986 /* Compute per line amount of line-dependent padding,
987 in tenths of characters. */
990 per_line_cost (str)
991 register char *str;
993 cost = 0;
994 if (str)
995 tputs (str, 0, evalcost);
996 cost = - cost;
997 if (str)
998 tputs (str, 10, evalcost);
999 return cost;
1002 #ifndef old
1003 /* char_ins_del_cost[n] is cost of inserting N characters.
1004 char_ins_del_cost[-n] is cost of deleting N characters. */
1006 int *char_ins_del_vector;
1008 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WIDTH ((f))])
1009 #endif
1011 /* ARGSUSED */
1012 static void
1013 calculate_ins_del_char_costs (frame)
1014 FRAME_PTR frame;
1016 int ins_startup_cost, del_startup_cost;
1017 int ins_cost_per_char, del_cost_per_char;
1018 register int i;
1019 register int *p;
1021 if (TS_ins_multi_chars)
1023 ins_cost_per_char = 0;
1024 ins_startup_cost = string_cost_one_line (TS_ins_multi_chars);
1026 else if (TS_ins_char || TS_pad_inserted_char
1027 || (TS_insert_mode && TS_end_insert_mode))
1029 ins_startup_cost = (30 * (string_cost (TS_insert_mode)
1030 + string_cost (TS_end_insert_mode))) / 100;
1031 ins_cost_per_char = (string_cost_one_line (TS_ins_char)
1032 + string_cost_one_line (TS_pad_inserted_char));
1034 else
1036 ins_startup_cost = 9999;
1037 ins_cost_per_char = 0;
1040 if (TS_del_multi_chars)
1042 del_cost_per_char = 0;
1043 del_startup_cost = string_cost_one_line (TS_del_multi_chars);
1045 else if (TS_del_char)
1047 del_startup_cost = (string_cost (TS_delete_mode)
1048 + string_cost (TS_end_delete_mode));
1049 if (delete_in_insert_mode)
1050 del_startup_cost /= 2;
1051 del_cost_per_char = string_cost_one_line (TS_del_char);
1053 else
1055 del_startup_cost = 9999;
1056 del_cost_per_char = 0;
1059 /* Delete costs are at negative offsets */
1060 p = &char_ins_del_cost (frame)[0];
1061 for (i = FRAME_WIDTH (selected_frame); --i >= 0;)
1062 *--p = (del_startup_cost += del_cost_per_char);
1064 /* Doing nothing is free */
1065 p = &char_ins_del_cost (frame)[0];
1066 *p++ = 0;
1068 /* Insert costs are at positive offsets */
1069 for (i = FRAME_WIDTH (frame); --i >= 0;)
1070 *p++ = (ins_startup_cost += ins_cost_per_char);
1073 #ifdef HAVE_X_WINDOWS
1074 extern int x_screen_planes;
1075 #endif
1077 extern do_line_insertion_deletion_costs ();
1079 calculate_costs (frame)
1080 FRAME_PTR frame;
1082 register char *f = TS_set_scroll_region ?
1083 TS_set_scroll_region
1084 : TS_set_scroll_region_1;
1086 if (dont_calculate_costs)
1087 return;
1089 #ifdef HAVE_X_WINDOWS
1090 if (FRAME_X_P (frame))
1092 do_line_insertion_deletion_costs (frame, 0, ".5*", 0, ".5*",
1093 0, 0, x_screen_planes);
1094 return;
1096 #endif
1098 /* These variables are only used for terminal stuff. They are allocated
1099 once for the terminal frame of X-windows emacs, but not used afterwards.
1101 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1102 X turns off char_ins_del_ok.
1104 chars_wasted and copybuf are only used here in term.c in cases where
1105 the term hook isn't called. */
1107 if (chars_wasted != 0)
1108 chars_wasted = (char *) xrealloc (chars_wasted, FRAME_HEIGHT (frame));
1109 else
1110 chars_wasted = (char *) xmalloc (FRAME_HEIGHT (frame));
1112 if (copybuf != 0)
1113 copybuf = (char *) xrealloc (copybuf, FRAME_HEIGHT (frame));
1114 else
1115 copybuf = (char *) xmalloc (FRAME_HEIGHT (frame));
1117 if (char_ins_del_vector != 0)
1118 char_ins_del_vector
1119 = (int *) xrealloc (char_ins_del_vector,
1120 (sizeof (int)
1121 + 2 * FRAME_WIDTH (frame) * sizeof (int)));
1122 else
1123 char_ins_del_vector
1124 = (int *) xmalloc (sizeof (int)
1125 + 2 * FRAME_WIDTH (frame) * sizeof (int));
1127 bzero (chars_wasted, FRAME_HEIGHT (frame));
1128 bzero (copybuf, FRAME_HEIGHT (frame));
1129 bzero (char_ins_del_vector, (sizeof (int)
1130 + 2 * FRAME_WIDTH (frame) * sizeof (int)));
1132 if (f && (!TS_ins_line && !TS_del_line))
1133 do_line_insertion_deletion_costs (frame,
1134 TS_rev_scroll, TS_ins_multi_lines,
1135 TS_fwd_scroll, TS_del_multi_lines,
1136 f, f, 1);
1137 else
1138 do_line_insertion_deletion_costs (frame,
1139 TS_ins_line, TS_ins_multi_lines,
1140 TS_del_line, TS_del_multi_lines,
1141 0, 0, 1);
1143 calculate_ins_del_char_costs (frame);
1145 /* Don't use TS_repeat if its padding is worse than sending the chars */
1146 if (TS_repeat && per_line_cost (TS_repeat) * baud_rate < 9000)
1147 RPov = string_cost (TS_repeat);
1148 else
1149 RPov = FRAME_WIDTH (frame) * 2;
1151 cmcostinit (); /* set up cursor motion costs */
1154 struct fkey_table {
1155 char *cap, *name;
1158 /* Termcap capability names that correspond directly to X keysyms.
1159 Some of these (marked "terminfo") aren't supplied by old-style
1160 (Berkeley) termcap entries. They're listed in X keysym order;
1161 except we put the keypad keys first, so that if they clash with
1162 other keys (as on the IBM PC keyboard) they get overridden.
1165 static struct fkey_table keys[] = {
1166 "kh", "home", /* termcap */
1167 "kl", "left", /* termcap */
1168 "ku", "up", /* termcap */
1169 "kr", "right", /* termcap */
1170 "kd", "down", /* termcap */
1171 "%8", "prior", /* terminfo */
1172 "%5", "next", /* terminfo */
1173 "@7", "end", /* terminfo */
1174 "@1", "begin", /* terminfo */
1175 "*6", "select", /* terminfo */
1176 "%9", "print", /* terminfo */
1177 "@4", "execute", /* terminfo --- actually the `command' key */
1179 * "insert" --- see below
1181 "&8", "undo", /* terminfo */
1182 "%0", "redo", /* terminfo */
1183 "%7", "menu", /* terminfo --- actually the `options' key */
1184 "@0", "find", /* terminfo */
1185 "@2", "cancel", /* terminfo */
1186 "%1", "help", /* terminfo */
1188 * "break" goes here, but can't be reliably intercepted with termcap
1190 "&4", "reset", /* terminfo --- actually `restart' */
1192 * "system" and "user" --- no termcaps
1194 "kE", "clearline", /* terminfo */
1195 "kA", "insertline", /* terminfo */
1196 "kL", "deleteline", /* terminfo */
1197 "kI", "insertchar", /* terminfo */
1198 "kD", "deletechar", /* terminfo */
1199 "kB", "backtab", /* terminfo */
1201 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1203 "@8", "kp-enter", /* terminfo */
1205 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1206 * "kp-multiply", "kp-add", "kp-separator",
1207 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1208 * --- no termcaps for any of these.
1210 "K4", "kp-1", /* terminfo */
1212 * "kp-2" --- no termcap
1214 "K5", "kp-3", /* terminfo */
1216 * "kp-4" --- no termcap
1218 "K2", "kp-5", /* terminfo */
1220 * "kp-6" --- no termcap
1222 "K1", "kp-7", /* terminfo */
1224 * "kp-8" --- no termcap
1226 "K3", "kp-9", /* terminfo */
1228 * "kp-equal" --- no termcap
1230 "k1", "f1",
1231 "k2", "f2",
1232 "k3", "f3",
1233 "k4", "f4",
1234 "k5", "f5",
1235 "k6", "f6",
1236 "k7", "f7",
1237 "k8", "f8",
1238 "k9", "f9",
1241 static char **term_get_fkeys_arg;
1242 static Lisp_Object term_get_fkeys_1 ();
1244 /* Find the escape codes sent by the function keys for Vfunction_key_map.
1245 This function scans the termcap function key sequence entries, and
1246 adds entries to Vfunction_key_map for each function key it finds. */
1248 void
1249 term_get_fkeys (address)
1250 char **address;
1252 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1253 errors during the call. The only errors should be from Fdefine_key
1254 when given a key sequence containing an invalid prefix key. If the
1255 termcap defines function keys which use a prefix that is already bound
1256 to a command by the default bindings, we should silently ignore that
1257 function key specification, rather than giving the user an error and
1258 refusing to run at all on such a terminal. */
1260 extern Lisp_Object Fidentity ();
1261 term_get_fkeys_arg = address;
1262 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1265 static Lisp_Object
1266 term_get_fkeys_1 ()
1268 int i;
1270 char **address = term_get_fkeys_arg;
1272 /* This can happen if CANNOT_DUMP or with strange options. */
1273 if (!initialized)
1274 Vfunction_key_map = Fmake_sparse_keymap (Qnil);
1276 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1278 char *sequence = tgetstr (keys[i].cap, address);
1279 if (sequence)
1280 Fdefine_key (Vfunction_key_map, build_string (sequence),
1281 Fmake_vector (make_number (1),
1282 intern (keys[i].name)));
1285 /* The uses of the "k0" capability are inconsistent; sometimes it
1286 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1287 We will attempt to politely accommodate both systems by testing for
1288 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1291 char *k_semi = tgetstr ("k;", address);
1292 char *k0 = tgetstr ("k0", address);
1293 char *k0_name = "f10";
1295 if (k_semi)
1297 Fdefine_key (Vfunction_key_map, build_string (k_semi),
1298 Fmake_vector (make_number (1), intern ("f10")));
1299 k0_name = "f0";
1302 if (k0)
1303 Fdefine_key (Vfunction_key_map, build_string (k0),
1304 Fmake_vector (make_number (1), intern (k0_name)));
1307 /* Set up cookies for numbered function keys above f10. */
1309 char fcap[3], fkey[4];
1311 fcap[0] = 'F'; fcap[2] = '\0';
1312 for (i = 11; i < 64; i++)
1314 if (i <= 19)
1315 fcap[1] = '1' + i - 11;
1316 else if (i <= 45)
1317 fcap[1] = 'A' + i - 11;
1318 else
1319 fcap[1] = 'a' + i - 11;
1322 char *sequence = tgetstr (fcap, address);
1323 if (sequence)
1325 sprintf (fkey, "f%d", i);
1326 Fdefine_key (Vfunction_key_map, build_string (sequence),
1327 Fmake_vector (make_number (1),
1328 intern (fkey)));
1335 * Various mappings to try and get a better fit.
1338 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1339 if (!tgetstr (cap1, address)) \
1341 char *sequence = tgetstr (cap2, address); \
1342 if (sequence) \
1343 Fdefine_key (Vfunction_key_map, build_string (sequence), \
1344 Fmake_vector (make_number (1), \
1345 intern (sym))); \
1348 /* if there's no key_next keycap, map key_npage to `next' keysym */
1349 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1350 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1351 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1352 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1353 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1354 #undef CONDITIONAL_REASSIGN
1359 term_init (terminal_type)
1360 char *terminal_type;
1362 char *area;
1363 char **address = &area;
1364 char buffer[2044];
1365 register char *p;
1366 int status;
1368 Wcm_clear ();
1369 dont_calculate_costs = 0;
1371 status = tgetent (buffer, terminal_type);
1372 if (status < 0)
1373 fatal ("Cannot open termcap database file.\n");
1374 if (status == 0)
1375 fatal ("Terminal type %s is not defined.\n\
1376 If that is not the actual type of terminal you have,\n\
1377 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
1378 `setenv TERM ...') to specify the correct type. It may be necessary\n\
1379 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.\n",
1380 terminal_type);
1382 #ifdef TERMINFO
1383 area = (char *) malloc (2044);
1384 #else
1385 area = (char *) malloc (strlen (buffer));
1386 #endif /* not TERMINFO */
1387 if (area == 0)
1388 abort ();
1390 TS_ins_line = tgetstr ("al", address);
1391 TS_ins_multi_lines = tgetstr ("AL", address);
1392 TS_bell = tgetstr ("bl", address);
1393 BackTab = tgetstr ("bt", address);
1394 TS_clr_to_bottom = tgetstr ("cd", address);
1395 TS_clr_line = tgetstr ("ce", address);
1396 TS_clr_frame = tgetstr ("cl", address);
1397 ColPosition = tgetstr ("ch", address);
1398 AbsPosition = tgetstr ("cm", address);
1399 CR = tgetstr ("cr", address);
1400 TS_set_scroll_region = tgetstr ("cs", address);
1401 TS_set_scroll_region_1 = tgetstr ("cS", address);
1402 RowPosition = tgetstr ("cv", address);
1403 TS_del_char = tgetstr ("dc", address);
1404 TS_del_multi_chars = tgetstr ("DC", address);
1405 TS_del_line = tgetstr ("dl", address);
1406 TS_del_multi_lines = tgetstr ("DL", address);
1407 TS_delete_mode = tgetstr ("dm", address);
1408 TS_end_delete_mode = tgetstr ("ed", address);
1409 TS_end_insert_mode = tgetstr ("ei", address);
1410 Home = tgetstr ("ho", address);
1411 TS_ins_char = tgetstr ("ic", address);
1412 TS_ins_multi_chars = tgetstr ("IC", address);
1413 TS_insert_mode = tgetstr ("im", address);
1414 TS_pad_inserted_char = tgetstr ("ip", address);
1415 TS_end_keypad_mode = tgetstr ("ke", address);
1416 TS_keypad_mode = tgetstr ("ks", address);
1417 LastLine = tgetstr ("ll", address);
1418 Right = tgetstr ("nd", address);
1419 Down = tgetstr ("do", address);
1420 if (!Down)
1421 Down = tgetstr ("nl", address); /* Obsolete name for "do" */
1422 #ifdef VMS
1423 /* VMS puts a carriage return before each linefeed,
1424 so it is not safe to use linefeeds. */
1425 if (Down && Down[0] == '\n' && Down[1] == '\0')
1426 Down = 0;
1427 #endif /* VMS */
1428 if (tgetflag ("bs"))
1429 Left = "\b"; /* can't possibly be longer! */
1430 else /* (Actually, "bs" is obsolete...) */
1431 Left = tgetstr ("le", address);
1432 if (!Left)
1433 Left = tgetstr ("bc", address); /* Obsolete name for "le" */
1434 TS_pad_char = tgetstr ("pc", address);
1435 TS_repeat = tgetstr ("rp", address);
1436 TS_end_standout_mode = tgetstr ("se", address);
1437 TS_fwd_scroll = tgetstr ("sf", address);
1438 TS_standout_mode = tgetstr ("so", address);
1439 TS_rev_scroll = tgetstr ("sr", address);
1440 Wcm.cm_tab = tgetstr ("ta", address);
1441 TS_end_termcap_modes = tgetstr ("te", address);
1442 TS_termcap_modes = tgetstr ("ti", address);
1443 Up = tgetstr ("up", address);
1444 TS_visible_bell = tgetstr ("vb", address);
1445 TS_end_visual_mode = tgetstr ("ve", address);
1446 TS_visual_mode = tgetstr ("vs", address);
1447 TS_set_window = tgetstr ("wi", address);
1448 MultiUp = tgetstr ("UP", address);
1449 MultiDown = tgetstr ("DO", address);
1450 MultiLeft = tgetstr ("LE", address);
1451 MultiRight = tgetstr ("RI", address);
1453 AutoWrap = tgetflag ("am");
1454 memory_below_frame = tgetflag ("db");
1455 TF_hazeltine = tgetflag ("hz");
1456 must_write_spaces = tgetflag ("in");
1457 meta_key = tgetflag ("km") || tgetflag ("MT");
1458 TF_insmode_motion = tgetflag ("mi");
1459 TF_standout_motion = tgetflag ("ms");
1460 TF_underscore = tgetflag ("ul");
1461 MagicWrap = tgetflag ("xn");
1462 TF_xs = tgetflag ("xs");
1463 TF_teleray = tgetflag ("xt");
1465 term_get_fkeys (address);
1467 /* Get frame size from system, or else from termcap. */
1468 get_frame_size (&FRAME_WIDTH (selected_frame),
1469 &FRAME_HEIGHT (selected_frame));
1470 if (FRAME_WIDTH (selected_frame) <= 0)
1471 FRAME_WIDTH (selected_frame) = tgetnum ("co");
1472 if (FRAME_HEIGHT (selected_frame) <= 0)
1473 FRAME_HEIGHT (selected_frame) = tgetnum ("li");
1475 min_padding_speed = tgetnum ("pb");
1476 TN_standout_width = tgetnum ("sg");
1477 TabWidth = tgetnum ("tw");
1479 #ifdef VMS
1480 /* These capabilities commonly use ^J.
1481 I don't know why, but sending them on VMS does not work;
1482 it causes following spaces to be lost, sometimes.
1483 For now, the simplest fix is to avoid using these capabilities ever. */
1484 if (Down && Down[0] == '\n')
1485 Down = 0;
1486 #endif /* VMS */
1488 if (!TS_bell)
1489 TS_bell = "\07";
1491 if (!TS_fwd_scroll)
1492 TS_fwd_scroll = Down;
1494 PC = TS_pad_char ? *TS_pad_char : 0;
1496 if (TabWidth < 0)
1497 TabWidth = 8;
1499 /* Turned off since /etc/termcap seems to have :ta= for most terminals
1500 and newer termcap doc does not seem to say there is a default.
1501 if (!Wcm.cm_tab)
1502 Wcm.cm_tab = "\t";
1505 if (TS_standout_mode == 0)
1507 TN_standout_width = tgetnum ("ug");
1508 TS_end_standout_mode = tgetstr ("ue", address);
1509 TS_standout_mode = tgetstr ("us", address);
1512 /* If no `se' string, try using a `me' string instead.
1513 If that fails, we can't use standout mode at all. */
1514 if (TS_end_standout_mode == 0)
1516 char *s = tgetstr ("me", address);
1517 if (s != 0)
1518 TS_end_standout_mode = s;
1519 else
1520 TS_standout_mode = 0;
1523 if (TF_teleray)
1525 Wcm.cm_tab = 0;
1526 /* Teleray: most programs want a space in front of TS_standout_mode,
1527 but Emacs can do without it (and give one extra column). */
1528 TS_standout_mode = "\033RD";
1529 TN_standout_width = 1;
1530 /* But that means we cannot rely on ^M to go to column zero! */
1531 CR = 0;
1532 /* LF can't be trusted either -- can alter hpos */
1533 /* if move at column 0 thru a line with TS_standout_mode */
1534 Down = 0;
1537 /* Special handling for certain terminal types known to need it */
1539 if (!strcmp (terminal_type, "supdup"))
1541 memory_below_frame = 1;
1542 Wcm.cm_losewrap = 1;
1544 if (!strncmp (terminal_type, "c10", 3)
1545 || !strcmp (terminal_type, "perq"))
1547 /* Supply a makeshift :wi string.
1548 This string is not valid in general since it works only
1549 for windows starting at the upper left corner;
1550 but that is all Emacs uses.
1552 This string works only if the frame is using
1553 the top of the video memory, because addressing is memory-relative.
1554 So first check the :ti string to see if that is true.
1556 It would be simpler if the :wi string could go in the termcap
1557 entry, but it can't because it is not fully valid.
1558 If it were in the termcap entry, it would confuse other programs. */
1559 if (!TS_set_window)
1561 p = TS_termcap_modes;
1562 while (*p && strcmp (p, "\033v "))
1563 p++;
1564 if (*p)
1565 TS_set_window = "\033v%C %C %C %C ";
1567 /* Termcap entry often fails to have :in: flag */
1568 must_write_spaces = 1;
1569 /* :ti string typically fails to have \E^G! in it */
1570 /* This limits scope of insert-char to one line. */
1571 strcpy (area, TS_termcap_modes);
1572 strcat (area, "\033\007!");
1573 TS_termcap_modes = area;
1574 area += strlen (area) + 1;
1575 p = AbsPosition;
1576 /* Change all %+ parameters to %C, to handle
1577 values above 96 correctly for the C100. */
1578 while (*p)
1580 if (p[0] == '%' && p[1] == '+')
1581 p[1] = 'C';
1582 p++;
1586 FrameRows = FRAME_HEIGHT (selected_frame);
1587 FrameCols = FRAME_WIDTH (selected_frame);
1588 specified_window = FRAME_HEIGHT (selected_frame);
1590 if (Wcm_init () == -1) /* can't do cursor motion */
1591 #ifdef VMS
1592 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
1593 It lacks the ability to position the cursor.\n\
1594 If that is not the actual type of terminal you have, use either the\n\
1595 DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
1596 or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.\n",
1597 terminal_type);
1598 #else
1599 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
1600 It lacks the ability to position the cursor.\n\
1601 If that is not the actual type of terminal you have,\n\
1602 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
1603 `setenv TERM ...') to specify the correct type. It may be necessary\n\
1604 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.\n",
1605 terminal_type);
1606 #endif
1607 if (FRAME_HEIGHT (selected_frame) <= 0
1608 || FRAME_WIDTH (selected_frame) <= 0)
1609 fatal ("The frame size has not been specified.");
1611 delete_in_insert_mode
1612 = TS_delete_mode && TS_insert_mode
1613 && !strcmp (TS_delete_mode, TS_insert_mode);
1615 se_is_so = (TS_standout_mode
1616 && TS_end_standout_mode
1617 && !strcmp (TS_standout_mode, TS_end_standout_mode));
1619 /* Remove width of standout marker from usable width of line */
1620 if (TN_standout_width > 0)
1621 FRAME_WIDTH (selected_frame) -= TN_standout_width;
1623 UseTabs = tabs_safe_p () && TabWidth == 8;
1625 scroll_region_ok
1626 = (Wcm.cm_abs
1627 && (TS_set_window || TS_set_scroll_region || TS_set_scroll_region_1));
1629 line_ins_del_ok = (((TS_ins_line || TS_ins_multi_lines)
1630 && (TS_del_line || TS_del_multi_lines))
1631 || (scroll_region_ok && TS_fwd_scroll && TS_rev_scroll));
1633 char_ins_del_ok = ((TS_ins_char || TS_insert_mode
1634 || TS_pad_inserted_char || TS_ins_multi_chars)
1635 && (TS_del_char || TS_del_multi_chars));
1637 fast_clear_end_of_line = TS_clr_line != 0;
1639 init_baud_rate ();
1640 if (read_socket_hook) /* Baudrate is somewhat */
1641 /* meaningless in this case */
1642 baud_rate = 9600;
1644 FRAME_CAN_HAVE_SCROLL_BARS (selected_frame) = 0;
1645 FRAME_HAS_VERTICAL_SCROLL_BARS (selected_frame) = 0;
1648 /* VARARGS 1 */
1649 fatal (str, arg1, arg2)
1650 char *str, *arg1, *arg2;
1652 fprintf (stderr, "emacs: ");
1653 fprintf (stderr, str, arg1, arg2);
1654 fflush (stderr);
1655 exit (1);
1658 syms_of_term ()
1660 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
1661 "Non-nil means the system uses terminfo rather than termcap.\n\
1662 This variable can be used by terminal emulator packages.");
1663 #ifdef TERMINFO
1664 system_uses_terminfo = 1;
1665 #else
1666 system_uses_terminfo = 0;
1667 #endif