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