(show-paren-command-hook): Position show-paren-overlay-1
[emacs.git] / src / term.c
blobed34f85e78d5777b4d9956fd9d04f9f526ec82cd
1 /* terminal control module for terminals described by TERMCAP
2 Copyright (C) 1985, 86, 87, 93, 94, 95 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, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
22 #include <config.h>
23 #include <stdio.h>
24 #include <ctype.h>
25 #include "termchar.h"
26 #include "termopts.h"
27 #include "cm.h"
28 #undef NULL
29 #include "lisp.h"
30 #include "frame.h"
31 #include "disptab.h"
32 #include "termhooks.h"
33 #include "keyboard.h"
35 extern Lisp_Object Fmake_sparse_keymap ();
37 #define max(a, b) ((a) > (b) ? (a) : (b))
38 #define min(a, b) ((a) < (b) ? (a) : (b))
40 #define OUTPUT(a) tputs (a, FRAME_HEIGHT (selected_frame) - curY, cmputc)
41 #define OUTPUT1(a) tputs (a, 1, cmputc)
42 #define OUTPUTL(a, lines) tputs (a, lines, cmputc)
43 #define OUTPUT_IF(a) { if (a) tputs (a, FRAME_HEIGHT (selected_frame) - curY, cmputc); }
44 #define OUTPUT1_IF(a) { if (a) tputs (a, 1, cmputc); }
46 /* Terminal characteristics that higher levels want to look at.
47 These are all extern'd in termchar.h */
49 int must_write_spaces; /* Nonzero means spaces in the text
50 must actually be output; can't just skip
51 over some columns to leave them blank. */
52 int min_padding_speed; /* Speed below which no padding necessary */
54 int line_ins_del_ok; /* Terminal can insert and delete lines */
55 int char_ins_del_ok; /* Terminal can insert and delete chars */
56 int scroll_region_ok; /* Terminal supports setting the
57 scroll window */
58 int scroll_region_cost; /* Cost of setting a scroll window,
59 measured in characters */
60 int memory_below_frame; /* Terminal remembers lines
61 scrolled off bottom */
62 int fast_clear_end_of_line; /* Terminal has a `ce' string */
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, int insist,
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 fiery 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 /* The largest frame width in any call to calculate_costs. */
259 int max_frame_width;
260 /* The largest frame height in any call to calculate_costs. */
261 int max_frame_height;
263 /* Number of chars of space used for standout marker at beginning of line,
264 or'd with 0100. Zero if no standout marker at all.
265 The length of these vectors is max_frame_height.
267 Used IFF TN_standout_width >= 0. */
269 static char *chars_wasted;
270 static char *copybuf;
272 /* nonzero means supposed to write text in standout mode. */
273 int standout_requested;
275 int insert_mode; /* Nonzero when in insert mode. */
276 int standout_mode; /* Nonzero when in standout mode. */
278 /* Size of window specified by higher levels.
279 This is the number of lines, from the top of frame downwards,
280 which can participate in insert-line/delete-line operations.
282 Effectively it excludes the bottom frame_height - specified_window_size
283 lines from those operations. */
285 int specified_window;
287 /* Frame currently being redisplayed; 0 if not currently redisplaying.
288 (Direct output does not count). */
290 FRAME_PTR updating_frame;
292 /* Provided for lisp packages. */
293 static int system_uses_terminfo;
295 char *tparam ();
297 extern char *tgetstr ();
300 #ifdef WINDOWSNT
301 #ifndef HAVE_NTGUI
302 /* We aren't X windows, but we aren't termcap either. This makes me
303 uncertain as to what value to use for frame.output_method. For
304 this file, we'll define FRAME_TERMCAP_P to be zero so that our
305 output hooks get called instead of the termcap functions. Probably
306 the best long-term solution is to define an output_windows_nt... */
308 #undef FRAME_TERMCAP_P
309 #define FRAME_TERMCAP_P(_f_) 0
310 #endif /* not HAVE_NTGUI */
311 #endif /* WINDOWSNT */
313 ring_bell ()
315 if (! FRAME_TERMCAP_P (selected_frame))
317 (*ring_bell_hook) ();
318 return;
320 OUTPUT (TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell);
323 set_terminal_modes ()
325 if (! FRAME_TERMCAP_P (selected_frame))
327 (*set_terminal_modes_hook) ();
328 return;
330 OUTPUT_IF (TS_termcap_modes);
331 OUTPUT_IF (TS_visual_mode);
332 OUTPUT_IF (TS_keypad_mode);
333 losecursor ();
336 reset_terminal_modes ()
338 if (! FRAME_TERMCAP_P (selected_frame))
340 (*reset_terminal_modes_hook) ();
341 return;
343 if (TN_standout_width < 0)
344 turn_off_highlight ();
345 turn_off_insert ();
346 OUTPUT_IF (TS_end_keypad_mode);
347 OUTPUT_IF (TS_end_visual_mode);
348 OUTPUT_IF (TS_end_termcap_modes);
349 /* Output raw CR so kernel can track the cursor hpos. */
350 /* But on magic-cookie terminals this can erase an end-standout marker and
351 cause the rest of the frame to be in standout, so move down first. */
352 if (TN_standout_width >= 0)
353 cmputc ('\n');
354 cmputc ('\r');
357 update_begin (f)
358 FRAME_PTR f;
360 updating_frame = f;
361 if (! FRAME_TERMCAP_P (updating_frame))
362 (*update_begin_hook) (f);
365 update_end (f)
366 FRAME_PTR f;
368 if (! FRAME_TERMCAP_P (updating_frame))
370 (*update_end_hook) (f);
371 updating_frame = 0;
372 return;
374 turn_off_insert ();
375 background_highlight ();
376 standout_requested = 0;
377 updating_frame = 0;
380 set_terminal_window (size)
381 int size;
383 if (! FRAME_TERMCAP_P (updating_frame))
385 (*set_terminal_window_hook) (size);
386 return;
388 specified_window = size ? size : FRAME_HEIGHT (selected_frame);
389 if (!scroll_region_ok)
390 return;
391 set_scroll_region (0, specified_window);
394 set_scroll_region (start, stop)
395 int start, stop;
397 char *buf;
398 if (TS_set_scroll_region)
400 buf = tparam (TS_set_scroll_region, 0, 0, start, stop - 1);
402 else if (TS_set_scroll_region_1)
404 buf = tparam (TS_set_scroll_region_1, 0, 0,
405 FRAME_HEIGHT (selected_frame), start,
406 FRAME_HEIGHT (selected_frame) - stop,
407 FRAME_HEIGHT (selected_frame));
409 else
411 buf = tparam (TS_set_window, 0, 0, start, 0, stop, FRAME_WIDTH (selected_frame));
413 OUTPUT (buf);
414 xfree (buf);
415 losecursor ();
418 turn_on_insert ()
420 if (!insert_mode)
421 OUTPUT (TS_insert_mode);
422 insert_mode = 1;
425 turn_off_insert ()
427 if (insert_mode)
428 OUTPUT (TS_end_insert_mode);
429 insert_mode = 0;
432 /* Handle highlighting when TN_standout_width (termcap sg) is not specified.
433 In these terminals, output is affected by the value of standout
434 mode when the output is written.
436 These functions are called on all terminals, but do nothing
437 on terminals whose standout mode does not work that way. */
439 turn_off_highlight ()
441 if (TN_standout_width < 0)
443 if (standout_mode)
444 OUTPUT_IF (TS_end_standout_mode);
445 standout_mode = 0;
449 turn_on_highlight ()
451 if (TN_standout_width < 0)
453 if (!standout_mode)
454 OUTPUT_IF (TS_standout_mode);
455 standout_mode = 1;
459 /* Set standout mode to the state it should be in for
460 empty space inside windows. What this is,
461 depends on the user option inverse-video. */
463 background_highlight ()
465 if (TN_standout_width >= 0)
466 return;
467 if (inverse_video)
468 turn_on_highlight ();
469 else
470 turn_off_highlight ();
473 /* Set standout mode to the mode specified for the text to be output. */
475 static
476 highlight_if_desired ()
478 if (TN_standout_width >= 0)
479 return;
480 if (!inverse_video == !standout_requested)
481 turn_off_highlight ();
482 else
483 turn_on_highlight ();
486 /* Handle standout mode for terminals in which TN_standout_width >= 0.
487 On these terminals, standout is controlled by markers that
488 live inside the terminal's memory. TN_standout_width is the width
489 that the marker occupies in memory. Standout runs from the marker
490 to the end of the line on some terminals, or to the next
491 turn-off-standout marker (TS_end_standout_mode) string
492 on other terminals. */
494 /* Write a standout marker or end-standout marker at the front of the line
495 at vertical position vpos. */
497 write_standout_marker (flag, vpos)
498 int flag, vpos;
500 if (flag || (TS_end_standout_mode && !TF_teleray && !se_is_so
501 && !(TF_xs && TN_standout_width == 0)))
503 cmgoto (vpos, 0);
504 cmplus (TN_standout_width);
505 OUTPUT (flag ? TS_standout_mode : TS_end_standout_mode);
506 chars_wasted[curY] = TN_standout_width | 0100;
510 /* External interface to control of standout mode.
511 Call this when about to modify line at position VPOS
512 and not change whether it is highlighted. */
514 reassert_line_highlight (highlight, vpos)
515 int highlight;
516 int vpos;
518 if (! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
520 (*reassert_line_highlight_hook) (highlight, vpos);
521 return;
523 if (TN_standout_width < 0)
524 /* Handle terminals where standout takes affect at output time */
525 standout_requested = highlight;
526 else if (chars_wasted[vpos] == 0)
527 /* For terminals with standout markers, write one on this line
528 if there isn't one already. */
529 write_standout_marker (highlight, vpos);
532 /* Call this when about to modify line at position VPOS
533 and change whether it is highlighted. */
535 change_line_highlight (new_highlight, vpos, first_unused_hpos)
536 int new_highlight, vpos, first_unused_hpos;
538 standout_requested = new_highlight;
539 if (! FRAME_TERMCAP_P (updating_frame))
541 (*change_line_highlight_hook) (new_highlight, vpos, first_unused_hpos);
542 return;
545 cursor_to (vpos, 0);
547 if (TN_standout_width < 0)
548 background_highlight ();
549 /* If line starts with a marker, delete the marker */
550 else if (TS_clr_line && chars_wasted[curY])
552 turn_off_insert ();
553 /* On Teleray, make sure to erase the SO marker. */
554 if (TF_teleray)
556 cmgoto (curY - 1, FRAME_WIDTH (selected_frame) - 4);
557 OUTPUT ("\033S");
558 curY++; /* ESC S moves to next line where the TS_standout_mode was */
559 curX = 0;
561 else
562 cmgoto (curY, 0); /* reposition to kill standout marker */
564 clear_end_of_line_raw (first_unused_hpos);
565 reassert_line_highlight (new_highlight, curY);
569 /* Move to absolute position, specified origin 0 */
571 cursor_to (row, col)
572 int row, col;
574 if (! FRAME_TERMCAP_P ((updating_frame
575 ? updating_frame
576 : selected_frame))
577 && cursor_to_hook)
579 (*cursor_to_hook) (row, col);
580 return;
583 /* Detect the case where we are called from reset_sys_modes
584 and the costs have never been calculated. Do nothing. */
585 if (chars_wasted == 0)
586 return;
588 col += chars_wasted[row] & 077;
589 if (curY == row && curX == col)
590 return;
591 if (!TF_standout_motion)
592 background_highlight ();
593 if (!TF_insmode_motion)
594 turn_off_insert ();
595 cmgoto (row, col);
598 /* Similar but don't take any account of the wasted characters. */
600 raw_cursor_to (row, col)
601 int row, col;
603 if (! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
605 (*raw_cursor_to_hook) (row, col);
606 return;
608 if (curY == row && curX == col)
609 return;
610 if (!TF_standout_motion)
611 background_highlight ();
612 if (!TF_insmode_motion)
613 turn_off_insert ();
614 cmgoto (row, col);
617 /* Erase operations */
619 /* clear from cursor to end of frame */
620 clear_to_end ()
622 register int i;
624 if (clear_to_end_hook && ! FRAME_TERMCAP_P (updating_frame))
626 (*clear_to_end_hook) ();
627 return;
629 if (TS_clr_to_bottom)
631 background_highlight ();
632 OUTPUT (TS_clr_to_bottom);
633 bzero (chars_wasted + curY, FRAME_HEIGHT (selected_frame) - curY);
635 else
637 for (i = curY; i < FRAME_HEIGHT (selected_frame); i++)
639 cursor_to (i, 0);
640 clear_end_of_line_raw (FRAME_WIDTH (selected_frame));
645 /* Clear entire frame */
647 clear_frame ()
649 if (clear_frame_hook
650 && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
652 (*clear_frame_hook) ();
653 return;
655 if (TS_clr_frame)
657 background_highlight ();
658 OUTPUT (TS_clr_frame);
659 bzero (chars_wasted, FRAME_HEIGHT (selected_frame));
660 cmat (0, 0);
662 else
664 cursor_to (0, 0);
665 clear_to_end ();
669 /* Clear to end of line, but do not clear any standout marker.
670 Assumes that the cursor is positioned at a character of real text,
671 which implies it cannot be before a standout marker
672 unless the marker has zero width.
674 Note that the cursor may be moved. */
676 clear_end_of_line (first_unused_hpos)
677 int first_unused_hpos;
679 static GLYPH buf = SPACEGLYPH;
680 if (FRAME_TERMCAP_P (selected_frame)
681 && chars_wasted != 0
682 && TN_standout_width == 0 && curX == 0 && chars_wasted[curY] != 0)
683 write_glyphs (&buf, 1);
684 clear_end_of_line_raw (first_unused_hpos);
687 /* Clear from cursor to end of line.
688 Assume that the line is already clear starting at column first_unused_hpos.
689 If the cursor is at a standout marker, erase the marker.
691 Note that the cursor may be moved, on terminals lacking a `ce' string. */
693 clear_end_of_line_raw (first_unused_hpos)
694 int first_unused_hpos;
696 register int i;
698 if (clear_end_of_line_hook
699 && ! FRAME_TERMCAP_P ((updating_frame
700 ? updating_frame
701 : selected_frame)))
703 (*clear_end_of_line_hook) (first_unused_hpos);
704 return;
707 /* Detect the case where we are called from reset_sys_modes
708 and the costs have never been calculated. Do nothing. */
709 if (chars_wasted == 0)
710 return;
712 first_unused_hpos += chars_wasted[curY] & 077;
713 if (curX >= first_unused_hpos)
714 return;
715 /* Notice if we are erasing a magic cookie */
716 if (curX == 0)
717 chars_wasted[curY] = 0;
718 background_highlight ();
719 if (TS_clr_line)
721 OUTPUT1 (TS_clr_line);
723 else
724 { /* have to do it the hard way */
725 turn_off_insert ();
727 /* Do not write in last row last col with Autowrap on. */
728 if (AutoWrap && curY == FRAME_HEIGHT (selected_frame) - 1
729 && first_unused_hpos == FRAME_WIDTH (selected_frame))
730 first_unused_hpos--;
732 for (i = curX; i < first_unused_hpos; i++)
734 if (termscript)
735 fputc (' ', termscript);
736 putchar (' ');
738 cmplus (first_unused_hpos - curX);
743 write_glyphs (string, len)
744 register GLYPH *string;
745 register int len;
747 register GLYPH g;
748 register int tlen = GLYPH_TABLE_LENGTH;
749 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
751 if (write_glyphs_hook
752 && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
754 (*write_glyphs_hook) (string, len);
755 return;
758 highlight_if_desired ();
759 turn_off_insert ();
761 /* Don't dare write in last column of bottom line, if AutoWrap,
762 since that would scroll the whole frame on some terminals. */
764 if (AutoWrap
765 && curY + 1 == FRAME_HEIGHT (selected_frame)
766 && (curX + len - (chars_wasted[curY] & 077)
767 == FRAME_WIDTH (selected_frame)))
768 len --;
770 cmplus (len);
771 while (--len >= 0)
773 g = *string++;
774 /* Check quickly for G beyond length of table.
775 That implies it isn't an alias and is simple. */
776 if (g >= tlen)
778 simple:
779 putc (g & 0xff, stdout);
780 if (ferror (stdout))
781 clearerr (stdout);
782 if (termscript)
783 putc (g & 0xff, termscript);
785 else
787 /* G has an entry in Vglyph_table,
788 so process any alias and then test for simpleness. */
789 while (GLYPH_ALIAS_P (tbase, tlen, g))
790 g = GLYPH_ALIAS (tbase, g);
791 if (GLYPH_SIMPLE_P (tbase, tlen, g))
792 goto simple;
793 else
795 /* Here if G (or its definition as an alias) is not simple. */
796 fwrite (GLYPH_STRING (tbase, g), 1, GLYPH_LENGTH (tbase, g),
797 stdout);
798 if (ferror (stdout))
799 clearerr (stdout);
800 if (termscript)
801 fwrite (GLYPH_STRING (tbase, g), 1, GLYPH_LENGTH (tbase, g),
802 termscript);
806 cmcheckmagic ();
809 /* If start is zero, insert blanks instead of a string at start */
811 insert_glyphs (start, len)
812 register GLYPH *start;
813 register int len;
815 char *buf;
816 register GLYPH g;
817 register int tlen = GLYPH_TABLE_LENGTH;
818 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
820 if (insert_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame))
822 (*insert_glyphs_hook) (start, len);
823 return;
825 highlight_if_desired ();
827 if (TS_ins_multi_chars)
829 buf = tparam (TS_ins_multi_chars, 0, 0, len);
830 OUTPUT1 (buf);
831 xfree (buf);
832 if (start)
833 write_glyphs (start, len);
834 return;
837 turn_on_insert ();
838 cmplus (len);
839 while (--len >= 0)
841 OUTPUT1_IF (TS_ins_char);
842 if (!start)
843 g = SPACEGLYPH;
844 else
845 g = *start++;
847 if (GLYPH_SIMPLE_P (tbase, tlen, g))
849 putc (g & 0xff, stdout);
850 if (ferror (stdout))
851 clearerr (stdout);
852 if (termscript)
853 putc (g & 0xff, termscript);
855 else
857 fwrite (GLYPH_STRING (tbase, g), 1, GLYPH_LENGTH (tbase, g), stdout);
858 if (ferror (stdout))
859 clearerr (stdout);
860 if (termscript)
861 fwrite (GLYPH_STRING (tbase, g), 1, GLYPH_LENGTH (tbase, g),
862 termscript);
865 OUTPUT1_IF (TS_pad_inserted_char);
867 cmcheckmagic ();
870 delete_glyphs (n)
871 register int n;
873 char *buf;
874 register int i;
876 if (delete_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame))
878 (*delete_glyphs_hook) (n);
879 return;
882 if (delete_in_insert_mode)
884 turn_on_insert ();
886 else
888 turn_off_insert ();
889 OUTPUT_IF (TS_delete_mode);
892 if (TS_del_multi_chars)
894 buf = tparam (TS_del_multi_chars, 0, 0, n);
895 OUTPUT1 (buf);
896 xfree (buf);
898 else
899 for (i = 0; i < n; i++)
900 OUTPUT1 (TS_del_char);
901 if (!delete_in_insert_mode)
902 OUTPUT_IF (TS_end_delete_mode);
905 /* Insert N lines at vpos VPOS. If N is negative, delete -N lines. */
907 ins_del_lines (vpos, n)
908 int vpos, n;
910 char *multi = n > 0 ? TS_ins_multi_lines : TS_del_multi_lines;
911 char *single = n > 0 ? TS_ins_line : TS_del_line;
912 char *scroll = n > 0 ? TS_rev_scroll : TS_fwd_scroll;
914 register int i = n > 0 ? n : -n;
915 register char *buf;
917 if (ins_del_lines_hook && ! FRAME_TERMCAP_P (updating_frame))
919 (*ins_del_lines_hook) (vpos, n);
920 return;
923 /* If the lines below the insertion are being pushed
924 into the end of the window, this is the same as clearing;
925 and we know the lines are already clear, since the matching
926 deletion has already been done. So can ignore this. */
927 /* If the lines below the deletion are blank lines coming
928 out of the end of the window, don't bother,
929 as there will be a matching inslines later that will flush them. */
930 if (scroll_region_ok && vpos + i >= specified_window)
931 return;
932 if (!memory_below_frame && vpos + i >= FRAME_HEIGHT (selected_frame))
933 return;
935 if (multi)
937 raw_cursor_to (vpos, 0);
938 background_highlight ();
939 buf = tparam (multi, 0, 0, i);
940 OUTPUT (buf);
941 xfree (buf);
943 else if (single)
945 raw_cursor_to (vpos, 0);
946 background_highlight ();
947 while (--i >= 0)
948 OUTPUT (single);
949 if (TF_teleray)
950 curX = 0;
952 else
954 set_scroll_region (vpos, specified_window);
955 if (n < 0)
956 raw_cursor_to (specified_window - 1, 0);
957 else
958 raw_cursor_to (vpos, 0);
959 background_highlight ();
960 while (--i >= 0)
961 OUTPUTL (scroll, specified_window - vpos);
962 set_scroll_region (0, specified_window);
965 if (TN_standout_width >= 0)
967 register lower_limit
968 = (scroll_region_ok
969 ? specified_window
970 : FRAME_HEIGHT (selected_frame));
972 if (n < 0)
974 bcopy (&chars_wasted[vpos - n], &chars_wasted[vpos],
975 lower_limit - vpos + n);
976 bzero (&chars_wasted[lower_limit + n], - n);
978 else
980 bcopy (&chars_wasted[vpos], &copybuf[vpos], lower_limit - vpos - n);
981 bcopy (&copybuf[vpos], &chars_wasted[vpos + n],
982 lower_limit - vpos - n);
983 bzero (&chars_wasted[vpos], n);
986 if (!scroll_region_ok && memory_below_frame && n < 0)
988 cursor_to (FRAME_HEIGHT (selected_frame) + n, 0);
989 clear_to_end ();
993 /* Compute cost of sending "str", in characters,
994 not counting any line-dependent padding. */
997 string_cost (str)
998 char *str;
1000 cost = 0;
1001 if (str)
1002 tputs (str, 0, evalcost);
1003 return cost;
1006 /* Compute cost of sending "str", in characters,
1007 counting any line-dependent padding at one line. */
1009 static int
1010 string_cost_one_line (str)
1011 char *str;
1013 cost = 0;
1014 if (str)
1015 tputs (str, 1, evalcost);
1016 return cost;
1019 /* Compute per line amount of line-dependent padding,
1020 in tenths of characters. */
1023 per_line_cost (str)
1024 register char *str;
1026 cost = 0;
1027 if (str)
1028 tputs (str, 0, evalcost);
1029 cost = - cost;
1030 if (str)
1031 tputs (str, 10, evalcost);
1032 return cost;
1035 #ifndef old
1036 /* char_ins_del_cost[n] is cost of inserting N characters.
1037 char_ins_del_cost[-n] is cost of deleting N characters.
1038 The length of this vector is based on max_frame_width. */
1040 int *char_ins_del_vector;
1042 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WIDTH ((f))])
1043 #endif
1045 /* ARGSUSED */
1046 static void
1047 calculate_ins_del_char_costs (frame)
1048 FRAME_PTR frame;
1050 int ins_startup_cost, del_startup_cost;
1051 int ins_cost_per_char, del_cost_per_char;
1052 register int i;
1053 register int *p;
1055 if (TS_ins_multi_chars)
1057 ins_cost_per_char = 0;
1058 ins_startup_cost = string_cost_one_line (TS_ins_multi_chars);
1060 else if (TS_ins_char || TS_pad_inserted_char
1061 || (TS_insert_mode && TS_end_insert_mode))
1063 ins_startup_cost = (30 * (string_cost (TS_insert_mode)
1064 + string_cost (TS_end_insert_mode))) / 100;
1065 ins_cost_per_char = (string_cost_one_line (TS_ins_char)
1066 + string_cost_one_line (TS_pad_inserted_char));
1068 else
1070 ins_startup_cost = 9999;
1071 ins_cost_per_char = 0;
1074 if (TS_del_multi_chars)
1076 del_cost_per_char = 0;
1077 del_startup_cost = string_cost_one_line (TS_del_multi_chars);
1079 else if (TS_del_char)
1081 del_startup_cost = (string_cost (TS_delete_mode)
1082 + string_cost (TS_end_delete_mode));
1083 if (delete_in_insert_mode)
1084 del_startup_cost /= 2;
1085 del_cost_per_char = string_cost_one_line (TS_del_char);
1087 else
1089 del_startup_cost = 9999;
1090 del_cost_per_char = 0;
1093 /* Delete costs are at negative offsets */
1094 p = &char_ins_del_cost (frame)[0];
1095 for (i = FRAME_WIDTH (selected_frame); --i >= 0;)
1096 *--p = (del_startup_cost += del_cost_per_char);
1098 /* Doing nothing is free */
1099 p = &char_ins_del_cost (frame)[0];
1100 *p++ = 0;
1102 /* Insert costs are at positive offsets */
1103 for (i = FRAME_WIDTH (frame); --i >= 0;)
1104 *p++ = (ins_startup_cost += ins_cost_per_char);
1107 extern do_line_insertion_deletion_costs ();
1109 calculate_costs (frame)
1110 FRAME_PTR frame;
1112 register char *f = (TS_set_scroll_region
1113 ? TS_set_scroll_region
1114 : TS_set_scroll_region_1);
1116 FRAME_COST_BAUD_RATE (frame) = baud_rate;
1118 scroll_region_cost = string_cost (f);
1119 #ifdef HAVE_X_WINDOWS
1120 if (FRAME_X_P (frame))
1122 do_line_insertion_deletion_costs (frame, 0, ".5*", 0, ".5*",
1123 0, 0,
1124 x_screen_planes (frame));
1125 scroll_region_cost = 0;
1126 return;
1128 #endif
1130 /* These variables are only used for terminal stuff. They are allocated
1131 once for the terminal frame of X-windows emacs, but not used afterwards.
1133 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1134 X turns off char_ins_del_ok.
1136 chars_wasted and copybuf are only used here in term.c in cases where
1137 the term hook isn't called. */
1139 max_frame_height = max (max_frame_height, FRAME_HEIGHT (frame));
1140 max_frame_width = max (max_frame_width, FRAME_WIDTH (frame));
1142 if (chars_wasted != 0)
1143 chars_wasted = (char *) xrealloc (chars_wasted, max_frame_height);
1144 else
1145 chars_wasted = (char *) xmalloc (max_frame_height);
1147 if (copybuf != 0)
1148 copybuf = (char *) xrealloc (copybuf, max_frame_height);
1149 else
1150 copybuf = (char *) xmalloc (max_frame_height);
1152 if (char_ins_del_vector != 0)
1153 char_ins_del_vector
1154 = (int *) xrealloc (char_ins_del_vector,
1155 (sizeof (int)
1156 + 2 * max_frame_width * sizeof (int)));
1157 else
1158 char_ins_del_vector
1159 = (int *) xmalloc (sizeof (int)
1160 + 2 * max_frame_width * sizeof (int));
1162 bzero (chars_wasted, max_frame_height);
1163 bzero (copybuf, max_frame_height);
1164 bzero (char_ins_del_vector, (sizeof (int)
1165 + 2 * max_frame_width * sizeof (int)));
1167 if (f && (!TS_ins_line && !TS_del_line))
1168 do_line_insertion_deletion_costs (frame,
1169 TS_rev_scroll, TS_ins_multi_lines,
1170 TS_fwd_scroll, TS_del_multi_lines,
1171 f, f, 1);
1172 else
1173 do_line_insertion_deletion_costs (frame,
1174 TS_ins_line, TS_ins_multi_lines,
1175 TS_del_line, TS_del_multi_lines,
1176 0, 0, 1);
1178 calculate_ins_del_char_costs (frame);
1180 /* Don't use TS_repeat if its padding is worse than sending the chars */
1181 if (TS_repeat && per_line_cost (TS_repeat) * baud_rate < 9000)
1182 RPov = string_cost (TS_repeat);
1183 else
1184 RPov = FRAME_WIDTH (frame) * 2;
1186 cmcostinit (); /* set up cursor motion costs */
1189 struct fkey_table {
1190 char *cap, *name;
1193 /* Termcap capability names that correspond directly to X keysyms.
1194 Some of these (marked "terminfo") aren't supplied by old-style
1195 (Berkeley) termcap entries. They're listed in X keysym order;
1196 except we put the keypad keys first, so that if they clash with
1197 other keys (as on the IBM PC keyboard) they get overridden.
1200 static struct fkey_table keys[] = {
1201 "kh", "home", /* termcap */
1202 "kl", "left", /* termcap */
1203 "ku", "up", /* termcap */
1204 "kr", "right", /* termcap */
1205 "kd", "down", /* termcap */
1206 "%8", "prior", /* terminfo */
1207 "%5", "next", /* terminfo */
1208 "@7", "end", /* terminfo */
1209 "@1", "begin", /* terminfo */
1210 "*6", "select", /* terminfo */
1211 "%9", "print", /* terminfo */
1212 "@4", "execute", /* terminfo --- actually the `command' key */
1214 * "insert" --- see below
1216 "&8", "undo", /* terminfo */
1217 "%0", "redo", /* terminfo */
1218 "%7", "menu", /* terminfo --- actually the `options' key */
1219 "@0", "find", /* terminfo */
1220 "@2", "cancel", /* terminfo */
1221 "%1", "help", /* terminfo */
1223 * "break" goes here, but can't be reliably intercepted with termcap
1225 "&4", "reset", /* terminfo --- actually `restart' */
1227 * "system" and "user" --- no termcaps
1229 "kE", "clearline", /* terminfo */
1230 "kA", "insertline", /* terminfo */
1231 "kL", "deleteline", /* terminfo */
1232 "kI", "insertchar", /* terminfo */
1233 "kD", "deletechar", /* terminfo */
1234 "kB", "backtab", /* terminfo */
1236 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1238 "@8", "kp-enter", /* terminfo */
1240 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1241 * "kp-multiply", "kp-add", "kp-separator",
1242 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1243 * --- no termcaps for any of these.
1245 "K4", "kp-1", /* terminfo */
1247 * "kp-2" --- no termcap
1249 "K5", "kp-3", /* terminfo */
1251 * "kp-4" --- no termcap
1253 "K2", "kp-5", /* terminfo */
1255 * "kp-6" --- no termcap
1257 "K1", "kp-7", /* terminfo */
1259 * "kp-8" --- no termcap
1261 "K3", "kp-9", /* terminfo */
1263 * "kp-equal" --- no termcap
1265 "k1", "f1",
1266 "k2", "f2",
1267 "k3", "f3",
1268 "k4", "f4",
1269 "k5", "f5",
1270 "k6", "f6",
1271 "k7", "f7",
1272 "k8", "f8",
1273 "k9", "f9",
1276 static char **term_get_fkeys_arg;
1277 static Lisp_Object term_get_fkeys_1 ();
1279 /* Find the escape codes sent by the function keys for Vfunction_key_map.
1280 This function scans the termcap function key sequence entries, and
1281 adds entries to Vfunction_key_map for each function key it finds. */
1283 void
1284 term_get_fkeys (address)
1285 char **address;
1287 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1288 errors during the call. The only errors should be from Fdefine_key
1289 when given a key sequence containing an invalid prefix key. If the
1290 termcap defines function keys which use a prefix that is already bound
1291 to a command by the default bindings, we should silently ignore that
1292 function key specification, rather than giving the user an error and
1293 refusing to run at all on such a terminal. */
1295 extern Lisp_Object Fidentity ();
1296 term_get_fkeys_arg = address;
1297 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1300 static Lisp_Object
1301 term_get_fkeys_1 ()
1303 int i;
1305 char **address = term_get_fkeys_arg;
1307 /* This can happen if CANNOT_DUMP or with strange options. */
1308 if (!initialized)
1309 Vfunction_key_map = Fmake_sparse_keymap (Qnil);
1311 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1313 char *sequence = tgetstr (keys[i].cap, address);
1314 if (sequence)
1315 Fdefine_key (Vfunction_key_map, build_string (sequence),
1316 Fmake_vector (make_number (1),
1317 intern (keys[i].name)));
1320 /* The uses of the "k0" capability are inconsistent; sometimes it
1321 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1322 We will attempt to politely accommodate both systems by testing for
1323 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1326 char *k_semi = tgetstr ("k;", address);
1327 char *k0 = tgetstr ("k0", address);
1328 char *k0_name = "f10";
1330 if (k_semi)
1332 Fdefine_key (Vfunction_key_map, build_string (k_semi),
1333 Fmake_vector (make_number (1), intern ("f10")));
1334 k0_name = "f0";
1337 if (k0)
1338 Fdefine_key (Vfunction_key_map, build_string (k0),
1339 Fmake_vector (make_number (1), intern (k0_name)));
1342 /* Set up cookies for numbered function keys above f10. */
1344 char fcap[3], fkey[4];
1346 fcap[0] = 'F'; fcap[2] = '\0';
1347 for (i = 11; i < 64; i++)
1349 if (i <= 19)
1350 fcap[1] = '1' + i - 11;
1351 else if (i <= 45)
1352 fcap[1] = 'A' + i - 20;
1353 else
1354 fcap[1] = 'a' + i - 46;
1357 char *sequence = tgetstr (fcap, address);
1358 if (sequence)
1360 sprintf (fkey, "f%d", i);
1361 Fdefine_key (Vfunction_key_map, build_string (sequence),
1362 Fmake_vector (make_number (1),
1363 intern (fkey)));
1370 * Various mappings to try and get a better fit.
1373 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1374 if (!tgetstr (cap1, address)) \
1376 char *sequence = tgetstr (cap2, address); \
1377 if (sequence) \
1378 Fdefine_key (Vfunction_key_map, build_string (sequence), \
1379 Fmake_vector (make_number (1), \
1380 intern (sym))); \
1383 /* if there's no key_next keycap, map key_npage to `next' keysym */
1384 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1385 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1386 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1387 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1388 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1390 /* IBM has their own non-standard dialect of terminfo.
1391 If the standard name isn't found, try the IBM name. */
1392 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1393 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1394 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1395 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1396 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1397 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1398 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1399 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1400 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1401 #undef CONDITIONAL_REASSIGN
1406 term_init (terminal_type)
1407 char *terminal_type;
1409 char *area;
1410 char **address = &area;
1411 char buffer[2044];
1412 register char *p;
1413 int status;
1415 #ifdef WINDOWSNT
1416 initialize_win_nt_display ();
1418 Wcm_clear ();
1420 area = (char *) malloc (2044);
1422 if (area == 0)
1423 abort ();
1425 FrameRows = FRAME_HEIGHT (selected_frame);
1426 FrameCols = FRAME_WIDTH (selected_frame);
1427 specified_window = FRAME_HEIGHT (selected_frame);
1429 delete_in_insert_mode = 1;
1431 UseTabs = 0;
1432 scroll_region_ok = 0;
1434 /* Seems to insert lines when it's not supposed to, messing
1435 up the display. In doing a trace, it didn't seem to be
1436 called much, so I don't think we're losing anything by
1437 turning it off. */
1439 line_ins_del_ok = 0;
1440 char_ins_del_ok = 1;
1442 baud_rate = 19200;
1444 FRAME_CAN_HAVE_SCROLL_BARS (selected_frame) = 0;
1445 FRAME_HAS_VERTICAL_SCROLL_BARS (selected_frame) = 0;
1447 return;
1448 #endif /* WINDOWSNT */
1450 Wcm_clear ();
1452 status = tgetent (buffer, terminal_type);
1453 if (status < 0)
1455 #ifdef TERMINFO
1456 fatal ("Cannot open terminfo database file.\n");
1457 #else
1458 fatal ("Cannot open termcap database file.\n");
1459 #endif
1461 if (status == 0)
1463 #ifdef TERMINFO
1464 fatal ("Terminal type %s is not defined.\n\
1465 If that is not the actual type of terminal you have,\n\
1466 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
1467 `setenv TERM ...') to specify the correct type. It may be necessary\n\
1468 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.\n",
1469 terminal_type);
1470 #else
1471 fatal ("Terminal type %s is not defined.\n\
1472 If that is not the actual type of terminal you have,\n\
1473 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
1474 `setenv TERM ...') to specify the correct type. It may be necessary\n\
1475 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.\n",
1476 terminal_type);
1477 #endif
1479 #ifdef TERMINFO
1480 area = (char *) malloc (2044);
1481 #else
1482 area = (char *) malloc (strlen (buffer));
1483 #endif /* not TERMINFO */
1484 if (area == 0)
1485 abort ();
1487 TS_ins_line = tgetstr ("al", address);
1488 TS_ins_multi_lines = tgetstr ("AL", address);
1489 TS_bell = tgetstr ("bl", address);
1490 BackTab = tgetstr ("bt", address);
1491 TS_clr_to_bottom = tgetstr ("cd", address);
1492 TS_clr_line = tgetstr ("ce", address);
1493 TS_clr_frame = tgetstr ("cl", address);
1494 ColPosition = tgetstr ("ch", address);
1495 AbsPosition = tgetstr ("cm", address);
1496 CR = tgetstr ("cr", address);
1497 TS_set_scroll_region = tgetstr ("cs", address);
1498 TS_set_scroll_region_1 = tgetstr ("cS", address);
1499 RowPosition = tgetstr ("cv", address);
1500 TS_del_char = tgetstr ("dc", address);
1501 TS_del_multi_chars = tgetstr ("DC", address);
1502 TS_del_line = tgetstr ("dl", address);
1503 TS_del_multi_lines = tgetstr ("DL", address);
1504 TS_delete_mode = tgetstr ("dm", address);
1505 TS_end_delete_mode = tgetstr ("ed", address);
1506 TS_end_insert_mode = tgetstr ("ei", address);
1507 Home = tgetstr ("ho", address);
1508 TS_ins_char = tgetstr ("ic", address);
1509 TS_ins_multi_chars = tgetstr ("IC", address);
1510 TS_insert_mode = tgetstr ("im", address);
1511 TS_pad_inserted_char = tgetstr ("ip", address);
1512 TS_end_keypad_mode = tgetstr ("ke", address);
1513 TS_keypad_mode = tgetstr ("ks", address);
1514 LastLine = tgetstr ("ll", address);
1515 Right = tgetstr ("nd", address);
1516 Down = tgetstr ("do", address);
1517 if (!Down)
1518 Down = tgetstr ("nl", address); /* Obsolete name for "do" */
1519 #ifdef VMS
1520 /* VMS puts a carriage return before each linefeed,
1521 so it is not safe to use linefeeds. */
1522 if (Down && Down[0] == '\n' && Down[1] == '\0')
1523 Down = 0;
1524 #endif /* VMS */
1525 if (tgetflag ("bs"))
1526 Left = "\b"; /* can't possibly be longer! */
1527 else /* (Actually, "bs" is obsolete...) */
1528 Left = tgetstr ("le", address);
1529 if (!Left)
1530 Left = tgetstr ("bc", address); /* Obsolete name for "le" */
1531 TS_pad_char = tgetstr ("pc", address);
1532 TS_repeat = tgetstr ("rp", address);
1533 TS_end_standout_mode = tgetstr ("se", address);
1534 TS_fwd_scroll = tgetstr ("sf", address);
1535 TS_standout_mode = tgetstr ("so", address);
1536 TS_rev_scroll = tgetstr ("sr", address);
1537 Wcm.cm_tab = tgetstr ("ta", address);
1538 TS_end_termcap_modes = tgetstr ("te", address);
1539 TS_termcap_modes = tgetstr ("ti", address);
1540 Up = tgetstr ("up", address);
1541 TS_visible_bell = tgetstr ("vb", address);
1542 TS_end_visual_mode = tgetstr ("ve", address);
1543 TS_visual_mode = tgetstr ("vs", address);
1544 TS_set_window = tgetstr ("wi", address);
1545 MultiUp = tgetstr ("UP", address);
1546 MultiDown = tgetstr ("DO", address);
1547 MultiLeft = tgetstr ("LE", address);
1548 MultiRight = tgetstr ("RI", address);
1550 MagicWrap = tgetflag ("xn");
1551 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
1552 the former flag imply the latter. */
1553 AutoWrap = MagicWrap || tgetflag ("am");
1554 memory_below_frame = tgetflag ("db");
1555 TF_hazeltine = tgetflag ("hz");
1556 must_write_spaces = tgetflag ("in");
1557 meta_key = tgetflag ("km") || tgetflag ("MT");
1558 TF_insmode_motion = tgetflag ("mi");
1559 TF_standout_motion = tgetflag ("ms");
1560 TF_underscore = tgetflag ("ul");
1561 TF_xs = tgetflag ("xs");
1562 TF_teleray = tgetflag ("xt");
1564 term_get_fkeys (address);
1566 /* Get frame size from system, or else from termcap. */
1567 get_frame_size (&FRAME_WIDTH (selected_frame),
1568 &FRAME_HEIGHT (selected_frame));
1569 if (FRAME_WIDTH (selected_frame) <= 0)
1570 FRAME_WIDTH (selected_frame) = tgetnum ("co");
1571 if (FRAME_HEIGHT (selected_frame) <= 0)
1572 FRAME_HEIGHT (selected_frame) = tgetnum ("li");
1574 if (FRAME_HEIGHT (selected_frame) < 3
1575 || FRAME_WIDTH (selected_frame) < 3)
1576 fatal ("Screen size %dx%d is too small.\n",
1577 FRAME_HEIGHT (selected_frame), FRAME_WIDTH (selected_frame));
1579 min_padding_speed = tgetnum ("pb");
1580 TN_standout_width = tgetnum ("sg");
1581 TabWidth = tgetnum ("tw");
1583 #ifdef VMS
1584 /* These capabilities commonly use ^J.
1585 I don't know why, but sending them on VMS does not work;
1586 it causes following spaces to be lost, sometimes.
1587 For now, the simplest fix is to avoid using these capabilities ever. */
1588 if (Down && Down[0] == '\n')
1589 Down = 0;
1590 #endif /* VMS */
1592 if (!TS_bell)
1593 TS_bell = "\07";
1595 if (!TS_fwd_scroll)
1596 TS_fwd_scroll = Down;
1598 PC = TS_pad_char ? *TS_pad_char : 0;
1600 if (TabWidth < 0)
1601 TabWidth = 8;
1603 /* Turned off since /etc/termcap seems to have :ta= for most terminals
1604 and newer termcap doc does not seem to say there is a default.
1605 if (!Wcm.cm_tab)
1606 Wcm.cm_tab = "\t";
1609 if (TS_standout_mode == 0)
1611 TN_standout_width = tgetnum ("ug");
1612 TS_end_standout_mode = tgetstr ("ue", address);
1613 TS_standout_mode = tgetstr ("us", address);
1616 /* If no `se' string, try using a `me' string instead.
1617 If that fails, we can't use standout mode at all. */
1618 if (TS_end_standout_mode == 0)
1620 char *s = tgetstr ("me", address);
1621 if (s != 0)
1622 TS_end_standout_mode = s;
1623 else
1624 TS_standout_mode = 0;
1627 if (TF_teleray)
1629 Wcm.cm_tab = 0;
1630 /* Teleray: most programs want a space in front of TS_standout_mode,
1631 but Emacs can do without it (and give one extra column). */
1632 TS_standout_mode = "\033RD";
1633 TN_standout_width = 1;
1634 /* But that means we cannot rely on ^M to go to column zero! */
1635 CR = 0;
1636 /* LF can't be trusted either -- can alter hpos */
1637 /* if move at column 0 thru a line with TS_standout_mode */
1638 Down = 0;
1641 /* Special handling for certain terminal types known to need it */
1643 if (!strcmp (terminal_type, "supdup"))
1645 memory_below_frame = 1;
1646 Wcm.cm_losewrap = 1;
1648 if (!strncmp (terminal_type, "c10", 3)
1649 || !strcmp (terminal_type, "perq"))
1651 /* Supply a makeshift :wi string.
1652 This string is not valid in general since it works only
1653 for windows starting at the upper left corner;
1654 but that is all Emacs uses.
1656 This string works only if the frame is using
1657 the top of the video memory, because addressing is memory-relative.
1658 So first check the :ti string to see if that is true.
1660 It would be simpler if the :wi string could go in the termcap
1661 entry, but it can't because it is not fully valid.
1662 If it were in the termcap entry, it would confuse other programs. */
1663 if (!TS_set_window)
1665 p = TS_termcap_modes;
1666 while (*p && strcmp (p, "\033v "))
1667 p++;
1668 if (*p)
1669 TS_set_window = "\033v%C %C %C %C ";
1671 /* Termcap entry often fails to have :in: flag */
1672 must_write_spaces = 1;
1673 /* :ti string typically fails to have \E^G! in it */
1674 /* This limits scope of insert-char to one line. */
1675 strcpy (area, TS_termcap_modes);
1676 strcat (area, "\033\007!");
1677 TS_termcap_modes = area;
1678 area += strlen (area) + 1;
1679 p = AbsPosition;
1680 /* Change all %+ parameters to %C, to handle
1681 values above 96 correctly for the C100. */
1682 while (*p)
1684 if (p[0] == '%' && p[1] == '+')
1685 p[1] = 'C';
1686 p++;
1690 FrameRows = FRAME_HEIGHT (selected_frame);
1691 FrameCols = FRAME_WIDTH (selected_frame);
1692 specified_window = FRAME_HEIGHT (selected_frame);
1694 if (Wcm_init () == -1) /* can't do cursor motion */
1695 #ifdef VMS
1696 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
1697 It lacks the ability to position the cursor.\n\
1698 If that is not the actual type of terminal you have, use either the\n\
1699 DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
1700 or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.\n",
1701 terminal_type);
1702 #else /* not VMS */
1703 # ifdef TERMINFO
1704 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
1705 It lacks the ability to position the cursor.\n\
1706 If that is not the actual type of terminal you have,\n\
1707 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
1708 `setenv TERM ...') to specify the correct type. It may be necessary\n\
1709 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.\n",
1710 terminal_type);
1711 # else /* TERMCAP */
1712 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
1713 It lacks the ability to position the cursor.\n\
1714 If that is not the actual type of terminal you have,\n\
1715 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
1716 `setenv TERM ...') to specify the correct type. It may be necessary\n\
1717 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.\n",
1718 terminal_type);
1719 # endif /* TERMINFO */
1720 #endif /*VMS */
1721 if (FRAME_HEIGHT (selected_frame) <= 0
1722 || FRAME_WIDTH (selected_frame) <= 0)
1723 fatal ("The frame size has not been specified.");
1725 delete_in_insert_mode
1726 = TS_delete_mode && TS_insert_mode
1727 && !strcmp (TS_delete_mode, TS_insert_mode);
1729 se_is_so = (TS_standout_mode
1730 && TS_end_standout_mode
1731 && !strcmp (TS_standout_mode, TS_end_standout_mode));
1733 /* Remove width of standout marker from usable width of line */
1734 if (TN_standout_width > 0)
1735 FRAME_WIDTH (selected_frame) -= TN_standout_width;
1737 UseTabs = tabs_safe_p () && TabWidth == 8;
1739 scroll_region_ok
1740 = (Wcm.cm_abs
1741 && (TS_set_window || TS_set_scroll_region || TS_set_scroll_region_1));
1743 line_ins_del_ok = (((TS_ins_line || TS_ins_multi_lines)
1744 && (TS_del_line || TS_del_multi_lines))
1745 || (scroll_region_ok && TS_fwd_scroll && TS_rev_scroll));
1747 char_ins_del_ok = ((TS_ins_char || TS_insert_mode
1748 || TS_pad_inserted_char || TS_ins_multi_chars)
1749 && (TS_del_char || TS_del_multi_chars));
1751 fast_clear_end_of_line = TS_clr_line != 0;
1753 init_baud_rate ();
1754 if (read_socket_hook) /* Baudrate is somewhat */
1755 /* meaningless in this case */
1756 baud_rate = 9600;
1758 FRAME_CAN_HAVE_SCROLL_BARS (selected_frame) = 0;
1759 FRAME_HAS_VERTICAL_SCROLL_BARS (selected_frame) = 0;
1762 /* VARARGS 1 */
1763 fatal (str, arg1, arg2)
1764 char *str, *arg1, *arg2;
1766 fprintf (stderr, "emacs: ");
1767 fprintf (stderr, str, arg1, arg2);
1768 fflush (stderr);
1769 exit (1);
1772 syms_of_term ()
1774 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
1775 "Non-nil means the system uses terminfo rather than termcap.\n\
1776 This variable can be used by terminal emulator packages.");
1777 #ifdef TERMINFO
1778 system_uses_terminfo = 1;
1779 #else
1780 system_uses_terminfo = 0;
1781 #endif