(make-lucid-menu-keymap): Allow Lucid-style keyword-based menu items.
[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 33
c8951b18
KH
34extern Lisp_Object Fmake_sparse_keymap ();
35
08a24c47
JB
36#define max(a, b) ((a) > (b) ? (a) : (b))
37#define min(a, b) ((a) < (b) ? (a) : (b))
38
ff11dfa1 39#define OUTPUT(a) tputs (a, FRAME_HEIGHT (selected_frame) - curY, cmputc)
08a24c47
JB
40#define OUTPUT1(a) tputs (a, 1, cmputc)
41#define OUTPUTL(a, lines) tputs (a, lines, cmputc)
ff11dfa1 42#define OUTPUT_IF(a) { if (a) tputs (a, FRAME_HEIGHT (selected_frame) - curY, cmputc); }
08a24c47
JB
43#define OUTPUT1_IF(a) { if (a) tputs (a, 1, cmputc); }
44
eb8c3be9 45/* Terminal characteristics that higher levels want to look at.
08a24c47
JB
46 These are all extern'd in termchar.h */
47
08a24c47
JB
48int must_write_spaces; /* Nonzero means spaces in the text
49 must actually be output; can't just skip
50 over some columns to leave them blank. */
51int min_padding_speed; /* Speed below which no padding necessary */
52
53int line_ins_del_ok; /* Terminal can insert and delete lines */
54int char_ins_del_ok; /* Terminal can insert and delete chars */
55int scroll_region_ok; /* Terminal supports setting the
56 scroll window */
ff11dfa1 57int memory_below_frame; /* Terminal remembers lines
08a24c47
JB
58 scrolled off bottom */
59int fast_clear_end_of_line; /* Terminal has a `ce' string */
60
61int dont_calculate_costs; /* Nonzero means don't bother computing */
62 /* various cost tables; we won't use them. */
63
ff11dfa1 64/* Nonzero means no need to redraw the entire frame on resuming
08a24c47
JB
65 a suspended Emacs. This is useful on terminals with multiple pages,
66 where one page is used for Emacs and another for all else. */
67int no_redraw_on_reenter;
68
69/* Hook functions that you can set to snap out the functions in this file.
70 These are all extern'd in termhooks.h */
71
72int (*cursor_to_hook) ();
73int (*raw_cursor_to_hook) ();
74
75int (*clear_to_end_hook) ();
ff11dfa1 76int (*clear_frame_hook) ();
08a24c47
JB
77int (*clear_end_of_line_hook) ();
78
79int (*ins_del_lines_hook) ();
80
81int (*change_line_highlight_hook) ();
82int (*reassert_line_highlight_hook) ();
83
84int (*insert_glyphs_hook) ();
85int (*write_glyphs_hook) ();
86int (*delete_glyphs_hook) ();
87
88int (*ring_bell_hook) ();
89
90int (*reset_terminal_modes_hook) ();
91int (*set_terminal_modes_hook) ();
92int (*update_begin_hook) ();
93int (*update_end_hook) ();
94int (*set_terminal_window_hook) ();
95
96int (*read_socket_hook) ();
97
55cc089c
RS
98int (*frame_up_to_date_hook) ();
99
20a558dc 100/* Return the current position of the mouse.
371fbaeb
JB
101
102 Set *f to the frame the mouse is in, or zero if the mouse is in no
103 Emacs frame. If it is set to zero, all the other arguments are
104 garbage.
105
a3c87d4e
JB
106 If the motion started in a scroll bar, set *bar_window to the
107 scroll bar's window, *part to the part the mouse is currently over,
108 *x to the position of the mouse along the scroll bar, and *y to the
109 overall length of the scroll bar.
371fbaeb
JB
110
111 Otherwise, set *bar_window to Qnil, and *x and *y to the column and
112 row of the character cell the mouse is over.
113
114 Set *time to the time the mouse was at the returned position.
115
116 This should clear mouse_moved until the next motion
117 event arrives. */
ff11dfa1 118void (*mouse_position_hook) ( /* FRAME_PTR *f,
371fbaeb 119 Lisp_Object *bar_window,
a3c87d4e 120 enum scroll_bar_part *part,
20a558dc
JB
121 Lisp_Object *x,
122 Lisp_Object *y,
123 unsigned long *time */ );
08a24c47 124
ff11dfa1
JB
125/* When reading from a minibuffer in a different frame, Emacs wants
126 to shift the highlight from the selected frame to the minibuffer's
127 frame; under X, this means it lies about where the focus is.
2e146aa4
JB
128 This hook tells the window system code to re-decide where to put
129 the highlight. */
ff11dfa1 130void (*frame_rehighlight_hook) ( /* FRAME_PTR f */ );
2e146aa4 131
dbc4e1c1
JB
132/* If we're displaying frames using a window system that can stack
133 frames on top of each other, this hook allows you to bring a frame
134 to the front, or bury it behind all the other windows. If this
135 hook is zero, that means the device we're displaying on doesn't
136 support overlapping frames, so there's no need to raise or lower
137 anything.
138
139 If RAISE is non-zero, F is brought to the front, before all other
140 windows. If RAISE is zero, F is sent to the back, behind all other
141 windows. */
142void (*frame_raise_lower_hook) ( /* FRAME_PTR f, int raise */ );
143
a3c87d4e 144/* Set the vertical scroll bar for WINDOW to have its upper left corner
371fbaeb
JB
145 at (TOP, LEFT), and be LENGTH rows high. Set its handle to
146 indicate that we are displaying PORTION characters out of a total
147 of WHOLE characters, starting at POSITION. If WINDOW doesn't yet
a3c87d4e
JB
148 have a scroll bar, create one for it. */
149void (*set_vertical_scroll_bar_hook)
371fbaeb 150 ( /* struct window *window,
20a558dc
JB
151 int portion, int whole, int position */ );
152
371fbaeb 153
20a558dc 154/* The following three hooks are used when we're doing a thorough
a3c87d4e 155 redisplay of the frame. We don't explicitly know which scroll bars
20a558dc
JB
156 are going to be deleted, because keeping track of when windows go
157 away is a real pain - can you say set-window-configuration?
158 Instead, we just assert at the beginning of redisplay that *all*
a3c87d4e 159 scroll bars are to be removed, and then save scroll bars from the
20a558dc
JB
160 firey pit when we actually redisplay their window. */
161
a3c87d4e
JB
162/* Arrange for all scroll bars on FRAME to be removed at the next call
163 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
164 `*redeem_scroll_bar_hook' is applied to its window before the judgement.
20a558dc 165
371fbaeb 166 This should be applied to each frame each time its window tree is
a3c87d4e
JB
167 redisplayed, even if it is not displaying scroll bars at the moment;
168 if the HAS_SCROLL_BARS flag has just been turned off, only calling
169 this and the judge_scroll_bars_hook will get rid of them.
371fbaeb
JB
170
171 If non-zero, this hook should be safe to apply to any frame,
a3c87d4e 172 whether or not it can support scroll bars, and whether or not it is
371fbaeb 173 currently displaying them. */
a3c87d4e 174void (*condemn_scroll_bars_hook)( /* FRAME_PTR *frame */ );
371fbaeb 175
a3c87d4e
JB
176/* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
177 Note that it's okay to redeem a scroll bar that is not condemned. */
178void (*redeem_scroll_bar_hook)( /* struct window *window */ );
20a558dc 179
a3c87d4e
JB
180/* Remove all scroll bars on FRAME that haven't been saved since the
181 last call to `*condemn_scroll_bars_hook'.
20a558dc 182
371fbaeb 183 This should be applied to each frame after each time its window
a3c87d4e
JB
184 tree is redisplayed, even if it is not displaying scroll bars at the
185 moment; if the HAS_SCROLL_BARS flag has just been turned off, only
186 calling this and condemn_scroll_bars_hook will get rid of them.
371fbaeb
JB
187
188 If non-zero, this hook should be safe to apply to any frame,
a3c87d4e 189 whether or not it can support scroll bars, and whether or not it is
371fbaeb 190 currently displaying them. */
a3c87d4e 191void (*judge_scroll_bars_hook)( /* FRAME_PTR *FRAME */ );
20a558dc
JB
192
193
08a24c47
JB
194/* Strings, numbers and flags taken from the termcap entry. */
195
196char *TS_ins_line; /* termcap "al" */
197char *TS_ins_multi_lines; /* "AL" (one parameter, # lines to insert) */
198char *TS_bell; /* "bl" */
199char *TS_clr_to_bottom; /* "cd" */
200char *TS_clr_line; /* "ce", clear to end of line */
ff11dfa1 201char *TS_clr_frame; /* "cl" */
08a24c47
JB
202char *TS_set_scroll_region; /* "cs" (2 params, first line and last line) */
203char *TS_set_scroll_region_1; /* "cS" (4 params: total lines,
204 lines above scroll region, lines below it,
205 total lines again) */
206char *TS_del_char; /* "dc" */
207char *TS_del_multi_chars; /* "DC" (one parameter, # chars to delete) */
208char *TS_del_line; /* "dl" */
209char *TS_del_multi_lines; /* "DL" (one parameter, # lines to delete) */
210char *TS_delete_mode; /* "dm", enter character-delete mode */
211char *TS_end_delete_mode; /* "ed", leave character-delete mode */
212char *TS_end_insert_mode; /* "ei", leave character-insert mode */
213char *TS_ins_char; /* "ic" */
214char *TS_ins_multi_chars; /* "IC" (one parameter, # chars to insert) */
215char *TS_insert_mode; /* "im", enter character-insert mode */
216char *TS_pad_inserted_char; /* "ip". Just padding, no commands. */
217char *TS_end_keypad_mode; /* "ke" */
218char *TS_keypad_mode; /* "ks" */
219char *TS_pad_char; /* "pc", char to use as padding */
220char *TS_repeat; /* "rp" (2 params, # times to repeat
221 and character to be repeated) */
222char *TS_end_standout_mode; /* "se" */
223char *TS_fwd_scroll; /* "sf" */
224char *TS_standout_mode; /* "so" */
225char *TS_rev_scroll; /* "sr" */
226char *TS_end_termcap_modes; /* "te" */
227char *TS_termcap_modes; /* "ti" */
228char *TS_visible_bell; /* "vb" */
229char *TS_end_visual_mode; /* "ve" */
230char *TS_visual_mode; /* "vi" */
231char *TS_set_window; /* "wi" (4 params, start and end of window,
232 each as vpos and hpos) */
233
234int TF_hazeltine; /* termcap hz flag. */
235int TF_insmode_motion; /* termcap mi flag: can move while in insert mode. */
236int TF_standout_motion; /* termcap mi flag: can move while in standout mode. */
237int TF_underscore; /* termcap ul flag: _ underlines if overstruck on
238 nonblank position. Must clear before writing _. */
239int TF_teleray; /* termcap xt flag: many weird consequences.
240 For t1061. */
241
242int TF_xs; /* Nonzero for "xs". If set together with
243 TN_standout_width == 0, it means don't bother
244 to write any end-standout cookies. */
245
246int TN_standout_width; /* termcap sg number: width occupied by standout
247 markers */
248
249static int RPov; /* # chars to start a TS_repeat */
250
251static int delete_in_insert_mode; /* delete mode == insert mode */
252
253static int se_is_so; /* 1 if same string both enters and leaves
254 standout mode */
255
256/* internal state */
257
258/* Number of chars of space used for standout marker at beginning of line,
259 or'd with 0100. Zero if no standout marker at all.
260
261 Used IFF TN_standout_width >= 0. */
262
263static char *chars_wasted;
264static char *copybuf;
265
266/* nonzero means supposed to write text in standout mode. */
267int standout_requested;
268
269int insert_mode; /* Nonzero when in insert mode. */
270int standout_mode; /* Nonzero when in standout mode. */
271
272/* Size of window specified by higher levels.
ff11dfa1 273 This is the number of lines, from the top of frame downwards,
08a24c47
JB
274 which can participate in insert-line/delete-line operations.
275
ff11dfa1 276 Effectively it excludes the bottom frame_height - specified_window_size
08a24c47
JB
277 lines from those operations. */
278
279int specified_window;
280
ff11dfa1 281/* Frame currently being redisplayed; 0 if not currently redisplaying.
08a24c47
JB
282 (Direct output does not count). */
283
ff11dfa1 284FRAME_PTR updating_frame;
08a24c47 285
07c57952
KH
286/* Provided for lisp packages. */
287static int system_uses_terminfo;
288
08a24c47 289char *tparam ();
e4bfb3b6
RS
290
291extern char *tgetstr ();
08a24c47
JB
292\f
293ring_bell ()
294{
1820044b 295 if (! FRAME_TERMCAP_P (selected_frame))
08a24c47
JB
296 {
297 (*ring_bell_hook) ();
298 return;
299 }
300 OUTPUT (TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell);
301}
302
303set_terminal_modes ()
304{
1820044b 305 if (! FRAME_TERMCAP_P (selected_frame))
08a24c47
JB
306 {
307 (*set_terminal_modes_hook) ();
308 return;
309 }
310 OUTPUT_IF (TS_termcap_modes);
311 OUTPUT_IF (TS_visual_mode);
312 OUTPUT_IF (TS_keypad_mode);
313 losecursor ();
314}
315
316reset_terminal_modes ()
317{
1820044b 318 if (! FRAME_TERMCAP_P (selected_frame))
08a24c47
JB
319 {
320 (*reset_terminal_modes_hook) ();
321 return;
322 }
323 if (TN_standout_width < 0)
324 turn_off_highlight ();
325 turn_off_insert ();
326 OUTPUT_IF (TS_end_keypad_mode);
327 OUTPUT_IF (TS_end_visual_mode);
328 OUTPUT_IF (TS_end_termcap_modes);
329 /* Output raw CR so kernel can track the cursor hpos. */
330 /* But on magic-cookie terminals this can erase an end-standout marker and
ff11dfa1 331 cause the rest of the frame to be in standout, so move down first. */
08a24c47
JB
332 if (TN_standout_width >= 0)
333 cmputc ('\n');
334 cmputc ('\r');
335}
336
ff11dfa1
JB
337update_begin (f)
338 FRAME_PTR f;
08a24c47 339{
ff11dfa1 340 updating_frame = f;
1820044b 341 if (! FRAME_TERMCAP_P (updating_frame))
ff11dfa1 342 (*update_begin_hook) (f);
08a24c47
JB
343}
344
ff11dfa1
JB
345update_end (f)
346 FRAME_PTR f;
08a24c47 347{
1820044b 348 if (! FRAME_TERMCAP_P (updating_frame))
08a24c47 349 {
7a8e3e30 350 (*update_end_hook) (f);
cc4ee3c7 351 updating_frame = 0;
08a24c47
JB
352 return;
353 }
354 turn_off_insert ();
355 background_highlight ();
356 standout_requested = 0;
ff11dfa1 357 updating_frame = 0;
08a24c47
JB
358}
359
360set_terminal_window (size)
361 int size;
362{
1820044b 363 if (! FRAME_TERMCAP_P (updating_frame))
08a24c47
JB
364 {
365 (*set_terminal_window_hook) (size);
366 return;
367 }
ff11dfa1 368 specified_window = size ? size : FRAME_HEIGHT (selected_frame);
08a24c47
JB
369 if (!scroll_region_ok)
370 return;
371 set_scroll_region (0, specified_window);
372}
373
374set_scroll_region (start, stop)
375 int start, stop;
376{
377 char *buf;
378 if (TS_set_scroll_region)
379 {
380 buf = tparam (TS_set_scroll_region, 0, 0, start, stop - 1);
381 }
382 else if (TS_set_scroll_region_1)
383 {
384 buf = tparam (TS_set_scroll_region_1, 0, 0,
ff11dfa1
JB
385 FRAME_HEIGHT (selected_frame), start,
386 FRAME_HEIGHT (selected_frame) - stop,
387 FRAME_HEIGHT (selected_frame));
08a24c47
JB
388 }
389 else
390 {
ff11dfa1 391 buf = tparam (TS_set_window, 0, 0, start, 0, stop, FRAME_WIDTH (selected_frame));
08a24c47
JB
392 }
393 OUTPUT (buf);
9ac0d9e0 394 xfree (buf);
08a24c47
JB
395 losecursor ();
396}
397\f
398turn_on_insert ()
399{
400 if (!insert_mode)
401 OUTPUT (TS_insert_mode);
402 insert_mode = 1;
403}
404
405turn_off_insert ()
406{
407 if (insert_mode)
408 OUTPUT (TS_end_insert_mode);
409 insert_mode = 0;
410}
411\f
412/* Handle highlighting when TN_standout_width (termcap sg) is not specified.
413 In these terminals, output is affected by the value of standout
414 mode when the output is written.
415
416 These functions are called on all terminals, but do nothing
417 on terminals whose standout mode does not work that way. */
418
419turn_off_highlight ()
420{
421 if (TN_standout_width < 0)
422 {
423 if (standout_mode)
424 OUTPUT_IF (TS_end_standout_mode);
425 standout_mode = 0;
426 }
427}
428
429turn_on_highlight ()
430{
431 if (TN_standout_width < 0)
432 {
433 if (!standout_mode)
434 OUTPUT_IF (TS_standout_mode);
435 standout_mode = 1;
436 }
437}
438
439/* Set standout mode to the state it should be in for
440 empty space inside windows. What this is,
441 depends on the user option inverse-video. */
442
443background_highlight ()
444{
445 if (TN_standout_width >= 0)
446 return;
447 if (inverse_video)
448 turn_on_highlight ();
449 else
450 turn_off_highlight ();
451}
452
453/* Set standout mode to the mode specified for the text to be output. */
454
455static
456highlight_if_desired ()
457{
458 if (TN_standout_width >= 0)
459 return;
460 if (!inverse_video == !standout_requested)
461 turn_off_highlight ();
462 else
463 turn_on_highlight ();
464}
465\f
466/* Handle standout mode for terminals in which TN_standout_width >= 0.
467 On these terminals, standout is controlled by markers that
ff11dfa1 468 live inside the terminal's memory. TN_standout_width is the width
08a24c47
JB
469 that the marker occupies in memory. Standout runs from the marker
470 to the end of the line on some terminals, or to the next
471 turn-off-standout marker (TS_end_standout_mode) string
472 on other terminals. */
473
474/* Write a standout marker or end-standout marker at the front of the line
475 at vertical position vpos. */
476
477write_standout_marker (flag, vpos)
478 int flag, vpos;
479{
480 if (flag || (TS_end_standout_mode && !TF_teleray && !se_is_so
481 && !(TF_xs && TN_standout_width == 0)))
482 {
483 cmgoto (vpos, 0);
484 cmplus (TN_standout_width);
485 OUTPUT (flag ? TS_standout_mode : TS_end_standout_mode);
486 chars_wasted[curY] = TN_standout_width | 0100;
487 }
488}
489\f
490/* External interface to control of standout mode.
491 Call this when about to modify line at position VPOS
492 and not change whether it is highlighted. */
493
494reassert_line_highlight (highlight, vpos)
495 int highlight;
496 int vpos;
497{
1820044b 498 if (! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
08a24c47
JB
499 {
500 (*reassert_line_highlight_hook) (highlight, vpos);
501 return;
502 }
503 if (TN_standout_width < 0)
504 /* Handle terminals where standout takes affect at output time */
505 standout_requested = highlight;
506 else if (chars_wasted[vpos] == 0)
507 /* For terminals with standout markers, write one on this line
508 if there isn't one already. */
509 write_standout_marker (highlight, vpos);
510}
511
512/* Call this when about to modify line at position VPOS
513 and change whether it is highlighted. */
514
515change_line_highlight (new_highlight, vpos, first_unused_hpos)
516 int new_highlight, vpos, first_unused_hpos;
517{
518 standout_requested = new_highlight;
1820044b 519 if (! FRAME_TERMCAP_P (updating_frame))
08a24c47
JB
520 {
521 (*change_line_highlight_hook) (new_highlight, vpos, first_unused_hpos);
522 return;
523 }
524
525 cursor_to (vpos, 0);
526
527 if (TN_standout_width < 0)
528 background_highlight ();
529 /* If line starts with a marker, delete the marker */
530 else if (TS_clr_line && chars_wasted[curY])
531 {
532 turn_off_insert ();
533 /* On Teleray, make sure to erase the SO marker. */
534 if (TF_teleray)
535 {
ff11dfa1 536 cmgoto (curY - 1, FRAME_WIDTH (selected_frame) - 4);
08a24c47
JB
537 OUTPUT ("\033S");
538 curY++; /* ESC S moves to next line where the TS_standout_mode was */
539 curX = 0;
540 }
541 else
542 cmgoto (curY, 0); /* reposition to kill standout marker */
543 }
544 clear_end_of_line_raw (first_unused_hpos);
545 reassert_line_highlight (new_highlight, curY);
546}
547\f
548
549/* Move to absolute position, specified origin 0 */
550
551cursor_to (row, col)
4746118a 552 int row, col;
08a24c47 553{
1820044b 554 if (! FRAME_TERMCAP_P ((updating_frame
ff11dfa1
JB
555 ? updating_frame
556 : selected_frame))
08a24c47
JB
557 && cursor_to_hook)
558 {
559 (*cursor_to_hook) (row, col);
560 return;
561 }
562
563 col += chars_wasted[row] & 077;
564 if (curY == row && curX == col)
565 return;
566 if (!TF_standout_motion)
567 background_highlight ();
568 if (!TF_insmode_motion)
569 turn_off_insert ();
570 cmgoto (row, col);
571}
572
573/* Similar but don't take any account of the wasted characters. */
574
575raw_cursor_to (row, col)
4746118a 576 int row, col;
08a24c47 577{
1820044b 578 if (! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
08a24c47
JB
579 {
580 (*raw_cursor_to_hook) (row, col);
581 return;
582 }
583 if (curY == row && curX == col)
584 return;
585 if (!TF_standout_motion)
586 background_highlight ();
587 if (!TF_insmode_motion)
588 turn_off_insert ();
589 cmgoto (row, col);
590}
591\f
592/* Erase operations */
593
ff11dfa1 594/* clear from cursor to end of frame */
08a24c47
JB
595clear_to_end ()
596{
597 register int i;
598
759d9005 599 if (clear_to_end_hook && ! FRAME_TERMCAP_P (updating_frame))
08a24c47
JB
600 {
601 (*clear_to_end_hook) ();
602 return;
603 }
604 if (TS_clr_to_bottom)
605 {
606 background_highlight ();
607 OUTPUT (TS_clr_to_bottom);
ff11dfa1 608 bzero (chars_wasted + curY, FRAME_HEIGHT (selected_frame) - curY);
08a24c47
JB
609 }
610 else
611 {
ff11dfa1 612 for (i = curY; i < FRAME_HEIGHT (selected_frame); i++)
08a24c47
JB
613 {
614 cursor_to (i, 0);
ff11dfa1 615 clear_end_of_line_raw (FRAME_WIDTH (selected_frame));
08a24c47
JB
616 }
617 }
618}
619
ff11dfa1 620/* Clear entire frame */
08a24c47 621
ff11dfa1 622clear_frame ()
08a24c47 623{
ff11dfa1 624 if (clear_frame_hook
1820044b 625 && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
08a24c47 626 {
ff11dfa1 627 (*clear_frame_hook) ();
08a24c47
JB
628 return;
629 }
ff11dfa1 630 if (TS_clr_frame)
08a24c47
JB
631 {
632 background_highlight ();
ff11dfa1
JB
633 OUTPUT (TS_clr_frame);
634 bzero (chars_wasted, FRAME_HEIGHT (selected_frame));
08a24c47
JB
635 cmat (0, 0);
636 }
637 else
638 {
639 cursor_to (0, 0);
640 clear_to_end ();
641 }
642}
643
644/* Clear to end of line, but do not clear any standout marker.
645 Assumes that the cursor is positioned at a character of real text,
646 which implies it cannot be before a standout marker
647 unless the marker has zero width.
648
649 Note that the cursor may be moved. */
650
651clear_end_of_line (first_unused_hpos)
652 int first_unused_hpos;
653{
a796ac82 654 static GLYPH buf = SPACEGLYPH;
1820044b 655 if (FRAME_TERMCAP_P (selected_frame)
08a24c47 656 && TN_standout_width == 0 && curX == 0 && chars_wasted[curY] != 0)
a796ac82 657 write_glyphs (&buf, 1);
08a24c47
JB
658 clear_end_of_line_raw (first_unused_hpos);
659}
660
661/* Clear from cursor to end of line.
662 Assume that the line is already clear starting at column first_unused_hpos.
663 If the cursor is at a standout marker, erase the marker.
664
665 Note that the cursor may be moved, on terminals lacking a `ce' string. */
666
667clear_end_of_line_raw (first_unused_hpos)
668 int first_unused_hpos;
669{
670 register int i;
671
672 if (clear_end_of_line_hook
1820044b 673 && ! FRAME_TERMCAP_P ((updating_frame
ff11dfa1
JB
674 ? updating_frame
675 : selected_frame)))
08a24c47
JB
676 {
677 (*clear_end_of_line_hook) (first_unused_hpos);
678 return;
679 }
680
681 first_unused_hpos += chars_wasted[curY] & 077;
682 if (curX >= first_unused_hpos)
683 return;
684 /* Notice if we are erasing a magic cookie */
685 if (curX == 0)
686 chars_wasted[curY] = 0;
687 background_highlight ();
688 if (TS_clr_line)
689 {
690 OUTPUT1 (TS_clr_line);
691 }
692 else
693 { /* have to do it the hard way */
694 turn_off_insert ();
695
696 /* Do not write in last row last col with Autowrap on. */
ff11dfa1
JB
697 if (AutoWrap && curY == FRAME_HEIGHT (selected_frame) - 1
698 && first_unused_hpos == FRAME_WIDTH (selected_frame))
08a24c47
JB
699 first_unused_hpos--;
700
701 for (i = curX; i < first_unused_hpos; i++)
702 {
703 if (termscript)
704 fputc (' ', termscript);
705 putchar (' ');
706 }
707 cmplus (first_unused_hpos - curX);
708 }
709}
710\f
711
712write_glyphs (string, len)
713 register GLYPH *string;
714 register int len;
715{
716 register GLYPH g;
717 register int tlen = GLYPH_TABLE_LENGTH;
718 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
719
720 if (write_glyphs_hook
1820044b 721 && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
08a24c47
JB
722 {
723 (*write_glyphs_hook) (string, len);
724 return;
725 }
726
727 highlight_if_desired ();
728 turn_off_insert ();
729
730 /* Don't dare write in last column of bottom line, if AutoWrap,
ff11dfa1 731 since that would scroll the whole frame on some terminals. */
08a24c47
JB
732
733 if (AutoWrap
ff11dfa1 734 && curY + 1 == FRAME_HEIGHT (selected_frame)
08a24c47 735 && (curX + len - (chars_wasted[curY] & 077)
ff11dfa1 736 == FRAME_WIDTH (selected_frame)))
08a24c47
JB
737 len --;
738
739 cmplus (len);
740 while (--len >= 0)
741 {
742 g = *string++;
743 /* Check quickly for G beyond length of table.
744 That implies it isn't an alias and is simple. */
745 if (g >= tlen)
746 {
747 simple:
748 putc (g & 0xff, stdout);
749 if (ferror (stdout))
750 clearerr (stdout);
751 if (termscript)
752 putc (g & 0xff, termscript);
753 }
754 else
755 {
756 /* G has an entry in Vglyph_table,
757 so process any alias and then test for simpleness. */
758 while (GLYPH_ALIAS_P (tbase, tlen, g))
759 g = GLYPH_ALIAS (tbase, g);
760 if (GLYPH_SIMPLE_P (tbase, tlen, g))
761 goto simple;
762 else
763 {
764 /* Here if G (or its definition as an alias) is not simple. */
765 fwrite (GLYPH_STRING (tbase, g), 1, GLYPH_LENGTH (tbase, g),
766 stdout);
767 if (ferror (stdout))
768 clearerr (stdout);
769 if (termscript)
770 fwrite (GLYPH_STRING (tbase, g), 1, GLYPH_LENGTH (tbase, g),
771 termscript);
772 }
773 }
774 }
775}
776
777/* If start is zero, insert blanks instead of a string at start */
778
779insert_glyphs (start, len)
780 register GLYPH *start;
781 register int len;
782{
783 char *buf;
784 register GLYPH g;
785 register int tlen = GLYPH_TABLE_LENGTH;
786 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
787
1820044b 788 if (insert_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame))
08a24c47
JB
789 {
790 (*insert_glyphs_hook) (start, len);
791 return;
792 }
793 highlight_if_desired ();
794
795 if (TS_ins_multi_chars)
796 {
797 buf = tparam (TS_ins_multi_chars, 0, 0, len);
798 OUTPUT1 (buf);
9ac0d9e0 799 xfree (buf);
08a24c47
JB
800 if (start)
801 write_glyphs (start, len);
802 return;
803 }
804
805 turn_on_insert ();
806 cmplus (len);
807 while (--len >= 0)
808 {
809 OUTPUT1_IF (TS_ins_char);
810 if (!start)
811 g = SPACEGLYPH;
812 else
813 g = *start++;
814
815 if (GLYPH_SIMPLE_P (tbase, tlen, g))
816 {
817 putc (g & 0xff, stdout);
818 if (ferror (stdout))
819 clearerr (stdout);
820 if (termscript)
821 putc (g & 0xff, termscript);
822 }
823 else
824 {
825 fwrite (GLYPH_STRING (tbase, g), 1, GLYPH_LENGTH (tbase, g), stdout);
826 if (ferror (stdout))
827 clearerr (stdout);
828 if (termscript)
829 fwrite (GLYPH_STRING (tbase, g), 1, GLYPH_LENGTH (tbase, g),
830 termscript);
831 }
832
833 OUTPUT1_IF (TS_pad_inserted_char);
834 }
835}
836
837delete_glyphs (n)
838 register int n;
839{
840 char *buf;
841 register int i;
842
1820044b 843 if (delete_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame))
08a24c47
JB
844 {
845 (*delete_glyphs_hook) (n);
846 return;
847 }
848
849 if (delete_in_insert_mode)
850 {
851 turn_on_insert ();
852 }
853 else
854 {
855 turn_off_insert ();
856 OUTPUT_IF (TS_delete_mode);
857 }
858
859 if (TS_del_multi_chars)
860 {
861 buf = tparam (TS_del_multi_chars, 0, 0, n);
862 OUTPUT1 (buf);
9ac0d9e0 863 xfree (buf);
08a24c47
JB
864 }
865 else
866 for (i = 0; i < n; i++)
867 OUTPUT1 (TS_del_char);
868 if (!delete_in_insert_mode)
869 OUTPUT_IF (TS_end_delete_mode);
870}
871\f
872/* Insert N lines at vpos VPOS. If N is negative, delete -N lines. */
873
874ins_del_lines (vpos, n)
875 int vpos, n;
876{
877 char *multi = n > 0 ? TS_ins_multi_lines : TS_del_multi_lines;
878 char *single = n > 0 ? TS_ins_line : TS_del_line;
879 char *scroll = n > 0 ? TS_rev_scroll : TS_fwd_scroll;
880
881 register int i = n > 0 ? n : -n;
882 register char *buf;
883
1820044b 884 if (ins_del_lines_hook && ! FRAME_TERMCAP_P (updating_frame))
08a24c47
JB
885 {
886 (*ins_del_lines_hook) (vpos, n);
887 return;
888 }
889
890 /* If the lines below the insertion are being pushed
891 into the end of the window, this is the same as clearing;
892 and we know the lines are already clear, since the matching
893 deletion has already been done. So can ignore this. */
894 /* If the lines below the deletion are blank lines coming
895 out of the end of the window, don't bother,
896 as there will be a matching inslines later that will flush them. */
897 if (scroll_region_ok && vpos + i >= specified_window)
898 return;
ff11dfa1 899 if (!memory_below_frame && vpos + i >= FRAME_HEIGHT (selected_frame))
08a24c47
JB
900 return;
901
902 if (multi)
903 {
904 raw_cursor_to (vpos, 0);
905 background_highlight ();
906 buf = tparam (multi, 0, 0, i);
907 OUTPUT (buf);
9ac0d9e0 908 xfree (buf);
08a24c47
JB
909 }
910 else if (single)
911 {
912 raw_cursor_to (vpos, 0);
913 background_highlight ();
914 while (--i >= 0)
915 OUTPUT (single);
916 if (TF_teleray)
917 curX = 0;
918 }
919 else
920 {
921 set_scroll_region (vpos, specified_window);
922 if (n < 0)
923 raw_cursor_to (specified_window - 1, 0);
924 else
925 raw_cursor_to (vpos, 0);
926 background_highlight ();
927 while (--i >= 0)
928 OUTPUTL (scroll, specified_window - vpos);
929 set_scroll_region (0, specified_window);
930 }
931
932 if (TN_standout_width >= 0)
933 {
934 register lower_limit
935 = (scroll_region_ok
936 ? specified_window
ff11dfa1 937 : FRAME_HEIGHT (selected_frame));
08a24c47
JB
938
939 if (n < 0)
940 {
941 bcopy (&chars_wasted[vpos - n], &chars_wasted[vpos],
942 lower_limit - vpos + n);
943 bzero (&chars_wasted[lower_limit + n], - n);
944 }
945 else
946 {
947 bcopy (&chars_wasted[vpos], &copybuf[vpos], lower_limit - vpos - n);
948 bcopy (&copybuf[vpos], &chars_wasted[vpos + n],
949 lower_limit - vpos - n);
950 bzero (&chars_wasted[vpos], n);
951 }
952 }
ff11dfa1 953 if (!scroll_region_ok && memory_below_frame && n < 0)
08a24c47 954 {
ff11dfa1 955 cursor_to (FRAME_HEIGHT (selected_frame) + n, 0);
08a24c47
JB
956 clear_to_end ();
957 }
958}
959\f
960/* Compute cost of sending "str", in characters,
961 not counting any line-dependent padding. */
962
963int
964string_cost (str)
965 char *str;
966{
967 cost = 0;
968 if (str)
969 tputs (str, 0, evalcost);
970 return cost;
971}
972
973/* Compute cost of sending "str", in characters,
974 counting any line-dependent padding at one line. */
975
976static int
977string_cost_one_line (str)
978 char *str;
979{
980 cost = 0;
981 if (str)
982 tputs (str, 1, evalcost);
983 return cost;
984}
985
986/* Compute per line amount of line-dependent padding,
987 in tenths of characters. */
988
989int
990per_line_cost (str)
991 register char *str;
992{
993 cost = 0;
994 if (str)
995 tputs (str, 0, evalcost);
996 cost = - cost;
997 if (str)
998 tputs (str, 10, evalcost);
999 return cost;
1000}
1001
1002#ifndef old
1003/* char_ins_del_cost[n] is cost of inserting N characters.
1004 char_ins_del_cost[-n] is cost of deleting N characters. */
1005
1006int *char_ins_del_vector;
1007
ff11dfa1 1008#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WIDTH ((f))])
08a24c47
JB
1009#endif
1010
1011/* ARGSUSED */
1012static void
ff11dfa1
JB
1013calculate_ins_del_char_costs (frame)
1014 FRAME_PTR frame;
08a24c47
JB
1015{
1016 int ins_startup_cost, del_startup_cost;
1017 int ins_cost_per_char, del_cost_per_char;
1018 register int i;
1019 register int *p;
1020
1021 if (TS_ins_multi_chars)
1022 {
1023 ins_cost_per_char = 0;
1024 ins_startup_cost = string_cost_one_line (TS_ins_multi_chars);
1025 }
1026 else if (TS_ins_char || TS_pad_inserted_char
1027 || (TS_insert_mode && TS_end_insert_mode))
1028 {
1029 ins_startup_cost = (30 * (string_cost (TS_insert_mode)
1030 + string_cost (TS_end_insert_mode))) / 100;
1031 ins_cost_per_char = (string_cost_one_line (TS_ins_char)
1032 + string_cost_one_line (TS_pad_inserted_char));
1033 }
1034 else
1035 {
1036 ins_startup_cost = 9999;
1037 ins_cost_per_char = 0;
1038 }
1039
1040 if (TS_del_multi_chars)
1041 {
1042 del_cost_per_char = 0;
1043 del_startup_cost = string_cost_one_line (TS_del_multi_chars);
1044 }
1045 else if (TS_del_char)
1046 {
1047 del_startup_cost = (string_cost (TS_delete_mode)
1048 + string_cost (TS_end_delete_mode));
1049 if (delete_in_insert_mode)
1050 del_startup_cost /= 2;
1051 del_cost_per_char = string_cost_one_line (TS_del_char);
1052 }
1053 else
1054 {
1055 del_startup_cost = 9999;
1056 del_cost_per_char = 0;
1057 }
1058
1059 /* Delete costs are at negative offsets */
ff11dfa1
JB
1060 p = &char_ins_del_cost (frame)[0];
1061 for (i = FRAME_WIDTH (selected_frame); --i >= 0;)
08a24c47
JB
1062 *--p = (del_startup_cost += del_cost_per_char);
1063
1064 /* Doing nothing is free */
ff11dfa1 1065 p = &char_ins_del_cost (frame)[0];
08a24c47
JB
1066 *p++ = 0;
1067
1068 /* Insert costs are at positive offsets */
ff11dfa1 1069 for (i = FRAME_WIDTH (frame); --i >= 0;)
08a24c47
JB
1070 *p++ = (ins_startup_cost += ins_cost_per_char);
1071}
1072
1073#ifdef HAVE_X_WINDOWS
e7308e06 1074extern int x_screen_planes;
08a24c47
JB
1075#endif
1076
a790fee2
JB
1077extern do_line_insertion_deletion_costs ();
1078
ff11dfa1
JB
1079calculate_costs (frame)
1080 FRAME_PTR frame;
08a24c47 1081{
ff11dfa1 1082 register char *f = TS_set_scroll_region ?
08a24c47
JB
1083 TS_set_scroll_region
1084 : TS_set_scroll_region_1;
1085
1086 if (dont_calculate_costs)
1087 return;
1088
1089#ifdef HAVE_X_WINDOWS
1820044b 1090 if (FRAME_X_P (frame))
08a24c47 1091 {
ff11dfa1 1092 do_line_insertion_deletion_costs (frame, 0, ".5*", 0, ".5*",
e7308e06 1093 0, 0, x_screen_planes);
08a24c47
JB
1094 return;
1095 }
1096#endif
1097
1098 /* These variables are only used for terminal stuff. They are allocated
ff11dfa1 1099 once for the terminal frame of X-windows emacs, but not used afterwards.
08a24c47
JB
1100
1101 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1102 X turns off char_ins_del_ok.
1103
1104 chars_wasted and copybuf are only used here in term.c in cases where
1105 the term hook isn't called. */
1106
1107 if (chars_wasted != 0)
ff11dfa1 1108 chars_wasted = (char *) xrealloc (chars_wasted, FRAME_HEIGHT (frame));
08a24c47 1109 else
ff11dfa1 1110 chars_wasted = (char *) xmalloc (FRAME_HEIGHT (frame));
08a24c47
JB
1111
1112 if (copybuf != 0)
ff11dfa1 1113 copybuf = (char *) xrealloc (copybuf, FRAME_HEIGHT (frame));
08a24c47 1114 else
ff11dfa1 1115 copybuf = (char *) xmalloc (FRAME_HEIGHT (frame));
08a24c47
JB
1116
1117 if (char_ins_del_vector != 0)
1118 char_ins_del_vector
1119 = (int *) xrealloc (char_ins_del_vector,
1120 (sizeof (int)
ff11dfa1 1121 + 2 * FRAME_WIDTH (frame) * sizeof (int)));
08a24c47
JB
1122 else
1123 char_ins_del_vector
1124 = (int *) xmalloc (sizeof (int)
ff11dfa1 1125 + 2 * FRAME_WIDTH (frame) * sizeof (int));
08a24c47 1126
ff11dfa1
JB
1127 bzero (chars_wasted, FRAME_HEIGHT (frame));
1128 bzero (copybuf, FRAME_HEIGHT (frame));
08a24c47 1129 bzero (char_ins_del_vector, (sizeof (int)
ff11dfa1 1130 + 2 * FRAME_WIDTH (frame) * sizeof (int)));
08a24c47 1131
ff11dfa1
JB
1132 if (f && (!TS_ins_line && !TS_del_line))
1133 do_line_insertion_deletion_costs (frame,
08a24c47
JB
1134 TS_rev_scroll, TS_ins_multi_lines,
1135 TS_fwd_scroll, TS_del_multi_lines,
ff11dfa1 1136 f, f, 1);
08a24c47 1137 else
ff11dfa1 1138 do_line_insertion_deletion_costs (frame,
08a24c47
JB
1139 TS_ins_line, TS_ins_multi_lines,
1140 TS_del_line, TS_del_multi_lines,
1141 0, 0, 1);
1142
ff11dfa1 1143 calculate_ins_del_char_costs (frame);
08a24c47
JB
1144
1145 /* Don't use TS_repeat if its padding is worse than sending the chars */
1146 if (TS_repeat && per_line_cost (TS_repeat) * baud_rate < 9000)
1147 RPov = string_cost (TS_repeat);
1148 else
ff11dfa1 1149 RPov = FRAME_WIDTH (frame) * 2;
08a24c47
JB
1150
1151 cmcostinit (); /* set up cursor motion costs */
1152}
1153\f
a796ac82
JB
1154struct fkey_table {
1155 char *cap, *name;
1156};
1157
01d8deb0
ER
1158 /* Termcap capability names that correspond directly to X keysyms.
1159 Some of these (marked "terminfo") aren't supplied by old-style
1160 (Berkeley) termcap entries. They're listed in X keysym order;
1161 except we put the keypad keys first, so that if they clash with
1162 other keys (as on the IBM PC keyboard) they get overridden.
1163 */
1164
a796ac82 1165static struct fkey_table keys[] = {
01d8deb0
ER
1166 "kh", "home", /* termcap */
1167 "kl", "left", /* termcap */
1168 "ku", "up", /* termcap */
1169 "kr", "right", /* termcap */
1170 "kd", "down", /* termcap */
1171 "%8", "prior", /* terminfo */
1172 "%5", "next", /* terminfo */
1173 "@7", "end", /* terminfo */
1174 "@1", "begin", /* terminfo */
1175 "*6", "select", /* terminfo */
1176 "%9", "print", /* terminfo */
1177 "@4", "execute", /* terminfo --- actually the `command' key */
1178 /*
1179 * "insert" --- see below
1180 */
1181 "&8", "undo", /* terminfo */
1182 "%0", "redo", /* terminfo */
1183 "%7", "menu", /* terminfo --- actually the `options' key */
1184 "@0", "find", /* terminfo */
1185 "@2", "cancel", /* terminfo */
1186 "%1", "help", /* terminfo */
1187 /*
1188 * "break" goes here, but can't be reliably intercepted with termcap
1189 */
1190 "&4", "reset", /* terminfo --- actually `restart' */
1191 /*
1192 * "system" and "user" --- no termcaps
1193 */
1194 "kE", "clearline", /* terminfo */
1195 "kA", "insertline", /* terminfo */
1196 "kL", "deleteline", /* terminfo */
1197 "kI", "insertchar", /* terminfo */
1198 "kD", "deletechar", /* terminfo */
1199 "kB", "backtab", /* terminfo */
1200 /*
1201 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1202 */
1203 "@8", "kp-enter", /* terminfo */
1204 /*
1205 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1206 * "kp-multiply", "kp-add", "kp-separator",
1207 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1208 * --- no termcaps for any of these.
1209 */
1210 "K4", "kp-1", /* terminfo */
1211 /*
1212 * "kp-2" --- no termcap
1213 */
1214 "K5", "kp-3", /* terminfo */
1215 /*
1216 * "kp-4" --- no termcap
1217 */
1218 "K2", "kp-5", /* terminfo */
1219 /*
1220 * "kp-6" --- no termcap
1221 */
1222 "K1", "kp-7", /* terminfo */
1223 /*
1224 * "kp-8" --- no termcap
1225 */
1226 "K3", "kp-9", /* terminfo */
1227 /*
1228 * "kp-equal" --- no termcap
1229 */
1230 "k1", "f1",
1231 "k2", "f2",
1232 "k3", "f3",
1233 "k4", "f4",
1234 "k5", "f5",
1235 "k6", "f6",
1236 "k7", "f7",
1237 "k8", "f8",
1238 "k9", "f9",
a796ac82
JB
1239 };
1240
f2a00342
RM
1241static char **term_get_fkeys_arg;
1242static Lisp_Object term_get_fkeys_1 ();
465db27b 1243
01d8deb0
ER
1244/* Find the escape codes sent by the function keys for Vfunction_key_map.
1245 This function scans the termcap function key sequence entries, and
1246 adds entries to Vfunction_key_map for each function key it finds. */
1247
5c2c7893
JB
1248void
1249term_get_fkeys (address)
1250 char **address;
f2a00342
RM
1251{
1252 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1253 errors during the call. The only errors should be from Fdefine_key
1254 when given a key sequence containing an invalid prefix key. If the
1255 termcap defines function keys which use a prefix that is already bound
1256 to a command by the default bindings, we should silently ignore that
1257 function key specification, rather than giving the user an error and
1258 refusing to run at all on such a terminal. */
1259
1260 extern Lisp_Object Fidentity ();
f2a00342
RM
1261 term_get_fkeys_arg = address;
1262 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1263}
1264
1265static Lisp_Object
1266term_get_fkeys_1 ()
5c2c7893 1267{
5c2c7893
JB
1268 int i;
1269
37085233 1270 char **address = term_get_fkeys_arg;
f778aff2 1271
3e65092f
RS
1272 /* This can happen if CANNOT_DUMP or with strange options. */
1273 if (!initialized)
1274 Vfunction_key_map = Fmake_sparse_keymap (Qnil);
1275
5c2c7893
JB
1276 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1277 {
1278 char *sequence = tgetstr (keys[i].cap, address);
1279 if (sequence)
f2a00342
RM
1280 Fdefine_key (Vfunction_key_map, build_string (sequence),
1281 Fmake_vector (make_number (1),
1282 intern (keys[i].name)));
5c2c7893 1283 }
a796ac82
JB
1284
1285 /* The uses of the "k0" capability are inconsistent; sometimes it
1286 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
eb8c3be9 1287 We will attempt to politely accommodate both systems by testing for
a796ac82
JB
1288 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1289 */
1290 {
1291 char *k_semi = tgetstr ("k;", address);
1292 char *k0 = tgetstr ("k0", address);
1293 char *k0_name = "f10";
1294
1295 if (k_semi)
1296 {
f2a00342
RM
1297 Fdefine_key (Vfunction_key_map, build_string (k_semi),
1298 Fmake_vector (make_number (1), intern ("f10")));
a796ac82
JB
1299 k0_name = "f0";
1300 }
1301
1302 if (k0)
f2a00342
RM
1303 Fdefine_key (Vfunction_key_map, build_string (k0),
1304 Fmake_vector (make_number (1), intern (k0_name)));
a796ac82 1305 }
01d8deb0
ER
1306
1307 /* Set up cookies for numbered function keys above f10. */
1308 {
1309 char fcap[3], fkey[4];
1310
fc4f24da 1311 fcap[0] = 'F'; fcap[2] = '\0';
01d8deb0
ER
1312 for (i = 11; i < 64; i++)
1313 {
1314 if (i <= 19)
1315 fcap[1] = '1' + i - 11;
1316 else if (i <= 45)
1317 fcap[1] = 'A' + i - 11;
1318 else
1319 fcap[1] = 'a' + i - 11;
1320
fc4f24da
RS
1321 {
1322 char *sequence = tgetstr (fcap, address);
1323 if (sequence)
1324 {
465db27b 1325 sprintf (fkey, "f%d", i);
f2a00342
RM
1326 Fdefine_key (Vfunction_key_map, build_string (sequence),
1327 Fmake_vector (make_number (1),
1328 intern (fkey)));
fc4f24da
RS
1329 }
1330 }
01d8deb0
ER
1331 }
1332 }
1333
1334 /*
1335 * Various mappings to try and get a better fit.
1336 */
1337 {
fc4f24da
RS
1338#define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1339 if (!tgetstr (cap1, address)) \
1340 { \
1341 char *sequence = tgetstr (cap2, address); \
1342 if (sequence) \
f2a00342
RM
1343 Fdefine_key (Vfunction_key_map, build_string (sequence), \
1344 Fmake_vector (make_number (1), \
1345 intern (sym))); \
fc4f24da 1346 }
01d8deb0
ER
1347
1348 /* if there's no key_next keycap, map key_npage to `next' keysym */
27b61785 1349 CONDITIONAL_REASSIGN ("%5", "kN", "next");
01d8deb0 1350 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
381d11a1 1351 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
01d8deb0 1352 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
27b61785 1353 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1dd40212 1354#undef CONDITIONAL_REASSIGN
01d8deb0 1355 }
5c2c7893
JB
1356}
1357
1358\f
08a24c47
JB
1359term_init (terminal_type)
1360 char *terminal_type;
1361{
1362 char *area;
1363 char **address = &area;
1364 char buffer[2044];
1365 register char *p;
1366 int status;
1367
08a24c47
JB
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 {
e4bfb3b6 1516 char *s = tgetstr ("me", address);
afd359c4
RS
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}