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