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