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