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