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