Comment change.
[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
21#include <stdio.h>
22#include <ctype.h>
18160b98 23#include <config.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
JB
287char *tparam ();
288\f
289ring_bell ()
290{
1820044b 291 if (! FRAME_TERMCAP_P (selected_frame))
08a24c47
JB
292 {
293 (*ring_bell_hook) ();
294 return;
295 }
296 OUTPUT (TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell);
297}
298
299set_terminal_modes ()
300{
1820044b 301 if (! FRAME_TERMCAP_P (selected_frame))
08a24c47
JB
302 {
303 (*set_terminal_modes_hook) ();
304 return;
305 }
306 OUTPUT_IF (TS_termcap_modes);
307 OUTPUT_IF (TS_visual_mode);
308 OUTPUT_IF (TS_keypad_mode);
309 losecursor ();
310}
311
312reset_terminal_modes ()
313{
1820044b 314 if (! FRAME_TERMCAP_P (selected_frame))
08a24c47
JB
315 {
316 (*reset_terminal_modes_hook) ();
317 return;
318 }
319 if (TN_standout_width < 0)
320 turn_off_highlight ();
321 turn_off_insert ();
322 OUTPUT_IF (TS_end_keypad_mode);
323 OUTPUT_IF (TS_end_visual_mode);
324 OUTPUT_IF (TS_end_termcap_modes);
325 /* Output raw CR so kernel can track the cursor hpos. */
326 /* But on magic-cookie terminals this can erase an end-standout marker and
ff11dfa1 327 cause the rest of the frame to be in standout, so move down first. */
08a24c47
JB
328 if (TN_standout_width >= 0)
329 cmputc ('\n');
330 cmputc ('\r');
331}
332
ff11dfa1
JB
333update_begin (f)
334 FRAME_PTR f;
08a24c47 335{
ff11dfa1 336 updating_frame = f;
1820044b 337 if (! FRAME_TERMCAP_P (updating_frame))
ff11dfa1 338 (*update_begin_hook) (f);
08a24c47
JB
339}
340
ff11dfa1
JB
341update_end (f)
342 FRAME_PTR f;
08a24c47 343{
1820044b 344 if (! FRAME_TERMCAP_P (updating_frame))
08a24c47 345 {
7a8e3e30 346 (*update_end_hook) (f);
cc4ee3c7 347 updating_frame = 0;
08a24c47
JB
348 return;
349 }
350 turn_off_insert ();
351 background_highlight ();
352 standout_requested = 0;
ff11dfa1 353 updating_frame = 0;
08a24c47
JB
354}
355
356set_terminal_window (size)
357 int size;
358{
1820044b 359 if (! FRAME_TERMCAP_P (updating_frame))
08a24c47
JB
360 {
361 (*set_terminal_window_hook) (size);
362 return;
363 }
ff11dfa1 364 specified_window = size ? size : FRAME_HEIGHT (selected_frame);
08a24c47
JB
365 if (!scroll_region_ok)
366 return;
367 set_scroll_region (0, specified_window);
368}
369
370set_scroll_region (start, stop)
371 int start, stop;
372{
373 char *buf;
374 if (TS_set_scroll_region)
375 {
376 buf = tparam (TS_set_scroll_region, 0, 0, start, stop - 1);
377 }
378 else if (TS_set_scroll_region_1)
379 {
380 buf = tparam (TS_set_scroll_region_1, 0, 0,
ff11dfa1
JB
381 FRAME_HEIGHT (selected_frame), start,
382 FRAME_HEIGHT (selected_frame) - stop,
383 FRAME_HEIGHT (selected_frame));
08a24c47
JB
384 }
385 else
386 {
ff11dfa1 387 buf = tparam (TS_set_window, 0, 0, start, 0, stop, FRAME_WIDTH (selected_frame));
08a24c47
JB
388 }
389 OUTPUT (buf);
9ac0d9e0 390 xfree (buf);
08a24c47
JB
391 losecursor ();
392}
393\f
394turn_on_insert ()
395{
396 if (!insert_mode)
397 OUTPUT (TS_insert_mode);
398 insert_mode = 1;
399}
400
401turn_off_insert ()
402{
403 if (insert_mode)
404 OUTPUT (TS_end_insert_mode);
405 insert_mode = 0;
406}
407\f
408/* Handle highlighting when TN_standout_width (termcap sg) is not specified.
409 In these terminals, output is affected by the value of standout
410 mode when the output is written.
411
412 These functions are called on all terminals, but do nothing
413 on terminals whose standout mode does not work that way. */
414
415turn_off_highlight ()
416{
417 if (TN_standout_width < 0)
418 {
419 if (standout_mode)
420 OUTPUT_IF (TS_end_standout_mode);
421 standout_mode = 0;
422 }
423}
424
425turn_on_highlight ()
426{
427 if (TN_standout_width < 0)
428 {
429 if (!standout_mode)
430 OUTPUT_IF (TS_standout_mode);
431 standout_mode = 1;
432 }
433}
434
435/* Set standout mode to the state it should be in for
436 empty space inside windows. What this is,
437 depends on the user option inverse-video. */
438
439background_highlight ()
440{
441 if (TN_standout_width >= 0)
442 return;
443 if (inverse_video)
444 turn_on_highlight ();
445 else
446 turn_off_highlight ();
447}
448
449/* Set standout mode to the mode specified for the text to be output. */
450
451static
452highlight_if_desired ()
453{
454 if (TN_standout_width >= 0)
455 return;
456 if (!inverse_video == !standout_requested)
457 turn_off_highlight ();
458 else
459 turn_on_highlight ();
460}
461\f
462/* Handle standout mode for terminals in which TN_standout_width >= 0.
463 On these terminals, standout is controlled by markers that
ff11dfa1 464 live inside the terminal's memory. TN_standout_width is the width
08a24c47
JB
465 that the marker occupies in memory. Standout runs from the marker
466 to the end of the line on some terminals, or to the next
467 turn-off-standout marker (TS_end_standout_mode) string
468 on other terminals. */
469
470/* Write a standout marker or end-standout marker at the front of the line
471 at vertical position vpos. */
472
473write_standout_marker (flag, vpos)
474 int flag, vpos;
475{
476 if (flag || (TS_end_standout_mode && !TF_teleray && !se_is_so
477 && !(TF_xs && TN_standout_width == 0)))
478 {
479 cmgoto (vpos, 0);
480 cmplus (TN_standout_width);
481 OUTPUT (flag ? TS_standout_mode : TS_end_standout_mode);
482 chars_wasted[curY] = TN_standout_width | 0100;
483 }
484}
485\f
486/* External interface to control of standout mode.
487 Call this when about to modify line at position VPOS
488 and not change whether it is highlighted. */
489
490reassert_line_highlight (highlight, vpos)
491 int highlight;
492 int vpos;
493{
1820044b 494 if (! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
08a24c47
JB
495 {
496 (*reassert_line_highlight_hook) (highlight, vpos);
497 return;
498 }
499 if (TN_standout_width < 0)
500 /* Handle terminals where standout takes affect at output time */
501 standout_requested = highlight;
502 else if (chars_wasted[vpos] == 0)
503 /* For terminals with standout markers, write one on this line
504 if there isn't one already. */
505 write_standout_marker (highlight, vpos);
506}
507
508/* Call this when about to modify line at position VPOS
509 and change whether it is highlighted. */
510
511change_line_highlight (new_highlight, vpos, first_unused_hpos)
512 int new_highlight, vpos, first_unused_hpos;
513{
514 standout_requested = new_highlight;
1820044b 515 if (! FRAME_TERMCAP_P (updating_frame))
08a24c47
JB
516 {
517 (*change_line_highlight_hook) (new_highlight, vpos, first_unused_hpos);
518 return;
519 }
520
521 cursor_to (vpos, 0);
522
523 if (TN_standout_width < 0)
524 background_highlight ();
525 /* If line starts with a marker, delete the marker */
526 else if (TS_clr_line && chars_wasted[curY])
527 {
528 turn_off_insert ();
529 /* On Teleray, make sure to erase the SO marker. */
530 if (TF_teleray)
531 {
ff11dfa1 532 cmgoto (curY - 1, FRAME_WIDTH (selected_frame) - 4);
08a24c47
JB
533 OUTPUT ("\033S");
534 curY++; /* ESC S moves to next line where the TS_standout_mode was */
535 curX = 0;
536 }
537 else
538 cmgoto (curY, 0); /* reposition to kill standout marker */
539 }
540 clear_end_of_line_raw (first_unused_hpos);
541 reassert_line_highlight (new_highlight, curY);
542}
543\f
544
545/* Move to absolute position, specified origin 0 */
546
547cursor_to (row, col)
4746118a 548 int row, col;
08a24c47 549{
1820044b 550 if (! FRAME_TERMCAP_P ((updating_frame
ff11dfa1
JB
551 ? updating_frame
552 : selected_frame))
08a24c47
JB
553 && cursor_to_hook)
554 {
555 (*cursor_to_hook) (row, col);
556 return;
557 }
558
559 col += chars_wasted[row] & 077;
560 if (curY == row && curX == col)
561 return;
562 if (!TF_standout_motion)
563 background_highlight ();
564 if (!TF_insmode_motion)
565 turn_off_insert ();
566 cmgoto (row, col);
567}
568
569/* Similar but don't take any account of the wasted characters. */
570
571raw_cursor_to (row, col)
4746118a 572 int row, col;
08a24c47 573{
1820044b 574 if (! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
08a24c47
JB
575 {
576 (*raw_cursor_to_hook) (row, col);
577 return;
578 }
579 if (curY == row && curX == col)
580 return;
581 if (!TF_standout_motion)
582 background_highlight ();
583 if (!TF_insmode_motion)
584 turn_off_insert ();
585 cmgoto (row, col);
586}
587\f
588/* Erase operations */
589
ff11dfa1 590/* clear from cursor to end of frame */
08a24c47
JB
591clear_to_end ()
592{
593 register int i;
594
1820044b 595 if (clear_to_end_hook && FRAME_TERMCAP_P (updating_frame))
08a24c47
JB
596 {
597 (*clear_to_end_hook) ();
598 return;
599 }
600 if (TS_clr_to_bottom)
601 {
602 background_highlight ();
603 OUTPUT (TS_clr_to_bottom);
ff11dfa1 604 bzero (chars_wasted + curY, FRAME_HEIGHT (selected_frame) - curY);
08a24c47
JB
605 }
606 else
607 {
ff11dfa1 608 for (i = curY; i < FRAME_HEIGHT (selected_frame); i++)
08a24c47
JB
609 {
610 cursor_to (i, 0);
ff11dfa1 611 clear_end_of_line_raw (FRAME_WIDTH (selected_frame));
08a24c47
JB
612 }
613 }
614}
615
ff11dfa1 616/* Clear entire frame */
08a24c47 617
ff11dfa1 618clear_frame ()
08a24c47 619{
ff11dfa1 620 if (clear_frame_hook
1820044b 621 && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
08a24c47 622 {
ff11dfa1 623 (*clear_frame_hook) ();
08a24c47
JB
624 return;
625 }
ff11dfa1 626 if (TS_clr_frame)
08a24c47
JB
627 {
628 background_highlight ();
ff11dfa1
JB
629 OUTPUT (TS_clr_frame);
630 bzero (chars_wasted, FRAME_HEIGHT (selected_frame));
08a24c47
JB
631 cmat (0, 0);
632 }
633 else
634 {
635 cursor_to (0, 0);
636 clear_to_end ();
637 }
638}
639
640/* Clear to end of line, but do not clear any standout marker.
641 Assumes that the cursor is positioned at a character of real text,
642 which implies it cannot be before a standout marker
643 unless the marker has zero width.
644
645 Note that the cursor may be moved. */
646
647clear_end_of_line (first_unused_hpos)
648 int first_unused_hpos;
649{
a796ac82 650 static GLYPH buf = SPACEGLYPH;
1820044b 651 if (FRAME_TERMCAP_P (selected_frame)
08a24c47 652 && TN_standout_width == 0 && curX == 0 && chars_wasted[curY] != 0)
a796ac82 653 write_glyphs (&buf, 1);
08a24c47
JB
654 clear_end_of_line_raw (first_unused_hpos);
655}
656
657/* Clear from cursor to end of line.
658 Assume that the line is already clear starting at column first_unused_hpos.
659 If the cursor is at a standout marker, erase the marker.
660
661 Note that the cursor may be moved, on terminals lacking a `ce' string. */
662
663clear_end_of_line_raw (first_unused_hpos)
664 int first_unused_hpos;
665{
666 register int i;
667
668 if (clear_end_of_line_hook
1820044b 669 && ! FRAME_TERMCAP_P ((updating_frame
ff11dfa1
JB
670 ? updating_frame
671 : selected_frame)))
08a24c47
JB
672 {
673 (*clear_end_of_line_hook) (first_unused_hpos);
674 return;
675 }
676
677 first_unused_hpos += chars_wasted[curY] & 077;
678 if (curX >= first_unused_hpos)
679 return;
680 /* Notice if we are erasing a magic cookie */
681 if (curX == 0)
682 chars_wasted[curY] = 0;
683 background_highlight ();
684 if (TS_clr_line)
685 {
686 OUTPUT1 (TS_clr_line);
687 }
688 else
689 { /* have to do it the hard way */
690 turn_off_insert ();
691
692 /* Do not write in last row last col with Autowrap on. */
ff11dfa1
JB
693 if (AutoWrap && curY == FRAME_HEIGHT (selected_frame) - 1
694 && first_unused_hpos == FRAME_WIDTH (selected_frame))
08a24c47
JB
695 first_unused_hpos--;
696
697 for (i = curX; i < first_unused_hpos; i++)
698 {
699 if (termscript)
700 fputc (' ', termscript);
701 putchar (' ');
702 }
703 cmplus (first_unused_hpos - curX);
704 }
705}
706\f
707
708write_glyphs (string, len)
709 register GLYPH *string;
710 register int len;
711{
712 register GLYPH g;
713 register int tlen = GLYPH_TABLE_LENGTH;
714 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
715
716 if (write_glyphs_hook
1820044b 717 && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
08a24c47
JB
718 {
719 (*write_glyphs_hook) (string, len);
720 return;
721 }
722
723 highlight_if_desired ();
724 turn_off_insert ();
725
726 /* Don't dare write in last column of bottom line, if AutoWrap,
ff11dfa1 727 since that would scroll the whole frame on some terminals. */
08a24c47
JB
728
729 if (AutoWrap
ff11dfa1 730 && curY + 1 == FRAME_HEIGHT (selected_frame)
08a24c47 731 && (curX + len - (chars_wasted[curY] & 077)
ff11dfa1 732 == FRAME_WIDTH (selected_frame)))
08a24c47
JB
733 len --;
734
735 cmplus (len);
736 while (--len >= 0)
737 {
738 g = *string++;
739 /* Check quickly for G beyond length of table.
740 That implies it isn't an alias and is simple. */
741 if (g >= tlen)
742 {
743 simple:
744 putc (g & 0xff, stdout);
745 if (ferror (stdout))
746 clearerr (stdout);
747 if (termscript)
748 putc (g & 0xff, termscript);
749 }
750 else
751 {
752 /* G has an entry in Vglyph_table,
753 so process any alias and then test for simpleness. */
754 while (GLYPH_ALIAS_P (tbase, tlen, g))
755 g = GLYPH_ALIAS (tbase, g);
756 if (GLYPH_SIMPLE_P (tbase, tlen, g))
757 goto simple;
758 else
759 {
760 /* Here if G (or its definition as an alias) is not simple. */
761 fwrite (GLYPH_STRING (tbase, g), 1, GLYPH_LENGTH (tbase, g),
762 stdout);
763 if (ferror (stdout))
764 clearerr (stdout);
765 if (termscript)
766 fwrite (GLYPH_STRING (tbase, g), 1, GLYPH_LENGTH (tbase, g),
767 termscript);
768 }
769 }
770 }
771}
772
773/* If start is zero, insert blanks instead of a string at start */
774
775insert_glyphs (start, len)
776 register GLYPH *start;
777 register int len;
778{
779 char *buf;
780 register GLYPH g;
781 register int tlen = GLYPH_TABLE_LENGTH;
782 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
783
1820044b 784 if (insert_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame))
08a24c47
JB
785 {
786 (*insert_glyphs_hook) (start, len);
787 return;
788 }
789 highlight_if_desired ();
790
791 if (TS_ins_multi_chars)
792 {
793 buf = tparam (TS_ins_multi_chars, 0, 0, len);
794 OUTPUT1 (buf);
9ac0d9e0 795 xfree (buf);
08a24c47
JB
796 if (start)
797 write_glyphs (start, len);
798 return;
799 }
800
801 turn_on_insert ();
802 cmplus (len);
803 while (--len >= 0)
804 {
805 OUTPUT1_IF (TS_ins_char);
806 if (!start)
807 g = SPACEGLYPH;
808 else
809 g = *start++;
810
811 if (GLYPH_SIMPLE_P (tbase, tlen, g))
812 {
813 putc (g & 0xff, stdout);
814 if (ferror (stdout))
815 clearerr (stdout);
816 if (termscript)
817 putc (g & 0xff, termscript);
818 }
819 else
820 {
821 fwrite (GLYPH_STRING (tbase, g), 1, GLYPH_LENGTH (tbase, g), stdout);
822 if (ferror (stdout))
823 clearerr (stdout);
824 if (termscript)
825 fwrite (GLYPH_STRING (tbase, g), 1, GLYPH_LENGTH (tbase, g),
826 termscript);
827 }
828
829 OUTPUT1_IF (TS_pad_inserted_char);
830 }
831}
832
833delete_glyphs (n)
834 register int n;
835{
836 char *buf;
837 register int i;
838
1820044b 839 if (delete_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame))
08a24c47
JB
840 {
841 (*delete_glyphs_hook) (n);
842 return;
843 }
844
845 if (delete_in_insert_mode)
846 {
847 turn_on_insert ();
848 }
849 else
850 {
851 turn_off_insert ();
852 OUTPUT_IF (TS_delete_mode);
853 }
854
855 if (TS_del_multi_chars)
856 {
857 buf = tparam (TS_del_multi_chars, 0, 0, n);
858 OUTPUT1 (buf);
9ac0d9e0 859 xfree (buf);
08a24c47
JB
860 }
861 else
862 for (i = 0; i < n; i++)
863 OUTPUT1 (TS_del_char);
864 if (!delete_in_insert_mode)
865 OUTPUT_IF (TS_end_delete_mode);
866}
867\f
868/* Insert N lines at vpos VPOS. If N is negative, delete -N lines. */
869
870ins_del_lines (vpos, n)
871 int vpos, n;
872{
873 char *multi = n > 0 ? TS_ins_multi_lines : TS_del_multi_lines;
874 char *single = n > 0 ? TS_ins_line : TS_del_line;
875 char *scroll = n > 0 ? TS_rev_scroll : TS_fwd_scroll;
876
877 register int i = n > 0 ? n : -n;
878 register char *buf;
879
1820044b 880 if (ins_del_lines_hook && ! FRAME_TERMCAP_P (updating_frame))
08a24c47
JB
881 {
882 (*ins_del_lines_hook) (vpos, n);
883 return;
884 }
885
886 /* If the lines below the insertion are being pushed
887 into the end of the window, this is the same as clearing;
888 and we know the lines are already clear, since the matching
889 deletion has already been done. So can ignore this. */
890 /* If the lines below the deletion are blank lines coming
891 out of the end of the window, don't bother,
892 as there will be a matching inslines later that will flush them. */
893 if (scroll_region_ok && vpos + i >= specified_window)
894 return;
ff11dfa1 895 if (!memory_below_frame && vpos + i >= FRAME_HEIGHT (selected_frame))
08a24c47
JB
896 return;
897
898 if (multi)
899 {
900 raw_cursor_to (vpos, 0);
901 background_highlight ();
902 buf = tparam (multi, 0, 0, i);
903 OUTPUT (buf);
9ac0d9e0 904 xfree (buf);
08a24c47
JB
905 }
906 else if (single)
907 {
908 raw_cursor_to (vpos, 0);
909 background_highlight ();
910 while (--i >= 0)
911 OUTPUT (single);
912 if (TF_teleray)
913 curX = 0;
914 }
915 else
916 {
917 set_scroll_region (vpos, specified_window);
918 if (n < 0)
919 raw_cursor_to (specified_window - 1, 0);
920 else
921 raw_cursor_to (vpos, 0);
922 background_highlight ();
923 while (--i >= 0)
924 OUTPUTL (scroll, specified_window - vpos);
925 set_scroll_region (0, specified_window);
926 }
927
928 if (TN_standout_width >= 0)
929 {
930 register lower_limit
931 = (scroll_region_ok
932 ? specified_window
ff11dfa1 933 : FRAME_HEIGHT (selected_frame));
08a24c47
JB
934
935 if (n < 0)
936 {
937 bcopy (&chars_wasted[vpos - n], &chars_wasted[vpos],
938 lower_limit - vpos + n);
939 bzero (&chars_wasted[lower_limit + n], - n);
940 }
941 else
942 {
943 bcopy (&chars_wasted[vpos], &copybuf[vpos], lower_limit - vpos - n);
944 bcopy (&copybuf[vpos], &chars_wasted[vpos + n],
945 lower_limit - vpos - n);
946 bzero (&chars_wasted[vpos], n);
947 }
948 }
ff11dfa1 949 if (!scroll_region_ok && memory_below_frame && n < 0)
08a24c47 950 {
ff11dfa1 951 cursor_to (FRAME_HEIGHT (selected_frame) + n, 0);
08a24c47
JB
952 clear_to_end ();
953 }
954}
955\f
956/* Compute cost of sending "str", in characters,
957 not counting any line-dependent padding. */
958
959int
960string_cost (str)
961 char *str;
962{
963 cost = 0;
964 if (str)
965 tputs (str, 0, evalcost);
966 return cost;
967}
968
969/* Compute cost of sending "str", in characters,
970 counting any line-dependent padding at one line. */
971
972static int
973string_cost_one_line (str)
974 char *str;
975{
976 cost = 0;
977 if (str)
978 tputs (str, 1, evalcost);
979 return cost;
980}
981
982/* Compute per line amount of line-dependent padding,
983 in tenths of characters. */
984
985int
986per_line_cost (str)
987 register char *str;
988{
989 cost = 0;
990 if (str)
991 tputs (str, 0, evalcost);
992 cost = - cost;
993 if (str)
994 tputs (str, 10, evalcost);
995 return cost;
996}
997
998#ifndef old
999/* char_ins_del_cost[n] is cost of inserting N characters.
1000 char_ins_del_cost[-n] is cost of deleting N characters. */
1001
1002int *char_ins_del_vector;
1003
ff11dfa1 1004#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WIDTH ((f))])
08a24c47
JB
1005#endif
1006
1007/* ARGSUSED */
1008static void
ff11dfa1
JB
1009calculate_ins_del_char_costs (frame)
1010 FRAME_PTR frame;
08a24c47
JB
1011{
1012 int ins_startup_cost, del_startup_cost;
1013 int ins_cost_per_char, del_cost_per_char;
1014 register int i;
1015 register int *p;
1016
1017 if (TS_ins_multi_chars)
1018 {
1019 ins_cost_per_char = 0;
1020 ins_startup_cost = string_cost_one_line (TS_ins_multi_chars);
1021 }
1022 else if (TS_ins_char || TS_pad_inserted_char
1023 || (TS_insert_mode && TS_end_insert_mode))
1024 {
1025 ins_startup_cost = (30 * (string_cost (TS_insert_mode)
1026 + string_cost (TS_end_insert_mode))) / 100;
1027 ins_cost_per_char = (string_cost_one_line (TS_ins_char)
1028 + string_cost_one_line (TS_pad_inserted_char));
1029 }
1030 else
1031 {
1032 ins_startup_cost = 9999;
1033 ins_cost_per_char = 0;
1034 }
1035
1036 if (TS_del_multi_chars)
1037 {
1038 del_cost_per_char = 0;
1039 del_startup_cost = string_cost_one_line (TS_del_multi_chars);
1040 }
1041 else if (TS_del_char)
1042 {
1043 del_startup_cost = (string_cost (TS_delete_mode)
1044 + string_cost (TS_end_delete_mode));
1045 if (delete_in_insert_mode)
1046 del_startup_cost /= 2;
1047 del_cost_per_char = string_cost_one_line (TS_del_char);
1048 }
1049 else
1050 {
1051 del_startup_cost = 9999;
1052 del_cost_per_char = 0;
1053 }
1054
1055 /* Delete costs are at negative offsets */
ff11dfa1
JB
1056 p = &char_ins_del_cost (frame)[0];
1057 for (i = FRAME_WIDTH (selected_frame); --i >= 0;)
08a24c47
JB
1058 *--p = (del_startup_cost += del_cost_per_char);
1059
1060 /* Doing nothing is free */
ff11dfa1 1061 p = &char_ins_del_cost (frame)[0];
08a24c47
JB
1062 *p++ = 0;
1063
1064 /* Insert costs are at positive offsets */
ff11dfa1 1065 for (i = FRAME_WIDTH (frame); --i >= 0;)
08a24c47
JB
1066 *p++ = (ins_startup_cost += ins_cost_per_char);
1067}
1068
1069#ifdef HAVE_X_WINDOWS
e7308e06 1070extern int x_screen_planes;
08a24c47
JB
1071#endif
1072
a790fee2
JB
1073extern do_line_insertion_deletion_costs ();
1074
ff11dfa1
JB
1075calculate_costs (frame)
1076 FRAME_PTR frame;
08a24c47 1077{
ff11dfa1 1078 register char *f = TS_set_scroll_region ?
08a24c47
JB
1079 TS_set_scroll_region
1080 : TS_set_scroll_region_1;
1081
1082 if (dont_calculate_costs)
1083 return;
1084
1085#ifdef HAVE_X_WINDOWS
1820044b 1086 if (FRAME_X_P (frame))
08a24c47 1087 {
ff11dfa1 1088 do_line_insertion_deletion_costs (frame, 0, ".5*", 0, ".5*",
e7308e06 1089 0, 0, x_screen_planes);
08a24c47
JB
1090 return;
1091 }
1092#endif
1093
1094 /* These variables are only used for terminal stuff. They are allocated
ff11dfa1 1095 once for the terminal frame of X-windows emacs, but not used afterwards.
08a24c47
JB
1096
1097 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1098 X turns off char_ins_del_ok.
1099
1100 chars_wasted and copybuf are only used here in term.c in cases where
1101 the term hook isn't called. */
1102
1103 if (chars_wasted != 0)
ff11dfa1 1104 chars_wasted = (char *) xrealloc (chars_wasted, FRAME_HEIGHT (frame));
08a24c47 1105 else
ff11dfa1 1106 chars_wasted = (char *) xmalloc (FRAME_HEIGHT (frame));
08a24c47
JB
1107
1108 if (copybuf != 0)
ff11dfa1 1109 copybuf = (char *) xrealloc (copybuf, FRAME_HEIGHT (frame));
08a24c47 1110 else
ff11dfa1 1111 copybuf = (char *) xmalloc (FRAME_HEIGHT (frame));
08a24c47
JB
1112
1113 if (char_ins_del_vector != 0)
1114 char_ins_del_vector
1115 = (int *) xrealloc (char_ins_del_vector,
1116 (sizeof (int)
ff11dfa1 1117 + 2 * FRAME_WIDTH (frame) * sizeof (int)));
08a24c47
JB
1118 else
1119 char_ins_del_vector
1120 = (int *) xmalloc (sizeof (int)
ff11dfa1 1121 + 2 * FRAME_WIDTH (frame) * sizeof (int));
08a24c47 1122
ff11dfa1
JB
1123 bzero (chars_wasted, FRAME_HEIGHT (frame));
1124 bzero (copybuf, FRAME_HEIGHT (frame));
08a24c47 1125 bzero (char_ins_del_vector, (sizeof (int)
ff11dfa1 1126 + 2 * FRAME_WIDTH (frame) * sizeof (int)));
08a24c47 1127
ff11dfa1
JB
1128 if (f && (!TS_ins_line && !TS_del_line))
1129 do_line_insertion_deletion_costs (frame,
08a24c47
JB
1130 TS_rev_scroll, TS_ins_multi_lines,
1131 TS_fwd_scroll, TS_del_multi_lines,
ff11dfa1 1132 f, f, 1);
08a24c47 1133 else
ff11dfa1 1134 do_line_insertion_deletion_costs (frame,
08a24c47
JB
1135 TS_ins_line, TS_ins_multi_lines,
1136 TS_del_line, TS_del_multi_lines,
1137 0, 0, 1);
1138
ff11dfa1 1139 calculate_ins_del_char_costs (frame);
08a24c47
JB
1140
1141 /* Don't use TS_repeat if its padding is worse than sending the chars */
1142 if (TS_repeat && per_line_cost (TS_repeat) * baud_rate < 9000)
1143 RPov = string_cost (TS_repeat);
1144 else
ff11dfa1 1145 RPov = FRAME_WIDTH (frame) * 2;
08a24c47
JB
1146
1147 cmcostinit (); /* set up cursor motion costs */
1148}
1149\f
a796ac82
JB
1150struct fkey_table {
1151 char *cap, *name;
1152};
1153
01d8deb0
ER
1154 /* Termcap capability names that correspond directly to X keysyms.
1155 Some of these (marked "terminfo") aren't supplied by old-style
1156 (Berkeley) termcap entries. They're listed in X keysym order;
1157 except we put the keypad keys first, so that if they clash with
1158 other keys (as on the IBM PC keyboard) they get overridden.
1159 */
1160
a796ac82 1161static struct fkey_table keys[] = {
01d8deb0
ER
1162 "kh", "home", /* termcap */
1163 "kl", "left", /* termcap */
1164 "ku", "up", /* termcap */
1165 "kr", "right", /* termcap */
1166 "kd", "down", /* termcap */
1167 "%8", "prior", /* terminfo */
1168 "%5", "next", /* terminfo */
1169 "@7", "end", /* terminfo */
1170 "@1", "begin", /* terminfo */
1171 "*6", "select", /* terminfo */
1172 "%9", "print", /* terminfo */
1173 "@4", "execute", /* terminfo --- actually the `command' key */
1174 /*
1175 * "insert" --- see below
1176 */
1177 "&8", "undo", /* terminfo */
1178 "%0", "redo", /* terminfo */
1179 "%7", "menu", /* terminfo --- actually the `options' key */
1180 "@0", "find", /* terminfo */
1181 "@2", "cancel", /* terminfo */
1182 "%1", "help", /* terminfo */
1183 /*
1184 * "break" goes here, but can't be reliably intercepted with termcap
1185 */
1186 "&4", "reset", /* terminfo --- actually `restart' */
1187 /*
1188 * "system" and "user" --- no termcaps
1189 */
1190 "kE", "clearline", /* terminfo */
1191 "kA", "insertline", /* terminfo */
1192 "kL", "deleteline", /* terminfo */
1193 "kI", "insertchar", /* terminfo */
1194 "kD", "deletechar", /* terminfo */
1195 "kB", "backtab", /* terminfo */
1196 /*
1197 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1198 */
1199 "@8", "kp-enter", /* terminfo */
1200 /*
1201 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1202 * "kp-multiply", "kp-add", "kp-separator",
1203 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1204 * --- no termcaps for any of these.
1205 */
1206 "K4", "kp-1", /* terminfo */
1207 /*
1208 * "kp-2" --- no termcap
1209 */
1210 "K5", "kp-3", /* terminfo */
1211 /*
1212 * "kp-4" --- no termcap
1213 */
1214 "K2", "kp-5", /* terminfo */
1215 /*
1216 * "kp-6" --- no termcap
1217 */
1218 "K1", "kp-7", /* terminfo */
1219 /*
1220 * "kp-8" --- no termcap
1221 */
1222 "K3", "kp-9", /* terminfo */
1223 /*
1224 * "kp-equal" --- no termcap
1225 */
1226 "k1", "f1",
1227 "k2", "f2",
1228 "k3", "f3",
1229 "k4", "f4",
1230 "k5", "f5",
1231 "k6", "f6",
1232 "k7", "f7",
1233 "k8", "f8",
1234 "k9", "f9",
a796ac82
JB
1235 };
1236
f2a00342
RM
1237static char **term_get_fkeys_arg;
1238static Lisp_Object term_get_fkeys_1 ();
465db27b 1239
01d8deb0
ER
1240/* Find the escape codes sent by the function keys for Vfunction_key_map.
1241 This function scans the termcap function key sequence entries, and
1242 adds entries to Vfunction_key_map for each function key it finds. */
1243
5c2c7893
JB
1244void
1245term_get_fkeys (address)
1246 char **address;
f2a00342
RM
1247{
1248 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1249 errors during the call. The only errors should be from Fdefine_key
1250 when given a key sequence containing an invalid prefix key. If the
1251 termcap defines function keys which use a prefix that is already bound
1252 to a command by the default bindings, we should silently ignore that
1253 function key specification, rather than giving the user an error and
1254 refusing to run at all on such a terminal. */
1255
1256 extern Lisp_Object Fidentity ();
1257 static Lisp_Object term_get_fkeys_1 ();
1258 term_get_fkeys_arg = address;
1259 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1260}
1261
1262static Lisp_Object
1263term_get_fkeys_1 ()
5c2c7893
JB
1264{
1265 extern char *tgetstr ();
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
1366 extern char *tgetstr ();
1367
1368 Wcm_clear ();
1369 dont_calculate_costs = 0;
1370
1371 status = tgetent (buffer, terminal_type);
1372 if (status < 0)
1373 fatal ("Cannot open termcap database file.\n");
1374 if (status == 0)
c5a9c3e6
RS
1375 fatal ("Terminal type %s is not defined.\n\
1376If that is not the actual type of terminal you have,\n\
1377use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
1378`setenv TERM ...') to specify the correct type. It may be necessary\n\
1379to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.\n",
1380 terminal_type);
08a24c47
JB
1381
1382#ifdef TERMINFO
1383 area = (char *) malloc (2044);
1384#else
1385 area = (char *) malloc (strlen (buffer));
1386#endif /* not TERMINFO */
1387 if (area == 0)
1388 abort ();
1389
1390 TS_ins_line = tgetstr ("al", address);
1391 TS_ins_multi_lines = tgetstr ("AL", address);
1392 TS_bell = tgetstr ("bl", address);
1393 BackTab = tgetstr ("bt", address);
1394 TS_clr_to_bottom = tgetstr ("cd", address);
1395 TS_clr_line = tgetstr ("ce", address);
ff11dfa1 1396 TS_clr_frame = tgetstr ("cl", address);
08a24c47
JB
1397 ColPosition = tgetstr ("ch", address);
1398 AbsPosition = tgetstr ("cm", address);
1399 CR = tgetstr ("cr", address);
1400 TS_set_scroll_region = tgetstr ("cs", address);
1401 TS_set_scroll_region_1 = tgetstr ("cS", address);
1402 RowPosition = tgetstr ("cv", address);
1403 TS_del_char = tgetstr ("dc", address);
1404 TS_del_multi_chars = tgetstr ("DC", address);
1405 TS_del_line = tgetstr ("dl", address);
1406 TS_del_multi_lines = tgetstr ("DL", address);
1407 TS_delete_mode = tgetstr ("dm", address);
1408 TS_end_delete_mode = tgetstr ("ed", address);
1409 TS_end_insert_mode = tgetstr ("ei", address);
1410 Home = tgetstr ("ho", address);
1411 TS_ins_char = tgetstr ("ic", address);
1412 TS_ins_multi_chars = tgetstr ("IC", address);
1413 TS_insert_mode = tgetstr ("im", address);
1414 TS_pad_inserted_char = tgetstr ("ip", address);
1415 TS_end_keypad_mode = tgetstr ("ke", address);
1416 TS_keypad_mode = tgetstr ("ks", address);
1417 LastLine = tgetstr ("ll", address);
1418 Right = tgetstr ("nd", address);
1419 Down = tgetstr ("do", address);
1420 if (!Down)
1421 Down = tgetstr ("nl", address); /* Obsolete name for "do" */
1422#ifdef VMS
1423 /* VMS puts a carriage return before each linefeed,
1424 so it is not safe to use linefeeds. */
1425 if (Down && Down[0] == '\n' && Down[1] == '\0')
1426 Down = 0;
1427#endif /* VMS */
1428 if (tgetflag ("bs"))
1429 Left = "\b"; /* can't possibly be longer! */
1430 else /* (Actually, "bs" is obsolete...) */
1431 Left = tgetstr ("le", address);
1432 if (!Left)
1433 Left = tgetstr ("bc", address); /* Obsolete name for "le" */
1434 TS_pad_char = tgetstr ("pc", address);
1435 TS_repeat = tgetstr ("rp", address);
1436 TS_end_standout_mode = tgetstr ("se", address);
1437 TS_fwd_scroll = tgetstr ("sf", address);
1438 TS_standout_mode = tgetstr ("so", address);
1439 TS_rev_scroll = tgetstr ("sr", address);
1440 Wcm.cm_tab = tgetstr ("ta", address);
1441 TS_end_termcap_modes = tgetstr ("te", address);
1442 TS_termcap_modes = tgetstr ("ti", address);
1443 Up = tgetstr ("up", address);
1444 TS_visible_bell = tgetstr ("vb", address);
1445 TS_end_visual_mode = tgetstr ("ve", address);
1446 TS_visual_mode = tgetstr ("vs", address);
1447 TS_set_window = tgetstr ("wi", address);
1448 MultiUp = tgetstr ("UP", address);
1449 MultiDown = tgetstr ("DO", address);
1450 MultiLeft = tgetstr ("LE", address);
1451 MultiRight = tgetstr ("RI", address);
1452
1453 AutoWrap = tgetflag ("am");
ff11dfa1 1454 memory_below_frame = tgetflag ("db");
08a24c47
JB
1455 TF_hazeltine = tgetflag ("hz");
1456 must_write_spaces = tgetflag ("in");
1457 meta_key = tgetflag ("km") || tgetflag ("MT");
1458 TF_insmode_motion = tgetflag ("mi");
1459 TF_standout_motion = tgetflag ("ms");
1460 TF_underscore = tgetflag ("ul");
1461 MagicWrap = tgetflag ("xn");
1462 TF_xs = tgetflag ("xs");
1463 TF_teleray = tgetflag ("xt");
1464
5c2c7893
JB
1465 term_get_fkeys (address);
1466
ff11dfa1
JB
1467 /* Get frame size from system, or else from termcap. */
1468 get_frame_size (&FRAME_WIDTH (selected_frame),
1469 &FRAME_HEIGHT (selected_frame));
1470 if (FRAME_WIDTH (selected_frame) <= 0)
1471 FRAME_WIDTH (selected_frame) = tgetnum ("co");
1472 if (FRAME_HEIGHT (selected_frame) <= 0)
1473 FRAME_HEIGHT (selected_frame) = tgetnum ("li");
08a24c47
JB
1474
1475 min_padding_speed = tgetnum ("pb");
1476 TN_standout_width = tgetnum ("sg");
1477 TabWidth = tgetnum ("tw");
1478
1479#ifdef VMS
1480 /* These capabilities commonly use ^J.
1481 I don't know why, but sending them on VMS does not work;
1482 it causes following spaces to be lost, sometimes.
1483 For now, the simplest fix is to avoid using these capabilities ever. */
1484 if (Down && Down[0] == '\n')
1485 Down = 0;
1486#endif /* VMS */
1487
1488 if (!TS_bell)
1489 TS_bell = "\07";
1490
1491 if (!TS_fwd_scroll)
1492 TS_fwd_scroll = Down;
1493
1494 PC = TS_pad_char ? *TS_pad_char : 0;
1495
1496 if (TabWidth < 0)
1497 TabWidth = 8;
1498
1499/* Turned off since /etc/termcap seems to have :ta= for most terminals
1500 and newer termcap doc does not seem to say there is a default.
1501 if (!Wcm.cm_tab)
1502 Wcm.cm_tab = "\t";
1503*/
1504
1505 if (TS_standout_mode == 0)
1506 {
1507 TN_standout_width = tgetnum ("ug");
1508 TS_end_standout_mode = tgetstr ("ue", address);
1509 TS_standout_mode = tgetstr ("us", address);
1510 }
1511
afd359c4
RS
1512 /* If no `se' string, try using a `me' string instead.
1513 If that fails, we can't use standout mode at all. */
1514 if (TS_end_standout_mode == 0)
1515 {
1516 char *s = tgetstr ("me");
1517 if (s != 0)
1518 TS_end_standout_mode = s;
1519 else
1520 TS_standout_mode = 0;
1521 }
1522
08a24c47
JB
1523 if (TF_teleray)
1524 {
1525 Wcm.cm_tab = 0;
1526 /* Teleray: most programs want a space in front of TS_standout_mode,
1527 but Emacs can do without it (and give one extra column). */
1528 TS_standout_mode = "\033RD";
1529 TN_standout_width = 1;
1530 /* But that means we cannot rely on ^M to go to column zero! */
1531 CR = 0;
1532 /* LF can't be trusted either -- can alter hpos */
1533 /* if move at column 0 thru a line with TS_standout_mode */
1534 Down = 0;
1535 }
1536
1537 /* Special handling for certain terminal types known to need it */
1538
1539 if (!strcmp (terminal_type, "supdup"))
1540 {
ff11dfa1 1541 memory_below_frame = 1;
08a24c47
JB
1542 Wcm.cm_losewrap = 1;
1543 }
1544 if (!strncmp (terminal_type, "c10", 3)
1545 || !strcmp (terminal_type, "perq"))
1546 {
1547 /* Supply a makeshift :wi string.
1548 This string is not valid in general since it works only
1549 for windows starting at the upper left corner;
1550 but that is all Emacs uses.
1551
ff11dfa1 1552 This string works only if the frame is using
08a24c47
JB
1553 the top of the video memory, because addressing is memory-relative.
1554 So first check the :ti string to see if that is true.
1555
1556 It would be simpler if the :wi string could go in the termcap
1557 entry, but it can't because it is not fully valid.
1558 If it were in the termcap entry, it would confuse other programs. */
1559 if (!TS_set_window)
1560 {
1561 p = TS_termcap_modes;
1562 while (*p && strcmp (p, "\033v "))
1563 p++;
1564 if (*p)
1565 TS_set_window = "\033v%C %C %C %C ";
1566 }
1567 /* Termcap entry often fails to have :in: flag */
1568 must_write_spaces = 1;
1569 /* :ti string typically fails to have \E^G! in it */
1570 /* This limits scope of insert-char to one line. */
1571 strcpy (area, TS_termcap_modes);
1572 strcat (area, "\033\007!");
1573 TS_termcap_modes = area;
1574 area += strlen (area) + 1;
1575 p = AbsPosition;
1576 /* Change all %+ parameters to %C, to handle
1577 values above 96 correctly for the C100. */
1578 while (*p)
1579 {
1580 if (p[0] == '%' && p[1] == '+')
1581 p[1] = 'C';
1582 p++;
1583 }
1584 }
1585
ff11dfa1
JB
1586 FrameRows = FRAME_HEIGHT (selected_frame);
1587 FrameCols = FRAME_WIDTH (selected_frame);
1588 specified_window = FRAME_HEIGHT (selected_frame);
08a24c47
JB
1589
1590 if (Wcm_init () == -1) /* can't do cursor motion */
1591#ifdef VMS
1592 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
1593It lacks the ability to position the cursor.\n\
1594If that is not the actual type of terminal you have, use either the\n\
1595DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
1596or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.\n",
1597 terminal_type);
1598#else
1599 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
1600It lacks the ability to position the cursor.\n\
1601If that is not the actual type of terminal you have,\n\
c5a9c3e6
RS
1602use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
1603`setenv TERM ...') to specify the correct type. It may be necessary\n\
1604to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.\n",
08a24c47
JB
1605 terminal_type);
1606#endif
ff11dfa1
JB
1607 if (FRAME_HEIGHT (selected_frame) <= 0
1608 || FRAME_WIDTH (selected_frame) <= 0)
1609 fatal ("The frame size has not been specified.");
08a24c47
JB
1610
1611 delete_in_insert_mode
1612 = TS_delete_mode && TS_insert_mode
1613 && !strcmp (TS_delete_mode, TS_insert_mode);
1614
1615 se_is_so = (TS_standout_mode
1616 && TS_end_standout_mode
1617 && !strcmp (TS_standout_mode, TS_end_standout_mode));
1618
1619 /* Remove width of standout marker from usable width of line */
1620 if (TN_standout_width > 0)
ff11dfa1 1621 FRAME_WIDTH (selected_frame) -= TN_standout_width;
08a24c47
JB
1622
1623 UseTabs = tabs_safe_p () && TabWidth == 8;
1624
1625 scroll_region_ok
1626 = (Wcm.cm_abs
1627 && (TS_set_window || TS_set_scroll_region || TS_set_scroll_region_1));
1628
1629 line_ins_del_ok = (((TS_ins_line || TS_ins_multi_lines)
1630 && (TS_del_line || TS_del_multi_lines))
1631 || (scroll_region_ok && TS_fwd_scroll && TS_rev_scroll));
1632
1633 char_ins_del_ok = ((TS_ins_char || TS_insert_mode
1634 || TS_pad_inserted_char || TS_ins_multi_chars)
1635 && (TS_del_char || TS_del_multi_chars));
1636
1637 fast_clear_end_of_line = TS_clr_line != 0;
1638
1639 init_baud_rate ();
1640 if (read_socket_hook) /* Baudrate is somewhat */
1641 /* meaningless in this case */
1642 baud_rate = 9600;
20a558dc 1643
a3c87d4e
JB
1644 FRAME_CAN_HAVE_SCROLL_BARS (selected_frame) = 0;
1645 FRAME_HAS_VERTICAL_SCROLL_BARS (selected_frame) = 0;
08a24c47
JB
1646}
1647
1648/* VARARGS 1 */
1649fatal (str, arg1, arg2)
4746118a 1650 char *str, *arg1, *arg2;
08a24c47
JB
1651{
1652 fprintf (stderr, "emacs: ");
1653 fprintf (stderr, str, arg1, arg2);
1654 fflush (stderr);
1655 exit (1);
1656}
07c57952
KH
1657
1658syms_of_term ()
1659{
1660 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
1661 "Non-nil means the system uses terminfo rather than termcap.\n\
1662This variable can be used by terminal emulator packages.");
1663#ifdef TERMINFO
1664 system_uses_terminfo = 1;
1665#else
1666 system_uses_terminfo = 0;
1667#endif
1668}