1 /* terminal control module for terminals described by TERMCAP
2 Copyright (C) 1985, 1986, 1987, 1992 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 charateristics 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. This should clear
97 mouse_moved until the next motion event arrives. */
98 void (*mouse_position_hook
) ( /* FRAME_PTR *f,
101 unsigned long *time */ );
103 /* When reading from a minibuffer in a different frame, Emacs wants
104 to shift the highlight from the selected frame to the minibuffer's
105 frame; under X, this means it lies about where the focus is.
106 This hook tells the window system code to re-decide where to put
108 void (*frame_rehighlight_hook
) ( /* FRAME_PTR f */ );
110 /* Strings, numbers and flags taken from the termcap entry. */
112 char *TS_ins_line
; /* termcap "al" */
113 char *TS_ins_multi_lines
; /* "AL" (one parameter, # lines to insert) */
114 char *TS_bell
; /* "bl" */
115 char *TS_clr_to_bottom
; /* "cd" */
116 char *TS_clr_line
; /* "ce", clear to end of line */
117 char *TS_clr_frame
; /* "cl" */
118 char *TS_set_scroll_region
; /* "cs" (2 params, first line and last line) */
119 char *TS_set_scroll_region_1
; /* "cS" (4 params: total lines,
120 lines above scroll region, lines below it,
121 total lines again) */
122 char *TS_del_char
; /* "dc" */
123 char *TS_del_multi_chars
; /* "DC" (one parameter, # chars to delete) */
124 char *TS_del_line
; /* "dl" */
125 char *TS_del_multi_lines
; /* "DL" (one parameter, # lines to delete) */
126 char *TS_delete_mode
; /* "dm", enter character-delete mode */
127 char *TS_end_delete_mode
; /* "ed", leave character-delete mode */
128 char *TS_end_insert_mode
; /* "ei", leave character-insert mode */
129 char *TS_ins_char
; /* "ic" */
130 char *TS_ins_multi_chars
; /* "IC" (one parameter, # chars to insert) */
131 char *TS_insert_mode
; /* "im", enter character-insert mode */
132 char *TS_pad_inserted_char
; /* "ip". Just padding, no commands. */
133 char *TS_end_keypad_mode
; /* "ke" */
134 char *TS_keypad_mode
; /* "ks" */
135 char *TS_pad_char
; /* "pc", char to use as padding */
136 char *TS_repeat
; /* "rp" (2 params, # times to repeat
137 and character to be repeated) */
138 char *TS_end_standout_mode
; /* "se" */
139 char *TS_fwd_scroll
; /* "sf" */
140 char *TS_standout_mode
; /* "so" */
141 char *TS_rev_scroll
; /* "sr" */
142 char *TS_end_termcap_modes
; /* "te" */
143 char *TS_termcap_modes
; /* "ti" */
144 char *TS_visible_bell
; /* "vb" */
145 char *TS_end_visual_mode
; /* "ve" */
146 char *TS_visual_mode
; /* "vi" */
147 char *TS_set_window
; /* "wi" (4 params, start and end of window,
148 each as vpos and hpos) */
150 int TF_hazeltine
; /* termcap hz flag. */
151 int TF_insmode_motion
; /* termcap mi flag: can move while in insert mode. */
152 int TF_standout_motion
; /* termcap mi flag: can move while in standout mode. */
153 int TF_underscore
; /* termcap ul flag: _ underlines if overstruck on
154 nonblank position. Must clear before writing _. */
155 int TF_teleray
; /* termcap xt flag: many weird consequences.
158 int TF_xs
; /* Nonzero for "xs". If set together with
159 TN_standout_width == 0, it means don't bother
160 to write any end-standout cookies. */
162 int TN_standout_width
; /* termcap sg number: width occupied by standout
165 static int RPov
; /* # chars to start a TS_repeat */
167 static int delete_in_insert_mode
; /* delete mode == insert mode */
169 static int se_is_so
; /* 1 if same string both enters and leaves
174 /* Number of chars of space used for standout marker at beginning of line,
175 or'd with 0100. Zero if no standout marker at all.
177 Used IFF TN_standout_width >= 0. */
179 static char *chars_wasted
;
180 static char *copybuf
;
182 /* nonzero means supposed to write text in standout mode. */
183 int standout_requested
;
185 int insert_mode
; /* Nonzero when in insert mode. */
186 int standout_mode
; /* Nonzero when in standout mode. */
188 /* Size of window specified by higher levels.
189 This is the number of lines, from the top of frame downwards,
190 which can participate in insert-line/delete-line operations.
192 Effectively it excludes the bottom frame_height - specified_window_size
193 lines from those operations. */
195 int specified_window
;
197 /* Frame currently being redisplayed; 0 if not currently redisplaying.
198 (Direct output does not count). */
200 FRAME_PTR updating_frame
;
206 if (! FRAME_IS_TERMCAP (selected_frame
))
208 (*ring_bell_hook
) ();
211 OUTPUT (TS_visible_bell
&& visible_bell
? TS_visible_bell
: TS_bell
);
214 set_terminal_modes ()
216 if (! FRAME_IS_TERMCAP (selected_frame
))
218 (*set_terminal_modes_hook
) ();
221 OUTPUT_IF (TS_termcap_modes
);
222 OUTPUT_IF (TS_visual_mode
);
223 OUTPUT_IF (TS_keypad_mode
);
227 reset_terminal_modes ()
229 if (! FRAME_IS_TERMCAP (selected_frame
))
231 (*reset_terminal_modes_hook
) ();
234 if (TN_standout_width
< 0)
235 turn_off_highlight ();
237 OUTPUT_IF (TS_end_keypad_mode
);
238 OUTPUT_IF (TS_end_visual_mode
);
239 OUTPUT_IF (TS_end_termcap_modes
);
240 /* Output raw CR so kernel can track the cursor hpos. */
241 /* But on magic-cookie terminals this can erase an end-standout marker and
242 cause the rest of the frame to be in standout, so move down first. */
243 if (TN_standout_width
>= 0)
252 if (! FRAME_IS_TERMCAP (updating_frame
))
253 (*update_begin_hook
) (f
);
259 if (! FRAME_IS_TERMCAP (updating_frame
))
261 (*update_end_hook
) (f
);
266 background_highlight ();
267 standout_requested
= 0;
271 set_terminal_window (size
)
274 if (! FRAME_IS_TERMCAP (updating_frame
))
276 (*set_terminal_window_hook
) (size
);
279 specified_window
= size
? size
: FRAME_HEIGHT (selected_frame
);
280 if (!scroll_region_ok
)
282 set_scroll_region (0, specified_window
);
285 set_scroll_region (start
, stop
)
289 if (TS_set_scroll_region
)
291 buf
= tparam (TS_set_scroll_region
, 0, 0, start
, stop
- 1);
293 else if (TS_set_scroll_region_1
)
295 buf
= tparam (TS_set_scroll_region_1
, 0, 0,
296 FRAME_HEIGHT (selected_frame
), start
,
297 FRAME_HEIGHT (selected_frame
) - stop
,
298 FRAME_HEIGHT (selected_frame
));
302 buf
= tparam (TS_set_window
, 0, 0, start
, 0, stop
, FRAME_WIDTH (selected_frame
));
312 OUTPUT (TS_insert_mode
);
319 OUTPUT (TS_end_insert_mode
);
323 /* Handle highlighting when TN_standout_width (termcap sg) is not specified.
324 In these terminals, output is affected by the value of standout
325 mode when the output is written.
327 These functions are called on all terminals, but do nothing
328 on terminals whose standout mode does not work that way. */
330 turn_off_highlight ()
332 if (TN_standout_width
< 0)
335 OUTPUT_IF (TS_end_standout_mode
);
342 if (TN_standout_width
< 0)
345 OUTPUT_IF (TS_standout_mode
);
350 /* Set standout mode to the state it should be in for
351 empty space inside windows. What this is,
352 depends on the user option inverse-video. */
354 background_highlight ()
356 if (TN_standout_width
>= 0)
359 turn_on_highlight ();
361 turn_off_highlight ();
364 /* Set standout mode to the mode specified for the text to be output. */
367 highlight_if_desired ()
369 if (TN_standout_width
>= 0)
371 if (!inverse_video
== !standout_requested
)
372 turn_off_highlight ();
374 turn_on_highlight ();
377 /* Handle standout mode for terminals in which TN_standout_width >= 0.
378 On these terminals, standout is controlled by markers that
379 live inside the terminal's memory. TN_standout_width is the width
380 that the marker occupies in memory. Standout runs from the marker
381 to the end of the line on some terminals, or to the next
382 turn-off-standout marker (TS_end_standout_mode) string
383 on other terminals. */
385 /* Write a standout marker or end-standout marker at the front of the line
386 at vertical position vpos. */
388 write_standout_marker (flag
, vpos
)
391 if (flag
|| (TS_end_standout_mode
&& !TF_teleray
&& !se_is_so
392 && !(TF_xs
&& TN_standout_width
== 0)))
395 cmplus (TN_standout_width
);
396 OUTPUT (flag
? TS_standout_mode
: TS_end_standout_mode
);
397 chars_wasted
[curY
] = TN_standout_width
| 0100;
401 /* External interface to control of standout mode.
402 Call this when about to modify line at position VPOS
403 and not change whether it is highlighted. */
405 reassert_line_highlight (highlight
, vpos
)
409 if (! FRAME_IS_TERMCAP ((updating_frame
? updating_frame
: selected_frame
)))
411 (*reassert_line_highlight_hook
) (highlight
, vpos
);
414 if (TN_standout_width
< 0)
415 /* Handle terminals where standout takes affect at output time */
416 standout_requested
= highlight
;
417 else if (chars_wasted
[vpos
] == 0)
418 /* For terminals with standout markers, write one on this line
419 if there isn't one already. */
420 write_standout_marker (highlight
, vpos
);
423 /* Call this when about to modify line at position VPOS
424 and change whether it is highlighted. */
426 change_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
427 int new_highlight
, vpos
, first_unused_hpos
;
429 standout_requested
= new_highlight
;
430 if (! FRAME_IS_TERMCAP (updating_frame
))
432 (*change_line_highlight_hook
) (new_highlight
, vpos
, first_unused_hpos
);
438 if (TN_standout_width
< 0)
439 background_highlight ();
440 /* If line starts with a marker, delete the marker */
441 else if (TS_clr_line
&& chars_wasted
[curY
])
444 /* On Teleray, make sure to erase the SO marker. */
447 cmgoto (curY
- 1, FRAME_WIDTH (selected_frame
) - 4);
449 curY
++; /* ESC S moves to next line where the TS_standout_mode was */
453 cmgoto (curY
, 0); /* reposition to kill standout marker */
455 clear_end_of_line_raw (first_unused_hpos
);
456 reassert_line_highlight (new_highlight
, curY
);
460 /* Move to absolute position, specified origin 0 */
465 if (! FRAME_IS_TERMCAP ((updating_frame
470 (*cursor_to_hook
) (row
, col
);
474 col
+= chars_wasted
[row
] & 077;
475 if (curY
== row
&& curX
== col
)
477 if (!TF_standout_motion
)
478 background_highlight ();
479 if (!TF_insmode_motion
)
484 /* Similar but don't take any account of the wasted characters. */
486 raw_cursor_to (row
, col
)
489 if (! FRAME_IS_TERMCAP ((updating_frame
? updating_frame
: selected_frame
)))
491 (*raw_cursor_to_hook
) (row
, col
);
494 if (curY
== row
&& curX
== col
)
496 if (!TF_standout_motion
)
497 background_highlight ();
498 if (!TF_insmode_motion
)
503 /* Erase operations */
505 /* clear from cursor to end of frame */
510 if (clear_to_end_hook
&& FRAME_IS_TERMCAP (updating_frame
))
512 (*clear_to_end_hook
) ();
515 if (TS_clr_to_bottom
)
517 background_highlight ();
518 OUTPUT (TS_clr_to_bottom
);
519 bzero (chars_wasted
+ curY
, FRAME_HEIGHT (selected_frame
) - curY
);
523 for (i
= curY
; i
< FRAME_HEIGHT (selected_frame
); i
++)
526 clear_end_of_line_raw (FRAME_WIDTH (selected_frame
));
531 /* Clear entire frame */
536 && ! FRAME_IS_TERMCAP ((updating_frame
? updating_frame
: selected_frame
)))
538 (*clear_frame_hook
) ();
543 background_highlight ();
544 OUTPUT (TS_clr_frame
);
545 bzero (chars_wasted
, FRAME_HEIGHT (selected_frame
));
555 /* Clear to end of line, but do not clear any standout marker.
556 Assumes that the cursor is positioned at a character of real text,
557 which implies it cannot be before a standout marker
558 unless the marker has zero width.
560 Note that the cursor may be moved. */
562 clear_end_of_line (first_unused_hpos
)
563 int first_unused_hpos
;
565 static GLYPH buf
[1] = {SPACEGLYPH
};
566 if (FRAME_IS_TERMCAP (selected_frame
)
567 && TN_standout_width
== 0 && curX
== 0 && chars_wasted
[curY
] != 0)
568 write_glyphs (buf
, 1);
569 clear_end_of_line_raw (first_unused_hpos
);
572 /* Clear from cursor to end of line.
573 Assume that the line is already clear starting at column first_unused_hpos.
574 If the cursor is at a standout marker, erase the marker.
576 Note that the cursor may be moved, on terminals lacking a `ce' string. */
578 clear_end_of_line_raw (first_unused_hpos
)
579 int first_unused_hpos
;
583 if (clear_end_of_line_hook
584 && ! FRAME_IS_TERMCAP ((updating_frame
588 (*clear_end_of_line_hook
) (first_unused_hpos
);
592 first_unused_hpos
+= chars_wasted
[curY
] & 077;
593 if (curX
>= first_unused_hpos
)
595 /* Notice if we are erasing a magic cookie */
597 chars_wasted
[curY
] = 0;
598 background_highlight ();
601 OUTPUT1 (TS_clr_line
);
604 { /* have to do it the hard way */
607 /* Do not write in last row last col with Autowrap on. */
608 if (AutoWrap
&& curY
== FRAME_HEIGHT (selected_frame
) - 1
609 && first_unused_hpos
== FRAME_WIDTH (selected_frame
))
612 for (i
= curX
; i
< first_unused_hpos
; i
++)
615 fputc (' ', termscript
);
618 cmplus (first_unused_hpos
- curX
);
623 write_glyphs (string
, len
)
624 register GLYPH
*string
;
628 register int tlen
= GLYPH_TABLE_LENGTH
;
629 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
631 if (write_glyphs_hook
632 && ! FRAME_IS_TERMCAP ((updating_frame
? updating_frame
: selected_frame
)))
634 (*write_glyphs_hook
) (string
, len
);
638 highlight_if_desired ();
641 /* Don't dare write in last column of bottom line, if AutoWrap,
642 since that would scroll the whole frame on some terminals. */
645 && curY
+ 1 == FRAME_HEIGHT (selected_frame
)
646 && (curX
+ len
- (chars_wasted
[curY
] & 077)
647 == FRAME_WIDTH (selected_frame
)))
654 /* Check quickly for G beyond length of table.
655 That implies it isn't an alias and is simple. */
659 putc (g
& 0xff, stdout
);
663 putc (g
& 0xff, termscript
);
667 /* G has an entry in Vglyph_table,
668 so process any alias and then test for simpleness. */
669 while (GLYPH_ALIAS_P (tbase
, tlen
, g
))
670 g
= GLYPH_ALIAS (tbase
, g
);
671 if (GLYPH_SIMPLE_P (tbase
, tlen
, g
))
675 /* Here if G (or its definition as an alias) is not simple. */
676 fwrite (GLYPH_STRING (tbase
, g
), 1, GLYPH_LENGTH (tbase
, g
),
681 fwrite (GLYPH_STRING (tbase
, g
), 1, GLYPH_LENGTH (tbase
, g
),
688 /* If start is zero, insert blanks instead of a string at start */
690 insert_glyphs (start
, len
)
691 register GLYPH
*start
;
696 register int tlen
= GLYPH_TABLE_LENGTH
;
697 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
699 if (insert_glyphs_hook
&& ! FRAME_IS_TERMCAP (updating_frame
))
701 (*insert_glyphs_hook
) (start
, len
);
704 highlight_if_desired ();
706 if (TS_ins_multi_chars
)
708 buf
= tparam (TS_ins_multi_chars
, 0, 0, len
);
712 write_glyphs (start
, len
);
720 OUTPUT1_IF (TS_ins_char
);
726 if (GLYPH_SIMPLE_P (tbase
, tlen
, g
))
728 putc (g
& 0xff, stdout
);
732 putc (g
& 0xff, termscript
);
736 fwrite (GLYPH_STRING (tbase
, g
), 1, GLYPH_LENGTH (tbase
, g
), stdout
);
740 fwrite (GLYPH_STRING (tbase
, g
), 1, GLYPH_LENGTH (tbase
, g
),
744 OUTPUT1_IF (TS_pad_inserted_char
);
754 if (delete_glyphs_hook
&& ! FRAME_IS_TERMCAP (updating_frame
))
756 (*delete_glyphs_hook
) (n
);
760 if (delete_in_insert_mode
)
767 OUTPUT_IF (TS_delete_mode
);
770 if (TS_del_multi_chars
)
772 buf
= tparam (TS_del_multi_chars
, 0, 0, n
);
777 for (i
= 0; i
< n
; i
++)
778 OUTPUT1 (TS_del_char
);
779 if (!delete_in_insert_mode
)
780 OUTPUT_IF (TS_end_delete_mode
);
783 /* Insert N lines at vpos VPOS. If N is negative, delete -N lines. */
785 ins_del_lines (vpos
, n
)
788 char *multi
= n
> 0 ? TS_ins_multi_lines
: TS_del_multi_lines
;
789 char *single
= n
> 0 ? TS_ins_line
: TS_del_line
;
790 char *scroll
= n
> 0 ? TS_rev_scroll
: TS_fwd_scroll
;
792 register int i
= n
> 0 ? n
: -n
;
795 if (ins_del_lines_hook
&& ! FRAME_IS_TERMCAP (updating_frame
))
797 (*ins_del_lines_hook
) (vpos
, n
);
801 /* If the lines below the insertion are being pushed
802 into the end of the window, this is the same as clearing;
803 and we know the lines are already clear, since the matching
804 deletion has already been done. So can ignore this. */
805 /* If the lines below the deletion are blank lines coming
806 out of the end of the window, don't bother,
807 as there will be a matching inslines later that will flush them. */
808 if (scroll_region_ok
&& vpos
+ i
>= specified_window
)
810 if (!memory_below_frame
&& vpos
+ i
>= FRAME_HEIGHT (selected_frame
))
815 raw_cursor_to (vpos
, 0);
816 background_highlight ();
817 buf
= tparam (multi
, 0, 0, i
);
823 raw_cursor_to (vpos
, 0);
824 background_highlight ();
832 set_scroll_region (vpos
, specified_window
);
834 raw_cursor_to (specified_window
- 1, 0);
836 raw_cursor_to (vpos
, 0);
837 background_highlight ();
839 OUTPUTL (scroll
, specified_window
- vpos
);
840 set_scroll_region (0, specified_window
);
843 if (TN_standout_width
>= 0)
848 : FRAME_HEIGHT (selected_frame
));
852 bcopy (&chars_wasted
[vpos
- n
], &chars_wasted
[vpos
],
853 lower_limit
- vpos
+ n
);
854 bzero (&chars_wasted
[lower_limit
+ n
], - n
);
858 bcopy (&chars_wasted
[vpos
], ©buf
[vpos
], lower_limit
- vpos
- n
);
859 bcopy (©buf
[vpos
], &chars_wasted
[vpos
+ n
],
860 lower_limit
- vpos
- n
);
861 bzero (&chars_wasted
[vpos
], n
);
864 if (!scroll_region_ok
&& memory_below_frame
&& n
< 0)
866 cursor_to (FRAME_HEIGHT (selected_frame
) + n
, 0);
871 /* Compute cost of sending "str", in characters,
872 not counting any line-dependent padding. */
880 tputs (str
, 0, evalcost
);
884 /* Compute cost of sending "str", in characters,
885 counting any line-dependent padding at one line. */
888 string_cost_one_line (str
)
893 tputs (str
, 1, evalcost
);
897 /* Compute per line amount of line-dependent padding,
898 in tenths of characters. */
906 tputs (str
, 0, evalcost
);
909 tputs (str
, 10, evalcost
);
914 /* char_ins_del_cost[n] is cost of inserting N characters.
915 char_ins_del_cost[-n] is cost of deleting N characters. */
917 int *char_ins_del_vector
;
919 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WIDTH ((f))])
924 calculate_ins_del_char_costs (frame
)
927 int ins_startup_cost
, del_startup_cost
;
928 int ins_cost_per_char
, del_cost_per_char
;
932 if (TS_ins_multi_chars
)
934 ins_cost_per_char
= 0;
935 ins_startup_cost
= string_cost_one_line (TS_ins_multi_chars
);
937 else if (TS_ins_char
|| TS_pad_inserted_char
938 || (TS_insert_mode
&& TS_end_insert_mode
))
940 ins_startup_cost
= (30 * (string_cost (TS_insert_mode
)
941 + string_cost (TS_end_insert_mode
))) / 100;
942 ins_cost_per_char
= (string_cost_one_line (TS_ins_char
)
943 + string_cost_one_line (TS_pad_inserted_char
));
947 ins_startup_cost
= 9999;
948 ins_cost_per_char
= 0;
951 if (TS_del_multi_chars
)
953 del_cost_per_char
= 0;
954 del_startup_cost
= string_cost_one_line (TS_del_multi_chars
);
956 else if (TS_del_char
)
958 del_startup_cost
= (string_cost (TS_delete_mode
)
959 + string_cost (TS_end_delete_mode
));
960 if (delete_in_insert_mode
)
961 del_startup_cost
/= 2;
962 del_cost_per_char
= string_cost_one_line (TS_del_char
);
966 del_startup_cost
= 9999;
967 del_cost_per_char
= 0;
970 /* Delete costs are at negative offsets */
971 p
= &char_ins_del_cost (frame
)[0];
972 for (i
= FRAME_WIDTH (selected_frame
); --i
>= 0;)
973 *--p
= (del_startup_cost
+= del_cost_per_char
);
975 /* Doing nothing is free */
976 p
= &char_ins_del_cost (frame
)[0];
979 /* Insert costs are at positive offsets */
980 for (i
= FRAME_WIDTH (frame
); --i
>= 0;)
981 *p
++ = (ins_startup_cost
+= ins_cost_per_char
);
984 #ifdef HAVE_X_WINDOWS
985 extern int x_screen_planes
;
988 calculate_costs (frame
)
991 register char *f
= TS_set_scroll_region
?
993 : TS_set_scroll_region_1
;
995 if (dont_calculate_costs
)
998 #ifdef HAVE_X_WINDOWS
999 if (FRAME_IS_X (frame
))
1001 do_line_insertion_deletion_costs (frame
, 0, ".5*", 0, ".5*",
1002 0, 0, x_screen_planes
);
1007 /* These variables are only used for terminal stuff. They are allocated
1008 once for the terminal frame of X-windows emacs, but not used afterwards.
1010 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1011 X turns off char_ins_del_ok.
1013 chars_wasted and copybuf are only used here in term.c in cases where
1014 the term hook isn't called. */
1016 if (chars_wasted
!= 0)
1017 chars_wasted
= (char *) xrealloc (chars_wasted
, FRAME_HEIGHT (frame
));
1019 chars_wasted
= (char *) xmalloc (FRAME_HEIGHT (frame
));
1022 copybuf
= (char *) xrealloc (copybuf
, FRAME_HEIGHT (frame
));
1024 copybuf
= (char *) xmalloc (FRAME_HEIGHT (frame
));
1026 if (char_ins_del_vector
!= 0)
1028 = (int *) xrealloc (char_ins_del_vector
,
1030 + 2 * FRAME_WIDTH (frame
) * sizeof (int)));
1033 = (int *) xmalloc (sizeof (int)
1034 + 2 * FRAME_WIDTH (frame
) * sizeof (int));
1036 bzero (chars_wasted
, FRAME_HEIGHT (frame
));
1037 bzero (copybuf
, FRAME_HEIGHT (frame
));
1038 bzero (char_ins_del_vector
, (sizeof (int)
1039 + 2 * FRAME_WIDTH (frame
) * sizeof (int)));
1041 if (f
&& (!TS_ins_line
&& !TS_del_line
))
1042 do_line_insertion_deletion_costs (frame
,
1043 TS_rev_scroll
, TS_ins_multi_lines
,
1044 TS_fwd_scroll
, TS_del_multi_lines
,
1047 do_line_insertion_deletion_costs (frame
,
1048 TS_ins_line
, TS_ins_multi_lines
,
1049 TS_del_line
, TS_del_multi_lines
,
1052 calculate_ins_del_char_costs (frame
);
1054 /* Don't use TS_repeat if its padding is worse than sending the chars */
1055 if (TS_repeat
&& per_line_cost (TS_repeat
) * baud_rate
< 9000)
1056 RPov
= string_cost (TS_repeat
);
1058 RPov
= FRAME_WIDTH (frame
) * 2;
1060 cmcostinit (); /* set up cursor motion costs */
1063 /* Find the escape codes sent by the function keys for Vfunction_key_map.
1064 This function scans the termcap function key sequence entries, and
1065 adds entries to Vfunction_key_map for each function key it finds. */
1068 term_get_fkeys (address
)
1071 extern char *tgetstr ();
1075 static struct fkey_table keys
[] = {
1097 "kM", "exit-insert",
1104 "kF", "scroll-forward",
1105 "kR", "scroll-reverse"
1109 for (i
= 0; i
< (sizeof (keys
)/sizeof (keys
[0])); i
++)
1111 char *sequence
= tgetstr (keys
[i
].cap
, address
);
1113 Fdefine_key (Vfunction_key_map
,
1114 build_string (sequence
),
1115 Fmake_vector (make_number (1), intern (keys
[i
].name
)));
1120 term_init (terminal_type
)
1121 char *terminal_type
;
1124 char **address
= &area
;
1129 extern char *tgetstr ();
1132 dont_calculate_costs
= 0;
1134 status
= tgetent (buffer
, terminal_type
);
1136 fatal ("Cannot open termcap database file.\n");
1138 fatal ("Terminal type %s is not defined.\n", terminal_type
);
1141 area
= (char *) malloc (2044);
1143 area
= (char *) malloc (strlen (buffer
));
1144 #endif /* not TERMINFO */
1148 TS_ins_line
= tgetstr ("al", address
);
1149 TS_ins_multi_lines
= tgetstr ("AL", address
);
1150 TS_bell
= tgetstr ("bl", address
);
1151 BackTab
= tgetstr ("bt", address
);
1152 TS_clr_to_bottom
= tgetstr ("cd", address
);
1153 TS_clr_line
= tgetstr ("ce", address
);
1154 TS_clr_frame
= tgetstr ("cl", address
);
1155 ColPosition
= tgetstr ("ch", address
);
1156 AbsPosition
= tgetstr ("cm", address
);
1157 CR
= tgetstr ("cr", address
);
1158 TS_set_scroll_region
= tgetstr ("cs", address
);
1159 TS_set_scroll_region_1
= tgetstr ("cS", address
);
1160 RowPosition
= tgetstr ("cv", address
);
1161 TS_del_char
= tgetstr ("dc", address
);
1162 TS_del_multi_chars
= tgetstr ("DC", address
);
1163 TS_del_line
= tgetstr ("dl", address
);
1164 TS_del_multi_lines
= tgetstr ("DL", address
);
1165 TS_delete_mode
= tgetstr ("dm", address
);
1166 TS_end_delete_mode
= tgetstr ("ed", address
);
1167 TS_end_insert_mode
= tgetstr ("ei", address
);
1168 Home
= tgetstr ("ho", address
);
1169 TS_ins_char
= tgetstr ("ic", address
);
1170 TS_ins_multi_chars
= tgetstr ("IC", address
);
1171 TS_insert_mode
= tgetstr ("im", address
);
1172 TS_pad_inserted_char
= tgetstr ("ip", address
);
1173 TS_end_keypad_mode
= tgetstr ("ke", address
);
1174 TS_keypad_mode
= tgetstr ("ks", address
);
1175 LastLine
= tgetstr ("ll", address
);
1176 Right
= tgetstr ("nd", address
);
1177 Down
= tgetstr ("do", address
);
1179 Down
= tgetstr ("nl", address
); /* Obsolete name for "do" */
1181 /* VMS puts a carriage return before each linefeed,
1182 so it is not safe to use linefeeds. */
1183 if (Down
&& Down
[0] == '\n' && Down
[1] == '\0')
1186 if (tgetflag ("bs"))
1187 Left
= "\b"; /* can't possibly be longer! */
1188 else /* (Actually, "bs" is obsolete...) */
1189 Left
= tgetstr ("le", address
);
1191 Left
= tgetstr ("bc", address
); /* Obsolete name for "le" */
1192 TS_pad_char
= tgetstr ("pc", address
);
1193 TS_repeat
= tgetstr ("rp", address
);
1194 TS_end_standout_mode
= tgetstr ("se", address
);
1195 TS_fwd_scroll
= tgetstr ("sf", address
);
1196 TS_standout_mode
= tgetstr ("so", address
);
1197 TS_rev_scroll
= tgetstr ("sr", address
);
1198 Wcm
.cm_tab
= tgetstr ("ta", address
);
1199 TS_end_termcap_modes
= tgetstr ("te", address
);
1200 TS_termcap_modes
= tgetstr ("ti", address
);
1201 Up
= tgetstr ("up", address
);
1202 TS_visible_bell
= tgetstr ("vb", address
);
1203 TS_end_visual_mode
= tgetstr ("ve", address
);
1204 TS_visual_mode
= tgetstr ("vs", address
);
1205 TS_set_window
= tgetstr ("wi", address
);
1206 MultiUp
= tgetstr ("UP", address
);
1207 MultiDown
= tgetstr ("DO", address
);
1208 MultiLeft
= tgetstr ("LE", address
);
1209 MultiRight
= tgetstr ("RI", address
);
1211 AutoWrap
= tgetflag ("am");
1212 memory_below_frame
= tgetflag ("db");
1213 TF_hazeltine
= tgetflag ("hz");
1214 must_write_spaces
= tgetflag ("in");
1215 meta_key
= tgetflag ("km") || tgetflag ("MT");
1216 TF_insmode_motion
= tgetflag ("mi");
1217 TF_standout_motion
= tgetflag ("ms");
1218 TF_underscore
= tgetflag ("ul");
1219 MagicWrap
= tgetflag ("xn");
1220 TF_xs
= tgetflag ("xs");
1221 TF_teleray
= tgetflag ("xt");
1223 term_get_fkeys (address
);
1225 /* Get frame size from system, or else from termcap. */
1226 get_frame_size (&FRAME_WIDTH (selected_frame
),
1227 &FRAME_HEIGHT (selected_frame
));
1228 if (FRAME_WIDTH (selected_frame
) <= 0)
1229 FRAME_WIDTH (selected_frame
) = tgetnum ("co");
1230 if (FRAME_HEIGHT (selected_frame
) <= 0)
1231 FRAME_HEIGHT (selected_frame
) = tgetnum ("li");
1233 min_padding_speed
= tgetnum ("pb");
1234 TN_standout_width
= tgetnum ("sg");
1235 TabWidth
= tgetnum ("tw");
1238 /* These capabilities commonly use ^J.
1239 I don't know why, but sending them on VMS does not work;
1240 it causes following spaces to be lost, sometimes.
1241 For now, the simplest fix is to avoid using these capabilities ever. */
1242 if (Down
&& Down
[0] == '\n')
1250 TS_fwd_scroll
= Down
;
1252 PC
= TS_pad_char
? *TS_pad_char
: 0;
1257 /* Turned off since /etc/termcap seems to have :ta= for most terminals
1258 and newer termcap doc does not seem to say there is a default.
1263 if (TS_standout_mode
== 0)
1265 TN_standout_width
= tgetnum ("ug");
1266 TS_end_standout_mode
= tgetstr ("ue", address
);
1267 TS_standout_mode
= tgetstr ("us", address
);
1273 /* Teleray: most programs want a space in front of TS_standout_mode,
1274 but Emacs can do without it (and give one extra column). */
1275 TS_standout_mode
= "\033RD";
1276 TN_standout_width
= 1;
1277 /* But that means we cannot rely on ^M to go to column zero! */
1279 /* LF can't be trusted either -- can alter hpos */
1280 /* if move at column 0 thru a line with TS_standout_mode */
1284 /* Special handling for certain terminal types known to need it */
1286 if (!strcmp (terminal_type
, "supdup"))
1288 memory_below_frame
= 1;
1289 Wcm
.cm_losewrap
= 1;
1291 if (!strncmp (terminal_type
, "c10", 3)
1292 || !strcmp (terminal_type
, "perq"))
1294 /* Supply a makeshift :wi string.
1295 This string is not valid in general since it works only
1296 for windows starting at the upper left corner;
1297 but that is all Emacs uses.
1299 This string works only if the frame is using
1300 the top of the video memory, because addressing is memory-relative.
1301 So first check the :ti string to see if that is true.
1303 It would be simpler if the :wi string could go in the termcap
1304 entry, but it can't because it is not fully valid.
1305 If it were in the termcap entry, it would confuse other programs. */
1308 p
= TS_termcap_modes
;
1309 while (*p
&& strcmp (p
, "\033v "))
1312 TS_set_window
= "\033v%C %C %C %C ";
1314 /* Termcap entry often fails to have :in: flag */
1315 must_write_spaces
= 1;
1316 /* :ti string typically fails to have \E^G! in it */
1317 /* This limits scope of insert-char to one line. */
1318 strcpy (area
, TS_termcap_modes
);
1319 strcat (area
, "\033\007!");
1320 TS_termcap_modes
= area
;
1321 area
+= strlen (area
) + 1;
1323 /* Change all %+ parameters to %C, to handle
1324 values above 96 correctly for the C100. */
1327 if (p
[0] == '%' && p
[1] == '+')
1333 FrameRows
= FRAME_HEIGHT (selected_frame
);
1334 FrameCols
= FRAME_WIDTH (selected_frame
);
1335 specified_window
= FRAME_HEIGHT (selected_frame
);
1337 if (Wcm_init () == -1) /* can't do cursor motion */
1339 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
1340 It lacks the ability to position the cursor.\n\
1341 If that is not the actual type of terminal you have, use either the\n\
1342 DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
1343 or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.\n",
1346 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
1347 It lacks the ability to position the cursor.\n\
1348 If that is not the actual type of terminal you have,\n\
1349 use the C-shell command `setenv TERM ...' to specify the correct type.\n\
1350 It may be necessary to do `unsetenv TERMCAP' as well.\n",
1353 if (FRAME_HEIGHT (selected_frame
) <= 0
1354 || FRAME_WIDTH (selected_frame
) <= 0)
1355 fatal ("The frame size has not been specified.");
1357 delete_in_insert_mode
1358 = TS_delete_mode
&& TS_insert_mode
1359 && !strcmp (TS_delete_mode
, TS_insert_mode
);
1361 se_is_so
= (TS_standout_mode
1362 && TS_end_standout_mode
1363 && !strcmp (TS_standout_mode
, TS_end_standout_mode
));
1365 /* Remove width of standout marker from usable width of line */
1366 if (TN_standout_width
> 0)
1367 FRAME_WIDTH (selected_frame
) -= TN_standout_width
;
1369 UseTabs
= tabs_safe_p () && TabWidth
== 8;
1373 && (TS_set_window
|| TS_set_scroll_region
|| TS_set_scroll_region_1
));
1375 line_ins_del_ok
= (((TS_ins_line
|| TS_ins_multi_lines
)
1376 && (TS_del_line
|| TS_del_multi_lines
))
1377 || (scroll_region_ok
&& TS_fwd_scroll
&& TS_rev_scroll
));
1379 char_ins_del_ok
= ((TS_ins_char
|| TS_insert_mode
1380 || TS_pad_inserted_char
|| TS_ins_multi_chars
)
1381 && (TS_del_char
|| TS_del_multi_chars
));
1383 fast_clear_end_of_line
= TS_clr_line
!= 0;
1386 if (read_socket_hook
) /* Baudrate is somewhat */
1387 /* meaningless in this case */
1392 fatal (str
, arg1
, arg2
)
1393 char *str
, *arg1
, *arg2
;
1395 fprintf (stderr
, "emacs: ");
1396 fprintf (stderr
, str
, arg1
, arg2
);