1 /* terminal control module for terminals described by TERMCAP
2 Copyright (C) 1985, 1986, 1987 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 1, 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"
33 #define max(a, b) ((a) > (b) ? (a) : (b))
34 #define min(a, b) ((a) < (b) ? (a) : (b))
36 #define OUTPUT(a) tputs (a, SCREEN_HEIGHT (selected_screen) - curY, cmputc)
37 #define OUTPUT1(a) tputs (a, 1, cmputc)
38 #define OUTPUTL(a, lines) tputs (a, lines, cmputc)
39 #define OUTPUT_IF(a) { if (a) tputs (a, SCREEN_HEIGHT (selected_screen) - curY, cmputc); }
40 #define OUTPUT1_IF(a) { if (a) tputs (a, 1, cmputc); }
42 /* Terminal charateristics that higher levels want to look at.
43 These are all extern'd in termchar.h */
46 int screen_width
; /* Number of usable columns */
47 int screen_height
; /* Number of lines */
50 int must_write_spaces
; /* Nonzero means spaces in the text
51 must actually be output; can't just skip
52 over some columns to leave them blank. */
53 int min_padding_speed
; /* Speed below which no padding necessary */
55 int line_ins_del_ok
; /* Terminal can insert and delete lines */
56 int char_ins_del_ok
; /* Terminal can insert and delete chars */
57 int scroll_region_ok
; /* Terminal supports setting the
59 int memory_below_screen
; /* Terminal remembers lines
60 scrolled off bottom */
61 int fast_clear_end_of_line
; /* Terminal has a `ce' string */
63 int dont_calculate_costs
; /* Nonzero means don't bother computing */
64 /* various cost tables; we won't use them. */
66 /* Nonzero means no need to redraw the entire screen on resuming
67 a suspended Emacs. This is useful on terminals with multiple pages,
68 where one page is used for Emacs and another for all else. */
69 int no_redraw_on_reenter
;
71 /* Hook functions that you can set to snap out the functions in this file.
72 These are all extern'd in termhooks.h */
74 int (*cursor_to_hook
) ();
75 int (*raw_cursor_to_hook
) ();
77 int (*clear_to_end_hook
) ();
78 int (*clear_screen_hook
) ();
79 int (*clear_end_of_line_hook
) ();
81 int (*ins_del_lines_hook
) ();
83 int (*change_line_highlight_hook
) ();
84 int (*reassert_line_highlight_hook
) ();
86 int (*insert_glyphs_hook
) ();
87 int (*write_glyphs_hook
) ();
88 int (*delete_glyphs_hook
) ();
90 int (*ring_bell_hook
) ();
92 int (*reset_terminal_modes_hook
) ();
93 int (*set_terminal_modes_hook
) ();
94 int (*update_begin_hook
) ();
95 int (*update_end_hook
) ();
96 int (*set_terminal_window_hook
) ();
98 int (*read_socket_hook
) ();
100 /* Return the current position of the mouse. This should clear
101 mouse_moved until the next motion event arrives. */
102 void (*mouse_position_hook
) ( /* SCREEN_PTR *s,
105 Lisp_Object *time */ );
107 /* When reading from a minibuffer in a different screen, Emacs wants
108 to shift the highlight from the selected screen to the minibuffer's
109 screen; under X, this means it lies about where the focus is.
110 This hook tells the window system code to re-decide where to put
112 void (*screen_rehighlight_hook
) ( /* SCREEN_PTR s */ );
114 /* Strings, numbers and flags taken from the termcap entry. */
116 char *TS_ins_line
; /* termcap "al" */
117 char *TS_ins_multi_lines
; /* "AL" (one parameter, # lines to insert) */
118 char *TS_bell
; /* "bl" */
119 char *TS_clr_to_bottom
; /* "cd" */
120 char *TS_clr_line
; /* "ce", clear to end of line */
121 char *TS_clr_screen
; /* "cl" */
122 char *TS_set_scroll_region
; /* "cs" (2 params, first line and last line) */
123 char *TS_set_scroll_region_1
; /* "cS" (4 params: total lines,
124 lines above scroll region, lines below it,
125 total lines again) */
126 char *TS_del_char
; /* "dc" */
127 char *TS_del_multi_chars
; /* "DC" (one parameter, # chars to delete) */
128 char *TS_del_line
; /* "dl" */
129 char *TS_del_multi_lines
; /* "DL" (one parameter, # lines to delete) */
130 char *TS_delete_mode
; /* "dm", enter character-delete mode */
131 char *TS_end_delete_mode
; /* "ed", leave character-delete mode */
132 char *TS_end_insert_mode
; /* "ei", leave character-insert mode */
133 char *TS_ins_char
; /* "ic" */
134 char *TS_ins_multi_chars
; /* "IC" (one parameter, # chars to insert) */
135 char *TS_insert_mode
; /* "im", enter character-insert mode */
136 char *TS_pad_inserted_char
; /* "ip". Just padding, no commands. */
137 char *TS_end_keypad_mode
; /* "ke" */
138 char *TS_keypad_mode
; /* "ks" */
139 char *TS_pad_char
; /* "pc", char to use as padding */
140 char *TS_repeat
; /* "rp" (2 params, # times to repeat
141 and character to be repeated) */
142 char *TS_end_standout_mode
; /* "se" */
143 char *TS_fwd_scroll
; /* "sf" */
144 char *TS_standout_mode
; /* "so" */
145 char *TS_rev_scroll
; /* "sr" */
146 char *TS_end_termcap_modes
; /* "te" */
147 char *TS_termcap_modes
; /* "ti" */
148 char *TS_visible_bell
; /* "vb" */
149 char *TS_end_visual_mode
; /* "ve" */
150 char *TS_visual_mode
; /* "vi" */
151 char *TS_set_window
; /* "wi" (4 params, start and end of window,
152 each as vpos and hpos) */
154 int TF_hazeltine
; /* termcap hz flag. */
155 int TF_insmode_motion
; /* termcap mi flag: can move while in insert mode. */
156 int TF_standout_motion
; /* termcap mi flag: can move while in standout mode. */
157 int TF_underscore
; /* termcap ul flag: _ underlines if overstruck on
158 nonblank position. Must clear before writing _. */
159 int TF_teleray
; /* termcap xt flag: many weird consequences.
162 int TF_xs
; /* Nonzero for "xs". If set together with
163 TN_standout_width == 0, it means don't bother
164 to write any end-standout cookies. */
166 int TN_standout_width
; /* termcap sg number: width occupied by standout
169 static int RPov
; /* # chars to start a TS_repeat */
171 static int delete_in_insert_mode
; /* delete mode == insert mode */
173 static int se_is_so
; /* 1 if same string both enters and leaves
178 /* Number of chars of space used for standout marker at beginning of line,
179 or'd with 0100. Zero if no standout marker at all.
181 Used IFF TN_standout_width >= 0. */
183 static char *chars_wasted
;
184 static char *copybuf
;
186 /* nonzero means supposed to write text in standout mode. */
187 int standout_requested
;
189 int insert_mode
; /* Nonzero when in insert mode. */
190 int standout_mode
; /* Nonzero when in standout mode. */
192 /* Size of window specified by higher levels.
193 This is the number of lines, from the top of screen downwards,
194 which can participate in insert-line/delete-line operations.
196 Effectively it excludes the bottom screen_height - specified_window_size
197 lines from those operations. */
199 int specified_window
;
201 /* Screen currently being redisplayed; 0 if not currently redisplaying.
202 (Direct output does not count). */
204 SCREEN_PTR updating_screen
;
210 if (! SCREEN_IS_TERMCAP (selected_screen
))
212 (*ring_bell_hook
) ();
215 OUTPUT (TS_visible_bell
&& visible_bell
? TS_visible_bell
: TS_bell
);
218 set_terminal_modes ()
220 if (! SCREEN_IS_TERMCAP (selected_screen
))
222 (*set_terminal_modes_hook
) ();
225 OUTPUT_IF (TS_termcap_modes
);
226 OUTPUT_IF (TS_visual_mode
);
227 OUTPUT_IF (TS_keypad_mode
);
231 reset_terminal_modes ()
233 if (! SCREEN_IS_TERMCAP (selected_screen
))
235 (*reset_terminal_modes_hook
) ();
238 if (TN_standout_width
< 0)
239 turn_off_highlight ();
241 OUTPUT_IF (TS_end_keypad_mode
);
242 OUTPUT_IF (TS_end_visual_mode
);
243 OUTPUT_IF (TS_end_termcap_modes
);
244 /* Output raw CR so kernel can track the cursor hpos. */
245 /* But on magic-cookie terminals this can erase an end-standout marker and
246 cause the rest of the screen to be in standout, so move down first. */
247 if (TN_standout_width
>= 0)
256 if (! SCREEN_IS_TERMCAP (updating_screen
))
257 (*update_begin_hook
) (s
);
263 if (! SCREEN_IS_TERMCAP (updating_screen
))
265 (*update_end_hook
) (s
);
270 background_highlight ();
271 standout_requested
= 0;
275 set_terminal_window (size
)
278 if (! SCREEN_IS_TERMCAP (updating_screen
))
280 (*set_terminal_window_hook
) (size
);
283 specified_window
= size
? size
: SCREEN_HEIGHT (selected_screen
);
284 if (!scroll_region_ok
)
286 set_scroll_region (0, specified_window
);
289 set_scroll_region (start
, stop
)
293 if (TS_set_scroll_region
)
295 buf
= tparam (TS_set_scroll_region
, 0, 0, start
, stop
- 1);
297 else if (TS_set_scroll_region_1
)
299 buf
= tparam (TS_set_scroll_region_1
, 0, 0,
300 SCREEN_HEIGHT (selected_screen
), start
,
301 SCREEN_HEIGHT (selected_screen
) - stop
,
302 SCREEN_HEIGHT (selected_screen
));
306 buf
= tparam (TS_set_window
, 0, 0, start
, 0, stop
, SCREEN_WIDTH (selected_screen
));
316 OUTPUT (TS_insert_mode
);
323 OUTPUT (TS_end_insert_mode
);
327 /* Handle highlighting when TN_standout_width (termcap sg) is not specified.
328 In these terminals, output is affected by the value of standout
329 mode when the output is written.
331 These functions are called on all terminals, but do nothing
332 on terminals whose standout mode does not work that way. */
334 turn_off_highlight ()
336 if (TN_standout_width
< 0)
339 OUTPUT_IF (TS_end_standout_mode
);
346 if (TN_standout_width
< 0)
349 OUTPUT_IF (TS_standout_mode
);
354 /* Set standout mode to the state it should be in for
355 empty space inside windows. What this is,
356 depends on the user option inverse-video. */
358 background_highlight ()
360 if (TN_standout_width
>= 0)
363 turn_on_highlight ();
365 turn_off_highlight ();
368 /* Set standout mode to the mode specified for the text to be output. */
371 highlight_if_desired ()
373 if (TN_standout_width
>= 0)
375 if (!inverse_video
== !standout_requested
)
376 turn_off_highlight ();
378 turn_on_highlight ();
381 /* Handle standout mode for terminals in which TN_standout_width >= 0.
382 On these terminals, standout is controlled by markers that
383 live inside the screen memory. TN_standout_width is the width
384 that the marker occupies in memory. Standout runs from the marker
385 to the end of the line on some terminals, or to the next
386 turn-off-standout marker (TS_end_standout_mode) string
387 on other terminals. */
389 /* Write a standout marker or end-standout marker at the front of the line
390 at vertical position vpos. */
392 write_standout_marker (flag
, vpos
)
395 if (flag
|| (TS_end_standout_mode
&& !TF_teleray
&& !se_is_so
396 && !(TF_xs
&& TN_standout_width
== 0)))
399 cmplus (TN_standout_width
);
400 OUTPUT (flag
? TS_standout_mode
: TS_end_standout_mode
);
401 chars_wasted
[curY
] = TN_standout_width
| 0100;
405 /* External interface to control of standout mode.
406 Call this when about to modify line at position VPOS
407 and not change whether it is highlighted. */
409 reassert_line_highlight (highlight
, vpos
)
413 if (! SCREEN_IS_TERMCAP ((updating_screen
? updating_screen
: selected_screen
)))
415 (*reassert_line_highlight_hook
) (highlight
, vpos
);
418 if (TN_standout_width
< 0)
419 /* Handle terminals where standout takes affect at output time */
420 standout_requested
= highlight
;
421 else if (chars_wasted
[vpos
] == 0)
422 /* For terminals with standout markers, write one on this line
423 if there isn't one already. */
424 write_standout_marker (highlight
, vpos
);
427 /* Call this when about to modify line at position VPOS
428 and change whether it is highlighted. */
430 change_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
431 int new_highlight
, vpos
, first_unused_hpos
;
433 standout_requested
= new_highlight
;
434 if (! SCREEN_IS_TERMCAP (updating_screen
))
436 (*change_line_highlight_hook
) (new_highlight
, vpos
, first_unused_hpos
);
442 if (TN_standout_width
< 0)
443 background_highlight ();
444 /* If line starts with a marker, delete the marker */
445 else if (TS_clr_line
&& chars_wasted
[curY
])
448 /* On Teleray, make sure to erase the SO marker. */
451 cmgoto (curY
- 1, SCREEN_WIDTH (selected_screen
) - 4);
453 curY
++; /* ESC S moves to next line where the TS_standout_mode was */
457 cmgoto (curY
, 0); /* reposition to kill standout marker */
459 clear_end_of_line_raw (first_unused_hpos
);
460 reassert_line_highlight (new_highlight
, curY
);
464 /* Move to absolute position, specified origin 0 */
468 if (! SCREEN_IS_TERMCAP ((updating_screen
473 (*cursor_to_hook
) (row
, col
);
477 col
+= chars_wasted
[row
] & 077;
478 if (curY
== row
&& curX
== col
)
480 if (!TF_standout_motion
)
481 background_highlight ();
482 if (!TF_insmode_motion
)
487 /* Similar but don't take any account of the wasted characters. */
489 raw_cursor_to (row
, col
)
491 if (! SCREEN_IS_TERMCAP ((updating_screen
? updating_screen
: selected_screen
)))
493 (*raw_cursor_to_hook
) (row
, col
);
496 if (curY
== row
&& curX
== col
)
498 if (!TF_standout_motion
)
499 background_highlight ();
500 if (!TF_insmode_motion
)
505 /* Erase operations */
507 /* clear from cursor to end of screen */
512 if (clear_to_end_hook
&& SCREEN_IS_TERMCAP (updating_screen
))
514 (*clear_to_end_hook
) ();
517 if (TS_clr_to_bottom
)
519 background_highlight ();
520 OUTPUT (TS_clr_to_bottom
);
521 bzero (chars_wasted
+ curY
, SCREEN_HEIGHT (selected_screen
) - curY
);
525 for (i
= curY
; i
< SCREEN_HEIGHT (selected_screen
); i
++)
528 clear_end_of_line_raw (SCREEN_WIDTH (selected_screen
));
533 /* Clear entire screen */
537 if (clear_screen_hook
538 && ! SCREEN_IS_TERMCAP ((updating_screen
? updating_screen
: selected_screen
)))
540 (*clear_screen_hook
) ();
545 background_highlight ();
546 OUTPUT (TS_clr_screen
);
547 bzero (chars_wasted
, SCREEN_HEIGHT (selected_screen
));
557 /* Clear to end of line, but do not clear any standout marker.
558 Assumes that the cursor is positioned at a character of real text,
559 which implies it cannot be before a standout marker
560 unless the marker has zero width.
562 Note that the cursor may be moved. */
564 clear_end_of_line (first_unused_hpos
)
565 int first_unused_hpos
;
567 static GLYPH buf
[1] = {SPACEGLYPH
};
568 if (SCREEN_IS_TERMCAP (selected_screen
)
569 && TN_standout_width
== 0 && curX
== 0 && chars_wasted
[curY
] != 0)
570 write_glyphs (buf
, 1);
571 clear_end_of_line_raw (first_unused_hpos
);
574 /* Clear from cursor to end of line.
575 Assume that the line is already clear starting at column first_unused_hpos.
576 If the cursor is at a standout marker, erase the marker.
578 Note that the cursor may be moved, on terminals lacking a `ce' string. */
580 clear_end_of_line_raw (first_unused_hpos
)
581 int first_unused_hpos
;
585 if (clear_end_of_line_hook
586 && ! SCREEN_IS_TERMCAP ((updating_screen
590 (*clear_end_of_line_hook
) (first_unused_hpos
);
594 first_unused_hpos
+= chars_wasted
[curY
] & 077;
595 if (curX
>= first_unused_hpos
)
597 /* Notice if we are erasing a magic cookie */
599 chars_wasted
[curY
] = 0;
600 background_highlight ();
603 OUTPUT1 (TS_clr_line
);
606 { /* have to do it the hard way */
609 /* Do not write in last row last col with Autowrap on. */
610 if (AutoWrap
&& curY
== SCREEN_HEIGHT (selected_screen
) - 1
611 && first_unused_hpos
== SCREEN_WIDTH (selected_screen
))
614 for (i
= curX
; i
< first_unused_hpos
; i
++)
617 fputc (' ', termscript
);
620 cmplus (first_unused_hpos
- curX
);
625 write_glyphs (string
, len
)
626 register GLYPH
*string
;
630 register int tlen
= GLYPH_TABLE_LENGTH
;
631 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
633 if (write_glyphs_hook
634 && ! SCREEN_IS_TERMCAP ((updating_screen
? updating_screen
: selected_screen
)))
636 (*write_glyphs_hook
) (string
, len
);
640 highlight_if_desired ();
643 /* Don't dare write in last column of bottom line, if AutoWrap,
644 since that would scroll the whole screen on some terminals. */
647 && curY
+ 1 == SCREEN_HEIGHT (selected_screen
)
648 && (curX
+ len
- (chars_wasted
[curY
] & 077)
649 == SCREEN_WIDTH (selected_screen
)))
656 /* Check quickly for G beyond length of table.
657 That implies it isn't an alias and is simple. */
661 putc (g
& 0xff, stdout
);
665 putc (g
& 0xff, termscript
);
669 /* G has an entry in Vglyph_table,
670 so process any alias and then test for simpleness. */
671 while (GLYPH_ALIAS_P (tbase
, tlen
, g
))
672 g
= GLYPH_ALIAS (tbase
, g
);
673 if (GLYPH_SIMPLE_P (tbase
, tlen
, g
))
677 /* Here if G (or its definition as an alias) is not simple. */
678 fwrite (GLYPH_STRING (tbase
, g
), 1, GLYPH_LENGTH (tbase
, g
),
683 fwrite (GLYPH_STRING (tbase
, g
), 1, GLYPH_LENGTH (tbase
, g
),
690 /* If start is zero, insert blanks instead of a string at start */
692 insert_glyphs (start
, len
)
693 register GLYPH
*start
;
698 register int tlen
= GLYPH_TABLE_LENGTH
;
699 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
701 if (insert_glyphs_hook
&& ! SCREEN_IS_TERMCAP (updating_screen
))
703 (*insert_glyphs_hook
) (start
, len
);
706 highlight_if_desired ();
708 if (TS_ins_multi_chars
)
710 buf
= tparam (TS_ins_multi_chars
, 0, 0, len
);
714 write_glyphs (start
, len
);
722 OUTPUT1_IF (TS_ins_char
);
728 if (GLYPH_SIMPLE_P (tbase
, tlen
, g
))
730 putc (g
& 0xff, stdout
);
734 putc (g
& 0xff, termscript
);
738 fwrite (GLYPH_STRING (tbase
, g
), 1, GLYPH_LENGTH (tbase
, g
), stdout
);
742 fwrite (GLYPH_STRING (tbase
, g
), 1, GLYPH_LENGTH (tbase
, g
),
746 OUTPUT1_IF (TS_pad_inserted_char
);
756 if (delete_glyphs_hook
&& ! SCREEN_IS_TERMCAP (updating_screen
))
758 (*delete_glyphs_hook
) (n
);
762 if (delete_in_insert_mode
)
769 OUTPUT_IF (TS_delete_mode
);
772 if (TS_del_multi_chars
)
774 buf
= tparam (TS_del_multi_chars
, 0, 0, n
);
779 for (i
= 0; i
< n
; i
++)
780 OUTPUT1 (TS_del_char
);
781 if (!delete_in_insert_mode
)
782 OUTPUT_IF (TS_end_delete_mode
);
785 /* Insert N lines at vpos VPOS. If N is negative, delete -N lines. */
787 ins_del_lines (vpos
, n
)
790 char *multi
= n
> 0 ? TS_ins_multi_lines
: TS_del_multi_lines
;
791 char *single
= n
> 0 ? TS_ins_line
: TS_del_line
;
792 char *scroll
= n
> 0 ? TS_rev_scroll
: TS_fwd_scroll
;
794 register int i
= n
> 0 ? n
: -n
;
797 if (ins_del_lines_hook
&& ! SCREEN_IS_TERMCAP (updating_screen
))
799 (*ins_del_lines_hook
) (vpos
, n
);
803 /* If the lines below the insertion are being pushed
804 into the end of the window, this is the same as clearing;
805 and we know the lines are already clear, since the matching
806 deletion has already been done. So can ignore this. */
807 /* If the lines below the deletion are blank lines coming
808 out of the end of the window, don't bother,
809 as there will be a matching inslines later that will flush them. */
810 if (scroll_region_ok
&& vpos
+ i
>= specified_window
)
812 if (!memory_below_screen
&& vpos
+ i
>= SCREEN_HEIGHT (selected_screen
))
817 raw_cursor_to (vpos
, 0);
818 background_highlight ();
819 buf
= tparam (multi
, 0, 0, i
);
825 raw_cursor_to (vpos
, 0);
826 background_highlight ();
834 set_scroll_region (vpos
, specified_window
);
836 raw_cursor_to (specified_window
- 1, 0);
838 raw_cursor_to (vpos
, 0);
839 background_highlight ();
841 OUTPUTL (scroll
, specified_window
- vpos
);
842 set_scroll_region (0, specified_window
);
845 if (TN_standout_width
>= 0)
850 : SCREEN_HEIGHT (selected_screen
));
854 bcopy (&chars_wasted
[vpos
- n
], &chars_wasted
[vpos
],
855 lower_limit
- vpos
+ n
);
856 bzero (&chars_wasted
[lower_limit
+ n
], - n
);
860 bcopy (&chars_wasted
[vpos
], ©buf
[vpos
], lower_limit
- vpos
- n
);
861 bcopy (©buf
[vpos
], &chars_wasted
[vpos
+ n
],
862 lower_limit
- vpos
- n
);
863 bzero (&chars_wasted
[vpos
], n
);
866 if (!scroll_region_ok
&& memory_below_screen
&& n
< 0)
868 cursor_to (SCREEN_HEIGHT (selected_screen
) + n
, 0);
873 /* Compute cost of sending "str", in characters,
874 not counting any line-dependent padding. */
882 tputs (str
, 0, evalcost
);
886 /* Compute cost of sending "str", in characters,
887 counting any line-dependent padding at one line. */
890 string_cost_one_line (str
)
895 tputs (str
, 1, evalcost
);
899 /* Compute per line amount of line-dependent padding,
900 in tenths of characters. */
908 tputs (str
, 0, evalcost
);
911 tputs (str
, 10, evalcost
);
916 /* char_ins_del_cost[n] is cost of inserting N characters.
917 char_ins_del_cost[-n] is cost of deleting N characters. */
919 int *char_ins_del_vector
;
921 #define char_ins_del_cost(s) (&char_ins_del_vector[SCREEN_WIDTH ((s))])
926 calculate_ins_del_char_costs (screen
)
929 int ins_startup_cost
, del_startup_cost
;
930 int ins_cost_per_char
, del_cost_per_char
;
934 if (TS_ins_multi_chars
)
936 ins_cost_per_char
= 0;
937 ins_startup_cost
= string_cost_one_line (TS_ins_multi_chars
);
939 else if (TS_ins_char
|| TS_pad_inserted_char
940 || (TS_insert_mode
&& TS_end_insert_mode
))
942 ins_startup_cost
= (30 * (string_cost (TS_insert_mode
)
943 + string_cost (TS_end_insert_mode
))) / 100;
944 ins_cost_per_char
= (string_cost_one_line (TS_ins_char
)
945 + string_cost_one_line (TS_pad_inserted_char
));
949 ins_startup_cost
= 9999;
950 ins_cost_per_char
= 0;
953 if (TS_del_multi_chars
)
955 del_cost_per_char
= 0;
956 del_startup_cost
= string_cost_one_line (TS_del_multi_chars
);
958 else if (TS_del_char
)
960 del_startup_cost
= (string_cost (TS_delete_mode
)
961 + string_cost (TS_end_delete_mode
));
962 if (delete_in_insert_mode
)
963 del_startup_cost
/= 2;
964 del_cost_per_char
= string_cost_one_line (TS_del_char
);
968 del_startup_cost
= 9999;
969 del_cost_per_char
= 0;
972 /* Delete costs are at negative offsets */
973 p
= &char_ins_del_cost (screen
)[0];
974 for (i
= SCREEN_WIDTH (selected_screen
); --i
>= 0;)
975 *--p
= (del_startup_cost
+= del_cost_per_char
);
977 /* Doing nothing is free */
978 p
= &char_ins_del_cost (screen
)[0];
981 /* Insert costs are at positive offsets */
982 for (i
= SCREEN_WIDTH (screen
); --i
>= 0;)
983 *p
++ = (ins_startup_cost
+= ins_cost_per_char
);
986 #ifdef HAVE_X_WINDOWS
987 extern int x_screen_planes
;
990 calculate_costs (screen
)
993 register char *s
= TS_set_scroll_region
?
995 : TS_set_scroll_region_1
;
997 if (dont_calculate_costs
)
1000 #ifdef HAVE_X_WINDOWS
1001 if (SCREEN_IS_X (screen
))
1003 do_line_insertion_deletion_costs (screen
, 0, ".5*", 0, ".5*",
1004 0, 0, x_screen_planes
);
1009 /* These variables are only used for terminal stuff. They are allocated
1010 once for the terminal screen of X-windows emacs, but not used afterwards.
1012 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1013 X turns off char_ins_del_ok.
1015 chars_wasted and copybuf are only used here in term.c in cases where
1016 the term hook isn't called. */
1018 if (chars_wasted
!= 0)
1019 chars_wasted
= (char *) xrealloc (chars_wasted
, SCREEN_HEIGHT (screen
));
1021 chars_wasted
= (char *) xmalloc (SCREEN_HEIGHT (screen
));
1024 copybuf
= (char *) xrealloc (copybuf
, SCREEN_HEIGHT (screen
));
1026 copybuf
= (char *) xmalloc (SCREEN_HEIGHT (screen
));
1028 if (char_ins_del_vector
!= 0)
1030 = (int *) xrealloc (char_ins_del_vector
,
1032 + 2 * SCREEN_WIDTH (screen
) * sizeof (int)));
1035 = (int *) xmalloc (sizeof (int)
1036 + 2 * SCREEN_WIDTH (screen
) * sizeof (int));
1038 bzero (chars_wasted
, SCREEN_HEIGHT (screen
));
1039 bzero (copybuf
, SCREEN_HEIGHT (screen
));
1040 bzero (char_ins_del_vector
, (sizeof (int)
1041 + 2 * SCREEN_WIDTH (screen
) * sizeof (int)));
1043 if (s
&& (!TS_ins_line
&& !TS_del_line
))
1044 do_line_insertion_deletion_costs (screen
,
1045 TS_rev_scroll
, TS_ins_multi_lines
,
1046 TS_fwd_scroll
, TS_del_multi_lines
,
1049 do_line_insertion_deletion_costs (screen
,
1050 TS_ins_line
, TS_ins_multi_lines
,
1051 TS_del_line
, TS_del_multi_lines
,
1054 calculate_ins_del_char_costs (screen
);
1056 /* Don't use TS_repeat if its padding is worse than sending the chars */
1057 if (TS_repeat
&& per_line_cost (TS_repeat
) * baud_rate
< 9000)
1058 RPov
= string_cost (TS_repeat
);
1060 RPov
= SCREEN_WIDTH (screen
) * 2;
1062 cmcostinit (); /* set up cursor motion costs */
1065 term_init (terminal_type
)
1066 char *terminal_type
;
1069 char **address
= &area
;
1074 extern char *tgetstr ();
1077 dont_calculate_costs
= 0;
1079 status
= tgetent (buffer
, terminal_type
);
1081 fatal ("Cannot open termcap database file.\n");
1083 fatal ("Terminal type %s is not defined.\n", terminal_type
);
1086 area
= (char *) malloc (2044);
1088 area
= (char *) malloc (strlen (buffer
));
1089 #endif /* not TERMINFO */
1093 TS_ins_line
= tgetstr ("al", address
);
1094 TS_ins_multi_lines
= tgetstr ("AL", address
);
1095 TS_bell
= tgetstr ("bl", address
);
1096 BackTab
= tgetstr ("bt", address
);
1097 TS_clr_to_bottom
= tgetstr ("cd", address
);
1098 TS_clr_line
= tgetstr ("ce", address
);
1099 TS_clr_screen
= tgetstr ("cl", address
);
1100 ColPosition
= tgetstr ("ch", address
);
1101 AbsPosition
= tgetstr ("cm", address
);
1102 CR
= tgetstr ("cr", address
);
1103 TS_set_scroll_region
= tgetstr ("cs", address
);
1104 TS_set_scroll_region_1
= tgetstr ("cS", address
);
1105 RowPosition
= tgetstr ("cv", address
);
1106 TS_del_char
= tgetstr ("dc", address
);
1107 TS_del_multi_chars
= tgetstr ("DC", address
);
1108 TS_del_line
= tgetstr ("dl", address
);
1109 TS_del_multi_lines
= tgetstr ("DL", address
);
1110 TS_delete_mode
= tgetstr ("dm", address
);
1111 TS_end_delete_mode
= tgetstr ("ed", address
);
1112 TS_end_insert_mode
= tgetstr ("ei", address
);
1113 Home
= tgetstr ("ho", address
);
1114 TS_ins_char
= tgetstr ("ic", address
);
1115 TS_ins_multi_chars
= tgetstr ("IC", address
);
1116 TS_insert_mode
= tgetstr ("im", address
);
1117 TS_pad_inserted_char
= tgetstr ("ip", address
);
1118 TS_end_keypad_mode
= tgetstr ("ke", address
);
1119 TS_keypad_mode
= tgetstr ("ks", address
);
1120 LastLine
= tgetstr ("ll", address
);
1121 Right
= tgetstr ("nd", address
);
1122 Down
= tgetstr ("do", address
);
1124 Down
= tgetstr ("nl", address
); /* Obsolete name for "do" */
1126 /* VMS puts a carriage return before each linefeed,
1127 so it is not safe to use linefeeds. */
1128 if (Down
&& Down
[0] == '\n' && Down
[1] == '\0')
1131 if (tgetflag ("bs"))
1132 Left
= "\b"; /* can't possibly be longer! */
1133 else /* (Actually, "bs" is obsolete...) */
1134 Left
= tgetstr ("le", address
);
1136 Left
= tgetstr ("bc", address
); /* Obsolete name for "le" */
1137 TS_pad_char
= tgetstr ("pc", address
);
1138 TS_repeat
= tgetstr ("rp", address
);
1139 TS_end_standout_mode
= tgetstr ("se", address
);
1140 TS_fwd_scroll
= tgetstr ("sf", address
);
1141 TS_standout_mode
= tgetstr ("so", address
);
1142 TS_rev_scroll
= tgetstr ("sr", address
);
1143 Wcm
.cm_tab
= tgetstr ("ta", address
);
1144 TS_end_termcap_modes
= tgetstr ("te", address
);
1145 TS_termcap_modes
= tgetstr ("ti", address
);
1146 Up
= tgetstr ("up", address
);
1147 TS_visible_bell
= tgetstr ("vb", address
);
1148 TS_end_visual_mode
= tgetstr ("ve", address
);
1149 TS_visual_mode
= tgetstr ("vs", address
);
1150 TS_set_window
= tgetstr ("wi", address
);
1151 MultiUp
= tgetstr ("UP", address
);
1152 MultiDown
= tgetstr ("DO", address
);
1153 MultiLeft
= tgetstr ("LE", address
);
1154 MultiRight
= tgetstr ("RI", address
);
1156 AutoWrap
= tgetflag ("am");
1157 memory_below_screen
= tgetflag ("db");
1158 TF_hazeltine
= tgetflag ("hz");
1159 must_write_spaces
= tgetflag ("in");
1160 meta_key
= tgetflag ("km") || tgetflag ("MT");
1161 TF_insmode_motion
= tgetflag ("mi");
1162 TF_standout_motion
= tgetflag ("ms");
1163 TF_underscore
= tgetflag ("ul");
1164 MagicWrap
= tgetflag ("xn");
1165 TF_xs
= tgetflag ("xs");
1166 TF_teleray
= tgetflag ("xt");
1168 /* Get screen size from system, or else from termcap. */
1169 get_screen_size (&SCREEN_WIDTH (selected_screen
),
1170 &SCREEN_HEIGHT (selected_screen
));
1171 if (SCREEN_WIDTH (selected_screen
) <= 0)
1172 SCREEN_WIDTH (selected_screen
) = tgetnum ("co");
1173 if (SCREEN_HEIGHT (selected_screen
) <= 0)
1174 SCREEN_HEIGHT (selected_screen
) = tgetnum ("li");
1176 min_padding_speed
= tgetnum ("pb");
1177 TN_standout_width
= tgetnum ("sg");
1178 TabWidth
= tgetnum ("tw");
1181 /* These capabilities commonly use ^J.
1182 I don't know why, but sending them on VMS does not work;
1183 it causes following spaces to be lost, sometimes.
1184 For now, the simplest fix is to avoid using these capabilities ever. */
1185 if (Down
&& Down
[0] == '\n')
1193 TS_fwd_scroll
= Down
;
1195 PC
= TS_pad_char
? *TS_pad_char
: 0;
1200 /* Turned off since /etc/termcap seems to have :ta= for most terminals
1201 and newer termcap doc does not seem to say there is a default.
1206 if (TS_standout_mode
== 0)
1208 TN_standout_width
= tgetnum ("ug");
1209 TS_end_standout_mode
= tgetstr ("ue", address
);
1210 TS_standout_mode
= tgetstr ("us", address
);
1216 /* Teleray: most programs want a space in front of TS_standout_mode,
1217 but Emacs can do without it (and give one extra column). */
1218 TS_standout_mode
= "\033RD";
1219 TN_standout_width
= 1;
1220 /* But that means we cannot rely on ^M to go to column zero! */
1222 /* LF can't be trusted either -- can alter hpos */
1223 /* if move at column 0 thru a line with TS_standout_mode */
1227 /* Special handling for certain terminal types known to need it */
1229 if (!strcmp (terminal_type
, "supdup"))
1231 memory_below_screen
= 1;
1232 Wcm
.cm_losewrap
= 1;
1234 if (!strncmp (terminal_type
, "c10", 3)
1235 || !strcmp (terminal_type
, "perq"))
1237 /* Supply a makeshift :wi string.
1238 This string is not valid in general since it works only
1239 for windows starting at the upper left corner;
1240 but that is all Emacs uses.
1242 This string works only if the screen is using
1243 the top of the video memory, because addressing is memory-relative.
1244 So first check the :ti string to see if that is true.
1246 It would be simpler if the :wi string could go in the termcap
1247 entry, but it can't because it is not fully valid.
1248 If it were in the termcap entry, it would confuse other programs. */
1251 p
= TS_termcap_modes
;
1252 while (*p
&& strcmp (p
, "\033v "))
1255 TS_set_window
= "\033v%C %C %C %C ";
1257 /* Termcap entry often fails to have :in: flag */
1258 must_write_spaces
= 1;
1259 /* :ti string typically fails to have \E^G! in it */
1260 /* This limits scope of insert-char to one line. */
1261 strcpy (area
, TS_termcap_modes
);
1262 strcat (area
, "\033\007!");
1263 TS_termcap_modes
= area
;
1264 area
+= strlen (area
) + 1;
1266 /* Change all %+ parameters to %C, to handle
1267 values above 96 correctly for the C100. */
1270 if (p
[0] == '%' && p
[1] == '+')
1276 ScreenRows
= SCREEN_HEIGHT (selected_screen
);
1277 ScreenCols
= SCREEN_WIDTH (selected_screen
);
1278 specified_window
= SCREEN_HEIGHT (selected_screen
);
1280 if (Wcm_init () == -1) /* can't do cursor motion */
1282 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
1283 It lacks the ability to position the cursor.\n\
1284 If that is not the actual type of terminal you have, use either the\n\
1285 DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
1286 or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.\n",
1289 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
1290 It lacks the ability to position the cursor.\n\
1291 If that is not the actual type of terminal you have,\n\
1292 use the C-shell command `setenv TERM ...' to specify the correct type.\n\
1293 It may be necessary to do `unsetenv TERMCAP' as well.\n",
1296 if (SCREEN_HEIGHT (selected_screen
) <= 0
1297 || SCREEN_WIDTH (selected_screen
) <= 0)
1298 fatal ("The screen size has not been specified.");
1300 delete_in_insert_mode
1301 = TS_delete_mode
&& TS_insert_mode
1302 && !strcmp (TS_delete_mode
, TS_insert_mode
);
1304 se_is_so
= (TS_standout_mode
1305 && TS_end_standout_mode
1306 && !strcmp (TS_standout_mode
, TS_end_standout_mode
));
1308 /* Remove width of standout marker from usable width of line */
1309 if (TN_standout_width
> 0)
1310 SCREEN_WIDTH (selected_screen
) -= TN_standout_width
;
1312 UseTabs
= tabs_safe_p () && TabWidth
== 8;
1316 && (TS_set_window
|| TS_set_scroll_region
|| TS_set_scroll_region_1
));
1318 line_ins_del_ok
= (((TS_ins_line
|| TS_ins_multi_lines
)
1319 && (TS_del_line
|| TS_del_multi_lines
))
1320 || (scroll_region_ok
&& TS_fwd_scroll
&& TS_rev_scroll
));
1322 char_ins_del_ok
= ((TS_ins_char
|| TS_insert_mode
1323 || TS_pad_inserted_char
|| TS_ins_multi_chars
)
1324 && (TS_del_char
|| TS_del_multi_chars
));
1326 fast_clear_end_of_line
= TS_clr_line
!= 0;
1329 if (read_socket_hook
) /* Baudrate is somewhat */
1330 /* meaningless in this case */
1335 fatal (str
, arg1
, arg2
)
1337 fprintf (stderr
, "emacs: ");
1338 fprintf (stderr
, str
, arg1
, arg2
);