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