(Info-edit): Move the customary mode-initialization calls out of here.
[bpt/emacs.git] / src / term.c
CommitLineData
08a24c47 1/* terminal control module for terminals described by TERMCAP
f2a00342 2 Copyright (C) 1985, 1986, 1987, 1993, 1994 Free Software Foundation, Inc.
08a24c47
JB
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
4746118a 8the Free Software Foundation; either version 2, or (at your option)
08a24c47
JB
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20
565620a5 21#include <config.h>
08a24c47
JB
22#include <stdio.h>
23#include <ctype.h>
08a24c47
JB
24#include "termchar.h"
25#include "termopts.h"
26#include "cm.h"
27#undef NULL
28#include "lisp.h"
ff11dfa1 29#include "frame.h"
08a24c47
JB
30#include "disptab.h"
31#include "termhooks.h"
5c2c7893 32#include "keyboard.h"
08a24c47
JB
33
34#define max(a, b) ((a) > (b) ? (a) : (b))
35#define min(a, b) ((a) < (b) ? (a) : (b))
36
ff11dfa1 37#define OUTPUT(a) tputs (a, FRAME_HEIGHT (selected_frame) - curY, cmputc)
08a24c47
JB
38#define OUTPUT1(a) tputs (a, 1, cmputc)
39#define OUTPUTL(a, lines) tputs (a, lines, cmputc)
ff11dfa1 40#define OUTPUT_IF(a) { if (a) tputs (a, FRAME_HEIGHT (selected_frame) - curY, cmputc); }
08a24c47
JB
41#define OUTPUT1_IF(a) { if (a) tputs (a, 1, cmputc); }
42
eb8c3be9 43/* Terminal characteristics that higher levels want to look at.
08a24c47
JB
44 These are all extern'd in termchar.h */
45
08a24c47
JB
46int 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. */
49int min_padding_speed; /* Speed below which no padding necessary */
50
51int line_ins_del_ok; /* Terminal can insert and delete lines */
52int char_ins_del_ok; /* Terminal can insert and delete chars */
53int scroll_region_ok; /* Terminal supports setting the
54 scroll window */
ff11dfa1 55int memory_below_frame; /* Terminal remembers lines
08a24c47
JB
56 scrolled off bottom */
57int fast_clear_end_of_line; /* Terminal has a `ce' string */
58
59int dont_calculate_costs; /* Nonzero means don't bother computing */
60 /* various cost tables; we won't use them. */
61
ff11dfa1 62/* Nonzero means no need to redraw the entire frame on resuming
08a24c47
JB
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. */
65int no_redraw_on_reenter;
66
67/* Hook functions that you can set to snap out the functions in this file.
68 These are all extern'd in termhooks.h */
69
70int (*cursor_to_hook) ();
71int (*raw_cursor_to_hook) ();
72
73int (*clear_to_end_hook) ();
ff11dfa1 74int (*clear_frame_hook) ();
08a24c47
JB
75int (*clear_end_of_line_hook) ();
76
77int (*ins_del_lines_hook) ();
78
79int (*change_line_highlight_hook) ();
80int (*reassert_line_highlight_hook) ();
81
82int (*insert_glyphs_hook) ();
83int (*write_glyphs_hook) ();
84int (*delete_glyphs_hook) ();
85
86int (*ring_bell_hook) ();
87
88int (*reset_terminal_modes_hook) ();
89int (*set_terminal_modes_hook) ();
90int (*update_begin_hook) ();
91int (*update_end_hook) ();
92int (*set_terminal_window_hook) ();
93
94int (*read_socket_hook) ();
95
55cc089c
RS
96int (*frame_up_to_date_hook) ();
97
20a558dc 98/* Return the current position of the mouse.
371fbaeb
JB
99
100 Set *f to the frame the mouse is in, or zero if the mouse is in no
101 Emacs frame. If it is set to zero, all the other arguments are
102 garbage.
103
a3c87d4e
JB
104 If the motion started in a scroll bar, set *bar_window to the
105 scroll bar's window, *part to the part the mouse is currently over,
106 *x to the position of the mouse along the scroll bar, and *y to the
107 overall length of the scroll bar.
371fbaeb
JB
108
109 Otherwise, set *bar_window to Qnil, and *x and *y to the column and
110 row of the character cell the mouse is over.
111
112 Set *time to the time the mouse was at the returned position.
113
114 This should clear mouse_moved until the next motion
115 event arrives. */
ff11dfa1 116void (*mouse_position_hook) ( /* FRAME_PTR *f,
371fbaeb 117 Lisp_Object *bar_window,
a3c87d4e 118 enum scroll_bar_part *part,
20a558dc
JB
119 Lisp_Object *x,
120 Lisp_Object *y,
121 unsigned long *time */ );
08a24c47 122
ff11dfa1
JB
123/* When reading from a minibuffer in a different frame, Emacs wants
124 to shift the highlight from the selected frame to the minibuffer's
125 frame; under X, this means it lies about where the focus is.
2e146aa4
JB
126 This hook tells the window system code to re-decide where to put
127 the highlight. */
ff11dfa1 128void (*frame_rehighlight_hook) ( /* FRAME_PTR f */ );
2e146aa4 129
dbc4e1c1
JB
130/* If we're displaying frames using a window system that can stack
131 frames on top of each other, this hook allows you to bring a frame
132 to the front, or bury it behind all the other windows. If this
133 hook is zero, that means the device we're displaying on doesn't
134 support overlapping frames, so there's no need to raise or lower
135 anything.
136
137 If RAISE is non-zero, F is brought to the front, before all other
138 windows. If RAISE is zero, F is sent to the back, behind all other
139 windows. */
140void (*frame_raise_lower_hook) ( /* FRAME_PTR f, int raise */ );
141
a3c87d4e 142/* Set the vertical scroll bar for WINDOW to have its upper left corner
371fbaeb
JB
143 at (TOP, LEFT), and be LENGTH rows high. Set its handle to
144 indicate that we are displaying PORTION characters out of a total
145 of WHOLE characters, starting at POSITION. If WINDOW doesn't yet
a3c87d4e
JB
146 have a scroll bar, create one for it. */
147void (*set_vertical_scroll_bar_hook)
371fbaeb 148 ( /* struct window *window,
20a558dc
JB
149 int portion, int whole, int position */ );
150
371fbaeb 151
20a558dc 152/* The following three hooks are used when we're doing a thorough
a3c87d4e 153 redisplay of the frame. We don't explicitly know which scroll bars
20a558dc
JB
154 are going to be deleted, because keeping track of when windows go
155 away is a real pain - can you say set-window-configuration?
156 Instead, we just assert at the beginning of redisplay that *all*
a3c87d4e 157 scroll bars are to be removed, and then save scroll bars from the
20a558dc
JB
158 firey pit when we actually redisplay their window. */
159
a3c87d4e
JB
160/* Arrange for all scroll bars on FRAME to be removed at the next call
161 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
162 `*redeem_scroll_bar_hook' is applied to its window before the judgement.
20a558dc 163
371fbaeb 164 This should be applied to each frame each time its window tree is
a3c87d4e
JB
165 redisplayed, even if it is not displaying scroll bars at the moment;
166 if the HAS_SCROLL_BARS flag has just been turned off, only calling
167 this and the judge_scroll_bars_hook will get rid of them.
371fbaeb
JB
168
169 If non-zero, this hook should be safe to apply to any frame,
a3c87d4e 170 whether or not it can support scroll bars, and whether or not it is
371fbaeb 171 currently displaying them. */
a3c87d4e 172void (*condemn_scroll_bars_hook)( /* FRAME_PTR *frame */ );
371fbaeb 173
a3c87d4e
JB
174/* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
175 Note that it's okay to redeem a scroll bar that is not condemned. */
176void (*redeem_scroll_bar_hook)( /* struct window *window */ );
20a558dc 177
a3c87d4e
JB
178/* Remove all scroll bars on FRAME that haven't been saved since the
179 last call to `*condemn_scroll_bars_hook'.
20a558dc 180
371fbaeb 181 This should be applied to each frame after each time its window
a3c87d4e
JB
182 tree is redisplayed, even if it is not displaying scroll bars at the
183 moment; if the HAS_SCROLL_BARS flag has just been turned off, only
184 calling this and condemn_scroll_bars_hook will get rid of them.
371fbaeb
JB
185
186 If non-zero, this hook should be safe to apply to any frame,
a3c87d4e 187 whether or not it can support scroll bars, and whether or not it is
371fbaeb 188 currently displaying them. */
a3c87d4e 189void (*judge_scroll_bars_hook)( /* FRAME_PTR *FRAME */ );
20a558dc
JB
190
191
08a24c47
JB
192/* Strings, numbers and flags taken from the termcap entry. */
193
194char *TS_ins_line; /* termcap "al" */
195char *TS_ins_multi_lines; /* "AL" (one parameter, # lines to insert) */
196char *TS_bell; /* "bl" */
197char *TS_clr_to_bottom; /* "cd" */
198char *TS_clr_line; /* "ce", clear to end of line */
ff11dfa1 199char *TS_clr_frame; /* "cl" */
08a24c47
JB
200char *TS_set_scroll_region; /* "cs" (2 params, first line and last line) */
201char *TS_set_scroll_region_1; /* "cS" (4 params: total lines,
202 lines above scroll region, lines below it,
203 total lines again) */
204char *TS_del_char; /* "dc" */
205char *TS_del_multi_chars; /* "DC" (one parameter, # chars to delete) */
206char *TS_del_line; /* "dl" */
207char *TS_del_multi_lines; /* "DL" (one parameter, # lines to delete) */
208char *TS_delete_mode; /* "dm", enter character-delete mode */
209char *TS_end_delete_mode; /* "ed", leave character-delete mode */
210char *TS_end_insert_mode; /* "ei", leave character-insert mode */
211char *TS_ins_char; /* "ic" */
212char *TS_ins_multi_chars; /* "IC" (one parameter, # chars to insert) */
213char *TS_insert_mode; /* "im", enter character-insert mode */
214char *TS_pad_inserted_char; /* "ip". Just padding, no commands. */
215char *TS_end_keypad_mode; /* "ke" */
216char *TS_keypad_mode; /* "ks" */
217char *TS_pad_char; /* "pc", char to use as padding */
218char *TS_repeat; /* "rp" (2 params, # times to repeat
219 and character to be repeated) */
220char *TS_end_standout_mode; /* "se" */
221char *TS_fwd_scroll; /* "sf" */
222char *TS_standout_mode; /* "so" */
223char *TS_rev_scroll; /* "sr" */
224char *TS_end_termcap_modes; /* "te" */
225char *TS_termcap_modes; /* "ti" */
226char *TS_visible_bell; /* "vb" */
227char *TS_end_visual_mode; /* "ve" */
228char *TS_visual_mode; /* "vi" */
229char *TS_set_window; /* "wi" (4 params, start and end of window,
230 each as vpos and hpos) */
231
232int TF_hazeltine; /* termcap hz flag. */
233int TF_insmode_motion; /* termcap mi flag: can move while in insert mode. */
234int TF_standout_motion; /* termcap mi flag: can move while in standout mode. */
235int TF_underscore; /* termcap ul flag: _ underlines if overstruck on
236 nonblank position. Must clear before writing _. */
237int TF_teleray; /* termcap xt flag: many weird consequences.
238 For t1061. */
239
240int TF_xs; /* Nonzero for "xs". If set together with
241 TN_standout_width == 0, it means don't bother
242 to write any end-standout cookies. */
243
244int TN_standout_width; /* termcap sg number: width occupied by standout
245 markers */
246
247static int RPov; /* # chars to start a TS_repeat */
248
249static int delete_in_insert_mode; /* delete mode == insert mode */
250
251static int se_is_so; /* 1 if same string both enters and leaves
252 standout mode */
253
254/* internal state */
255
256/* Number of chars of space used for standout marker at beginning of line,
257 or'd with 0100. Zero if no standout marker at all.
258
259 Used IFF TN_standout_width >= 0. */
260
261static char *chars_wasted;
262static char *copybuf;
263
264/* nonzero means supposed to write text in standout mode. */
265int standout_requested;
266
267int insert_mode; /* Nonzero when in insert mode. */
268int standout_mode; /* Nonzero when in standout mode. */
269
270/* Size of window specified by higher levels.
ff11dfa1 271 This is the number of lines, from the top of frame downwards,
08a24c47
JB
272 which can participate in insert-line/delete-line operations.
273
ff11dfa1 274 Effectively it excludes the bottom frame_height - specified_window_size
08a24c47
JB
275 lines from those operations. */
276
277int specified_window;
278
ff11dfa1 279/* Frame currently being redisplayed; 0 if not currently redisplaying.
08a24c47
JB
280 (Direct output does not count). */
281
ff11dfa1 282FRAME_PTR updating_frame;
08a24c47 283
07c57952
KH
284/* Provided for lisp packages. */
285static int system_uses_terminfo;
286
08a24c47 287char *tparam ();
e4bfb3b6
RS
288
289extern char *tgetstr ();
08a24c47
JB
290\f
291ring_bell ()
292{
1820044b 293 if (! FRAME_TERMCAP_P (selected_frame))
08a24c47
JB
294 {
295 (*ring_bell_hook) ();
296 return;
297 }
298 OUTPUT (TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell);
299}
300
301set_terminal_modes ()
302{
1820044b 303 if (! FRAME_TERMCAP_P (selected_frame))
08a24c47
JB
304 {
305 (*set_terminal_modes_hook) ();
306 return;
307 }
308 OUTPUT_IF (TS_termcap_modes);
309 OUTPUT_IF (TS_visual_mode);
310 OUTPUT_IF (TS_keypad_mode);
311 losecursor ();
312}
313
314reset_terminal_modes ()
315{
1820044b 316 if (! FRAME_TERMCAP_P (selected_frame))
08a24c47
JB
317 {
318 (*reset_terminal_modes_hook) ();
319 return;
320 }
321 if (TN_standout_width < 0)
322 turn_off_highlight ();
323 turn_off_insert ();
324 OUTPUT_IF (TS_end_keypad_mode);
325 OUTPUT_IF (TS_end_visual_mode);
326 OUTPUT_IF (TS_end_termcap_modes);
327 /* Output raw CR so kernel can track the cursor hpos. */
328 /* But on magic-cookie terminals this can erase an end-standout marker and
ff11dfa1 329 cause the rest of the frame to be in standout, so move down first. */
08a24c47
JB
330 if (TN_standout_width >= 0)
331 cmputc ('\n');
332 cmputc ('\r');
333}
334
ff11dfa1
JB
335update_begin (f)
336 FRAME_PTR f;
08a24c47 337{
ff11dfa1 338 updating_frame = f;
1820044b 339 if (! FRAME_TERMCAP_P (updating_frame))
ff11dfa1 340 (*update_begin_hook) (f);
08a24c47
JB
341}
342
ff11dfa1
JB
343update_end (f)
344 FRAME_PTR f;
08a24c47 345{
1820044b 346 if (! FRAME_TERMCAP_P (updating_frame))
08a24c47 347 {
7a8e3e30 348 (*update_end_hook) (f);
cc4ee3c7 349 updating_frame = 0;
08a24c47
JB
350 return;
351 }
352 turn_off_insert ();
353 background_highlight ();
354 standout_requested = 0;
ff11dfa1 355 updating_frame = 0;
08a24c47
JB
356}
357
358set_terminal_window (size)
359 int size;
360{
1820044b 361 if (! FRAME_TERMCAP_P (updating_frame))
08a24c47
JB
362 {
363 (*set_terminal_window_hook) (size);
364 return;
365 }
ff11dfa1 366 specified_window = size ? size : FRAME_HEIGHT (selected_frame);
08a24c47
JB
367 if (!scroll_region_ok)
368 return;
369 set_scroll_region (0, specified_window);
370}
371
372set_scroll_region (start, stop)
373 int start, stop;
374{
375 char *buf;
376 if (TS_set_scroll_region)
377 {
378 buf = tparam (TS_set_scroll_region, 0, 0, start, stop - 1);
379 }
380 else if (TS_set_scroll_region_1)
381 {
382 buf = tparam (TS_set_scroll_region_1, 0, 0,
ff11dfa1
JB
383 FRAME_HEIGHT (selected_frame), start,
384 FRAME_HEIGHT (selected_frame) - stop,
385 FRAME_HEIGHT (selected_frame));
08a24c47
JB
386 }
387 else
388 {
ff11dfa1 389 buf = tparam (TS_set_window, 0, 0, start, 0, stop, FRAME_WIDTH (selected_frame));
08a24c47
JB
390 }
391 OUTPUT (buf);
9ac0d9e0 392 xfree (buf);
08a24c47
JB
393 losecursor ();
394}
395\f
396turn_on_insert ()
397{
398 if (!insert_mode)
399 OUTPUT (TS_insert_mode);
400 insert_mode = 1;
401}
402
403turn_off_insert ()
404{
405 if (insert_mode)
406 OUTPUT (TS_end_insert_mode);
407 insert_mode = 0;
408}
409\f
410/* Handle highlighting when TN_standout_width (termcap sg) is not specified.
411 In these terminals, output is affected by the value of standout
412 mode when the output is written.
413
414 These functions are called on all terminals, but do nothing
415 on terminals whose standout mode does not work that way. */
416
417turn_off_highlight ()
418{
419 if (TN_standout_width < 0)
420 {
421 if (standout_mode)
422 OUTPUT_IF (TS_end_standout_mode);
423 standout_mode = 0;
424 }
425}
426
427turn_on_highlight ()
428{
429 if (TN_standout_width < 0)
430 {
431 if (!standout_mode)
432 OUTPUT_IF (TS_standout_mode);
433 standout_mode = 1;
434 }
435}
436
437/* Set standout mode to the state it should be in for
438 empty space inside windows. What this is,
439 depends on the user option inverse-video. */
440
441background_highlight ()
442{
443 if (TN_standout_width >= 0)
444 return;
445 if (inverse_video)
446 turn_on_highlight ();
447 else
448 turn_off_highlight ();
449}
450
451/* Set standout mode to the mode specified for the text to be output. */
452
453static
454highlight_if_desired ()
455{
456 if (TN_standout_width >= 0)
457 return;
458 if (!inverse_video == !standout_requested)
459 turn_off_highlight ();
460 else
461 turn_on_highlight ();
462}
463\f
464/* Handle standout mode for terminals in which TN_standout_width >= 0.
465 On these terminals, standout is controlled by markers that
ff11dfa1 466 live inside the terminal's memory. TN_standout_width is the width
08a24c47
JB
467 that the marker occupies in memory. Standout runs from the marker
468 to the end of the line on some terminals, or to the next
469 turn-off-standout marker (TS_end_standout_mode) string
470 on other terminals. */
471
472/* Write a standout marker or end-standout marker at the front of the line
473 at vertical position vpos. */
474
475write_standout_marker (flag, vpos)
476 int flag, vpos;
477{
478 if (flag || (TS_end_standout_mode && !TF_teleray && !se_is_so
479 && !(TF_xs && TN_standout_width == 0)))
480 {
481 cmgoto (vpos, 0);
482 cmplus (TN_standout_width);
483 OUTPUT (flag ? TS_standout_mode : TS_end_standout_mode);
484 chars_wasted[curY] = TN_standout_width | 0100;
485 }
486}
487\f
488/* External interface to control of standout mode.
489 Call this when about to modify line at position VPOS
490 and not change whether it is highlighted. */
491
492reassert_line_highlight (highlight, vpos)
493 int highlight;
494 int vpos;
495{
1820044b 496 if (! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
08a24c47
JB
497 {
498 (*reassert_line_highlight_hook) (highlight, vpos);
499 return;
500 }
501 if (TN_standout_width < 0)
502 /* Handle terminals where standout takes affect at output time */
503 standout_requested = highlight;
504 else if (chars_wasted[vpos] == 0)
505 /* For terminals with standout markers, write one on this line
506 if there isn't one already. */
507 write_standout_marker (highlight, vpos);
508}
509
510/* Call this when about to modify line at position VPOS
511 and change whether it is highlighted. */
512
513change_line_highlight (new_highlight, vpos, first_unused_hpos)
514 int new_highlight, vpos, first_unused_hpos;
515{
516 standout_requested = new_highlight;
1820044b 517 if (! FRAME_TERMCAP_P (updating_frame))
08a24c47
JB
518 {
519 (*change_line_highlight_hook) (new_highlight, vpos, first_unused_hpos);
520 return;
521 }
522
523 cursor_to (vpos, 0);
524
525 if (TN_standout_width < 0)
526 background_highlight ();
527 /* If line starts with a marker, delete the marker */
528 else if (TS_clr_line && chars_wasted[curY])
529 {
530 turn_off_insert ();
531 /* On Teleray, make sure to erase the SO marker. */
532 if (TF_teleray)
533 {
ff11dfa1 534 cmgoto (curY - 1, FRAME_WIDTH (selected_frame) - 4);
08a24c47
JB
535 OUTPUT ("\033S");
536 curY++; /* ESC S moves to next line where the TS_standout_mode was */
537 curX = 0;
538 }
539 else
540 cmgoto (curY, 0); /* reposition to kill standout marker */
541 }
542 clear_end_of_line_raw (first_unused_hpos);
543 reassert_line_highlight (new_highlight, curY);
544}
545\f
546
547/* Move to absolute position, specified origin 0 */
548
549cursor_to (row, col)
4746118a 550 int row, col;
08a24c47 551{
1820044b 552 if (! FRAME_TERMCAP_P ((updating_frame
ff11dfa1
JB
553 ? updating_frame
554 : selected_frame))
08a24c47
JB
555 && cursor_to_hook)
556 {
557 (*cursor_to_hook) (row, col);
558 return;
559 }
560
561 col += chars_wasted[row] & 077;
562 if (curY == row && curX == col)
563 return;
564 if (!TF_standout_motion)
565 background_highlight ();
566 if (!TF_insmode_motion)
567 turn_off_insert ();
568 cmgoto (row, col);
569}
570
571/* Similar but don't take any account of the wasted characters. */
572
573raw_cursor_to (row, col)
4746118a 574 int row, col;
08a24c47 575{
1820044b 576 if (! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
08a24c47
JB
577 {
578 (*raw_cursor_to_hook) (row, col);
579 return;
580 }
581 if (curY == row && curX == col)
582 return;
583 if (!TF_standout_motion)
584 background_highlight ();
585 if (!TF_insmode_motion)
586 turn_off_insert ();
587 cmgoto (row, col);
588}
589\f
590/* Erase operations */
591
ff11dfa1 592/* clear from cursor to end of frame */
08a24c47
JB
593clear_to_end ()
594{
595 register int i;
596
1820044b 597 if (clear_to_end_hook && FRAME_TERMCAP_P (updating_frame))
08a24c47
JB
598 {
599 (*clear_to_end_hook) ();
600 return;
601 }
602 if (TS_clr_to_bottom)
603 {
604 background_highlight ();
605 OUTPUT (TS_clr_to_bottom);
ff11dfa1 606 bzero (chars_wasted + curY, FRAME_HEIGHT (selected_frame) - curY);
08a24c47
JB
607 }
608 else
609 {
ff11dfa1 610 for (i = curY; i < FRAME_HEIGHT (selected_frame); i++)
08a24c47
JB
611 {
612 cursor_to (i, 0);
ff11dfa1 613 clear_end_of_line_raw (FRAME_WIDTH (selected_frame));
08a24c47
JB
614 }
615 }
616}
617
ff11dfa1 618/* Clear entire frame */
08a24c47 619
ff11dfa1 620clear_frame ()
08a24c47 621{
ff11dfa1 622 if (clear_frame_hook
1820044b 623 && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
08a24c47 624 {
ff11dfa1 625 (*clear_frame_hook) ();
08a24c47
JB
626 return;
627 }
ff11dfa1 628 if (TS_clr_frame)
08a24c47
JB
629 {
630 background_highlight ();
ff11dfa1
JB
631 OUTPUT (TS_clr_frame);
632 bzero (chars_wasted, FRAME_HEIGHT (selected_frame));
08a24c47
JB
633 cmat (0, 0);
634 }
635 else
636 {
637 cursor_to (0, 0);
638 clear_to_end ();
639 }
640}
641
642/* Clear to end of line, but do not clear any standout marker.
643 Assumes that the cursor is positioned at a character of real text,
644 which implies it cannot be before a standout marker
645 unless the marker has zero width.
646
647 Note that the cursor may be moved. */
648
649clear_end_of_line (first_unused_hpos)
650 int first_unused_hpos;
651{
a796ac82 652 static GLYPH buf = SPACEGLYPH;
1820044b 653 if (FRAME_TERMCAP_P (selected_frame)
08a24c47 654 && TN_standout_width == 0 && curX == 0 && chars_wasted[curY] != 0)
a796ac82 655 write_glyphs (&buf, 1);
08a24c47
JB
656 clear_end_of_line_raw (first_unused_hpos);
657}
658
659/* Clear from cursor to end of line.
660 Assume that the line is already clear starting at column first_unused_hpos.
661 If the cursor is at a standout marker, erase the marker.
662
663 Note that the cursor may be moved, on terminals lacking a `ce' string. */
664
665clear_end_of_line_raw (first_unused_hpos)
666 int first_unused_hpos;
667{
668 register int i;
669
670 if (clear_end_of_line_hook
1820044b 671 && ! FRAME_TERMCAP_P ((updating_frame
ff11dfa1
JB
672 ? updating_frame
673 : selected_frame)))
08a24c47
JB
674 {
675 (*clear_end_of_line_hook) (first_unused_hpos);
676 return;
677 }
678
679 first_unused_hpos += chars_wasted[curY] & 077;
680 if (curX >= first_unused_hpos)
681 return;
682 /* Notice if we are erasing a magic cookie */
683 if (curX == 0)
684 chars_wasted[curY] = 0;
685 background_highlight ();
686 if (TS_clr_line)
687 {
688 OUTPUT1 (TS_clr_line);
689 }
690 else
691 { /* have to do it the hard way */
692 turn_off_insert ();
693
694 /* Do not write in last row last col with Autowrap on. */
ff11dfa1
JB
695 if (AutoWrap && curY == FRAME_HEIGHT (selected_frame) - 1
696 && first_unused_hpos == FRAME_WIDTH (selected_frame))
08a24c47
JB
697 first_unused_hpos--;
698
699 for (i = curX; i < first_unused_hpos; i++)
700 {
701 if (termscript)
702 fputc (' ', termscript);
703 putchar (' ');
704 }
705 cmplus (first_unused_hpos - curX);
706 }
707}
708\f
709
710write_glyphs (string, len)
711 register GLYPH *string;
712 register int len;
713{
714 register GLYPH g;
715 register int tlen = GLYPH_TABLE_LENGTH;
716 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
717
718 if (write_glyphs_hook
1820044b 719 && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
08a24c47
JB
720 {
721 (*write_glyphs_hook) (string, len);
722 return;
723 }
724
725 highlight_if_desired ();
726 turn_off_insert ();
727
728 /* Don't dare write in last column of bottom line, if AutoWrap,
ff11dfa1 729 since that would scroll the whole frame on some terminals. */
08a24c47
JB
730
731 if (AutoWrap
ff11dfa1 732 && curY + 1 == FRAME_HEIGHT (selected_frame)
08a24c47 733 && (curX + len - (chars_wasted[curY] & 077)
ff11dfa1 734 == FRAME_WIDTH (selected_frame)))
08a24c47
JB
735 len --;
736
737 cmplus (len);
738 while (--len >= 0)
739 {
740 g = *string++;
741 /* Check quickly for G beyond length of table.
742 That implies it isn't an alias and is simple. */
743 if (g >= tlen)
744 {
745 simple:
746 putc (g & 0xff, stdout);
747 if (ferror (stdout))
748 clearerr (stdout);
749 if (termscript)
750 putc (g & 0xff, termscript);
751 }
752 else
753 {
754 /* G has an entry in Vglyph_table,
755 so process any alias and then test for simpleness. */
756 while (GLYPH_ALIAS_P (tbase, tlen, g))
757 g = GLYPH_ALIAS (tbase, g);
758 if (GLYPH_SIMPLE_P (tbase, tlen, g))
759 goto simple;
760 else
761 {
762 /* Here if G (or its definition as an alias) is not simple. */
763 fwrite (GLYPH_STRING (tbase, g), 1, GLYPH_LENGTH (tbase, g),
764 stdout);
765 if (ferror (stdout))
766 clearerr (stdout);
767 if (termscript)
768 fwrite (GLYPH_STRING (tbase, g), 1, GLYPH_LENGTH (tbase, g),
769 termscript);
770 }
771 }
772 }
773}
774
775/* If start is zero, insert blanks instead of a string at start */
776
777insert_glyphs (start, len)
778 register GLYPH *start;
779 register int len;
780{
781 char *buf;
782 register GLYPH g;
783 register int tlen = GLYPH_TABLE_LENGTH;
784 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
785
1820044b 786 if (insert_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame))
08a24c47
JB
787 {
788 (*insert_glyphs_hook) (start, len);
789 return;
790 }
791 highlight_if_desired ();
792
793 if (TS_ins_multi_chars)
794 {
795 buf = tparam (TS_ins_multi_chars, 0, 0, len);
796 OUTPUT1 (buf);
9ac0d9e0 797 xfree (buf);
08a24c47
JB
798 if (start)
799 write_glyphs (start, len);
800 return;
801 }
802
803 turn_on_insert ();
804 cmplus (len);
805 while (--len >= 0)
806 {
807 OUTPUT1_IF (TS_ins_char);
808 if (!start)
809 g = SPACEGLYPH;
810 else
811 g = *start++;
812
813 if (GLYPH_SIMPLE_P (tbase, tlen, g))
814 {
815 putc (g & 0xff, stdout);
816 if (ferror (stdout))
817 clearerr (stdout);
818 if (termscript)
819 putc (g & 0xff, termscript);
820 }
821 else
822 {
823 fwrite (GLYPH_STRING (tbase, g), 1, GLYPH_LENGTH (tbase, g), stdout);
824 if (ferror (stdout))
825 clearerr (stdout);
826 if (termscript)
827 fwrite (GLYPH_STRING (tbase, g), 1, GLYPH_LENGTH (tbase, g),
828 termscript);
829 }
830
831 OUTPUT1_IF (TS_pad_inserted_char);
832 }
833}
834
835delete_glyphs (n)
836 register int n;
837{
838 char *buf;
839 register int i;
840
1820044b 841 if (delete_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame))
08a24c47
JB
842 {
843 (*delete_glyphs_hook) (n);
844 return;
845 }
846
847 if (delete_in_insert_mode)
848 {
849 turn_on_insert ();
850 }
851 else
852 {
853 turn_off_insert ();
854 OUTPUT_IF (TS_delete_mode);
855 }
856
857 if (TS_del_multi_chars)
858 {
859 buf = tparam (TS_del_multi_chars, 0, 0, n);
860 OUTPUT1 (buf);
9ac0d9e0 861 xfree (buf);
08a24c47
JB
862 }
863 else
864 for (i = 0; i < n; i++)
865 OUTPUT1 (TS_del_char);
866 if (!delete_in_insert_mode)
867 OUTPUT_IF (TS_end_delete_mode);
868}
869\f
870/* Insert N lines at vpos VPOS. If N is negative, delete -N lines. */
871
872ins_del_lines (vpos, n)
873 int vpos, n;
874{
875 char *multi = n > 0 ? TS_ins_multi_lines : TS_del_multi_lines;
876 char *single = n > 0 ? TS_ins_line : TS_del_line;
877 char *scroll = n > 0 ? TS_rev_scroll : TS_fwd_scroll;
878
879 register int i = n > 0 ? n : -n;
880 register char *buf;
881
1820044b 882 if (ins_del_lines_hook && ! FRAME_TERMCAP_P (updating_frame))
08a24c47
JB
883 {
884 (*ins_del_lines_hook) (vpos, n);
885 return;
886 }
887
888 /* If the lines below the insertion are being pushed
889 into the end of the window, this is the same as clearing;
890 and we know the lines are already clear, since the matching
891 deletion has already been done. So can ignore this. */
892 /* If the lines below the deletion are blank lines coming
893 out of the end of the window, don't bother,
894 as there will be a matching inslines later that will flush them. */
895 if (scroll_region_ok && vpos + i >= specified_window)
896 return;
ff11dfa1 897 if (!memory_below_frame && vpos + i >= FRAME_HEIGHT (selected_frame))
08a24c47
JB
898 return;
899
900 if (multi)
901 {
902 raw_cursor_to (vpos, 0);
903 background_highlight ();
904 buf = tparam (multi, 0, 0, i);
905 OUTPUT (buf);
9ac0d9e0 906 xfree (buf);
08a24c47
JB
907 }
908 else if (single)
909 {
910 raw_cursor_to (vpos, 0);
911 background_highlight ();
912 while (--i >= 0)
913 OUTPUT (single);
914 if (TF_teleray)
915 curX = 0;
916 }
917 else
918 {
919 set_scroll_region (vpos, specified_window);
920 if (n < 0)
921 raw_cursor_to (specified_window - 1, 0);
922 else
923 raw_cursor_to (vpos, 0);
924 background_highlight ();
925 while (--i >= 0)
926 OUTPUTL (scroll, specified_window - vpos);
927 set_scroll_region (0, specified_window);
928 }
929
930 if (TN_standout_width >= 0)
931 {
932 register lower_limit
933 = (scroll_region_ok
934 ? specified_window
ff11dfa1 935 : FRAME_HEIGHT (selected_frame));
08a24c47
JB
936
937 if (n < 0)
938 {
939 bcopy (&chars_wasted[vpos - n], &chars_wasted[vpos],
940 lower_limit - vpos + n);
941 bzero (&chars_wasted[lower_limit + n], - n);
942 }
943 else
944 {
945 bcopy (&chars_wasted[vpos], &copybuf[vpos], lower_limit - vpos - n);
946 bcopy (&copybuf[vpos], &chars_wasted[vpos + n],
947 lower_limit - vpos - n);
948 bzero (&chars_wasted[vpos], n);
949 }
950 }
ff11dfa1 951 if (!scroll_region_ok && memory_below_frame && n < 0)
08a24c47 952 {
ff11dfa1 953 cursor_to (FRAME_HEIGHT (selected_frame) + n, 0);
08a24c47
JB
954 clear_to_end ();
955 }
956}
957\f
958/* Compute cost of sending "str", in characters,
959 not counting any line-dependent padding. */
960
961int
962string_cost (str)
963 char *str;
964{
965 cost = 0;
966 if (str)
967 tputs (str, 0, evalcost);
968 return cost;
969}
970
971/* Compute cost of sending "str", in characters,
972 counting any line-dependent padding at one line. */
973
974static int
975string_cost_one_line (str)
976 char *str;
977{
978 cost = 0;
979 if (str)
980 tputs (str, 1, evalcost);
981 return cost;
982}
983
984/* Compute per line amount of line-dependent padding,
985 in tenths of characters. */
986
987int
988per_line_cost (str)
989 register char *str;
990{
991 cost = 0;
992 if (str)
993 tputs (str, 0, evalcost);
994 cost = - cost;
995 if (str)
996 tputs (str, 10, evalcost);
997 return cost;
998}
999
1000#ifndef old
1001/* char_ins_del_cost[n] is cost of inserting N characters.
1002 char_ins_del_cost[-n] is cost of deleting N characters. */
1003
1004int *char_ins_del_vector;
1005
ff11dfa1 1006#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WIDTH ((f))])
08a24c47
JB
1007#endif
1008
1009/* ARGSUSED */
1010static void
ff11dfa1
JB
1011calculate_ins_del_char_costs (frame)
1012 FRAME_PTR frame;
08a24c47
JB
1013{
1014 int ins_startup_cost, del_startup_cost;
1015 int ins_cost_per_char, del_cost_per_char;
1016 register int i;
1017 register int *p;
1018
1019 if (TS_ins_multi_chars)
1020 {
1021 ins_cost_per_char = 0;
1022 ins_startup_cost = string_cost_one_line (TS_ins_multi_chars);
1023 }
1024 else if (TS_ins_char || TS_pad_inserted_char
1025 || (TS_insert_mode && TS_end_insert_mode))
1026 {
1027 ins_startup_cost = (30 * (string_cost (TS_insert_mode)
1028 + string_cost (TS_end_insert_mode))) / 100;
1029 ins_cost_per_char = (string_cost_one_line (TS_ins_char)
1030 + string_cost_one_line (TS_pad_inserted_char));
1031 }
1032 else
1033 {
1034 ins_startup_cost = 9999;
1035 ins_cost_per_char = 0;
1036 }
1037
1038 if (TS_del_multi_chars)
1039 {
1040 del_cost_per_char = 0;
1041 del_startup_cost = string_cost_one_line (TS_del_multi_chars);
1042 }
1043 else if (TS_del_char)
1044 {
1045 del_startup_cost = (string_cost (TS_delete_mode)
1046 + string_cost (TS_end_delete_mode));
1047 if (delete_in_insert_mode)
1048 del_startup_cost /= 2;
1049 del_cost_per_char = string_cost_one_line (TS_del_char);
1050 }
1051 else
1052 {
1053 del_startup_cost = 9999;
1054 del_cost_per_char = 0;
1055 }
1056
1057 /* Delete costs are at negative offsets */
ff11dfa1
JB
1058 p = &char_ins_del_cost (frame)[0];
1059 for (i = FRAME_WIDTH (selected_frame); --i >= 0;)
08a24c47
JB
1060 *--p = (del_startup_cost += del_cost_per_char);
1061
1062 /* Doing nothing is free */
ff11dfa1 1063 p = &char_ins_del_cost (frame)[0];
08a24c47
JB
1064 *p++ = 0;
1065
1066 /* Insert costs are at positive offsets */
ff11dfa1 1067 for (i = FRAME_WIDTH (frame); --i >= 0;)
08a24c47
JB
1068 *p++ = (ins_startup_cost += ins_cost_per_char);
1069}
1070
1071#ifdef HAVE_X_WINDOWS
e7308e06 1072extern int x_screen_planes;
08a24c47
JB
1073#endif
1074
a790fee2
JB
1075extern do_line_insertion_deletion_costs ();
1076
ff11dfa1
JB
1077calculate_costs (frame)
1078 FRAME_PTR frame;
08a24c47 1079{
ff11dfa1 1080 register char *f = TS_set_scroll_region ?
08a24c47
JB
1081 TS_set_scroll_region
1082 : TS_set_scroll_region_1;
1083
1084 if (dont_calculate_costs)
1085 return;
1086
1087#ifdef HAVE_X_WINDOWS
1820044b 1088 if (FRAME_X_P (frame))
08a24c47 1089 {
ff11dfa1 1090 do_line_insertion_deletion_costs (frame, 0, ".5*", 0, ".5*",
e7308e06 1091 0, 0, x_screen_planes);
08a24c47
JB
1092 return;
1093 }
1094#endif
1095
1096 /* These variables are only used for terminal stuff. They are allocated
ff11dfa1 1097 once for the terminal frame of X-windows emacs, but not used afterwards.
08a24c47
JB
1098
1099 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1100 X turns off char_ins_del_ok.
1101
1102 chars_wasted and copybuf are only used here in term.c in cases where
1103 the term hook isn't called. */
1104
1105 if (chars_wasted != 0)
ff11dfa1 1106 chars_wasted = (char *) xrealloc (chars_wasted, FRAME_HEIGHT (frame));
08a24c47 1107 else
ff11dfa1 1108 chars_wasted = (char *) xmalloc (FRAME_HEIGHT (frame));
08a24c47
JB
1109
1110 if (copybuf != 0)
ff11dfa1 1111 copybuf = (char *) xrealloc (copybuf, FRAME_HEIGHT (frame));
08a24c47 1112 else
ff11dfa1 1113 copybuf = (char *) xmalloc (FRAME_HEIGHT (frame));
08a24c47
JB
1114
1115 if (char_ins_del_vector != 0)
1116 char_ins_del_vector
1117 = (int *) xrealloc (char_ins_del_vector,
1118 (sizeof (int)
ff11dfa1 1119 + 2 * FRAME_WIDTH (frame) * sizeof (int)));
08a24c47
JB
1120 else
1121 char_ins_del_vector
1122 = (int *) xmalloc (sizeof (int)
ff11dfa1 1123 + 2 * FRAME_WIDTH (frame) * sizeof (int));
08a24c47 1124
ff11dfa1
JB
1125 bzero (chars_wasted, FRAME_HEIGHT (frame));
1126 bzero (copybuf, FRAME_HEIGHT (frame));
08a24c47 1127 bzero (char_ins_del_vector, (sizeof (int)
ff11dfa1 1128 + 2 * FRAME_WIDTH (frame) * sizeof (int)));
08a24c47 1129
ff11dfa1
JB
1130 if (f && (!TS_ins_line && !TS_del_line))
1131 do_line_insertion_deletion_costs (frame,
08a24c47
JB
1132 TS_rev_scroll, TS_ins_multi_lines,
1133 TS_fwd_scroll, TS_del_multi_lines,
ff11dfa1 1134 f, f, 1);
08a24c47 1135 else
ff11dfa1 1136 do_line_insertion_deletion_costs (frame,
08a24c47
JB
1137 TS_ins_line, TS_ins_multi_lines,
1138 TS_del_line, TS_del_multi_lines,
1139 0, 0, 1);
1140
ff11dfa1 1141 calculate_ins_del_char_costs (frame);
08a24c47
JB
1142
1143 /* Don't use TS_repeat if its padding is worse than sending the chars */
1144 if (TS_repeat && per_line_cost (TS_repeat) * baud_rate < 9000)
1145 RPov = string_cost (TS_repeat);
1146 else
ff11dfa1 1147 RPov = FRAME_WIDTH (frame) * 2;
08a24c47
JB
1148
1149 cmcostinit (); /* set up cursor motion costs */
1150}
1151\f
a796ac82
JB
1152struct fkey_table {
1153 char *cap, *name;
1154};
1155
01d8deb0
ER
1156 /* Termcap capability names that correspond directly to X keysyms.
1157 Some of these (marked "terminfo") aren't supplied by old-style
1158 (Berkeley) termcap entries. They're listed in X keysym order;
1159 except we put the keypad keys first, so that if they clash with
1160 other keys (as on the IBM PC keyboard) they get overridden.
1161 */
1162
a796ac82 1163static struct fkey_table keys[] = {
01d8deb0
ER
1164 "kh", "home", /* termcap */
1165 "kl", "left", /* termcap */
1166 "ku", "up", /* termcap */
1167 "kr", "right", /* termcap */
1168 "kd", "down", /* termcap */
1169 "%8", "prior", /* terminfo */
1170 "%5", "next", /* terminfo */
1171 "@7", "end", /* terminfo */
1172 "@1", "begin", /* terminfo */
1173 "*6", "select", /* terminfo */
1174 "%9", "print", /* terminfo */
1175 "@4", "execute", /* terminfo --- actually the `command' key */
1176 /*
1177 * "insert" --- see below
1178 */
1179 "&8", "undo", /* terminfo */
1180 "%0", "redo", /* terminfo */
1181 "%7", "menu", /* terminfo --- actually the `options' key */
1182 "@0", "find", /* terminfo */
1183 "@2", "cancel", /* terminfo */
1184 "%1", "help", /* terminfo */
1185 /*
1186 * "break" goes here, but can't be reliably intercepted with termcap
1187 */
1188 "&4", "reset", /* terminfo --- actually `restart' */
1189 /*
1190 * "system" and "user" --- no termcaps
1191 */
1192 "kE", "clearline", /* terminfo */
1193 "kA", "insertline", /* terminfo */
1194 "kL", "deleteline", /* terminfo */
1195 "kI", "insertchar", /* terminfo */
1196 "kD", "deletechar", /* terminfo */
1197 "kB", "backtab", /* terminfo */
1198 /*
1199 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1200 */
1201 "@8", "kp-enter", /* terminfo */
1202 /*
1203 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1204 * "kp-multiply", "kp-add", "kp-separator",
1205 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1206 * --- no termcaps for any of these.
1207 */
1208 "K4", "kp-1", /* terminfo */
1209 /*
1210 * "kp-2" --- no termcap
1211 */
1212 "K5", "kp-3", /* terminfo */
1213 /*
1214 * "kp-4" --- no termcap
1215 */
1216 "K2", "kp-5", /* terminfo */
1217 /*
1218 * "kp-6" --- no termcap
1219 */
1220 "K1", "kp-7", /* terminfo */
1221 /*
1222 * "kp-8" --- no termcap
1223 */
1224 "K3", "kp-9", /* terminfo */
1225 /*
1226 * "kp-equal" --- no termcap
1227 */
1228 "k1", "f1",
1229 "k2", "f2",
1230 "k3", "f3",
1231 "k4", "f4",
1232 "k5", "f5",
1233 "k6", "f6",
1234 "k7", "f7",
1235 "k8", "f8",
1236 "k9", "f9",
a796ac82
JB
1237 };
1238
f2a00342
RM
1239static char **term_get_fkeys_arg;
1240static Lisp_Object term_get_fkeys_1 ();
465db27b 1241
01d8deb0
ER
1242/* Find the escape codes sent by the function keys for Vfunction_key_map.
1243 This function scans the termcap function key sequence entries, and
1244 adds entries to Vfunction_key_map for each function key it finds. */
1245
5c2c7893
JB
1246void
1247term_get_fkeys (address)
1248 char **address;
f2a00342
RM
1249{
1250 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1251 errors during the call. The only errors should be from Fdefine_key
1252 when given a key sequence containing an invalid prefix key. If the
1253 termcap defines function keys which use a prefix that is already bound
1254 to a command by the default bindings, we should silently ignore that
1255 function key specification, rather than giving the user an error and
1256 refusing to run at all on such a terminal. */
1257
1258 extern Lisp_Object Fidentity ();
f2a00342
RM
1259 term_get_fkeys_arg = address;
1260 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1261}
1262
1263static Lisp_Object
1264term_get_fkeys_1 ()
5c2c7893 1265{
5c2c7893
JB
1266 int i;
1267
37085233 1268 char **address = term_get_fkeys_arg;
f778aff2 1269
3e65092f
RS
1270 /* This can happen if CANNOT_DUMP or with strange options. */
1271 if (!initialized)
1272 Vfunction_key_map = Fmake_sparse_keymap (Qnil);
1273
5c2c7893
JB
1274 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1275 {
1276 char *sequence = tgetstr (keys[i].cap, address);
1277 if (sequence)
f2a00342
RM
1278 Fdefine_key (Vfunction_key_map, build_string (sequence),
1279 Fmake_vector (make_number (1),
1280 intern (keys[i].name)));
5c2c7893 1281 }
a796ac82
JB
1282
1283 /* The uses of the "k0" capability are inconsistent; sometimes it
1284 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
eb8c3be9 1285 We will attempt to politely accommodate both systems by testing for
a796ac82
JB
1286 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1287 */
1288 {
1289 char *k_semi = tgetstr ("k;", address);
1290 char *k0 = tgetstr ("k0", address);
1291 char *k0_name = "f10";
1292
1293 if (k_semi)
1294 {
f2a00342
RM
1295 Fdefine_key (Vfunction_key_map, build_string (k_semi),
1296 Fmake_vector (make_number (1), intern ("f10")));
a796ac82
JB
1297 k0_name = "f0";
1298 }
1299
1300 if (k0)
f2a00342
RM
1301 Fdefine_key (Vfunction_key_map, build_string (k0),
1302 Fmake_vector (make_number (1), intern (k0_name)));
a796ac82 1303 }
01d8deb0
ER
1304
1305 /* Set up cookies for numbered function keys above f10. */
1306 {
1307 char fcap[3], fkey[4];
1308
fc4f24da 1309 fcap[0] = 'F'; fcap[2] = '\0';
01d8deb0
ER
1310 for (i = 11; i < 64; i++)
1311 {
1312 if (i <= 19)
1313 fcap[1] = '1' + i - 11;
1314 else if (i <= 45)
1315 fcap[1] = 'A' + i - 11;
1316 else
1317 fcap[1] = 'a' + i - 11;
1318
fc4f24da
RS
1319 {
1320 char *sequence = tgetstr (fcap, address);
1321 if (sequence)
1322 {
465db27b 1323 sprintf (fkey, "f%d", i);
f2a00342
RM
1324 Fdefine_key (Vfunction_key_map, build_string (sequence),
1325 Fmake_vector (make_number (1),
1326 intern (fkey)));
fc4f24da
RS
1327 }
1328 }
01d8deb0
ER
1329 }
1330 }
1331
1332 /*
1333 * Various mappings to try and get a better fit.
1334 */
1335 {
fc4f24da
RS
1336#define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1337 if (!tgetstr (cap1, address)) \
1338 { \
1339 char *sequence = tgetstr (cap2, address); \
1340 if (sequence) \
f2a00342
RM
1341 Fdefine_key (Vfunction_key_map, build_string (sequence), \
1342 Fmake_vector (make_number (1), \
1343 intern (sym))); \
fc4f24da 1344 }
01d8deb0
ER
1345
1346 /* if there's no key_next keycap, map key_npage to `next' keysym */
27b61785 1347 CONDITIONAL_REASSIGN ("%5", "kN", "next");
01d8deb0 1348 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
381d11a1 1349 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
01d8deb0 1350 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
27b61785 1351 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1dd40212 1352#undef CONDITIONAL_REASSIGN
01d8deb0 1353 }
5c2c7893
JB
1354}
1355
1356\f
08a24c47
JB
1357term_init (terminal_type)
1358 char *terminal_type;
1359{
1360 char *area;
1361 char **address = &area;
1362 char buffer[2044];
1363 register char *p;
1364 int status;
1365
08a24c47
JB
1366 Wcm_clear ();
1367 dont_calculate_costs = 0;
1368
1369 status = tgetent (buffer, terminal_type);
1370 if (status < 0)
1371 fatal ("Cannot open termcap database file.\n");
1372 if (status == 0)
c5a9c3e6
RS
1373 fatal ("Terminal type %s is not defined.\n\
1374If that is not the actual type of terminal you have,\n\
1375use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
1376`setenv TERM ...') to specify the correct type. It may be necessary\n\
1377to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.\n",
1378 terminal_type);
08a24c47
JB
1379
1380#ifdef TERMINFO
1381 area = (char *) malloc (2044);
1382#else
1383 area = (char *) malloc (strlen (buffer));
1384#endif /* not TERMINFO */
1385 if (area == 0)
1386 abort ();
1387
1388 TS_ins_line = tgetstr ("al", address);
1389 TS_ins_multi_lines = tgetstr ("AL", address);
1390 TS_bell = tgetstr ("bl", address);
1391 BackTab = tgetstr ("bt", address);
1392 TS_clr_to_bottom = tgetstr ("cd", address);
1393 TS_clr_line = tgetstr ("ce", address);
ff11dfa1 1394 TS_clr_frame = tgetstr ("cl", address);
08a24c47
JB
1395 ColPosition = tgetstr ("ch", address);
1396 AbsPosition = tgetstr ("cm", address);
1397 CR = tgetstr ("cr", address);
1398 TS_set_scroll_region = tgetstr ("cs", address);
1399 TS_set_scroll_region_1 = tgetstr ("cS", address);
1400 RowPosition = tgetstr ("cv", address);
1401 TS_del_char = tgetstr ("dc", address);
1402 TS_del_multi_chars = tgetstr ("DC", address);
1403 TS_del_line = tgetstr ("dl", address);
1404 TS_del_multi_lines = tgetstr ("DL", address);
1405 TS_delete_mode = tgetstr ("dm", address);
1406 TS_end_delete_mode = tgetstr ("ed", address);
1407 TS_end_insert_mode = tgetstr ("ei", address);
1408 Home = tgetstr ("ho", address);
1409 TS_ins_char = tgetstr ("ic", address);
1410 TS_ins_multi_chars = tgetstr ("IC", address);
1411 TS_insert_mode = tgetstr ("im", address);
1412 TS_pad_inserted_char = tgetstr ("ip", address);
1413 TS_end_keypad_mode = tgetstr ("ke", address);
1414 TS_keypad_mode = tgetstr ("ks", address);
1415 LastLine = tgetstr ("ll", address);
1416 Right = tgetstr ("nd", address);
1417 Down = tgetstr ("do", address);
1418 if (!Down)
1419 Down = tgetstr ("nl", address); /* Obsolete name for "do" */
1420#ifdef VMS
1421 /* VMS puts a carriage return before each linefeed,
1422 so it is not safe to use linefeeds. */
1423 if (Down && Down[0] == '\n' && Down[1] == '\0')
1424 Down = 0;
1425#endif /* VMS */
1426 if (tgetflag ("bs"))
1427 Left = "\b"; /* can't possibly be longer! */
1428 else /* (Actually, "bs" is obsolete...) */
1429 Left = tgetstr ("le", address);
1430 if (!Left)
1431 Left = tgetstr ("bc", address); /* Obsolete name for "le" */
1432 TS_pad_char = tgetstr ("pc", address);
1433 TS_repeat = tgetstr ("rp", address);
1434 TS_end_standout_mode = tgetstr ("se", address);
1435 TS_fwd_scroll = tgetstr ("sf", address);
1436 TS_standout_mode = tgetstr ("so", address);
1437 TS_rev_scroll = tgetstr ("sr", address);
1438 Wcm.cm_tab = tgetstr ("ta", address);
1439 TS_end_termcap_modes = tgetstr ("te", address);
1440 TS_termcap_modes = tgetstr ("ti", address);
1441 Up = tgetstr ("up", address);
1442 TS_visible_bell = tgetstr ("vb", address);
1443 TS_end_visual_mode = tgetstr ("ve", address);
1444 TS_visual_mode = tgetstr ("vs", address);
1445 TS_set_window = tgetstr ("wi", address);
1446 MultiUp = tgetstr ("UP", address);
1447 MultiDown = tgetstr ("DO", address);
1448 MultiLeft = tgetstr ("LE", address);
1449 MultiRight = tgetstr ("RI", address);
1450
1451 AutoWrap = tgetflag ("am");
ff11dfa1 1452 memory_below_frame = tgetflag ("db");
08a24c47
JB
1453 TF_hazeltine = tgetflag ("hz");
1454 must_write_spaces = tgetflag ("in");
1455 meta_key = tgetflag ("km") || tgetflag ("MT");
1456 TF_insmode_motion = tgetflag ("mi");
1457 TF_standout_motion = tgetflag ("ms");
1458 TF_underscore = tgetflag ("ul");
1459 MagicWrap = tgetflag ("xn");
1460 TF_xs = tgetflag ("xs");
1461 TF_teleray = tgetflag ("xt");
1462
5c2c7893
JB
1463 term_get_fkeys (address);
1464
ff11dfa1
JB
1465 /* Get frame size from system, or else from termcap. */
1466 get_frame_size (&FRAME_WIDTH (selected_frame),
1467 &FRAME_HEIGHT (selected_frame));
1468 if (FRAME_WIDTH (selected_frame) <= 0)
1469 FRAME_WIDTH (selected_frame) = tgetnum ("co");
1470 if (FRAME_HEIGHT (selected_frame) <= 0)
1471 FRAME_HEIGHT (selected_frame) = tgetnum ("li");
08a24c47
JB
1472
1473 min_padding_speed = tgetnum ("pb");
1474 TN_standout_width = tgetnum ("sg");
1475 TabWidth = tgetnum ("tw");
1476
1477#ifdef VMS
1478 /* These capabilities commonly use ^J.
1479 I don't know why, but sending them on VMS does not work;
1480 it causes following spaces to be lost, sometimes.
1481 For now, the simplest fix is to avoid using these capabilities ever. */
1482 if (Down && Down[0] == '\n')
1483 Down = 0;
1484#endif /* VMS */
1485
1486 if (!TS_bell)
1487 TS_bell = "\07";
1488
1489 if (!TS_fwd_scroll)
1490 TS_fwd_scroll = Down;
1491
1492 PC = TS_pad_char ? *TS_pad_char : 0;
1493
1494 if (TabWidth < 0)
1495 TabWidth = 8;
1496
1497/* Turned off since /etc/termcap seems to have :ta= for most terminals
1498 and newer termcap doc does not seem to say there is a default.
1499 if (!Wcm.cm_tab)
1500 Wcm.cm_tab = "\t";
1501*/
1502
1503 if (TS_standout_mode == 0)
1504 {
1505 TN_standout_width = tgetnum ("ug");
1506 TS_end_standout_mode = tgetstr ("ue", address);
1507 TS_standout_mode = tgetstr ("us", address);
1508 }
1509
afd359c4
RS
1510 /* If no `se' string, try using a `me' string instead.
1511 If that fails, we can't use standout mode at all. */
1512 if (TS_end_standout_mode == 0)
1513 {
e4bfb3b6 1514 char *s = tgetstr ("me", address);
afd359c4
RS
1515 if (s != 0)
1516 TS_end_standout_mode = s;
1517 else
1518 TS_standout_mode = 0;
1519 }
1520
08a24c47
JB
1521 if (TF_teleray)
1522 {
1523 Wcm.cm_tab = 0;
1524 /* Teleray: most programs want a space in front of TS_standout_mode,
1525 but Emacs can do without it (and give one extra column). */
1526 TS_standout_mode = "\033RD";
1527 TN_standout_width = 1;
1528 /* But that means we cannot rely on ^M to go to column zero! */
1529 CR = 0;
1530 /* LF can't be trusted either -- can alter hpos */
1531 /* if move at column 0 thru a line with TS_standout_mode */
1532 Down = 0;
1533 }
1534
1535 /* Special handling for certain terminal types known to need it */
1536
1537 if (!strcmp (terminal_type, "supdup"))
1538 {
ff11dfa1 1539 memory_below_frame = 1;
08a24c47
JB
1540 Wcm.cm_losewrap = 1;
1541 }
1542 if (!strncmp (terminal_type, "c10", 3)
1543 || !strcmp (terminal_type, "perq"))
1544 {
1545 /* Supply a makeshift :wi string.
1546 This string is not valid in general since it works only
1547 for windows starting at the upper left corner;
1548 but that is all Emacs uses.
1549
ff11dfa1 1550 This string works only if the frame is using
08a24c47
JB
1551 the top of the video memory, because addressing is memory-relative.
1552 So first check the :ti string to see if that is true.
1553
1554 It would be simpler if the :wi string could go in the termcap
1555 entry, but it can't because it is not fully valid.
1556 If it were in the termcap entry, it would confuse other programs. */
1557 if (!TS_set_window)
1558 {
1559 p = TS_termcap_modes;
1560 while (*p && strcmp (p, "\033v "))
1561 p++;
1562 if (*p)
1563 TS_set_window = "\033v%C %C %C %C ";
1564 }
1565 /* Termcap entry often fails to have :in: flag */
1566 must_write_spaces = 1;
1567 /* :ti string typically fails to have \E^G! in it */
1568 /* This limits scope of insert-char to one line. */
1569 strcpy (area, TS_termcap_modes);
1570 strcat (area, "\033\007!");
1571 TS_termcap_modes = area;
1572 area += strlen (area) + 1;
1573 p = AbsPosition;
1574 /* Change all %+ parameters to %C, to handle
1575 values above 96 correctly for the C100. */
1576 while (*p)
1577 {
1578 if (p[0] == '%' && p[1] == '+')
1579 p[1] = 'C';
1580 p++;
1581 }
1582 }
1583
ff11dfa1
JB
1584 FrameRows = FRAME_HEIGHT (selected_frame);
1585 FrameCols = FRAME_WIDTH (selected_frame);
1586 specified_window = FRAME_HEIGHT (selected_frame);
08a24c47
JB
1587
1588 if (Wcm_init () == -1) /* can't do cursor motion */
1589#ifdef VMS
1590 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
1591It lacks the ability to position the cursor.\n\
1592If that is not the actual type of terminal you have, use either the\n\
1593DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
1594or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.\n",
1595 terminal_type);
1596#else
1597 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
1598It lacks the ability to position the cursor.\n\
1599If that is not the actual type of terminal you have,\n\
c5a9c3e6
RS
1600use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
1601`setenv TERM ...') to specify the correct type. It may be necessary\n\
1602to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.\n",
08a24c47
JB
1603 terminal_type);
1604#endif
ff11dfa1
JB
1605 if (FRAME_HEIGHT (selected_frame) <= 0
1606 || FRAME_WIDTH (selected_frame) <= 0)
1607 fatal ("The frame size has not been specified.");
08a24c47
JB
1608
1609 delete_in_insert_mode
1610 = TS_delete_mode && TS_insert_mode
1611 && !strcmp (TS_delete_mode, TS_insert_mode);
1612
1613 se_is_so = (TS_standout_mode
1614 && TS_end_standout_mode
1615 && !strcmp (TS_standout_mode, TS_end_standout_mode));
1616
1617 /* Remove width of standout marker from usable width of line */
1618 if (TN_standout_width > 0)
ff11dfa1 1619 FRAME_WIDTH (selected_frame) -= TN_standout_width;
08a24c47
JB
1620
1621 UseTabs = tabs_safe_p () && TabWidth == 8;
1622
1623 scroll_region_ok
1624 = (Wcm.cm_abs
1625 && (TS_set_window || TS_set_scroll_region || TS_set_scroll_region_1));
1626
1627 line_ins_del_ok = (((TS_ins_line || TS_ins_multi_lines)
1628 && (TS_del_line || TS_del_multi_lines))
1629 || (scroll_region_ok && TS_fwd_scroll && TS_rev_scroll));
1630
1631 char_ins_del_ok = ((TS_ins_char || TS_insert_mode
1632 || TS_pad_inserted_char || TS_ins_multi_chars)
1633 && (TS_del_char || TS_del_multi_chars));
1634
1635 fast_clear_end_of_line = TS_clr_line != 0;
1636
1637 init_baud_rate ();
1638 if (read_socket_hook) /* Baudrate is somewhat */
1639 /* meaningless in this case */
1640 baud_rate = 9600;
20a558dc 1641
a3c87d4e
JB
1642 FRAME_CAN_HAVE_SCROLL_BARS (selected_frame) = 0;
1643 FRAME_HAS_VERTICAL_SCROLL_BARS (selected_frame) = 0;
08a24c47
JB
1644}
1645
1646/* VARARGS 1 */
1647fatal (str, arg1, arg2)
4746118a 1648 char *str, *arg1, *arg2;
08a24c47
JB
1649{
1650 fprintf (stderr, "emacs: ");
1651 fprintf (stderr, str, arg1, arg2);
1652 fflush (stderr);
1653 exit (1);
1654}
07c57952
KH
1655
1656syms_of_term ()
1657{
1658 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
1659 "Non-nil means the system uses terminfo rather than termcap.\n\
1660This variable can be used by terminal emulator packages.");
1661#ifdef TERMINFO
1662 system_uses_terminfo = 1;
1663#else
1664 system_uses_terminfo = 0;
1665#endif
1666}