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)
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. */
34 #include "termhooks.h"
37 extern Lisp_Object
Fmake_sparse_keymap ();
39 #define max(a, b) ((a) > (b) ? (a) : (b))
40 #define min(a, b) ((a) < (b) ? (a) : (b))
42 #define OUTPUT(a) tputs (a, (int) (FRAME_HEIGHT (selected_frame) - curY), cmputc)
43 #define OUTPUT1(a) tputs (a, 1, cmputc)
44 #define OUTPUTL(a, lines) tputs (a, lines, cmputc)
45 #define OUTPUT_IF(a) { if (a) tputs (a, (int) (FRAME_HEIGHT (selected_frame) - curY), cmputc); }
46 #define OUTPUT1_IF(a) { if (a) tputs (a, 1, cmputc); }
48 /* Function to use to ring the bell. */
49 Lisp_Object Vring_bell_function
;
51 /* Terminal characteristics that higher levels want to look at.
52 These are all extern'd in termchar.h */
54 int must_write_spaces
; /* Nonzero means spaces in the text
55 must actually be output; can't just skip
56 over some columns to leave them blank. */
57 int min_padding_speed
; /* Speed below which no padding necessary */
59 int line_ins_del_ok
; /* Terminal can insert and delete lines */
60 int char_ins_del_ok
; /* Terminal can insert and delete chars */
61 int scroll_region_ok
; /* Terminal supports setting the
63 int scroll_region_cost
; /* Cost of setting a scroll window,
64 measured in characters */
65 int memory_below_frame
; /* Terminal remembers lines
66 scrolled off bottom */
67 int fast_clear_end_of_line
; /* Terminal has a `ce' string */
69 /* Nonzero means no need to redraw the entire frame on resuming
70 a suspended Emacs. This is useful on terminals with multiple pages,
71 where one page is used for Emacs and another for all else. */
72 int no_redraw_on_reenter
;
74 /* Hook functions that you can set to snap out the functions in this file.
75 These are all extern'd in termhooks.h */
77 int (*cursor_to_hook
) ();
78 int (*raw_cursor_to_hook
) ();
80 int (*clear_to_end_hook
) ();
81 int (*clear_frame_hook
) ();
82 int (*clear_end_of_line_hook
) ();
84 int (*ins_del_lines_hook
) ();
86 int (*change_line_highlight_hook
) ();
87 int (*reassert_line_highlight_hook
) ();
89 int (*insert_glyphs_hook
) ();
90 int (*write_glyphs_hook
) ();
91 int (*delete_glyphs_hook
) ();
93 int (*ring_bell_hook
) ();
95 int (*reset_terminal_modes_hook
) ();
96 int (*set_terminal_modes_hook
) ();
97 int (*update_begin_hook
) ();
98 int (*update_end_hook
) ();
99 int (*set_terminal_window_hook
) ();
101 int (*read_socket_hook
) ();
103 int (*frame_up_to_date_hook
) ();
105 /* Return the current position of the mouse.
107 Set *f to the frame the mouse is in, or zero if the mouse is in no
108 Emacs frame. If it is set to zero, all the other arguments are
111 If the motion started in a scroll bar, set *bar_window to the
112 scroll bar's window, *part to the part the mouse is currently over,
113 *x to the position of the mouse along the scroll bar, and *y to the
114 overall length of the scroll bar.
116 Otherwise, set *bar_window to Qnil, and *x and *y to the column and
117 row of the character cell the mouse is over.
119 Set *time to the time the mouse was at the returned position.
121 This should clear mouse_moved until the next motion
123 void (*mouse_position_hook
) ( /* FRAME_PTR *f, int insist,
124 Lisp_Object *bar_window,
125 enum scroll_bar_part *part,
128 unsigned long *time */ );
130 /* When reading from a minibuffer in a different frame, Emacs wants
131 to shift the highlight from the selected frame to the minibuffer's
132 frame; under X, this means it lies about where the focus is.
133 This hook tells the window system code to re-decide where to put
135 void (*frame_rehighlight_hook
) ( /* FRAME_PTR f */ );
137 /* If we're displaying frames using a window system that can stack
138 frames on top of each other, this hook allows you to bring a frame
139 to the front, or bury it behind all the other windows. If this
140 hook is zero, that means the device we're displaying on doesn't
141 support overlapping frames, so there's no need to raise or lower
144 If RAISE is non-zero, F is brought to the front, before all other
145 windows. If RAISE is zero, F is sent to the back, behind all other
147 void (*frame_raise_lower_hook
) ( /* FRAME_PTR f, int raise */ );
149 /* Set the vertical scroll bar for WINDOW to have its upper left corner
150 at (TOP, LEFT), and be LENGTH rows high. Set its handle to
151 indicate that we are displaying PORTION characters out of a total
152 of WHOLE characters, starting at POSITION. If WINDOW doesn't yet
153 have a scroll bar, create one for it. */
154 void (*set_vertical_scroll_bar_hook
)
155 ( /* struct window *window,
156 int portion, int whole, int position */ );
159 /* The following three hooks are used when we're doing a thorough
160 redisplay of the frame. We don't explicitly know which scroll bars
161 are going to be deleted, because keeping track of when windows go
162 away is a real pain - can you say set-window-configuration?
163 Instead, we just assert at the beginning of redisplay that *all*
164 scroll bars are to be removed, and then save scroll bars from the
165 fiery pit when we actually redisplay their window. */
167 /* Arrange for all scroll bars on FRAME to be removed at the next call
168 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
169 `*redeem_scroll_bar_hook' is applied to its window before the judgement.
171 This should be applied to each frame each time its window tree is
172 redisplayed, even if it is not displaying scroll bars at the moment;
173 if the HAS_SCROLL_BARS flag has just been turned off, only calling
174 this and the judge_scroll_bars_hook will get rid of them.
176 If non-zero, this hook should be safe to apply to any frame,
177 whether or not it can support scroll bars, and whether or not it is
178 currently displaying them. */
179 void (*condemn_scroll_bars_hook
)( /* FRAME_PTR *frame */ );
181 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
182 Note that it's okay to redeem a scroll bar that is not condemned. */
183 void (*redeem_scroll_bar_hook
)( /* struct window *window */ );
185 /* Remove all scroll bars on FRAME that haven't been saved since the
186 last call to `*condemn_scroll_bars_hook'.
188 This should be applied to each frame after each time its window
189 tree is redisplayed, even if it is not displaying scroll bars at the
190 moment; if the HAS_SCROLL_BARS flag has just been turned off, only
191 calling this and condemn_scroll_bars_hook will get rid of them.
193 If non-zero, this hook should be safe to apply to any frame,
194 whether or not it can support scroll bars, and whether or not it is
195 currently displaying them. */
196 void (*judge_scroll_bars_hook
)( /* FRAME_PTR *FRAME */ );
199 /* Strings, numbers and flags taken from the termcap entry. */
201 char *TS_end_italic_mode
; /* termcap "ae" */
202 char *TS_ins_line
; /* "al" */
203 char *TS_italic_mode
; /* "as" */
204 char *TS_ins_multi_lines
; /* "AL" (one parameter, # lines to insert) */
205 char *TS_bell
; /* "bl" */
206 char *TS_clr_to_bottom
; /* "cd" */
207 char *TS_clr_line
; /* "ce", clear to end of line */
208 char *TS_clr_frame
; /* "cl" */
209 char *TS_set_scroll_region
; /* "cs" (2 params, first line and last line) */
210 char *TS_set_scroll_region_1
; /* "cS" (4 params: total lines,
211 lines above scroll region, lines below it,
212 total lines again) */
213 char *TS_del_char
; /* "dc" */
214 char *TS_del_multi_chars
; /* "DC" (one parameter, # chars to delete) */
215 char *TS_del_line
; /* "dl" */
216 char *TS_del_multi_lines
; /* "DL" (one parameter, # lines to delete) */
217 char *TS_delete_mode
; /* "dm", enter character-delete mode */
218 char *TS_end_delete_mode
; /* "ed", leave character-delete mode */
219 char *TS_end_insert_mode
; /* "ei", leave character-insert mode */
220 char *TS_ins_char
; /* "ic" */
221 char *TS_ins_multi_chars
; /* "IC" (one parameter, # chars to insert) */
222 char *TS_insert_mode
; /* "im", enter character-insert mode */
223 char *TS_pad_inserted_char
; /* "ip". Just padding, no commands. */
224 char *TS_end_keypad_mode
; /* "ke" */
225 char *TS_keypad_mode
; /* "ks" */
226 char *TS_bold_mode
; /* "md" */
227 char *TS_end_bold_mode
; /* "me" */
228 char *TS_pad_char
; /* "pc", char to use as padding */
229 char *TS_repeat
; /* "rp" (2 params, # times to repeat
230 and character to be repeated) */
231 char *TS_end_standout_mode
; /* "se" */
232 char *TS_fwd_scroll
; /* "sf" */
233 char *TS_standout_mode
; /* "so" */
234 char *TS_rev_scroll
; /* "sr" */
235 char *TS_end_termcap_modes
; /* "te" */
236 char *TS_termcap_modes
; /* "ti" */
237 char *TS_end_underscore_mode
; /* "ue" */
238 char *TS_underscore_mode
; /* "us" */
239 char *TS_visible_bell
; /* "vb" */
240 char *TS_end_visual_mode
; /* "ve" */
241 char *TS_visual_mode
; /* "vi" */
242 char *TS_set_window
; /* "wi" (4 params, start and end of window,
243 each as vpos and hpos) */
245 int TF_hazeltine
; /* termcap hz flag. */
246 int TF_insmode_motion
; /* termcap mi flag: can move while in insert mode. */
247 int TF_standout_motion
; /* termcap mi flag: can move while in standout mode. */
248 int TF_underscore
; /* termcap ul flag: _ underlines if overstruck on
249 nonblank position. Must clear before writing _. */
250 int TF_teleray
; /* termcap xt flag: many weird consequences.
253 int TF_xs
; /* Nonzero for "xs". If set together with
254 TN_standout_width == 0, it means don't bother
255 to write any end-standout cookies. */
257 int TN_standout_width
; /* termcap sg number: width occupied by standout
260 static int RPov
; /* # chars to start a TS_repeat */
262 static int delete_in_insert_mode
; /* delete mode == insert mode */
264 static int se_is_so
; /* 1 if same string both enters and leaves
269 /* The largest frame width in any call to calculate_costs. */
271 /* The largest frame height in any call to calculate_costs. */
272 int max_frame_height
;
274 /* Number of chars of space used for standout marker at beginning of line,
275 or'd with 0100. Zero if no standout marker at all.
276 The length of these vectors is max_frame_height.
278 Used IFF TN_standout_width >= 0. */
280 static char *chars_wasted
;
281 static char *copybuf
;
283 /* nonzero means supposed to write text in standout mode. */
284 int standout_requested
;
286 int insert_mode
; /* Nonzero when in insert mode. */
287 int standout_mode
; /* Nonzero when in standout mode. */
289 /* Size of window specified by higher levels.
290 This is the number of lines, from the top of frame downwards,
291 which can participate in insert-line/delete-line operations.
293 Effectively it excludes the bottom frame_height - specified_window_size
294 lines from those operations. */
296 int specified_window
;
298 /* Frame currently being redisplayed; 0 if not currently redisplaying.
299 (Direct output does not count). */
301 FRAME_PTR updating_frame
;
303 /* Provided for lisp packages. */
304 static int system_uses_terminfo
;
308 extern char *tgetstr ();
312 /* We aren't X windows, but we aren't termcap either. This makes me
313 uncertain as to what value to use for frame.output_method. For
314 this file, we'll define FRAME_TERMCAP_P to be zero so that our
315 output hooks get called instead of the termcap functions. Probably
316 the best long-term solution is to define an output_windows_nt... */
318 #undef FRAME_TERMCAP_P
319 #define FRAME_TERMCAP_P(_f_) 0
320 #endif /* WINDOWSNT */
324 if (! NILP (Vring_bell_function
))
326 Lisp_Object function
;
328 /* Temporarily set the global variable to nil
329 so that if we get an error, it stays nil
330 and we don't call it over and over.
332 We don't specbind it, because that would carefully
333 restore the bad value if there's an error
334 and make the loop of errors happen anyway. */
335 function
= Vring_bell_function
;
336 Vring_bell_function
= Qnil
;
340 Vring_bell_function
= function
;
344 if (! FRAME_TERMCAP_P (selected_frame
))
346 (*ring_bell_hook
) ();
349 OUTPUT (TS_visible_bell
&& visible_bell
? TS_visible_bell
: TS_bell
);
352 set_terminal_modes ()
354 if (! FRAME_TERMCAP_P (selected_frame
))
356 (*set_terminal_modes_hook
) ();
359 OUTPUT_IF (TS_termcap_modes
);
360 OUTPUT_IF (TS_visual_mode
);
361 OUTPUT_IF (TS_keypad_mode
);
365 reset_terminal_modes ()
367 if (! FRAME_TERMCAP_P (selected_frame
))
369 (*reset_terminal_modes_hook
) ();
372 if (TN_standout_width
< 0)
373 turn_off_highlight ();
375 OUTPUT_IF (TS_end_keypad_mode
);
376 OUTPUT_IF (TS_end_visual_mode
);
377 OUTPUT_IF (TS_end_termcap_modes
);
378 /* Output raw CR so kernel can track the cursor hpos. */
379 /* But on magic-cookie terminals this can erase an end-standout marker and
380 cause the rest of the frame to be in standout, so move down first. */
381 if (TN_standout_width
>= 0)
390 if (! FRAME_TERMCAP_P (updating_frame
))
391 (*update_begin_hook
) (f
);
397 if (! FRAME_TERMCAP_P (updating_frame
))
399 (*update_end_hook
) (f
);
404 background_highlight ();
405 standout_requested
= 0;
409 set_terminal_window (size
)
412 if (! FRAME_TERMCAP_P (updating_frame
))
414 (*set_terminal_window_hook
) (size
);
417 specified_window
= size
? size
: FRAME_HEIGHT (selected_frame
);
418 if (!scroll_region_ok
)
420 set_scroll_region (0, specified_window
);
423 set_scroll_region (start
, stop
)
427 if (TS_set_scroll_region
)
429 buf
= tparam (TS_set_scroll_region
, 0, 0, start
, stop
- 1);
431 else if (TS_set_scroll_region_1
)
433 buf
= tparam (TS_set_scroll_region_1
, 0, 0,
434 FRAME_HEIGHT (selected_frame
), start
,
435 FRAME_HEIGHT (selected_frame
) - stop
,
436 FRAME_HEIGHT (selected_frame
));
440 buf
= tparam (TS_set_window
, 0, 0, start
, 0, stop
, FRAME_WIDTH (selected_frame
));
450 OUTPUT (TS_insert_mode
);
457 OUTPUT (TS_end_insert_mode
);
461 /* Handle highlighting when TN_standout_width (termcap sg) is not specified.
462 In these terminals, output is affected by the value of standout
463 mode when the output is written.
465 These functions are called on all terminals, but do nothing
466 on terminals whose standout mode does not work that way. */
468 turn_off_highlight ()
470 if (TN_standout_width
< 0)
473 OUTPUT_IF (TS_end_standout_mode
);
480 if (TN_standout_width
< 0)
483 OUTPUT_IF (TS_standout_mode
);
488 /* Set standout mode to the state it should be in for
489 empty space inside windows. What this is,
490 depends on the user option inverse-video. */
492 background_highlight ()
494 if (TN_standout_width
>= 0)
497 turn_on_highlight ();
499 turn_off_highlight ();
502 /* Set standout mode to the mode specified for the text to be output. */
505 highlight_if_desired ()
507 if (TN_standout_width
>= 0)
509 if (!inverse_video
== !standout_requested
)
510 turn_off_highlight ();
512 turn_on_highlight ();
515 /* Handle standout mode for terminals in which TN_standout_width >= 0.
516 On these terminals, standout is controlled by markers that
517 live inside the terminal's memory. TN_standout_width is the width
518 that the marker occupies in memory. Standout runs from the marker
519 to the end of the line on some terminals, or to the next
520 turn-off-standout marker (TS_end_standout_mode) string
521 on other terminals. */
523 /* Write a standout marker or end-standout marker at the front of the line
524 at vertical position vpos. */
526 write_standout_marker (flag
, vpos
)
529 if (flag
|| (TS_end_standout_mode
&& !TF_teleray
&& !se_is_so
530 && !(TF_xs
&& TN_standout_width
== 0)))
533 cmplus (TN_standout_width
);
534 OUTPUT (flag
? TS_standout_mode
: TS_end_standout_mode
);
535 chars_wasted
[curY
] = TN_standout_width
| 0100;
539 /* External interface to control of standout mode.
540 Call this when about to modify line at position VPOS
541 and not change whether it is highlighted. */
543 reassert_line_highlight (highlight
, vpos
)
547 if (! FRAME_TERMCAP_P ((updating_frame
? updating_frame
: selected_frame
)))
549 (*reassert_line_highlight_hook
) (highlight
, vpos
);
552 if (TN_standout_width
< 0)
553 /* Handle terminals where standout takes affect at output time */
554 standout_requested
= highlight
;
555 else if (chars_wasted
[vpos
] == 0)
556 /* For terminals with standout markers, write one on this line
557 if there isn't one already. */
558 write_standout_marker (highlight
, vpos
);
561 /* Call this when about to modify line at position VPOS
562 and change whether it is highlighted. */
564 change_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
565 int new_highlight
, vpos
, first_unused_hpos
;
567 standout_requested
= new_highlight
;
568 if (! FRAME_TERMCAP_P (updating_frame
))
570 (*change_line_highlight_hook
) (new_highlight
, vpos
, first_unused_hpos
);
576 if (TN_standout_width
< 0)
577 background_highlight ();
578 /* If line starts with a marker, delete the marker */
579 else if (TS_clr_line
&& chars_wasted
[curY
])
582 /* On Teleray, make sure to erase the SO marker. */
585 cmgoto (curY
- 1, FRAME_WIDTH (selected_frame
) - 4);
587 curY
++; /* ESC S moves to next line where the TS_standout_mode was */
591 cmgoto (curY
, 0); /* reposition to kill standout marker */
593 clear_end_of_line_raw (first_unused_hpos
);
594 reassert_line_highlight (new_highlight
, curY
);
598 /* Move to absolute position, specified origin 0 */
603 if (! FRAME_TERMCAP_P ((updating_frame
608 (*cursor_to_hook
) (row
, col
);
612 /* Detect the case where we are called from reset_sys_modes
613 and the costs have never been calculated. Do nothing. */
614 if (chars_wasted
== 0)
617 col
+= chars_wasted
[row
] & 077;
618 if (curY
== row
&& curX
== col
)
620 if (!TF_standout_motion
)
621 background_highlight ();
622 if (!TF_insmode_motion
)
627 /* Similar but don't take any account of the wasted characters. */
629 raw_cursor_to (row
, col
)
632 if (! FRAME_TERMCAP_P ((updating_frame
? updating_frame
: selected_frame
)))
634 (*raw_cursor_to_hook
) (row
, col
);
637 if (curY
== row
&& curX
== col
)
639 if (!TF_standout_motion
)
640 background_highlight ();
641 if (!TF_insmode_motion
)
646 /* Erase operations */
648 /* clear from cursor to end of frame */
653 if (clear_to_end_hook
&& ! FRAME_TERMCAP_P (updating_frame
))
655 (*clear_to_end_hook
) ();
658 if (TS_clr_to_bottom
)
660 background_highlight ();
661 OUTPUT (TS_clr_to_bottom
);
662 bzero (chars_wasted
+ curY
, FRAME_HEIGHT (selected_frame
) - curY
);
666 for (i
= curY
; i
< FRAME_HEIGHT (selected_frame
); i
++)
669 clear_end_of_line_raw (FRAME_WIDTH (selected_frame
));
674 /* Clear entire frame */
679 && ! FRAME_TERMCAP_P ((updating_frame
? updating_frame
: selected_frame
)))
681 (*clear_frame_hook
) ();
686 background_highlight ();
687 OUTPUT (TS_clr_frame
);
688 bzero (chars_wasted
, FRAME_HEIGHT (selected_frame
));
698 /* Clear to end of line, but do not clear any standout marker.
699 Assumes that the cursor is positioned at a character of real text,
700 which implies it cannot be before a standout marker
701 unless the marker has zero width.
703 Note that the cursor may be moved. */
705 clear_end_of_line (first_unused_hpos
)
706 int first_unused_hpos
;
708 static GLYPH buf
= SPACEGLYPH
;
709 if (FRAME_TERMCAP_P (selected_frame
)
711 && TN_standout_width
== 0 && curX
== 0 && chars_wasted
[curY
] != 0)
712 write_glyphs (&buf
, 1);
713 clear_end_of_line_raw (first_unused_hpos
);
716 /* Clear from cursor to end of line.
717 Assume that the line is already clear starting at column first_unused_hpos.
718 If the cursor is at a standout marker, erase the marker.
720 Note that the cursor may be moved, on terminals lacking a `ce' string. */
722 clear_end_of_line_raw (first_unused_hpos
)
723 int first_unused_hpos
;
727 if (clear_end_of_line_hook
728 && ! FRAME_TERMCAP_P ((updating_frame
732 (*clear_end_of_line_hook
) (first_unused_hpos
);
736 /* Detect the case where we are called from reset_sys_modes
737 and the costs have never been calculated. Do nothing. */
738 if (chars_wasted
== 0)
741 first_unused_hpos
+= chars_wasted
[curY
] & 077;
742 if (curX
>= first_unused_hpos
)
744 /* Notice if we are erasing a magic cookie */
746 chars_wasted
[curY
] = 0;
747 background_highlight ();
750 OUTPUT1 (TS_clr_line
);
753 { /* have to do it the hard way */
756 /* Do not write in last row last col with Autowrap on. */
757 if (AutoWrap
&& curY
== FRAME_HEIGHT (selected_frame
) - 1
758 && first_unused_hpos
== FRAME_WIDTH (selected_frame
))
761 for (i
= curX
; i
< first_unused_hpos
; i
++)
764 fputc (' ', termscript
);
767 cmplus (first_unused_hpos
- curX
);
771 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes and
772 store them at DST. Do not write more than DST_LEN bytes. That may
773 require stopping before all SRC_LEN input glyphs have been
776 We store the number of glyphs actually converted in *CONSUMED. The
777 return value is the number of bytes store in DST. */
780 encode_terminal_code (src
, dst
, src_len
, dst_len
, consumed
)
784 int dst_len
, *consumed
;
786 GLYPH
*src_start
= src
, *src_end
= src
+ src_len
;
787 unsigned char *dst_start
= dst
, *dst_end
= dst
+ dst_len
;
790 unsigned char workbuf
[4], *buf
;
792 register int tlen
= GLYPH_TABLE_LENGTH
;
793 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
794 struct coding_system
*coding
;
796 coding
= (CODING_REQUIRE_ENCODING (&terminal_coding
)
798 : &safe_terminal_coding
);
800 while (src
< src_end
)
803 /* We must skip glyphs to be padded for a wide character. */
804 if (! (g
& GLYPH_MASK_PADDING
))
806 if ((c
= GLYPH_CHAR (selected_frame
, g
)) > MAX_CHAR
)
809 g
= MAKE_GLYPH (selected_frame
, c
,
810 GLYPH_FACE (selected_frame
, g
));
812 if (COMPOSITE_CHAR_P (c
))
814 /* If C is a composite character, we can display
815 only the first component. */
816 g
= cmpchar_table
[COMPOSITE_CHAR_ID (c
)]->glyph
[0],
817 c
= GLYPH_CHAR (selected_frame
, g
);
821 /* G has an entry in Vglyph_table,
822 so process any alias before testing for simpleness. */
823 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
824 c
= GLYPH_CHAR (selected_frame
, g
);
826 if (GLYPH_SIMPLE_P (tbase
, tlen
, g
))
827 /* We set the multi-byte form of C at BUF. */
828 len
= CHAR_STRING (c
, workbuf
, buf
);
831 /* We have a string in Vglyph_table. */
832 len
= GLYPH_LENGTH (tbase
, g
);
833 buf
= GLYPH_STRING (tbase
, g
);
836 encode_coding (coding
, buf
, dst
, len
, dst_end
- dst
);
837 if (coding
->consumed
< len
)
838 /* We get a carryover because the remaining output
839 buffer is too short. We must break the loop here
840 without increasing SRC so that the next call of
841 this function start from the same glyph. */
843 dst
+= coding
->produced
;
847 *consumed
= src
- src_start
;
848 return (dst
- dst_start
);
852 write_glyphs (string
, len
)
853 register GLYPH
*string
;
857 register int tlen
= GLYPH_TABLE_LENGTH
;
858 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
859 int produced
, consumed
;
861 if (write_glyphs_hook
862 && ! FRAME_TERMCAP_P ((updating_frame
? updating_frame
: selected_frame
)))
864 (*write_glyphs_hook
) (string
, len
);
868 highlight_if_desired ();
871 /* Don't dare write in last column of bottom line, if AutoWrap,
872 since that would scroll the whole frame on some terminals. */
875 && curY
+ 1 == FRAME_HEIGHT (selected_frame
)
876 && (curX
+ len
- (chars_wasted
[curY
] & 077)
877 == FRAME_WIDTH (selected_frame
)))
883 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
885 terminal_coding
.mode
&= ~CODING_MODE_LAST_BLOCK
;
888 /* We use shared conversion buffer of the current size (1024
889 bytes at least). Usually it is sufficient, but if not, we
890 just repeat the loop. */
891 produced
= encode_terminal_code (string
, conversion_buffer
,
892 len
, conversion_buffer_size
, &consumed
);
895 fwrite (conversion_buffer
, 1, produced
, stdout
);
899 fwrite (conversion_buffer
, 1, produced
, termscript
);
904 /* We may have to output some codes to terminate the writing. */
905 if (CODING_REQUIRE_FLUSHING (&terminal_coding
))
907 terminal_coding
.mode
|= CODING_MODE_LAST_BLOCK
;
908 encode_coding (&terminal_coding
, (char *)0, conversion_buffer
,
909 0, conversion_buffer_size
);
910 if (terminal_coding
.produced
> 0)
912 fwrite (conversion_buffer
, 1, terminal_coding
.produced
, stdout
);
916 fwrite (conversion_buffer
, 1, terminal_coding
.produced
,
923 /* If start is zero, insert blanks instead of a string at start */
925 insert_glyphs (start
, len
)
926 register GLYPH
*start
;
931 register int tlen
= GLYPH_TABLE_LENGTH
;
932 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
937 if (insert_glyphs_hook
&& ! FRAME_TERMCAP_P (updating_frame
))
939 (*insert_glyphs_hook
) (start
, len
);
942 highlight_if_desired ();
944 if (TS_ins_multi_chars
)
946 buf
= tparam (TS_ins_multi_chars
, 0, 0, len
);
950 write_glyphs (start
, len
);
956 /* The bit CODING_MODE_LAST_BLOCK should be set to 1 only at the tail. */
957 terminal_coding
.mode
&= ~CODING_MODE_LAST_BLOCK
;
960 int produced
, consumed
;
962 OUTPUT1_IF (TS_ins_char
);
968 /* We must open sufficient space for a character which
969 occupies more than one column. */
970 while (*start
& GLYPH_MASK_PADDING
)
972 OUTPUT1_IF (TS_ins_char
);
978 /* This is the last glyph. */
979 terminal_coding
.mode
|= CODING_MODE_LAST_BLOCK
;
981 /* We use shared conversion buffer of the current size (1024
982 bytes at least). It is surely sufficient for just one glyph. */
983 produced
= encode_terminal_code (&g
, conversion_buffer
,
984 1, conversion_buffer_size
, &consumed
);
987 fwrite (conversion_buffer
, 1, produced
, stdout
);
991 fwrite (conversion_buffer
, 1, produced
, termscript
);
994 OUTPUT1_IF (TS_pad_inserted_char
);
1005 if (delete_glyphs_hook
&& ! FRAME_TERMCAP_P (updating_frame
))
1007 (*delete_glyphs_hook
) (n
);
1011 if (delete_in_insert_mode
)
1018 OUTPUT_IF (TS_delete_mode
);
1021 if (TS_del_multi_chars
)
1023 buf
= tparam (TS_del_multi_chars
, 0, 0, n
);
1028 for (i
= 0; i
< n
; i
++)
1029 OUTPUT1 (TS_del_char
);
1030 if (!delete_in_insert_mode
)
1031 OUTPUT_IF (TS_end_delete_mode
);
1034 /* Insert N lines at vpos VPOS. If N is negative, delete -N lines. */
1036 ins_del_lines (vpos
, n
)
1039 char *multi
= n
> 0 ? TS_ins_multi_lines
: TS_del_multi_lines
;
1040 char *single
= n
> 0 ? TS_ins_line
: TS_del_line
;
1041 char *scroll
= n
> 0 ? TS_rev_scroll
: TS_fwd_scroll
;
1043 register int i
= n
> 0 ? n
: -n
;
1046 if (ins_del_lines_hook
&& ! FRAME_TERMCAP_P (updating_frame
))
1048 (*ins_del_lines_hook
) (vpos
, n
);
1052 /* If the lines below the insertion are being pushed
1053 into the end of the window, this is the same as clearing;
1054 and we know the lines are already clear, since the matching
1055 deletion has already been done. So can ignore this. */
1056 /* If the lines below the deletion are blank lines coming
1057 out of the end of the window, don't bother,
1058 as there will be a matching inslines later that will flush them. */
1059 if (scroll_region_ok
&& vpos
+ i
>= specified_window
)
1061 if (!memory_below_frame
&& vpos
+ i
>= FRAME_HEIGHT (selected_frame
))
1066 raw_cursor_to (vpos
, 0);
1067 background_highlight ();
1068 buf
= tparam (multi
, 0, 0, i
);
1074 raw_cursor_to (vpos
, 0);
1075 background_highlight ();
1083 set_scroll_region (vpos
, specified_window
);
1085 raw_cursor_to (specified_window
- 1, 0);
1087 raw_cursor_to (vpos
, 0);
1088 background_highlight ();
1090 OUTPUTL (scroll
, specified_window
- vpos
);
1091 set_scroll_region (0, specified_window
);
1094 if (TN_standout_width
>= 0)
1096 register lower_limit
1099 : FRAME_HEIGHT (selected_frame
));
1103 bcopy (&chars_wasted
[vpos
- n
], &chars_wasted
[vpos
],
1104 lower_limit
- vpos
+ n
);
1105 bzero (&chars_wasted
[lower_limit
+ n
], - n
);
1109 bcopy (&chars_wasted
[vpos
], ©buf
[vpos
], lower_limit
- vpos
- n
);
1110 bcopy (©buf
[vpos
], &chars_wasted
[vpos
+ n
],
1111 lower_limit
- vpos
- n
);
1112 bzero (&chars_wasted
[vpos
], n
);
1115 if (!scroll_region_ok
&& memory_below_frame
&& n
< 0)
1117 cursor_to (FRAME_HEIGHT (selected_frame
) + n
, 0);
1122 /* Compute cost of sending "str", in characters,
1123 not counting any line-dependent padding. */
1131 tputs (str
, 0, evalcost
);
1135 /* Compute cost of sending "str", in characters,
1136 counting any line-dependent padding at one line. */
1139 string_cost_one_line (str
)
1144 tputs (str
, 1, evalcost
);
1148 /* Compute per line amount of line-dependent padding,
1149 in tenths of characters. */
1157 tputs (str
, 0, evalcost
);
1160 tputs (str
, 10, evalcost
);
1165 /* char_ins_del_cost[n] is cost of inserting N characters.
1166 char_ins_del_cost[-n] is cost of deleting N characters.
1167 The length of this vector is based on max_frame_width. */
1169 int *char_ins_del_vector
;
1171 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WIDTH ((f))])
1176 calculate_ins_del_char_costs (frame
)
1179 int ins_startup_cost
, del_startup_cost
;
1180 int ins_cost_per_char
, del_cost_per_char
;
1184 if (TS_ins_multi_chars
)
1186 ins_cost_per_char
= 0;
1187 ins_startup_cost
= string_cost_one_line (TS_ins_multi_chars
);
1189 else if (TS_ins_char
|| TS_pad_inserted_char
1190 || (TS_insert_mode
&& TS_end_insert_mode
))
1192 ins_startup_cost
= (30 * (string_cost (TS_insert_mode
)
1193 + string_cost (TS_end_insert_mode
))) / 100;
1194 ins_cost_per_char
= (string_cost_one_line (TS_ins_char
)
1195 + string_cost_one_line (TS_pad_inserted_char
));
1199 ins_startup_cost
= 9999;
1200 ins_cost_per_char
= 0;
1203 if (TS_del_multi_chars
)
1205 del_cost_per_char
= 0;
1206 del_startup_cost
= string_cost_one_line (TS_del_multi_chars
);
1208 else if (TS_del_char
)
1210 del_startup_cost
= (string_cost (TS_delete_mode
)
1211 + string_cost (TS_end_delete_mode
));
1212 if (delete_in_insert_mode
)
1213 del_startup_cost
/= 2;
1214 del_cost_per_char
= string_cost_one_line (TS_del_char
);
1218 del_startup_cost
= 9999;
1219 del_cost_per_char
= 0;
1222 /* Delete costs are at negative offsets */
1223 p
= &char_ins_del_cost (frame
)[0];
1224 for (i
= FRAME_WIDTH (frame
); --i
>= 0;)
1225 *--p
= (del_startup_cost
+= del_cost_per_char
);
1227 /* Doing nothing is free */
1228 p
= &char_ins_del_cost (frame
)[0];
1231 /* Insert costs are at positive offsets */
1232 for (i
= FRAME_WIDTH (frame
); --i
>= 0;)
1233 *p
++ = (ins_startup_cost
+= ins_cost_per_char
);
1236 extern do_line_insertion_deletion_costs ();
1238 calculate_costs (frame
)
1241 register char *f
= (TS_set_scroll_region
1242 ? TS_set_scroll_region
1243 : TS_set_scroll_region_1
);
1245 FRAME_COST_BAUD_RATE (frame
) = baud_rate
;
1247 scroll_region_cost
= string_cost (f
);
1248 #ifdef HAVE_X_WINDOWS
1249 if (FRAME_X_P (frame
))
1251 do_line_insertion_deletion_costs (frame
, 0, ".5*", 0, ".5*",
1253 x_screen_planes (frame
));
1254 scroll_region_cost
= 0;
1259 /* These variables are only used for terminal stuff. They are allocated
1260 once for the terminal frame of X-windows emacs, but not used afterwards.
1262 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1263 X turns off char_ins_del_ok.
1265 chars_wasted and copybuf are only used here in term.c in cases where
1266 the term hook isn't called. */
1268 max_frame_height
= max (max_frame_height
, FRAME_HEIGHT (frame
));
1269 max_frame_width
= max (max_frame_width
, FRAME_WIDTH (frame
));
1271 if (chars_wasted
!= 0)
1272 chars_wasted
= (char *) xrealloc (chars_wasted
, max_frame_height
);
1274 chars_wasted
= (char *) xmalloc (max_frame_height
);
1277 copybuf
= (char *) xrealloc (copybuf
, max_frame_height
);
1279 copybuf
= (char *) xmalloc (max_frame_height
);
1281 if (char_ins_del_vector
!= 0)
1283 = (int *) xrealloc (char_ins_del_vector
,
1285 + 2 * max_frame_width
* sizeof (int)));
1288 = (int *) xmalloc (sizeof (int)
1289 + 2 * max_frame_width
* sizeof (int));
1291 bzero (chars_wasted
, max_frame_height
);
1292 bzero (copybuf
, max_frame_height
);
1293 bzero (char_ins_del_vector
, (sizeof (int)
1294 + 2 * max_frame_width
* sizeof (int)));
1296 if (f
&& (!TS_ins_line
&& !TS_del_line
))
1297 do_line_insertion_deletion_costs (frame
,
1298 TS_rev_scroll
, TS_ins_multi_lines
,
1299 TS_fwd_scroll
, TS_del_multi_lines
,
1302 do_line_insertion_deletion_costs (frame
,
1303 TS_ins_line
, TS_ins_multi_lines
,
1304 TS_del_line
, TS_del_multi_lines
,
1307 calculate_ins_del_char_costs (frame
);
1309 /* Don't use TS_repeat if its padding is worse than sending the chars */
1310 if (TS_repeat
&& per_line_cost (TS_repeat
) * baud_rate
< 9000)
1311 RPov
= string_cost (TS_repeat
);
1313 RPov
= FRAME_WIDTH (frame
) * 2;
1315 cmcostinit (); /* set up cursor motion costs */
1322 /* Termcap capability names that correspond directly to X keysyms.
1323 Some of these (marked "terminfo") aren't supplied by old-style
1324 (Berkeley) termcap entries. They're listed in X keysym order;
1325 except we put the keypad keys first, so that if they clash with
1326 other keys (as on the IBM PC keyboard) they get overridden.
1329 static struct fkey_table keys
[] = {
1330 "kh", "home", /* termcap */
1331 "kl", "left", /* termcap */
1332 "ku", "up", /* termcap */
1333 "kr", "right", /* termcap */
1334 "kd", "down", /* termcap */
1335 "%8", "prior", /* terminfo */
1336 "%5", "next", /* terminfo */
1337 "@7", "end", /* terminfo */
1338 "@1", "begin", /* terminfo */
1339 "*6", "select", /* terminfo */
1340 "%9", "print", /* terminfo */
1341 "@4", "execute", /* terminfo --- actually the `command' key */
1343 * "insert" --- see below
1345 "&8", "undo", /* terminfo */
1346 "%0", "redo", /* terminfo */
1347 "%7", "menu", /* terminfo --- actually the `options' key */
1348 "@0", "find", /* terminfo */
1349 "@2", "cancel", /* terminfo */
1350 "%1", "help", /* terminfo */
1352 * "break" goes here, but can't be reliably intercepted with termcap
1354 "&4", "reset", /* terminfo --- actually `restart' */
1356 * "system" and "user" --- no termcaps
1358 "kE", "clearline", /* terminfo */
1359 "kA", "insertline", /* terminfo */
1360 "kL", "deleteline", /* terminfo */
1361 "kI", "insertchar", /* terminfo */
1362 "kD", "deletechar", /* terminfo */
1363 "kB", "backtab", /* terminfo */
1365 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1367 "@8", "kp-enter", /* terminfo */
1369 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1370 * "kp-multiply", "kp-add", "kp-separator",
1371 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1372 * --- no termcaps for any of these.
1374 "K4", "kp-1", /* terminfo */
1376 * "kp-2" --- no termcap
1378 "K5", "kp-3", /* terminfo */
1380 * "kp-4" --- no termcap
1382 "K2", "kp-5", /* terminfo */
1384 * "kp-6" --- no termcap
1386 "K1", "kp-7", /* terminfo */
1388 * "kp-8" --- no termcap
1390 "K3", "kp-9", /* terminfo */
1392 * "kp-equal" --- no termcap
1405 static char **term_get_fkeys_arg
;
1406 static Lisp_Object
term_get_fkeys_1 ();
1408 /* Find the escape codes sent by the function keys for Vfunction_key_map.
1409 This function scans the termcap function key sequence entries, and
1410 adds entries to Vfunction_key_map for each function key it finds. */
1413 term_get_fkeys (address
)
1416 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1417 errors during the call. The only errors should be from Fdefine_key
1418 when given a key sequence containing an invalid prefix key. If the
1419 termcap defines function keys which use a prefix that is already bound
1420 to a command by the default bindings, we should silently ignore that
1421 function key specification, rather than giving the user an error and
1422 refusing to run at all on such a terminal. */
1424 extern Lisp_Object
Fidentity ();
1425 term_get_fkeys_arg
= address
;
1426 internal_condition_case (term_get_fkeys_1
, Qerror
, Fidentity
);
1434 char **address
= term_get_fkeys_arg
;
1436 /* This can happen if CANNOT_DUMP or with strange options. */
1438 Vfunction_key_map
= Fmake_sparse_keymap (Qnil
);
1440 for (i
= 0; i
< (sizeof (keys
)/sizeof (keys
[0])); i
++)
1442 char *sequence
= tgetstr (keys
[i
].cap
, address
);
1444 Fdefine_key (Vfunction_key_map
, build_string (sequence
),
1445 Fmake_vector (make_number (1),
1446 intern (keys
[i
].name
)));
1449 /* The uses of the "k0" capability are inconsistent; sometimes it
1450 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1451 We will attempt to politely accommodate both systems by testing for
1452 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1455 char *k_semi
= tgetstr ("k;", address
);
1456 char *k0
= tgetstr ("k0", address
);
1457 char *k0_name
= "f10";
1461 Fdefine_key (Vfunction_key_map
, build_string (k_semi
),
1462 Fmake_vector (make_number (1), intern ("f10")));
1467 Fdefine_key (Vfunction_key_map
, build_string (k0
),
1468 Fmake_vector (make_number (1), intern (k0_name
)));
1471 /* Set up cookies for numbered function keys above f10. */
1473 char fcap
[3], fkey
[4];
1475 fcap
[0] = 'F'; fcap
[2] = '\0';
1476 for (i
= 11; i
< 64; i
++)
1479 fcap
[1] = '1' + i
- 11;
1481 fcap
[1] = 'A' + i
- 20;
1483 fcap
[1] = 'a' + i
- 46;
1486 char *sequence
= tgetstr (fcap
, address
);
1489 sprintf (fkey
, "f%d", i
);
1490 Fdefine_key (Vfunction_key_map
, build_string (sequence
),
1491 Fmake_vector (make_number (1),
1499 * Various mappings to try and get a better fit.
1502 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1503 if (!tgetstr (cap1, address)) \
1505 char *sequence = tgetstr (cap2, address); \
1507 Fdefine_key (Vfunction_key_map, build_string (sequence), \
1508 Fmake_vector (make_number (1), \
1512 /* if there's no key_next keycap, map key_npage to `next' keysym */
1513 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1514 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1515 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1516 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1517 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1518 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1519 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1521 /* IBM has their own non-standard dialect of terminfo.
1522 If the standard name isn't found, try the IBM name. */
1523 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1524 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1525 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1526 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1527 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1528 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1529 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1530 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1531 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1532 #undef CONDITIONAL_REASSIGN
1537 term_init (terminal_type
)
1538 char *terminal_type
;
1541 char **address
= &area
;
1547 initialize_w32_display ();
1551 area
= (char *) malloc (2044);
1556 FrameRows
= FRAME_HEIGHT (selected_frame
);
1557 FrameCols
= FRAME_WIDTH (selected_frame
);
1558 specified_window
= FRAME_HEIGHT (selected_frame
);
1560 delete_in_insert_mode
= 1;
1563 scroll_region_ok
= 0;
1565 /* Seems to insert lines when it's not supposed to, messing
1566 up the display. In doing a trace, it didn't seem to be
1567 called much, so I don't think we're losing anything by
1570 line_ins_del_ok
= 0;
1571 char_ins_del_ok
= 1;
1575 FRAME_CAN_HAVE_SCROLL_BARS (selected_frame
) = 0;
1576 FRAME_VERTICAL_SCROLL_BAR_TYPE (selected_frame
) = vertical_scroll_bar_none
;
1579 #endif /* WINDOWSNT */
1583 status
= tgetent (buffer
, terminal_type
);
1587 fatal ("Cannot open terminfo database file");
1589 fatal ("Cannot open termcap database file");
1595 fatal ("Terminal type %s is not defined.\n\
1596 If that is not the actual type of terminal you have,\n\
1597 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
1598 `setenv TERM ...') to specify the correct type. It may be necessary\n\
1599 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
1602 fatal ("Terminal type %s is not defined.\n\
1603 If that is not the actual type of terminal you have,\n\
1604 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
1605 `setenv TERM ...') to specify the correct type. It may be necessary\n\
1606 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
1611 area
= (char *) malloc (2044);
1613 area
= (char *) malloc (strlen (buffer
));
1614 #endif /* not TERMINFO */
1618 TS_ins_line
= tgetstr ("al", address
);
1619 TS_ins_multi_lines
= tgetstr ("AL", address
);
1620 TS_bell
= tgetstr ("bl", address
);
1621 BackTab
= tgetstr ("bt", address
);
1622 TS_clr_to_bottom
= tgetstr ("cd", address
);
1623 TS_clr_line
= tgetstr ("ce", address
);
1624 TS_clr_frame
= tgetstr ("cl", address
);
1625 ColPosition
= tgetstr ("ch", address
);
1626 AbsPosition
= tgetstr ("cm", address
);
1627 CR
= tgetstr ("cr", address
);
1628 TS_set_scroll_region
= tgetstr ("cs", address
);
1629 TS_set_scroll_region_1
= tgetstr ("cS", address
);
1630 RowPosition
= tgetstr ("cv", address
);
1631 TS_del_char
= tgetstr ("dc", address
);
1632 TS_del_multi_chars
= tgetstr ("DC", address
);
1633 TS_del_line
= tgetstr ("dl", address
);
1634 TS_del_multi_lines
= tgetstr ("DL", address
);
1635 TS_delete_mode
= tgetstr ("dm", address
);
1636 TS_end_delete_mode
= tgetstr ("ed", address
);
1637 TS_end_insert_mode
= tgetstr ("ei", address
);
1638 Home
= tgetstr ("ho", address
);
1639 TS_ins_char
= tgetstr ("ic", address
);
1640 TS_ins_multi_chars
= tgetstr ("IC", address
);
1641 TS_insert_mode
= tgetstr ("im", address
);
1642 TS_pad_inserted_char
= tgetstr ("ip", address
);
1643 TS_end_keypad_mode
= tgetstr ("ke", address
);
1644 TS_keypad_mode
= tgetstr ("ks", address
);
1645 LastLine
= tgetstr ("ll", address
);
1646 Right
= tgetstr ("nd", address
);
1647 Down
= tgetstr ("do", address
);
1649 Down
= tgetstr ("nl", address
); /* Obsolete name for "do" */
1651 /* VMS puts a carriage return before each linefeed,
1652 so it is not safe to use linefeeds. */
1653 if (Down
&& Down
[0] == '\n' && Down
[1] == '\0')
1656 if (tgetflag ("bs"))
1657 Left
= "\b"; /* can't possibly be longer! */
1658 else /* (Actually, "bs" is obsolete...) */
1659 Left
= tgetstr ("le", address
);
1661 Left
= tgetstr ("bc", address
); /* Obsolete name for "le" */
1662 TS_pad_char
= tgetstr ("pc", address
);
1663 TS_repeat
= tgetstr ("rp", address
);
1664 TS_end_standout_mode
= tgetstr ("se", address
);
1665 TS_fwd_scroll
= tgetstr ("sf", address
);
1666 TS_standout_mode
= tgetstr ("so", address
);
1667 TS_rev_scroll
= tgetstr ("sr", address
);
1668 Wcm
.cm_tab
= tgetstr ("ta", address
);
1669 TS_end_termcap_modes
= tgetstr ("te", address
);
1670 TS_termcap_modes
= tgetstr ("ti", address
);
1671 TS_bold_mode
= tgetstr ("md", address
);
1672 TS_end_bold_mode
= tgetstr ("me", address
);
1673 TS_underscore_mode
= tgetstr ("us", address
);
1674 TS_end_underscore_mode
= tgetstr ("ue", address
);
1675 Up
= tgetstr ("up", address
);
1676 TS_visible_bell
= tgetstr ("vb", address
);
1677 TS_end_visual_mode
= tgetstr ("ve", address
);
1678 TS_visual_mode
= tgetstr ("vs", address
);
1679 TS_set_window
= tgetstr ("wi", address
);
1680 MultiUp
= tgetstr ("UP", address
);
1681 MultiDown
= tgetstr ("DO", address
);
1682 MultiLeft
= tgetstr ("LE", address
);
1683 MultiRight
= tgetstr ("RI", address
);
1685 MagicWrap
= tgetflag ("xn");
1686 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
1687 the former flag imply the latter. */
1688 AutoWrap
= MagicWrap
|| tgetflag ("am");
1689 memory_below_frame
= tgetflag ("db");
1690 TF_hazeltine
= tgetflag ("hz");
1691 must_write_spaces
= tgetflag ("in");
1692 meta_key
= tgetflag ("km") || tgetflag ("MT");
1693 TF_insmode_motion
= tgetflag ("mi");
1694 TF_standout_motion
= tgetflag ("ms");
1695 TF_underscore
= tgetflag ("ul");
1696 TF_xs
= tgetflag ("xs");
1697 TF_teleray
= tgetflag ("xt");
1699 term_get_fkeys (address
);
1701 /* Get frame size from system, or else from termcap. */
1704 get_frame_size (&width
, &height
);
1705 FRAME_WIDTH (selected_frame
) = width
;
1706 FRAME_HEIGHT (selected_frame
) = height
;
1709 if (FRAME_WIDTH (selected_frame
) <= 0)
1710 SET_FRAME_WIDTH (selected_frame
, tgetnum ("co"));
1712 /* Keep width and external_width consistent */
1713 SET_FRAME_WIDTH (selected_frame
, FRAME_WIDTH (selected_frame
));
1714 if (FRAME_HEIGHT (selected_frame
) <= 0)
1715 FRAME_HEIGHT (selected_frame
) = tgetnum ("li");
1717 if (FRAME_HEIGHT (selected_frame
) < 3
1718 || FRAME_WIDTH (selected_frame
) < 3)
1719 fatal ("Screen size %dx%d is too small",
1720 FRAME_HEIGHT (selected_frame
), FRAME_WIDTH (selected_frame
));
1722 min_padding_speed
= tgetnum ("pb");
1723 TN_standout_width
= tgetnum ("sg");
1724 TabWidth
= tgetnum ("tw");
1727 /* These capabilities commonly use ^J.
1728 I don't know why, but sending them on VMS does not work;
1729 it causes following spaces to be lost, sometimes.
1730 For now, the simplest fix is to avoid using these capabilities ever. */
1731 if (Down
&& Down
[0] == '\n')
1739 TS_fwd_scroll
= Down
;
1741 PC
= TS_pad_char
? *TS_pad_char
: 0;
1746 /* Turned off since /etc/termcap seems to have :ta= for most terminals
1747 and newer termcap doc does not seem to say there is a default.
1752 if (TS_standout_mode
== 0)
1754 TN_standout_width
= tgetnum ("ug");
1755 TS_end_standout_mode
= tgetstr ("ue", address
);
1756 TS_standout_mode
= tgetstr ("us", address
);
1759 /* If no `se' string, try using a `me' string instead.
1760 If that fails, we can't use standout mode at all. */
1761 if (TS_end_standout_mode
== 0)
1763 char *s
= tgetstr ("me", address
);
1765 TS_end_standout_mode
= s
;
1767 TS_standout_mode
= 0;
1773 /* Teleray: most programs want a space in front of TS_standout_mode,
1774 but Emacs can do without it (and give one extra column). */
1775 TS_standout_mode
= "\033RD";
1776 TN_standout_width
= 1;
1777 /* But that means we cannot rely on ^M to go to column zero! */
1779 /* LF can't be trusted either -- can alter hpos */
1780 /* if move at column 0 thru a line with TS_standout_mode */
1784 /* Special handling for certain terminal types known to need it */
1786 if (!strcmp (terminal_type
, "supdup"))
1788 memory_below_frame
= 1;
1789 Wcm
.cm_losewrap
= 1;
1791 if (!strncmp (terminal_type
, "c10", 3)
1792 || !strcmp (terminal_type
, "perq"))
1794 /* Supply a makeshift :wi string.
1795 This string is not valid in general since it works only
1796 for windows starting at the upper left corner;
1797 but that is all Emacs uses.
1799 This string works only if the frame is using
1800 the top of the video memory, because addressing is memory-relative.
1801 So first check the :ti string to see if that is true.
1803 It would be simpler if the :wi string could go in the termcap
1804 entry, but it can't because it is not fully valid.
1805 If it were in the termcap entry, it would confuse other programs. */
1808 p
= TS_termcap_modes
;
1809 while (*p
&& strcmp (p
, "\033v "))
1812 TS_set_window
= "\033v%C %C %C %C ";
1814 /* Termcap entry often fails to have :in: flag */
1815 must_write_spaces
= 1;
1816 /* :ti string typically fails to have \E^G! in it */
1817 /* This limits scope of insert-char to one line. */
1818 strcpy (area
, TS_termcap_modes
);
1819 strcat (area
, "\033\007!");
1820 TS_termcap_modes
= area
;
1821 area
+= strlen (area
) + 1;
1823 /* Change all %+ parameters to %C, to handle
1824 values above 96 correctly for the C100. */
1827 if (p
[0] == '%' && p
[1] == '+')
1833 FrameRows
= FRAME_HEIGHT (selected_frame
);
1834 FrameCols
= FRAME_WIDTH (selected_frame
);
1835 specified_window
= FRAME_HEIGHT (selected_frame
);
1837 if (Wcm_init () == -1) /* can't do cursor motion */
1839 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
1840 It lacks the ability to position the cursor.\n\
1841 If that is not the actual type of terminal you have, use either the\n\
1842 DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
1843 or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
1847 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
1848 It lacks the ability to position the cursor.\n\
1849 If that is not the actual type of terminal you have,\n\
1850 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
1851 `setenv TERM ...') to specify the correct type. It may be necessary\n\
1852 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
1854 # else /* TERMCAP */
1855 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
1856 It lacks the ability to position the cursor.\n\
1857 If that is not the actual type of terminal you have,\n\
1858 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
1859 `setenv TERM ...') to specify the correct type. It may be necessary\n\
1860 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
1862 # endif /* TERMINFO */
1864 if (FRAME_HEIGHT (selected_frame
) <= 0
1865 || FRAME_WIDTH (selected_frame
) <= 0)
1866 fatal ("The frame size has not been specified");
1868 delete_in_insert_mode
1869 = TS_delete_mode
&& TS_insert_mode
1870 && !strcmp (TS_delete_mode
, TS_insert_mode
);
1872 se_is_so
= (TS_standout_mode
1873 && TS_end_standout_mode
1874 && !strcmp (TS_standout_mode
, TS_end_standout_mode
));
1876 /* Remove width of standout marker from usable width of line */
1877 if (TN_standout_width
> 0)
1878 SET_FRAME_WIDTH (selected_frame
,
1879 FRAME_WIDTH (selected_frame
) - TN_standout_width
);
1881 UseTabs
= tabs_safe_p () && TabWidth
== 8;
1885 && (TS_set_window
|| TS_set_scroll_region
|| TS_set_scroll_region_1
));
1887 line_ins_del_ok
= (((TS_ins_line
|| TS_ins_multi_lines
)
1888 && (TS_del_line
|| TS_del_multi_lines
))
1889 || (scroll_region_ok
&& TS_fwd_scroll
&& TS_rev_scroll
));
1891 char_ins_del_ok
= ((TS_ins_char
|| TS_insert_mode
1892 || TS_pad_inserted_char
|| TS_ins_multi_chars
)
1893 && (TS_del_char
|| TS_del_multi_chars
));
1895 fast_clear_end_of_line
= TS_clr_line
!= 0;
1898 if (read_socket_hook
) /* Baudrate is somewhat */
1899 /* meaningless in this case */
1902 FRAME_CAN_HAVE_SCROLL_BARS (selected_frame
) = 0;
1903 FRAME_VERTICAL_SCROLL_BAR_TYPE (selected_frame
) = vertical_scroll_bar_none
;
1907 fatal (str
, arg1
, arg2
)
1908 char *str
, *arg1
, *arg2
;
1910 fprintf (stderr
, "emacs: ");
1911 fprintf (stderr
, str
, arg1
, arg2
);
1912 fprintf (stderr
, "\n");
1919 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo
,
1920 "Non-nil means the system uses terminfo rather than termcap.\n\
1921 This variable can be used by terminal emulator packages.");
1923 system_uses_terminfo
= 1;
1925 system_uses_terminfo
= 0;
1928 DEFVAR_LISP ("ring-bell-function", &Vring_bell_function
,
1929 "Non-nil means call this function to ring the bell.\n\
1930 The function should accept no arguments.");
1931 Vring_bell_function
= Qnil
;