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