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