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