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