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