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