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