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