1 /* terminal control module for terminals described by TERMCAP
2 Copyright (C) 1985, 1986, 1987, 1993 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
31 #include "termhooks.h"
34 #define max(a, b) ((a) > (b) ? (a) : (b))
35 #define min(a, b) ((a) < (b) ? (a) : (b))
37 #define OUTPUT(a) tputs (a, FRAME_HEIGHT (selected_frame) - curY, cmputc)
38 #define OUTPUT1(a) tputs (a, 1, cmputc)
39 #define OUTPUTL(a, lines) tputs (a, lines, cmputc)
40 #define OUTPUT_IF(a) { if (a) tputs (a, FRAME_HEIGHT (selected_frame) - curY, cmputc); }
41 #define OUTPUT1_IF(a) { if (a) tputs (a, 1, cmputc); }
43 /* Terminal characteristics that higher levels want to look at.
44 These are all extern'd in termchar.h */
46 int must_write_spaces
; /* Nonzero means spaces in the text
47 must actually be output; can't just skip
48 over some columns to leave them blank. */
49 int min_padding_speed
; /* Speed below which no padding necessary */
51 int line_ins_del_ok
; /* Terminal can insert and delete lines */
52 int char_ins_del_ok
; /* Terminal can insert and delete chars */
53 int scroll_region_ok
; /* Terminal supports setting the
55 int memory_below_frame
; /* Terminal remembers lines
56 scrolled off bottom */
57 int fast_clear_end_of_line
; /* Terminal has a `ce' string */
59 int dont_calculate_costs
; /* Nonzero means don't bother computing */
60 /* various cost tables; we won't use them. */
62 /* Nonzero means no need to redraw the entire frame on resuming
63 a suspended Emacs. This is useful on terminals with multiple pages,
64 where one page is used for Emacs and another for all else. */
65 int no_redraw_on_reenter
;
67 /* Hook functions that you can set to snap out the functions in this file.
68 These are all extern'd in termhooks.h */
70 int (*cursor_to_hook
) ();
71 int (*raw_cursor_to_hook
) ();
73 int (*clear_to_end_hook
) ();
74 int (*clear_frame_hook
) ();
75 int (*clear_end_of_line_hook
) ();
77 int (*ins_del_lines_hook
) ();
79 int (*change_line_highlight_hook
) ();
80 int (*reassert_line_highlight_hook
) ();
82 int (*insert_glyphs_hook
) ();
83 int (*write_glyphs_hook
) ();
84 int (*delete_glyphs_hook
) ();
86 int (*ring_bell_hook
) ();
88 int (*reset_terminal_modes_hook
) ();
89 int (*set_terminal_modes_hook
) ();
90 int (*update_begin_hook
) ();
91 int (*update_end_hook
) ();
92 int (*set_terminal_window_hook
) ();
94 int (*read_socket_hook
) ();
96 /* Return the current position of the mouse.
98 Set *f to the frame the mouse is in, or zero if the mouse is in no
99 Emacs frame. If it is set to zero, all the other arguments are
102 If the motion started in a scroll bar, set *bar_window to the
103 scroll bar's window, *part to the part the mouse is currently over,
104 *x to the position of the mouse along the scroll bar, and *y to the
105 overall length of the scroll bar.
107 Otherwise, set *bar_window to Qnil, and *x and *y to the column and
108 row of the character cell the mouse is over.
110 Set *time to the time the mouse was at the returned position.
112 This should clear mouse_moved until the next motion
114 void (*mouse_position_hook
) ( /* FRAME_PTR *f,
115 Lisp_Object *bar_window,
116 enum scroll_bar_part *part,
119 unsigned long *time */ );
121 /* When reading from a minibuffer in a different frame, Emacs wants
122 to shift the highlight from the selected frame to the minibuffer's
123 frame; under X, this means it lies about where the focus is.
124 This hook tells the window system code to re-decide where to put
126 void (*frame_rehighlight_hook
) ( /* FRAME_PTR f */ );
128 /* If we're displaying frames using a window system that can stack
129 frames on top of each other, this hook allows you to bring a frame
130 to the front, or bury it behind all the other windows. If this
131 hook is zero, that means the device we're displaying on doesn't
132 support overlapping frames, so there's no need to raise or lower
135 If RAISE is non-zero, F is brought to the front, before all other
136 windows. If RAISE is zero, F is sent to the back, behind all other
138 void (*frame_raise_lower_hook
) ( /* FRAME_PTR f, int raise */ );
140 /* Set the vertical scroll bar for WINDOW to have its upper left corner
141 at (TOP, LEFT), and be LENGTH rows high. Set its handle to
142 indicate that we are displaying PORTION characters out of a total
143 of WHOLE characters, starting at POSITION. If WINDOW doesn't yet
144 have a scroll bar, create one for it. */
145 void (*set_vertical_scroll_bar_hook
)
146 ( /* struct window *window,
147 int portion, int whole, int position */ );
150 /* The following three hooks are used when we're doing a thorough
151 redisplay of the frame. We don't explicitly know which scroll bars
152 are going to be deleted, because keeping track of when windows go
153 away is a real pain - can you say set-window-configuration?
154 Instead, we just assert at the beginning of redisplay that *all*
155 scroll bars are to be removed, and then save scroll bars from the
156 firey pit when we actually redisplay their window. */
158 /* Arrange for all scroll bars on FRAME to be removed at the next call
159 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
160 `*redeem_scroll_bar_hook' is applied to its window before the judgement.
162 This should be applied to each frame each time its window tree is
163 redisplayed, even if it is not displaying scroll bars at the moment;
164 if the HAS_SCROLL_BARS flag has just been turned off, only calling
165 this and the judge_scroll_bars_hook will get rid of them.
167 If non-zero, this hook should be safe to apply to any frame,
168 whether or not it can support scroll bars, and whether or not it is
169 currently displaying them. */
170 void (*condemn_scroll_bars_hook
)( /* FRAME_PTR *frame */ );
172 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
173 Note that it's okay to redeem a scroll bar that is not condemned. */
174 void (*redeem_scroll_bar_hook
)( /* struct window *window */ );
176 /* Remove all scroll bars on FRAME that haven't been saved since the
177 last call to `*condemn_scroll_bars_hook'.
179 This should be applied to each frame after each time its window
180 tree is redisplayed, even if it is not displaying scroll bars at the
181 moment; if the HAS_SCROLL_BARS flag has just been turned off, only
182 calling this and condemn_scroll_bars_hook will get rid of them.
184 If non-zero, this hook should be safe to apply to any frame,
185 whether or not it can support scroll bars, and whether or not it is
186 currently displaying them. */
187 void (*judge_scroll_bars_hook
)( /* FRAME_PTR *FRAME */ );
190 /* Strings, numbers and flags taken from the termcap entry. */
192 char *TS_ins_line
; /* termcap "al" */
193 char *TS_ins_multi_lines
; /* "AL" (one parameter, # lines to insert) */
194 char *TS_bell
; /* "bl" */
195 char *TS_clr_to_bottom
; /* "cd" */
196 char *TS_clr_line
; /* "ce", clear to end of line */
197 char *TS_clr_frame
; /* "cl" */
198 char *TS_set_scroll_region
; /* "cs" (2 params, first line and last line) */
199 char *TS_set_scroll_region_1
; /* "cS" (4 params: total lines,
200 lines above scroll region, lines below it,
201 total lines again) */
202 char *TS_del_char
; /* "dc" */
203 char *TS_del_multi_chars
; /* "DC" (one parameter, # chars to delete) */
204 char *TS_del_line
; /* "dl" */
205 char *TS_del_multi_lines
; /* "DL" (one parameter, # lines to delete) */
206 char *TS_delete_mode
; /* "dm", enter character-delete mode */
207 char *TS_end_delete_mode
; /* "ed", leave character-delete mode */
208 char *TS_end_insert_mode
; /* "ei", leave character-insert mode */
209 char *TS_ins_char
; /* "ic" */
210 char *TS_ins_multi_chars
; /* "IC" (one parameter, # chars to insert) */
211 char *TS_insert_mode
; /* "im", enter character-insert mode */
212 char *TS_pad_inserted_char
; /* "ip". Just padding, no commands. */
213 char *TS_end_keypad_mode
; /* "ke" */
214 char *TS_keypad_mode
; /* "ks" */
215 char *TS_pad_char
; /* "pc", char to use as padding */
216 char *TS_repeat
; /* "rp" (2 params, # times to repeat
217 and character to be repeated) */
218 char *TS_end_standout_mode
; /* "se" */
219 char *TS_fwd_scroll
; /* "sf" */
220 char *TS_standout_mode
; /* "so" */
221 char *TS_rev_scroll
; /* "sr" */
222 char *TS_end_termcap_modes
; /* "te" */
223 char *TS_termcap_modes
; /* "ti" */
224 char *TS_visible_bell
; /* "vb" */
225 char *TS_end_visual_mode
; /* "ve" */
226 char *TS_visual_mode
; /* "vi" */
227 char *TS_set_window
; /* "wi" (4 params, start and end of window,
228 each as vpos and hpos) */
230 int TF_hazeltine
; /* termcap hz flag. */
231 int TF_insmode_motion
; /* termcap mi flag: can move while in insert mode. */
232 int TF_standout_motion
; /* termcap mi flag: can move while in standout mode. */
233 int TF_underscore
; /* termcap ul flag: _ underlines if overstruck on
234 nonblank position. Must clear before writing _. */
235 int TF_teleray
; /* termcap xt flag: many weird consequences.
238 int TF_xs
; /* Nonzero for "xs". If set together with
239 TN_standout_width == 0, it means don't bother
240 to write any end-standout cookies. */
242 int TN_standout_width
; /* termcap sg number: width occupied by standout
245 static int RPov
; /* # chars to start a TS_repeat */
247 static int delete_in_insert_mode
; /* delete mode == insert mode */
249 static int se_is_so
; /* 1 if same string both enters and leaves
254 /* Number of chars of space used for standout marker at beginning of line,
255 or'd with 0100. Zero if no standout marker at all.
257 Used IFF TN_standout_width >= 0. */
259 static char *chars_wasted
;
260 static char *copybuf
;
262 /* nonzero means supposed to write text in standout mode. */
263 int standout_requested
;
265 int insert_mode
; /* Nonzero when in insert mode. */
266 int standout_mode
; /* Nonzero when in standout mode. */
268 /* Size of window specified by higher levels.
269 This is the number of lines, from the top of frame downwards,
270 which can participate in insert-line/delete-line operations.
272 Effectively it excludes the bottom frame_height - specified_window_size
273 lines from those operations. */
275 int specified_window
;
277 /* Frame currently being redisplayed; 0 if not currently redisplaying.
278 (Direct output does not count). */
280 FRAME_PTR updating_frame
;
286 if (! FRAME_TERMCAP_P (selected_frame
))
288 (*ring_bell_hook
) ();
291 OUTPUT (TS_visible_bell
&& visible_bell
? TS_visible_bell
: TS_bell
);
294 set_terminal_modes ()
296 if (! FRAME_TERMCAP_P (selected_frame
))
298 (*set_terminal_modes_hook
) ();
301 OUTPUT_IF (TS_termcap_modes
);
302 OUTPUT_IF (TS_visual_mode
);
303 OUTPUT_IF (TS_keypad_mode
);
307 reset_terminal_modes ()
309 if (! FRAME_TERMCAP_P (selected_frame
))
311 (*reset_terminal_modes_hook
) ();
314 if (TN_standout_width
< 0)
315 turn_off_highlight ();
317 OUTPUT_IF (TS_end_keypad_mode
);
318 OUTPUT_IF (TS_end_visual_mode
);
319 OUTPUT_IF (TS_end_termcap_modes
);
320 /* Output raw CR so kernel can track the cursor hpos. */
321 /* But on magic-cookie terminals this can erase an end-standout marker and
322 cause the rest of the frame to be in standout, so move down first. */
323 if (TN_standout_width
>= 0)
332 if (! FRAME_TERMCAP_P (updating_frame
))
333 (*update_begin_hook
) (f
);
339 if (! FRAME_TERMCAP_P (updating_frame
))
341 (*update_end_hook
) (f
);
346 background_highlight ();
347 standout_requested
= 0;
351 set_terminal_window (size
)
354 if (! FRAME_TERMCAP_P (updating_frame
))
356 (*set_terminal_window_hook
) (size
);
359 specified_window
= size
? size
: FRAME_HEIGHT (selected_frame
);
360 if (!scroll_region_ok
)
362 set_scroll_region (0, specified_window
);
365 set_scroll_region (start
, stop
)
369 if (TS_set_scroll_region
)
371 buf
= tparam (TS_set_scroll_region
, 0, 0, start
, stop
- 1);
373 else if (TS_set_scroll_region_1
)
375 buf
= tparam (TS_set_scroll_region_1
, 0, 0,
376 FRAME_HEIGHT (selected_frame
), start
,
377 FRAME_HEIGHT (selected_frame
) - stop
,
378 FRAME_HEIGHT (selected_frame
));
382 buf
= tparam (TS_set_window
, 0, 0, start
, 0, stop
, FRAME_WIDTH (selected_frame
));
392 OUTPUT (TS_insert_mode
);
399 OUTPUT (TS_end_insert_mode
);
403 /* Handle highlighting when TN_standout_width (termcap sg) is not specified.
404 In these terminals, output is affected by the value of standout
405 mode when the output is written.
407 These functions are called on all terminals, but do nothing
408 on terminals whose standout mode does not work that way. */
410 turn_off_highlight ()
412 if (TN_standout_width
< 0)
415 OUTPUT_IF (TS_end_standout_mode
);
422 if (TN_standout_width
< 0)
425 OUTPUT_IF (TS_standout_mode
);
430 /* Set standout mode to the state it should be in for
431 empty space inside windows. What this is,
432 depends on the user option inverse-video. */
434 background_highlight ()
436 if (TN_standout_width
>= 0)
439 turn_on_highlight ();
441 turn_off_highlight ();
444 /* Set standout mode to the mode specified for the text to be output. */
447 highlight_if_desired ()
449 if (TN_standout_width
>= 0)
451 if (!inverse_video
== !standout_requested
)
452 turn_off_highlight ();
454 turn_on_highlight ();
457 /* Handle standout mode for terminals in which TN_standout_width >= 0.
458 On these terminals, standout is controlled by markers that
459 live inside the terminal's memory. TN_standout_width is the width
460 that the marker occupies in memory. Standout runs from the marker
461 to the end of the line on some terminals, or to the next
462 turn-off-standout marker (TS_end_standout_mode) string
463 on other terminals. */
465 /* Write a standout marker or end-standout marker at the front of the line
466 at vertical position vpos. */
468 write_standout_marker (flag
, vpos
)
471 if (flag
|| (TS_end_standout_mode
&& !TF_teleray
&& !se_is_so
472 && !(TF_xs
&& TN_standout_width
== 0)))
475 cmplus (TN_standout_width
);
476 OUTPUT (flag
? TS_standout_mode
: TS_end_standout_mode
);
477 chars_wasted
[curY
] = TN_standout_width
| 0100;
481 /* External interface to control of standout mode.
482 Call this when about to modify line at position VPOS
483 and not change whether it is highlighted. */
485 reassert_line_highlight (highlight
, vpos
)
489 if (! FRAME_TERMCAP_P ((updating_frame
? updating_frame
: selected_frame
)))
491 (*reassert_line_highlight_hook
) (highlight
, vpos
);
494 if (TN_standout_width
< 0)
495 /* Handle terminals where standout takes affect at output time */
496 standout_requested
= highlight
;
497 else if (chars_wasted
[vpos
] == 0)
498 /* For terminals with standout markers, write one on this line
499 if there isn't one already. */
500 write_standout_marker (highlight
, vpos
);
503 /* Call this when about to modify line at position VPOS
504 and change whether it is highlighted. */
506 change_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
507 int new_highlight
, vpos
, first_unused_hpos
;
509 standout_requested
= new_highlight
;
510 if (! FRAME_TERMCAP_P (updating_frame
))
512 (*change_line_highlight_hook
) (new_highlight
, vpos
, first_unused_hpos
);
518 if (TN_standout_width
< 0)
519 background_highlight ();
520 /* If line starts with a marker, delete the marker */
521 else if (TS_clr_line
&& chars_wasted
[curY
])
524 /* On Teleray, make sure to erase the SO marker. */
527 cmgoto (curY
- 1, FRAME_WIDTH (selected_frame
) - 4);
529 curY
++; /* ESC S moves to next line where the TS_standout_mode was */
533 cmgoto (curY
, 0); /* reposition to kill standout marker */
535 clear_end_of_line_raw (first_unused_hpos
);
536 reassert_line_highlight (new_highlight
, curY
);
540 /* Move to absolute position, specified origin 0 */
545 if (! FRAME_TERMCAP_P ((updating_frame
550 (*cursor_to_hook
) (row
, col
);
554 col
+= chars_wasted
[row
] & 077;
555 if (curY
== row
&& curX
== col
)
557 if (!TF_standout_motion
)
558 background_highlight ();
559 if (!TF_insmode_motion
)
564 /* Similar but don't take any account of the wasted characters. */
566 raw_cursor_to (row
, col
)
569 if (! FRAME_TERMCAP_P ((updating_frame
? updating_frame
: selected_frame
)))
571 (*raw_cursor_to_hook
) (row
, col
);
574 if (curY
== row
&& curX
== col
)
576 if (!TF_standout_motion
)
577 background_highlight ();
578 if (!TF_insmode_motion
)
583 /* Erase operations */
585 /* clear from cursor to end of frame */
590 if (clear_to_end_hook
&& FRAME_TERMCAP_P (updating_frame
))
592 (*clear_to_end_hook
) ();
595 if (TS_clr_to_bottom
)
597 background_highlight ();
598 OUTPUT (TS_clr_to_bottom
);
599 bzero (chars_wasted
+ curY
, FRAME_HEIGHT (selected_frame
) - curY
);
603 for (i
= curY
; i
< FRAME_HEIGHT (selected_frame
); i
++)
606 clear_end_of_line_raw (FRAME_WIDTH (selected_frame
));
611 /* Clear entire frame */
616 && ! FRAME_TERMCAP_P ((updating_frame
? updating_frame
: selected_frame
)))
618 (*clear_frame_hook
) ();
623 background_highlight ();
624 OUTPUT (TS_clr_frame
);
625 bzero (chars_wasted
, FRAME_HEIGHT (selected_frame
));
635 /* Clear to end of line, but do not clear any standout marker.
636 Assumes that the cursor is positioned at a character of real text,
637 which implies it cannot be before a standout marker
638 unless the marker has zero width.
640 Note that the cursor may be moved. */
642 clear_end_of_line (first_unused_hpos
)
643 int first_unused_hpos
;
645 static GLYPH buf
= SPACEGLYPH
;
646 if (FRAME_TERMCAP_P (selected_frame
)
647 && TN_standout_width
== 0 && curX
== 0 && chars_wasted
[curY
] != 0)
648 write_glyphs (&buf
, 1);
649 clear_end_of_line_raw (first_unused_hpos
);
652 /* Clear from cursor to end of line.
653 Assume that the line is already clear starting at column first_unused_hpos.
654 If the cursor is at a standout marker, erase the marker.
656 Note that the cursor may be moved, on terminals lacking a `ce' string. */
658 clear_end_of_line_raw (first_unused_hpos
)
659 int first_unused_hpos
;
663 if (clear_end_of_line_hook
664 && ! FRAME_TERMCAP_P ((updating_frame
668 (*clear_end_of_line_hook
) (first_unused_hpos
);
672 first_unused_hpos
+= chars_wasted
[curY
] & 077;
673 if (curX
>= first_unused_hpos
)
675 /* Notice if we are erasing a magic cookie */
677 chars_wasted
[curY
] = 0;
678 background_highlight ();
681 OUTPUT1 (TS_clr_line
);
684 { /* have to do it the hard way */
687 /* Do not write in last row last col with Autowrap on. */
688 if (AutoWrap
&& curY
== FRAME_HEIGHT (selected_frame
) - 1
689 && first_unused_hpos
== FRAME_WIDTH (selected_frame
))
692 for (i
= curX
; i
< first_unused_hpos
; i
++)
695 fputc (' ', termscript
);
698 cmplus (first_unused_hpos
- curX
);
703 write_glyphs (string
, len
)
704 register GLYPH
*string
;
708 register int tlen
= GLYPH_TABLE_LENGTH
;
709 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
711 if (write_glyphs_hook
712 && ! FRAME_TERMCAP_P ((updating_frame
? updating_frame
: selected_frame
)))
714 (*write_glyphs_hook
) (string
, len
);
718 highlight_if_desired ();
721 /* Don't dare write in last column of bottom line, if AutoWrap,
722 since that would scroll the whole frame on some terminals. */
725 && curY
+ 1 == FRAME_HEIGHT (selected_frame
)
726 && (curX
+ len
- (chars_wasted
[curY
] & 077)
727 == FRAME_WIDTH (selected_frame
)))
734 /* Check quickly for G beyond length of table.
735 That implies it isn't an alias and is simple. */
739 putc (g
& 0xff, stdout
);
743 putc (g
& 0xff, termscript
);
747 /* G has an entry in Vglyph_table,
748 so process any alias and then test for simpleness. */
749 while (GLYPH_ALIAS_P (tbase
, tlen
, g
))
750 g
= GLYPH_ALIAS (tbase
, g
);
751 if (GLYPH_SIMPLE_P (tbase
, tlen
, g
))
755 /* Here if G (or its definition as an alias) is not simple. */
756 fwrite (GLYPH_STRING (tbase
, g
), 1, GLYPH_LENGTH (tbase
, g
),
761 fwrite (GLYPH_STRING (tbase
, g
), 1, GLYPH_LENGTH (tbase
, g
),
768 /* If start is zero, insert blanks instead of a string at start */
770 insert_glyphs (start
, len
)
771 register GLYPH
*start
;
776 register int tlen
= GLYPH_TABLE_LENGTH
;
777 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
779 if (insert_glyphs_hook
&& ! FRAME_TERMCAP_P (updating_frame
))
781 (*insert_glyphs_hook
) (start
, len
);
784 highlight_if_desired ();
786 if (TS_ins_multi_chars
)
788 buf
= tparam (TS_ins_multi_chars
, 0, 0, len
);
792 write_glyphs (start
, len
);
800 OUTPUT1_IF (TS_ins_char
);
806 if (GLYPH_SIMPLE_P (tbase
, tlen
, g
))
808 putc (g
& 0xff, stdout
);
812 putc (g
& 0xff, termscript
);
816 fwrite (GLYPH_STRING (tbase
, g
), 1, GLYPH_LENGTH (tbase
, g
), stdout
);
820 fwrite (GLYPH_STRING (tbase
, g
), 1, GLYPH_LENGTH (tbase
, g
),
824 OUTPUT1_IF (TS_pad_inserted_char
);
834 if (delete_glyphs_hook
&& ! FRAME_TERMCAP_P (updating_frame
))
836 (*delete_glyphs_hook
) (n
);
840 if (delete_in_insert_mode
)
847 OUTPUT_IF (TS_delete_mode
);
850 if (TS_del_multi_chars
)
852 buf
= tparam (TS_del_multi_chars
, 0, 0, n
);
857 for (i
= 0; i
< n
; i
++)
858 OUTPUT1 (TS_del_char
);
859 if (!delete_in_insert_mode
)
860 OUTPUT_IF (TS_end_delete_mode
);
863 /* Insert N lines at vpos VPOS. If N is negative, delete -N lines. */
865 ins_del_lines (vpos
, n
)
868 char *multi
= n
> 0 ? TS_ins_multi_lines
: TS_del_multi_lines
;
869 char *single
= n
> 0 ? TS_ins_line
: TS_del_line
;
870 char *scroll
= n
> 0 ? TS_rev_scroll
: TS_fwd_scroll
;
872 register int i
= n
> 0 ? n
: -n
;
875 if (ins_del_lines_hook
&& ! FRAME_TERMCAP_P (updating_frame
))
877 (*ins_del_lines_hook
) (vpos
, n
);
881 /* If the lines below the insertion are being pushed
882 into the end of the window, this is the same as clearing;
883 and we know the lines are already clear, since the matching
884 deletion has already been done. So can ignore this. */
885 /* If the lines below the deletion are blank lines coming
886 out of the end of the window, don't bother,
887 as there will be a matching inslines later that will flush them. */
888 if (scroll_region_ok
&& vpos
+ i
>= specified_window
)
890 if (!memory_below_frame
&& vpos
+ i
>= FRAME_HEIGHT (selected_frame
))
895 raw_cursor_to (vpos
, 0);
896 background_highlight ();
897 buf
= tparam (multi
, 0, 0, i
);
903 raw_cursor_to (vpos
, 0);
904 background_highlight ();
912 set_scroll_region (vpos
, specified_window
);
914 raw_cursor_to (specified_window
- 1, 0);
916 raw_cursor_to (vpos
, 0);
917 background_highlight ();
919 OUTPUTL (scroll
, specified_window
- vpos
);
920 set_scroll_region (0, specified_window
);
923 if (TN_standout_width
>= 0)
928 : FRAME_HEIGHT (selected_frame
));
932 bcopy (&chars_wasted
[vpos
- n
], &chars_wasted
[vpos
],
933 lower_limit
- vpos
+ n
);
934 bzero (&chars_wasted
[lower_limit
+ n
], - n
);
938 bcopy (&chars_wasted
[vpos
], ©buf
[vpos
], lower_limit
- vpos
- n
);
939 bcopy (©buf
[vpos
], &chars_wasted
[vpos
+ n
],
940 lower_limit
- vpos
- n
);
941 bzero (&chars_wasted
[vpos
], n
);
944 if (!scroll_region_ok
&& memory_below_frame
&& n
< 0)
946 cursor_to (FRAME_HEIGHT (selected_frame
) + n
, 0);
951 /* Compute cost of sending "str", in characters,
952 not counting any line-dependent padding. */
960 tputs (str
, 0, evalcost
);
964 /* Compute cost of sending "str", in characters,
965 counting any line-dependent padding at one line. */
968 string_cost_one_line (str
)
973 tputs (str
, 1, evalcost
);
977 /* Compute per line amount of line-dependent padding,
978 in tenths of characters. */
986 tputs (str
, 0, evalcost
);
989 tputs (str
, 10, evalcost
);
994 /* char_ins_del_cost[n] is cost of inserting N characters.
995 char_ins_del_cost[-n] is cost of deleting N characters. */
997 int *char_ins_del_vector
;
999 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WIDTH ((f))])
1004 calculate_ins_del_char_costs (frame
)
1007 int ins_startup_cost
, del_startup_cost
;
1008 int ins_cost_per_char
, del_cost_per_char
;
1012 if (TS_ins_multi_chars
)
1014 ins_cost_per_char
= 0;
1015 ins_startup_cost
= string_cost_one_line (TS_ins_multi_chars
);
1017 else if (TS_ins_char
|| TS_pad_inserted_char
1018 || (TS_insert_mode
&& TS_end_insert_mode
))
1020 ins_startup_cost
= (30 * (string_cost (TS_insert_mode
)
1021 + string_cost (TS_end_insert_mode
))) / 100;
1022 ins_cost_per_char
= (string_cost_one_line (TS_ins_char
)
1023 + string_cost_one_line (TS_pad_inserted_char
));
1027 ins_startup_cost
= 9999;
1028 ins_cost_per_char
= 0;
1031 if (TS_del_multi_chars
)
1033 del_cost_per_char
= 0;
1034 del_startup_cost
= string_cost_one_line (TS_del_multi_chars
);
1036 else if (TS_del_char
)
1038 del_startup_cost
= (string_cost (TS_delete_mode
)
1039 + string_cost (TS_end_delete_mode
));
1040 if (delete_in_insert_mode
)
1041 del_startup_cost
/= 2;
1042 del_cost_per_char
= string_cost_one_line (TS_del_char
);
1046 del_startup_cost
= 9999;
1047 del_cost_per_char
= 0;
1050 /* Delete costs are at negative offsets */
1051 p
= &char_ins_del_cost (frame
)[0];
1052 for (i
= FRAME_WIDTH (selected_frame
); --i
>= 0;)
1053 *--p
= (del_startup_cost
+= del_cost_per_char
);
1055 /* Doing nothing is free */
1056 p
= &char_ins_del_cost (frame
)[0];
1059 /* Insert costs are at positive offsets */
1060 for (i
= FRAME_WIDTH (frame
); --i
>= 0;)
1061 *p
++ = (ins_startup_cost
+= ins_cost_per_char
);
1064 #ifdef HAVE_X_WINDOWS
1065 extern int x_screen_planes
;
1068 extern do_line_insertion_deletion_costs ();
1070 calculate_costs (frame
)
1073 register char *f
= TS_set_scroll_region
?
1074 TS_set_scroll_region
1075 : TS_set_scroll_region_1
;
1077 if (dont_calculate_costs
)
1080 #ifdef HAVE_X_WINDOWS
1081 if (FRAME_X_P (frame
))
1083 do_line_insertion_deletion_costs (frame
, 0, ".5*", 0, ".5*",
1084 0, 0, x_screen_planes
);
1089 /* These variables are only used for terminal stuff. They are allocated
1090 once for the terminal frame of X-windows emacs, but not used afterwards.
1092 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1093 X turns off char_ins_del_ok.
1095 chars_wasted and copybuf are only used here in term.c in cases where
1096 the term hook isn't called. */
1098 if (chars_wasted
!= 0)
1099 chars_wasted
= (char *) xrealloc (chars_wasted
, FRAME_HEIGHT (frame
));
1101 chars_wasted
= (char *) xmalloc (FRAME_HEIGHT (frame
));
1104 copybuf
= (char *) xrealloc (copybuf
, FRAME_HEIGHT (frame
));
1106 copybuf
= (char *) xmalloc (FRAME_HEIGHT (frame
));
1108 if (char_ins_del_vector
!= 0)
1110 = (int *) xrealloc (char_ins_del_vector
,
1112 + 2 * FRAME_WIDTH (frame
) * sizeof (int)));
1115 = (int *) xmalloc (sizeof (int)
1116 + 2 * FRAME_WIDTH (frame
) * sizeof (int));
1118 bzero (chars_wasted
, FRAME_HEIGHT (frame
));
1119 bzero (copybuf
, FRAME_HEIGHT (frame
));
1120 bzero (char_ins_del_vector
, (sizeof (int)
1121 + 2 * FRAME_WIDTH (frame
) * sizeof (int)));
1123 if (f
&& (!TS_ins_line
&& !TS_del_line
))
1124 do_line_insertion_deletion_costs (frame
,
1125 TS_rev_scroll
, TS_ins_multi_lines
,
1126 TS_fwd_scroll
, TS_del_multi_lines
,
1129 do_line_insertion_deletion_costs (frame
,
1130 TS_ins_line
, TS_ins_multi_lines
,
1131 TS_del_line
, TS_del_multi_lines
,
1134 calculate_ins_del_char_costs (frame
);
1136 /* Don't use TS_repeat if its padding is worse than sending the chars */
1137 if (TS_repeat
&& per_line_cost (TS_repeat
) * baud_rate
< 9000)
1138 RPov
= string_cost (TS_repeat
);
1140 RPov
= FRAME_WIDTH (frame
) * 2;
1142 cmcostinit (); /* set up cursor motion costs */
1149 /* Termcap capability names that correspond directly to X keysyms.
1150 Some of these (marked "terminfo") aren't supplied by old-style
1151 (Berkeley) termcap entries. They're listed in X keysym order;
1152 except we put the keypad keys first, so that if they clash with
1153 other keys (as on the IBM PC keyboard) they get overridden.
1156 static struct fkey_table keys
[] = {
1157 "kh", "home", /* termcap */
1158 "kl", "left", /* termcap */
1159 "ku", "up", /* termcap */
1160 "kr", "right", /* termcap */
1161 "kd", "down", /* termcap */
1162 "%8", "prior", /* terminfo */
1163 "%5", "next", /* terminfo */
1164 "@7", "end", /* terminfo */
1165 "@1", "begin", /* terminfo */
1166 "*6", "select", /* terminfo */
1167 "%9", "print", /* terminfo */
1168 "@4", "execute", /* terminfo --- actually the `command' key */
1170 * "insert" --- see below
1172 "&8", "undo", /* terminfo */
1173 "%0", "redo", /* terminfo */
1174 "%7", "menu", /* terminfo --- actually the `options' key */
1175 "@0", "find", /* terminfo */
1176 "@2", "cancel", /* terminfo */
1177 "%1", "help", /* terminfo */
1179 * "break" goes here, but can't be reliably intercepted with termcap
1181 "&4", "reset", /* terminfo --- actually `restart' */
1183 * "system" and "user" --- no termcaps
1185 "kE", "clearline", /* terminfo */
1186 "kA", "insertline", /* terminfo */
1187 "kL", "deleteline", /* terminfo */
1188 "kI", "insertchar", /* terminfo */
1189 "kD", "deletechar", /* terminfo */
1190 "kB", "backtab", /* terminfo */
1192 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1194 "@8", "kp-enter", /* terminfo */
1196 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1197 * "kp-multiply", "kp-add", "kp-separator",
1198 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1199 * --- no termcaps for any of these.
1201 "K4", "kp-1", /* terminfo */
1203 * "kp-2" --- no termcap
1205 "K5", "kp-3", /* terminfo */
1207 * "kp-4" --- no termcap
1209 "K2", "kp-5", /* terminfo */
1211 * "kp-6" --- no termcap
1213 "K1", "kp-7", /* terminfo */
1215 * "kp-8" --- no termcap
1217 "K3", "kp-9", /* terminfo */
1219 * "kp-equal" --- no termcap
1232 /* Find the escape codes sent by the function keys for Vfunction_key_map.
1233 This function scans the termcap function key sequence entries, and
1234 adds entries to Vfunction_key_map for each function key it finds. */
1237 term_get_fkeys (address
)
1240 extern char *tgetstr ();
1243 /* This can happen if CANNOT_DUMP or with strange options. */
1245 Vfunction_key_map
= Fmake_sparse_keymap (Qnil
);
1247 for (i
= 0; i
< (sizeof (keys
)/sizeof (keys
[0])); i
++)
1249 char *sequence
= tgetstr (keys
[i
].cap
, address
);
1251 Fdefine_key (Vfunction_key_map
,
1252 build_string (sequence
),
1253 Fmake_vector (make_number (1), intern (keys
[i
].name
)));
1256 /* The uses of the "k0" capability are inconsistent; sometimes it
1257 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1258 We will attempt to politely accommodate both systems by testing for
1259 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1262 char *k_semi
= tgetstr ("k;", address
);
1263 char *k0
= tgetstr ("k0", address
);
1264 char *k0_name
= "f10";
1268 Fdefine_key (Vfunction_key_map
,
1269 build_string (k_semi
),
1270 Fmake_vector (make_number (1), intern ("f10")));
1275 Fdefine_key (Vfunction_key_map
,
1277 Fmake_vector (make_number (1), intern (k0_name
)));
1280 /* Set up cookies for numbered function keys above f10. */
1282 char fcap
[3], fkey
[4];
1284 fcap
[0] = 'F'; fcap
[2] = '\0';
1285 for (i
= 11; i
< 64; i
++)
1288 fcap
[1] = '1' + i
- 11;
1290 fcap
[1] = 'A' + i
- 11;
1292 fcap
[1] = 'a' + i
- 11;
1295 char *sequence
= tgetstr (fcap
, address
);
1298 (void) sprintf (fkey
, "f%d", i
);
1299 Fdefine_key (Vfunction_key_map
,
1300 build_string (sequence
),
1301 Fmake_vector (make_number (1), intern (fkey
)));
1308 * Various mappings to try and get a better fit.
1311 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1312 if (!tgetstr (cap1, address)) \
1314 char *sequence = tgetstr (cap2, address); \
1316 Fdefine_key (Vfunction_key_map, \
1317 build_string (sequence), \
1318 Fmake_vector (make_number (1), intern (sym))); \
1321 /* if there's no key_next keycap, map key_npage to `next' keysym */
1322 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1323 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1324 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1325 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1326 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1327 #undef CONDITIONAL_REASSIGN
1332 term_init (terminal_type
)
1333 char *terminal_type
;
1336 char **address
= &area
;
1341 extern char *tgetstr ();
1344 dont_calculate_costs
= 0;
1346 status
= tgetent (buffer
, terminal_type
);
1348 fatal ("Cannot open termcap database file.\n");
1350 fatal ("Terminal type %s is not defined.\n", terminal_type
);
1353 area
= (char *) malloc (2044);
1355 area
= (char *) malloc (strlen (buffer
));
1356 #endif /* not TERMINFO */
1360 TS_ins_line
= tgetstr ("al", address
);
1361 TS_ins_multi_lines
= tgetstr ("AL", address
);
1362 TS_bell
= tgetstr ("bl", address
);
1363 BackTab
= tgetstr ("bt", address
);
1364 TS_clr_to_bottom
= tgetstr ("cd", address
);
1365 TS_clr_line
= tgetstr ("ce", address
);
1366 TS_clr_frame
= tgetstr ("cl", address
);
1367 ColPosition
= tgetstr ("ch", address
);
1368 AbsPosition
= tgetstr ("cm", address
);
1369 CR
= tgetstr ("cr", address
);
1370 TS_set_scroll_region
= tgetstr ("cs", address
);
1371 TS_set_scroll_region_1
= tgetstr ("cS", address
);
1372 RowPosition
= tgetstr ("cv", address
);
1373 TS_del_char
= tgetstr ("dc", address
);
1374 TS_del_multi_chars
= tgetstr ("DC", address
);
1375 TS_del_line
= tgetstr ("dl", address
);
1376 TS_del_multi_lines
= tgetstr ("DL", address
);
1377 TS_delete_mode
= tgetstr ("dm", address
);
1378 TS_end_delete_mode
= tgetstr ("ed", address
);
1379 TS_end_insert_mode
= tgetstr ("ei", address
);
1380 Home
= tgetstr ("ho", address
);
1381 TS_ins_char
= tgetstr ("ic", address
);
1382 TS_ins_multi_chars
= tgetstr ("IC", address
);
1383 TS_insert_mode
= tgetstr ("im", address
);
1384 TS_pad_inserted_char
= tgetstr ("ip", address
);
1385 TS_end_keypad_mode
= tgetstr ("ke", address
);
1386 TS_keypad_mode
= tgetstr ("ks", address
);
1387 LastLine
= tgetstr ("ll", address
);
1388 Right
= tgetstr ("nd", address
);
1389 Down
= tgetstr ("do", address
);
1391 Down
= tgetstr ("nl", address
); /* Obsolete name for "do" */
1393 /* VMS puts a carriage return before each linefeed,
1394 so it is not safe to use linefeeds. */
1395 if (Down
&& Down
[0] == '\n' && Down
[1] == '\0')
1398 if (tgetflag ("bs"))
1399 Left
= "\b"; /* can't possibly be longer! */
1400 else /* (Actually, "bs" is obsolete...) */
1401 Left
= tgetstr ("le", address
);
1403 Left
= tgetstr ("bc", address
); /* Obsolete name for "le" */
1404 TS_pad_char
= tgetstr ("pc", address
);
1405 TS_repeat
= tgetstr ("rp", address
);
1406 TS_end_standout_mode
= tgetstr ("se", address
);
1407 TS_fwd_scroll
= tgetstr ("sf", address
);
1408 TS_standout_mode
= tgetstr ("so", address
);
1409 TS_rev_scroll
= tgetstr ("sr", address
);
1410 Wcm
.cm_tab
= tgetstr ("ta", address
);
1411 TS_end_termcap_modes
= tgetstr ("te", address
);
1412 TS_termcap_modes
= tgetstr ("ti", address
);
1413 Up
= tgetstr ("up", address
);
1414 TS_visible_bell
= tgetstr ("vb", address
);
1415 TS_end_visual_mode
= tgetstr ("ve", address
);
1416 TS_visual_mode
= tgetstr ("vs", address
);
1417 TS_set_window
= tgetstr ("wi", address
);
1418 MultiUp
= tgetstr ("UP", address
);
1419 MultiDown
= tgetstr ("DO", address
);
1420 MultiLeft
= tgetstr ("LE", address
);
1421 MultiRight
= tgetstr ("RI", address
);
1423 AutoWrap
= tgetflag ("am");
1424 memory_below_frame
= tgetflag ("db");
1425 TF_hazeltine
= tgetflag ("hz");
1426 must_write_spaces
= tgetflag ("in");
1427 meta_key
= tgetflag ("km") || tgetflag ("MT");
1428 TF_insmode_motion
= tgetflag ("mi");
1429 TF_standout_motion
= tgetflag ("ms");
1430 TF_underscore
= tgetflag ("ul");
1431 MagicWrap
= tgetflag ("xn");
1432 TF_xs
= tgetflag ("xs");
1433 TF_teleray
= tgetflag ("xt");
1435 term_get_fkeys (address
);
1437 /* Get frame size from system, or else from termcap. */
1438 get_frame_size (&FRAME_WIDTH (selected_frame
),
1439 &FRAME_HEIGHT (selected_frame
));
1440 if (FRAME_WIDTH (selected_frame
) <= 0)
1441 FRAME_WIDTH (selected_frame
) = tgetnum ("co");
1442 if (FRAME_HEIGHT (selected_frame
) <= 0)
1443 FRAME_HEIGHT (selected_frame
) = tgetnum ("li");
1445 min_padding_speed
= tgetnum ("pb");
1446 TN_standout_width
= tgetnum ("sg");
1447 TabWidth
= tgetnum ("tw");
1450 /* These capabilities commonly use ^J.
1451 I don't know why, but sending them on VMS does not work;
1452 it causes following spaces to be lost, sometimes.
1453 For now, the simplest fix is to avoid using these capabilities ever. */
1454 if (Down
&& Down
[0] == '\n')
1462 TS_fwd_scroll
= Down
;
1464 PC
= TS_pad_char
? *TS_pad_char
: 0;
1469 /* Turned off since /etc/termcap seems to have :ta= for most terminals
1470 and newer termcap doc does not seem to say there is a default.
1475 if (TS_standout_mode
== 0)
1477 TN_standout_width
= tgetnum ("ug");
1478 TS_end_standout_mode
= tgetstr ("ue", address
);
1479 TS_standout_mode
= tgetstr ("us", address
);
1485 /* Teleray: most programs want a space in front of TS_standout_mode,
1486 but Emacs can do without it (and give one extra column). */
1487 TS_standout_mode
= "\033RD";
1488 TN_standout_width
= 1;
1489 /* But that means we cannot rely on ^M to go to column zero! */
1491 /* LF can't be trusted either -- can alter hpos */
1492 /* if move at column 0 thru a line with TS_standout_mode */
1496 /* Special handling for certain terminal types known to need it */
1498 if (!strcmp (terminal_type
, "supdup"))
1500 memory_below_frame
= 1;
1501 Wcm
.cm_losewrap
= 1;
1503 if (!strncmp (terminal_type
, "c10", 3)
1504 || !strcmp (terminal_type
, "perq"))
1506 /* Supply a makeshift :wi string.
1507 This string is not valid in general since it works only
1508 for windows starting at the upper left corner;
1509 but that is all Emacs uses.
1511 This string works only if the frame is using
1512 the top of the video memory, because addressing is memory-relative.
1513 So first check the :ti string to see if that is true.
1515 It would be simpler if the :wi string could go in the termcap
1516 entry, but it can't because it is not fully valid.
1517 If it were in the termcap entry, it would confuse other programs. */
1520 p
= TS_termcap_modes
;
1521 while (*p
&& strcmp (p
, "\033v "))
1524 TS_set_window
= "\033v%C %C %C %C ";
1526 /* Termcap entry often fails to have :in: flag */
1527 must_write_spaces
= 1;
1528 /* :ti string typically fails to have \E^G! in it */
1529 /* This limits scope of insert-char to one line. */
1530 strcpy (area
, TS_termcap_modes
);
1531 strcat (area
, "\033\007!");
1532 TS_termcap_modes
= area
;
1533 area
+= strlen (area
) + 1;
1535 /* Change all %+ parameters to %C, to handle
1536 values above 96 correctly for the C100. */
1539 if (p
[0] == '%' && p
[1] == '+')
1545 FrameRows
= FRAME_HEIGHT (selected_frame
);
1546 FrameCols
= FRAME_WIDTH (selected_frame
);
1547 specified_window
= FRAME_HEIGHT (selected_frame
);
1549 if (Wcm_init () == -1) /* can't do cursor motion */
1551 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
1552 It lacks the ability to position the cursor.\n\
1553 If that is not the actual type of terminal you have, use either the\n\
1554 DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
1555 or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.\n",
1558 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
1559 It lacks the ability to position the cursor.\n\
1560 If that is not the actual type of terminal you have,\n\
1561 use the C-shell command `setenv TERM ...' to specify the correct type.\n\
1562 It may be necessary to do `unsetenv TERMCAP' as well.\n",
1565 if (FRAME_HEIGHT (selected_frame
) <= 0
1566 || FRAME_WIDTH (selected_frame
) <= 0)
1567 fatal ("The frame size has not been specified.");
1569 delete_in_insert_mode
1570 = TS_delete_mode
&& TS_insert_mode
1571 && !strcmp (TS_delete_mode
, TS_insert_mode
);
1573 se_is_so
= (TS_standout_mode
1574 && TS_end_standout_mode
1575 && !strcmp (TS_standout_mode
, TS_end_standout_mode
));
1577 /* Remove width of standout marker from usable width of line */
1578 if (TN_standout_width
> 0)
1579 FRAME_WIDTH (selected_frame
) -= TN_standout_width
;
1581 UseTabs
= tabs_safe_p () && TabWidth
== 8;
1585 && (TS_set_window
|| TS_set_scroll_region
|| TS_set_scroll_region_1
));
1587 line_ins_del_ok
= (((TS_ins_line
|| TS_ins_multi_lines
)
1588 && (TS_del_line
|| TS_del_multi_lines
))
1589 || (scroll_region_ok
&& TS_fwd_scroll
&& TS_rev_scroll
));
1591 char_ins_del_ok
= ((TS_ins_char
|| TS_insert_mode
1592 || TS_pad_inserted_char
|| TS_ins_multi_chars
)
1593 && (TS_del_char
|| TS_del_multi_chars
));
1595 fast_clear_end_of_line
= TS_clr_line
!= 0;
1598 if (read_socket_hook
) /* Baudrate is somewhat */
1599 /* meaningless in this case */
1602 FRAME_CAN_HAVE_SCROLL_BARS (selected_frame
) = 0;
1603 FRAME_HAS_VERTICAL_SCROLL_BARS (selected_frame
) = 0;
1607 fatal (str
, arg1
, arg2
)
1608 char *str
, *arg1
, *arg2
;
1610 fprintf (stderr
, "emacs: ");
1611 fprintf (stderr
, str
, arg1
, arg2
);