Use -gcoff instead of -g in CFLAGS, for those who
[emacs.git] / src / term.c
blob112722cfa78fef735ed1834ab7f30eaa30456e55
1 /* terminal control module for terminals described by TERMCAP
2 Copyright (C) 1985, 86, 87, 93, 94, 95 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
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.
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.
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. */
22 #include <config.h>
23 #include <stdio.h>
24 #include <ctype.h>
25 #include "termchar.h"
26 #include "termopts.h"
27 #undef NULL
28 #include "lisp.h"
29 #include "charset.h"
30 #include "coding.h"
31 #include "frame.h"
32 #include "disptab.h"
33 #include "termhooks.h"
34 #include "keyboard.h"
35 #include "dispextern.h"
36 #include "cm.h"
37 #ifdef HAVE_X_WINDOWS
38 #include "xterm.h"
39 #endif
41 #define max(a, b) ((a) > (b) ? (a) : (b))
42 #define min(a, b) ((a) < (b) ? (a) : (b))
44 #define OUTPUT(a) tputs (a, (int) (FRAME_HEIGHT (selected_frame) - curY), cmputc)
45 #define OUTPUT1(a) tputs (a, 1, cmputc)
46 #define OUTPUTL(a, lines) tputs (a, lines, cmputc)
47 #define OUTPUT_IF(a) { if (a) tputs (a, (int) (FRAME_HEIGHT (selected_frame) - curY), cmputc); }
48 #define OUTPUT1_IF(a) { if (a) tputs (a, 1, cmputc); }
50 /* Function to use to ring the bell. */
51 Lisp_Object Vring_bell_function;
53 /* Terminal characteristics that higher levels want to look at.
54 These are all extern'd in termchar.h */
56 int must_write_spaces; /* Nonzero means spaces in the text
57 must actually be output; can't just skip
58 over some columns to leave them blank. */
59 int min_padding_speed; /* Speed below which no padding necessary */
61 int line_ins_del_ok; /* Terminal can insert and delete lines */
62 int char_ins_del_ok; /* Terminal can insert and delete chars */
63 int scroll_region_ok; /* Terminal supports setting the
64 scroll window */
65 int scroll_region_cost; /* Cost of setting a scroll window,
66 measured in characters */
67 int memory_below_frame; /* Terminal remembers lines
68 scrolled off bottom */
69 int fast_clear_end_of_line; /* Terminal has a `ce' string */
71 /* Nonzero means no need to redraw the entire frame on resuming
72 a suspended Emacs. This is useful on terminals with multiple pages,
73 where one page is used for Emacs and another for all else. */
74 int no_redraw_on_reenter;
76 /* Hook functions that you can set to snap out the functions in this file.
77 These are all extern'd in termhooks.h */
79 void (*cursor_to_hook) P_ ((int, int));
80 void (*raw_cursor_to_hook) P_ ((int, int));
82 void (*clear_to_end_hook) P_ ((void));
83 void (*clear_frame_hook) P_ ((void));
84 void (*clear_end_of_line_hook) P_ ((int));
86 void (*ins_del_lines_hook) P_ ((int, int));
88 void (*change_line_highlight_hook) P_ ((int, int, int));
89 void (*reassert_line_highlight_hook) P_ ((int, int));
91 void (*insert_glyphs_hook) P_ ((GLYPH *, int));
92 void (*write_glyphs_hook) P_ ((GLYPH *, int));
93 void (*delete_glyphs_hook) P_ ((int));
95 void (*ring_bell_hook) P_ ((void));
97 void (*reset_terminal_modes_hook) P_ ((void));
98 void (*set_terminal_modes_hook) P_ ((void));
99 void (*update_begin_hook) P_ ((struct frame *));
100 void (*update_end_hook) P_ ((struct frame *));
101 void (*set_terminal_window_hook) P_ ((int));
103 int (*read_socket_hook) P_ ((int, struct input_event *, int, int));
105 void (*frame_up_to_date_hook) P_ ((struct frame *));
107 /* Return the current position of the mouse.
109 Set *f to the frame the mouse is in, or zero if the mouse is in no
110 Emacs frame. If it is set to zero, all the other arguments are
111 garbage.
113 If the motion started in a scroll bar, set *bar_window to the
114 scroll bar's window, *part to the part the mouse is currently over,
115 *x to the position of the mouse along the scroll bar, and *y to the
116 overall length of the scroll bar.
118 Otherwise, set *bar_window to Qnil, and *x and *y to the column and
119 row of the character cell the mouse is over.
121 Set *time to the time the mouse was at the returned position.
123 This should clear mouse_moved until the next motion
124 event arrives. */
125 void (*mouse_position_hook) P_ ((FRAME_PTR *f, int insist,
126 Lisp_Object *bar_window,
127 enum scroll_bar_part *part,
128 Lisp_Object *x,
129 Lisp_Object *y,
130 unsigned long *time));
132 /* When reading from a minibuffer in a different frame, Emacs wants
133 to shift the highlight from the selected frame to the minibuffer's
134 frame; under X, this means it lies about where the focus is.
135 This hook tells the window system code to re-decide where to put
136 the highlight. */
137 void (*frame_rehighlight_hook) P_ ((FRAME_PTR f));
139 /* If we're displaying frames using a window system that can stack
140 frames on top of each other, this hook allows you to bring a frame
141 to the front, or bury it behind all the other windows. If this
142 hook is zero, that means the device we're displaying on doesn't
143 support overlapping frames, so there's no need to raise or lower
144 anything.
146 If RAISE is non-zero, F is brought to the front, before all other
147 windows. If RAISE is zero, F is sent to the back, behind all other
148 windows. */
149 void (*frame_raise_lower_hook) P_ ((FRAME_PTR f, int raise));
151 /* Set the vertical scroll bar for WINDOW to have its upper left corner
152 at (TOP, LEFT), and be LENGTH rows high. Set its handle to
153 indicate that we are displaying PORTION characters out of a total
154 of WHOLE characters, starting at POSITION. If WINDOW doesn't yet
155 have a scroll bar, create one for it. */
156 void (*set_vertical_scroll_bar_hook)
157 P_ ((struct window *window,
158 int portion, int whole, int position));
161 /* The following three hooks are used when we're doing a thorough
162 redisplay of the frame. We don't explicitly know which scroll bars
163 are going to be deleted, because keeping track of when windows go
164 away is a real pain - can you say set-window-configuration?
165 Instead, we just assert at the beginning of redisplay that *all*
166 scroll bars are to be removed, and then save scroll bars from the
167 fiery pit when we actually redisplay their window. */
169 /* Arrange for all scroll bars on FRAME to be removed at the next call
170 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
171 `*redeem_scroll_bar_hook' is applied to its window before the judgement.
173 This should be applied to each frame each time its window tree is
174 redisplayed, even if it is not displaying scroll bars at the moment;
175 if the HAS_SCROLL_BARS flag has just been turned off, only calling
176 this and the judge_scroll_bars_hook will get rid of them.
178 If non-zero, this hook should be safe to apply to any frame,
179 whether or not it can support scroll bars, and whether or not it is
180 currently displaying them. */
181 void (*condemn_scroll_bars_hook) P_ ((FRAME_PTR frame));
183 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
184 Note that it's okay to redeem a scroll bar that is not condemned. */
185 void (*redeem_scroll_bar_hook) P_ ((struct window *window));
187 /* Remove all scroll bars on FRAME that haven't been saved since the
188 last call to `*condemn_scroll_bars_hook'.
190 This should be applied to each frame after each time its window
191 tree is redisplayed, even if it is not displaying scroll bars at the
192 moment; if the HAS_SCROLL_BARS flag has just been turned off, only
193 calling this and condemn_scroll_bars_hook will get rid of them.
195 If non-zero, this hook should be safe to apply to any frame,
196 whether or not it can support scroll bars, and whether or not it is
197 currently displaying them. */
198 void (*judge_scroll_bars_hook) P_ ((FRAME_PTR FRAME));
201 /* Strings, numbers and flags taken from the termcap entry. */
203 char *TS_end_italic_mode; /* termcap "ae" */
204 char *TS_ins_line; /* "al" */
205 char *TS_italic_mode; /* "as" */
206 char *TS_ins_multi_lines; /* "AL" (one parameter, # lines to insert) */
207 char *TS_bell; /* "bl" */
208 char *TS_clr_to_bottom; /* "cd" */
209 char *TS_clr_line; /* "ce", clear to end of line */
210 char *TS_clr_frame; /* "cl" */
211 char *TS_set_scroll_region; /* "cs" (2 params, first line and last line) */
212 char *TS_set_scroll_region_1; /* "cS" (4 params: total lines,
213 lines above scroll region, lines below it,
214 total lines again) */
215 char *TS_del_char; /* "dc" */
216 char *TS_del_multi_chars; /* "DC" (one parameter, # chars to delete) */
217 char *TS_del_line; /* "dl" */
218 char *TS_del_multi_lines; /* "DL" (one parameter, # lines to delete) */
219 char *TS_delete_mode; /* "dm", enter character-delete mode */
220 char *TS_end_delete_mode; /* "ed", leave character-delete mode */
221 char *TS_end_insert_mode; /* "ei", leave character-insert mode */
222 char *TS_ins_char; /* "ic" */
223 char *TS_ins_multi_chars; /* "IC" (one parameter, # chars to insert) */
224 char *TS_insert_mode; /* "im", enter character-insert mode */
225 char *TS_pad_inserted_char; /* "ip". Just padding, no commands. */
226 char *TS_end_keypad_mode; /* "ke" */
227 char *TS_keypad_mode; /* "ks" */
228 char *TS_bold_mode; /* "md" */
229 char *TS_end_bold_mode; /* "me" */
230 char *TS_pad_char; /* "pc", char to use as padding */
231 char *TS_repeat; /* "rp" (2 params, # times to repeat
232 and character to be repeated) */
233 char *TS_end_standout_mode; /* "se" */
234 char *TS_fwd_scroll; /* "sf" */
235 char *TS_standout_mode; /* "so" */
236 char *TS_rev_scroll; /* "sr" */
237 char *TS_end_termcap_modes; /* "te" */
238 char *TS_termcap_modes; /* "ti" */
239 char *TS_end_underscore_mode; /* "ue" */
240 char *TS_underscore_mode; /* "us" */
241 char *TS_visible_bell; /* "vb" */
242 char *TS_end_visual_mode; /* "ve" */
243 char *TS_visual_mode; /* "vi" */
244 char *TS_set_window; /* "wi" (4 params, start and end of window,
245 each as vpos and hpos) */
247 int TF_hazeltine; /* termcap hz flag. */
248 int TF_insmode_motion; /* termcap mi flag: can move while in insert mode. */
249 int TF_standout_motion; /* termcap mi flag: can move while in standout mode. */
250 int TF_underscore; /* termcap ul flag: _ underlines if overstruck on
251 nonblank position. Must clear before writing _. */
252 int TF_teleray; /* termcap xt flag: many weird consequences.
253 For t1061. */
255 int TF_xs; /* Nonzero for "xs". If set together with
256 TN_standout_width == 0, it means don't bother
257 to write any end-standout cookies. */
259 int TN_standout_width; /* termcap sg number: width occupied by standout
260 markers */
262 static int RPov; /* # chars to start a TS_repeat */
264 static int delete_in_insert_mode; /* delete mode == insert mode */
266 static int se_is_so; /* 1 if same string both enters and leaves
267 standout mode */
269 /* internal state */
271 /* The largest frame width in any call to calculate_costs. */
272 int max_frame_width;
273 /* The largest frame height in any call to calculate_costs. */
274 int max_frame_height;
276 /* Number of chars of space used for standout marker at beginning of line,
277 or'd with 0100. Zero if no standout marker at all.
278 The length of these vectors is max_frame_height.
280 Used IFF TN_standout_width >= 0. */
282 static char *chars_wasted;
283 static char *copybuf;
285 /* nonzero means supposed to write text in standout mode. */
286 int standout_requested;
288 int insert_mode; /* Nonzero when in insert mode. */
289 int standout_mode; /* Nonzero when in standout mode. */
291 /* Size of window specified by higher levels.
292 This is the number of lines, from the top of frame downwards,
293 which can participate in insert-line/delete-line operations.
295 Effectively it excludes the bottom frame_height - specified_window_size
296 lines from those operations. */
298 int specified_window;
300 /* Frame currently being redisplayed; 0 if not currently redisplaying.
301 (Direct output does not count). */
303 FRAME_PTR updating_frame;
305 /* Provided for lisp packages. */
306 static int system_uses_terminfo;
308 char *tparam ();
310 extern char *tgetstr ();
313 #ifdef WINDOWSNT
314 /* We aren't X windows, but we aren't termcap either. This makes me
315 uncertain as to what value to use for frame.output_method. For
316 this file, we'll define FRAME_TERMCAP_P to be zero so that our
317 output hooks get called instead of the termcap functions. Probably
318 the best long-term solution is to define an output_windows_nt... */
320 #undef FRAME_TERMCAP_P
321 #define FRAME_TERMCAP_P(_f_) 0
322 #endif /* WINDOWSNT */
324 void
325 ring_bell ()
327 if (! NILP (Vring_bell_function))
329 Lisp_Object function;
331 /* Temporarily set the global variable to nil
332 so that if we get an error, it stays nil
333 and we don't call it over and over.
335 We don't specbind it, because that would carefully
336 restore the bad value if there's an error
337 and make the loop of errors happen anyway. */
338 function = Vring_bell_function;
339 Vring_bell_function = Qnil;
341 call0 (function);
343 Vring_bell_function = function;
344 return;
347 if (! FRAME_TERMCAP_P (selected_frame))
349 (*ring_bell_hook) ();
350 return;
352 OUTPUT (TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell);
355 void
356 set_terminal_modes ()
358 if (! FRAME_TERMCAP_P (selected_frame))
360 (*set_terminal_modes_hook) ();
361 return;
363 OUTPUT_IF (TS_termcap_modes);
364 OUTPUT_IF (TS_visual_mode);
365 OUTPUT_IF (TS_keypad_mode);
366 losecursor ();
369 void
370 reset_terminal_modes ()
372 if (! FRAME_TERMCAP_P (selected_frame))
374 if (reset_terminal_modes_hook)
375 (*reset_terminal_modes_hook) ();
376 return;
378 if (TN_standout_width < 0)
379 turn_off_highlight ();
380 turn_off_insert ();
381 OUTPUT_IF (TS_end_keypad_mode);
382 OUTPUT_IF (TS_end_visual_mode);
383 OUTPUT_IF (TS_end_termcap_modes);
384 /* Output raw CR so kernel can track the cursor hpos. */
385 /* But on magic-cookie terminals this can erase an end-standout marker and
386 cause the rest of the frame to be in standout, so move down first. */
387 if (TN_standout_width >= 0)
388 cmputc ('\n');
389 cmputc ('\r');
392 void
393 update_begin (f)
394 FRAME_PTR f;
396 updating_frame = f;
397 if (! FRAME_TERMCAP_P (updating_frame))
398 (*update_begin_hook) (f);
401 void
402 update_end (f)
403 FRAME_PTR f;
405 if (! FRAME_TERMCAP_P (updating_frame))
407 (*update_end_hook) (f);
408 updating_frame = 0;
409 return;
411 turn_off_insert ();
412 background_highlight ();
413 standout_requested = 0;
414 updating_frame = 0;
417 void
418 set_terminal_window (size)
419 int size;
421 if (! FRAME_TERMCAP_P (updating_frame))
423 (*set_terminal_window_hook) (size);
424 return;
426 specified_window = size ? size : FRAME_HEIGHT (selected_frame);
427 if (!scroll_region_ok)
428 return;
429 set_scroll_region (0, specified_window);
432 void
433 set_scroll_region (start, stop)
434 int start, stop;
436 char *buf;
437 if (TS_set_scroll_region)
439 buf = tparam (TS_set_scroll_region, 0, 0, start, stop - 1);
441 else if (TS_set_scroll_region_1)
443 buf = tparam (TS_set_scroll_region_1, 0, 0,
444 FRAME_HEIGHT (selected_frame), start,
445 FRAME_HEIGHT (selected_frame) - stop,
446 FRAME_HEIGHT (selected_frame));
448 else
450 buf = tparam (TS_set_window, 0, 0, start, 0, stop, FRAME_WIDTH (selected_frame));
452 OUTPUT (buf);
453 xfree (buf);
454 losecursor ();
457 void
458 turn_on_insert ()
460 if (!insert_mode)
461 OUTPUT (TS_insert_mode);
462 insert_mode = 1;
465 void
466 turn_off_insert ()
468 if (insert_mode)
469 OUTPUT (TS_end_insert_mode);
470 insert_mode = 0;
473 /* Handle highlighting when TN_standout_width (termcap sg) is not specified.
474 In these terminals, output is affected by the value of standout
475 mode when the output is written.
477 These functions are called on all terminals, but do nothing
478 on terminals whose standout mode does not work that way. */
480 void
481 turn_off_highlight ()
483 if (TN_standout_width < 0)
485 if (standout_mode)
486 OUTPUT_IF (TS_end_standout_mode);
487 standout_mode = 0;
491 void
492 turn_on_highlight ()
494 if (TN_standout_width < 0)
496 if (!standout_mode)
497 OUTPUT_IF (TS_standout_mode);
498 standout_mode = 1;
502 /* Set standout mode to the state it should be in for
503 empty space inside windows. What this is,
504 depends on the user option inverse-video. */
506 void
507 background_highlight ()
509 if (TN_standout_width >= 0)
510 return;
511 if (inverse_video)
512 turn_on_highlight ();
513 else
514 turn_off_highlight ();
517 /* Set standout mode to the mode specified for the text to be output. */
519 static void
520 highlight_if_desired ()
522 if (TN_standout_width >= 0)
523 return;
524 if (!inverse_video == !standout_requested)
525 turn_off_highlight ();
526 else
527 turn_on_highlight ();
530 /* Handle standout mode for terminals in which TN_standout_width >= 0.
531 On these terminals, standout is controlled by markers that
532 live inside the terminal's memory. TN_standout_width is the width
533 that the marker occupies in memory. Standout runs from the marker
534 to the end of the line on some terminals, or to the next
535 turn-off-standout marker (TS_end_standout_mode) string
536 on other terminals. */
538 /* Write a standout marker or end-standout marker at the front of the line
539 at vertical position vpos. */
541 void
542 write_standout_marker (flag, vpos)
543 int flag, vpos;
545 if (flag || (TS_end_standout_mode && !TF_teleray && !se_is_so
546 && !(TF_xs && TN_standout_width == 0)))
548 cmgoto (vpos, 0);
549 cmplus (TN_standout_width);
550 OUTPUT (flag ? TS_standout_mode : TS_end_standout_mode);
551 chars_wasted[curY] = TN_standout_width | 0100;
555 /* External interface to control of standout mode.
556 Call this when about to modify line at position VPOS
557 and not change whether it is highlighted. */
559 void
560 reassert_line_highlight (highlight, vpos)
561 int highlight;
562 int vpos;
564 if (! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
566 (*reassert_line_highlight_hook) (highlight, vpos);
567 return;
569 if (TN_standout_width < 0)
570 /* Handle terminals where standout takes affect at output time */
571 standout_requested = highlight;
572 else if (chars_wasted[vpos] == 0)
573 /* For terminals with standout markers, write one on this line
574 if there isn't one already. */
575 write_standout_marker (highlight, vpos);
578 /* Call this when about to modify line at position VPOS
579 and change whether it is highlighted. */
581 void
582 change_line_highlight (new_highlight, vpos, first_unused_hpos)
583 int new_highlight, vpos, first_unused_hpos;
585 standout_requested = new_highlight;
586 if (! FRAME_TERMCAP_P (updating_frame))
588 (*change_line_highlight_hook) (new_highlight, vpos, first_unused_hpos);
589 return;
592 cursor_to (vpos, 0);
594 if (TN_standout_width < 0)
595 background_highlight ();
596 /* If line starts with a marker, delete the marker */
597 else if (TS_clr_line && chars_wasted[curY])
599 turn_off_insert ();
600 /* On Teleray, make sure to erase the SO marker. */
601 if (TF_teleray)
603 cmgoto (curY - 1, FRAME_WIDTH (selected_frame) - 4);
604 OUTPUT ("\033S");
605 curY++; /* ESC S moves to next line where the TS_standout_mode was */
606 curX = 0;
608 else
609 cmgoto (curY, 0); /* reposition to kill standout marker */
611 clear_end_of_line_raw (first_unused_hpos);
612 reassert_line_highlight (new_highlight, curY);
616 /* Move to absolute position, specified origin 0 */
618 void
619 cursor_to (row, col)
620 int row, col;
622 if (! FRAME_TERMCAP_P ((updating_frame
623 ? updating_frame
624 : selected_frame))
625 && cursor_to_hook)
627 (*cursor_to_hook) (row, col);
628 return;
631 /* Detect the case where we are called from reset_sys_modes
632 and the costs have never been calculated. Do nothing. */
633 if (chars_wasted == 0)
634 return;
636 col += chars_wasted[row] & 077;
637 if (curY == row && curX == col)
638 return;
639 if (!TF_standout_motion)
640 background_highlight ();
641 if (!TF_insmode_motion)
642 turn_off_insert ();
643 cmgoto (row, col);
646 /* Similar but don't take any account of the wasted characters. */
648 void
649 raw_cursor_to (row, col)
650 int row, col;
652 if (! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
654 (*raw_cursor_to_hook) (row, col);
655 return;
657 if (curY == row && curX == col)
658 return;
659 if (!TF_standout_motion)
660 background_highlight ();
661 if (!TF_insmode_motion)
662 turn_off_insert ();
663 cmgoto (row, col);
666 /* Erase operations */
668 /* clear from cursor to end of frame */
669 void
670 clear_to_end ()
672 register int i;
674 if (clear_to_end_hook && ! FRAME_TERMCAP_P (updating_frame))
676 (*clear_to_end_hook) ();
677 return;
679 if (TS_clr_to_bottom)
681 background_highlight ();
682 OUTPUT (TS_clr_to_bottom);
683 bzero (chars_wasted + curY, FRAME_HEIGHT (selected_frame) - curY);
685 else
687 for (i = curY; i < FRAME_HEIGHT (selected_frame); i++)
689 cursor_to (i, 0);
690 clear_end_of_line_raw (FRAME_WIDTH (selected_frame));
695 /* Clear entire frame */
697 void
698 clear_frame ()
700 if (clear_frame_hook
701 && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
703 (*clear_frame_hook) ();
704 return;
706 if (TS_clr_frame)
708 background_highlight ();
709 OUTPUT (TS_clr_frame);
710 bzero (chars_wasted, FRAME_HEIGHT (selected_frame));
711 cmat (0, 0);
713 else
715 cursor_to (0, 0);
716 clear_to_end ();
720 /* Clear to end of line, but do not clear any standout marker.
721 Assumes that the cursor is positioned at a character of real text,
722 which implies it cannot be before a standout marker
723 unless the marker has zero width.
725 Note that the cursor may be moved. */
727 void
728 clear_end_of_line (first_unused_hpos)
729 int first_unused_hpos;
731 static GLYPH buf = SPACEGLYPH;
732 if (FRAME_TERMCAP_P (selected_frame)
733 && chars_wasted != 0
734 && TN_standout_width == 0 && curX == 0 && chars_wasted[curY] != 0)
735 write_glyphs (&buf, 1);
736 clear_end_of_line_raw (first_unused_hpos);
739 /* Clear from cursor to end of line.
740 Assume that the line is already clear starting at column first_unused_hpos.
741 If the cursor is at a standout marker, erase the marker.
743 Note that the cursor may be moved, on terminals lacking a `ce' string. */
745 void
746 clear_end_of_line_raw (first_unused_hpos)
747 int first_unused_hpos;
749 register int i;
751 if (clear_end_of_line_hook
752 && ! FRAME_TERMCAP_P ((updating_frame
753 ? updating_frame
754 : selected_frame)))
756 (*clear_end_of_line_hook) (first_unused_hpos);
757 return;
760 /* Detect the case where we are called from reset_sys_modes
761 and the costs have never been calculated. Do nothing. */
762 if (chars_wasted == 0)
763 return;
765 first_unused_hpos += chars_wasted[curY] & 077;
766 if (curX >= first_unused_hpos)
767 return;
768 /* Notice if we are erasing a magic cookie */
769 if (curX == 0)
770 chars_wasted[curY] = 0;
771 background_highlight ();
772 if (TS_clr_line)
774 OUTPUT1 (TS_clr_line);
776 else
777 { /* have to do it the hard way */
778 turn_off_insert ();
780 /* Do not write in last row last col with Autowrap on. */
781 if (AutoWrap && curY == FRAME_HEIGHT (selected_frame) - 1
782 && first_unused_hpos == FRAME_WIDTH (selected_frame))
783 first_unused_hpos--;
785 for (i = curX; i < first_unused_hpos; i++)
787 if (termscript)
788 fputc (' ', termscript);
789 putchar (' ');
791 cmplus (first_unused_hpos - curX);
795 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes and
796 store them at DST. Do not write more than DST_LEN bytes. That may
797 require stopping before all SRC_LEN input glyphs have been
798 converted.
800 We store the number of glyphs actually converted in *CONSUMED. The
801 return value is the number of bytes store in DST. */
804 encode_terminal_code (src, dst, src_len, dst_len, consumed)
805 GLYPH *src;
806 int src_len;
807 unsigned char *dst;
808 int dst_len, *consumed;
810 GLYPH *src_start = src, *src_end = src + src_len;
811 unsigned char *dst_start = dst, *dst_end = dst + dst_len;
812 register GLYPH g;
813 unsigned int c;
814 unsigned char workbuf[4], *buf;
815 int len;
816 register int tlen = GLYPH_TABLE_LENGTH;
817 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
818 int result;
819 struct coding_system *coding;
821 coding = (CODING_REQUIRE_ENCODING (&terminal_coding)
822 ? &terminal_coding
823 : &safe_terminal_coding);
825 while (src < src_end)
827 g = *src;
828 /* We must skip glyphs to be padded for a wide character. */
829 if (! (g & GLYPH_MASK_PADDING))
831 if ((c = GLYPH_CHAR (selected_frame, g)) > MAX_CHAR)
833 c = ' ';
834 g = MAKE_GLYPH (selected_frame, c,
835 GLYPH_FACE (selected_frame, g));
837 if (COMPOSITE_CHAR_P (c))
839 /* If C is a composite character, we can display
840 only the first component. */
841 g = cmpchar_table[COMPOSITE_CHAR_ID (c)]->glyph[0],
842 c = GLYPH_CHAR (selected_frame, g);
844 if (c < tlen)
846 /* G has an entry in Vglyph_table,
847 so process any alias before testing for simpleness. */
848 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
849 c = GLYPH_CHAR (selected_frame, g);
851 if (GLYPH_SIMPLE_P (tbase, tlen, g))
852 /* We set the multi-byte form of C at BUF. */
853 len = CHAR_STRING (c, workbuf, buf);
854 else
856 /* We have a string in Vglyph_table. */
857 len = GLYPH_LENGTH (tbase, g);
858 buf = GLYPH_STRING (tbase, g);
861 result = encode_coding (coding, buf, dst, len, dst_end - dst);
862 len -= coding->consumed;
863 dst += coding->produced;
864 if (result == CODING_FINISH_INSUFFICIENT_DST
865 || (result == CODING_FINISH_INSUFFICIENT_SRC
866 && len > dst_end - dst))
867 /* The remaining output buffer is too short. We must
868 break the loop here without increasing SRC so that the
869 next call of this function starts from the same glyph. */
870 break;
872 if (len > 0)
874 /* This is the case that a code of the range 0200..0237
875 exists in buf. We must just write out such a code. */
876 buf += coding->consumed;
877 while (len--)
878 *dst++ = *buf++;
881 src++;
883 *consumed = src - src_start;
884 return (dst - dst_start);
888 void
889 write_glyphs (string, len)
890 register GLYPH *string;
891 register int len;
893 register GLYPH g;
894 register int tlen = GLYPH_TABLE_LENGTH;
895 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
896 int produced, consumed;
898 if (write_glyphs_hook
899 && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
901 (*write_glyphs_hook) (string, len);
902 return;
905 highlight_if_desired ();
906 turn_off_insert ();
908 /* Don't dare write in last column of bottom line, if AutoWrap,
909 since that would scroll the whole frame on some terminals. */
911 if (AutoWrap
912 && curY + 1 == FRAME_HEIGHT (selected_frame)
913 && (curX + len - (chars_wasted[curY] & 077)
914 == FRAME_WIDTH (selected_frame)))
915 len --;
916 if (len <= 0)
917 return;
919 cmplus (len);
920 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
921 the tail. */
922 terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
923 while (len > 0)
925 /* We use shared conversion buffer of the current size (1024
926 bytes at least). Usually it is sufficient, but if not, we
927 just repeat the loop. */
928 produced = encode_terminal_code (string, conversion_buffer,
929 len, conversion_buffer_size, &consumed);
930 if (produced > 0)
932 fwrite (conversion_buffer, 1, produced, stdout);
933 if (ferror (stdout))
934 clearerr (stdout);
935 if (termscript)
936 fwrite (conversion_buffer, 1, produced, termscript);
938 len -= consumed;
939 string += consumed;
941 /* We may have to output some codes to terminate the writing. */
942 if (CODING_REQUIRE_FLUSHING (&terminal_coding))
944 terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
945 encode_coding (&terminal_coding, "", conversion_buffer,
946 0, conversion_buffer_size);
947 if (terminal_coding.produced > 0)
949 fwrite (conversion_buffer, 1, terminal_coding.produced, stdout);
950 if (ferror (stdout))
951 clearerr (stdout);
952 if (termscript)
953 fwrite (conversion_buffer, 1, terminal_coding.produced,
954 termscript);
957 cmcheckmagic ();
960 /* If start is zero, insert blanks instead of a string at start */
962 void
963 insert_glyphs (start, len)
964 register GLYPH *start;
965 register int len;
967 char *buf;
968 GLYPH g;
969 register int tlen = GLYPH_TABLE_LENGTH;
970 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
972 if (len <= 0)
973 return;
975 if (insert_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame))
977 (*insert_glyphs_hook) (start, len);
978 return;
980 highlight_if_desired ();
982 if (TS_ins_multi_chars)
984 buf = tparam (TS_ins_multi_chars, 0, 0, len);
985 OUTPUT1 (buf);
986 xfree (buf);
987 if (start)
988 write_glyphs (start, len);
989 return;
992 turn_on_insert ();
993 cmplus (len);
994 /* The bit CODING_MODE_LAST_BLOCK should be set to 1 only at the tail. */
995 terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
996 while (len-- > 0)
998 int produced, consumed;
1000 OUTPUT1_IF (TS_ins_char);
1001 if (!start)
1002 g = SPACEGLYPH;
1003 else
1005 g = *start++;
1006 /* We must open sufficient space for a character which
1007 occupies more than one column. */
1008 while (*start & GLYPH_MASK_PADDING)
1010 OUTPUT1_IF (TS_ins_char);
1011 start++, len--;
1015 if (len <= 0)
1016 /* This is the last glyph. */
1017 terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
1019 /* We use shared conversion buffer of the current size (1024
1020 bytes at least). It is surely sufficient for just one glyph. */
1021 produced = encode_terminal_code (&g, conversion_buffer,
1022 1, conversion_buffer_size, &consumed);
1023 if (produced > 0)
1025 fwrite (conversion_buffer, 1, produced, stdout);
1026 if (ferror (stdout))
1027 clearerr (stdout);
1028 if (termscript)
1029 fwrite (conversion_buffer, 1, produced, termscript);
1032 OUTPUT1_IF (TS_pad_inserted_char);
1034 cmcheckmagic ();
1037 void
1038 delete_glyphs (n)
1039 register int n;
1041 char *buf;
1042 register int i;
1044 if (delete_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame))
1046 (*delete_glyphs_hook) (n);
1047 return;
1050 if (delete_in_insert_mode)
1052 turn_on_insert ();
1054 else
1056 turn_off_insert ();
1057 OUTPUT_IF (TS_delete_mode);
1060 if (TS_del_multi_chars)
1062 buf = tparam (TS_del_multi_chars, 0, 0, n);
1063 OUTPUT1 (buf);
1064 xfree (buf);
1066 else
1067 for (i = 0; i < n; i++)
1068 OUTPUT1 (TS_del_char);
1069 if (!delete_in_insert_mode)
1070 OUTPUT_IF (TS_end_delete_mode);
1073 /* Insert N lines at vpos VPOS. If N is negative, delete -N lines. */
1075 void
1076 ins_del_lines (vpos, n)
1077 int vpos, n;
1079 char *multi = n > 0 ? TS_ins_multi_lines : TS_del_multi_lines;
1080 char *single = n > 0 ? TS_ins_line : TS_del_line;
1081 char *scroll = n > 0 ? TS_rev_scroll : TS_fwd_scroll;
1083 register int i = n > 0 ? n : -n;
1084 register char *buf;
1086 if (ins_del_lines_hook && ! FRAME_TERMCAP_P (updating_frame))
1088 (*ins_del_lines_hook) (vpos, n);
1089 return;
1092 /* If the lines below the insertion are being pushed
1093 into the end of the window, this is the same as clearing;
1094 and we know the lines are already clear, since the matching
1095 deletion has already been done. So can ignore this. */
1096 /* If the lines below the deletion are blank lines coming
1097 out of the end of the window, don't bother,
1098 as there will be a matching inslines later that will flush them. */
1099 if (scroll_region_ok && vpos + i >= specified_window)
1100 return;
1101 if (!memory_below_frame && vpos + i >= FRAME_HEIGHT (selected_frame))
1102 return;
1104 if (multi)
1106 raw_cursor_to (vpos, 0);
1107 background_highlight ();
1108 buf = tparam (multi, 0, 0, i);
1109 OUTPUT (buf);
1110 xfree (buf);
1112 else if (single)
1114 raw_cursor_to (vpos, 0);
1115 background_highlight ();
1116 while (--i >= 0)
1117 OUTPUT (single);
1118 if (TF_teleray)
1119 curX = 0;
1121 else
1123 set_scroll_region (vpos, specified_window);
1124 if (n < 0)
1125 raw_cursor_to (specified_window - 1, 0);
1126 else
1127 raw_cursor_to (vpos, 0);
1128 background_highlight ();
1129 while (--i >= 0)
1130 OUTPUTL (scroll, specified_window - vpos);
1131 set_scroll_region (0, specified_window);
1134 if (TN_standout_width >= 0)
1136 register int lower_limit
1137 = (scroll_region_ok
1138 ? specified_window
1139 : FRAME_HEIGHT (selected_frame));
1141 if (n < 0)
1143 bcopy (&chars_wasted[vpos - n], &chars_wasted[vpos],
1144 lower_limit - vpos + n);
1145 bzero (&chars_wasted[lower_limit + n], - n);
1147 else
1149 bcopy (&chars_wasted[vpos], &copybuf[vpos], lower_limit - vpos - n);
1150 bcopy (&copybuf[vpos], &chars_wasted[vpos + n],
1151 lower_limit - vpos - n);
1152 bzero (&chars_wasted[vpos], n);
1155 if (!scroll_region_ok && memory_below_frame && n < 0)
1157 cursor_to (FRAME_HEIGHT (selected_frame) + n, 0);
1158 clear_to_end ();
1162 /* Compute cost of sending "str", in characters,
1163 not counting any line-dependent padding. */
1166 string_cost (str)
1167 char *str;
1169 cost = 0;
1170 if (str)
1171 tputs (str, 0, evalcost);
1172 return cost;
1175 /* Compute cost of sending "str", in characters,
1176 counting any line-dependent padding at one line. */
1178 static int
1179 string_cost_one_line (str)
1180 char *str;
1182 cost = 0;
1183 if (str)
1184 tputs (str, 1, evalcost);
1185 return cost;
1188 /* Compute per line amount of line-dependent padding,
1189 in tenths of characters. */
1192 per_line_cost (str)
1193 register char *str;
1195 cost = 0;
1196 if (str)
1197 tputs (str, 0, evalcost);
1198 cost = - cost;
1199 if (str)
1200 tputs (str, 10, evalcost);
1201 return cost;
1204 #ifndef old
1205 /* char_ins_del_cost[n] is cost of inserting N characters.
1206 char_ins_del_cost[-n] is cost of deleting N characters.
1207 The length of this vector is based on max_frame_width. */
1209 int *char_ins_del_vector;
1211 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WIDTH ((f))])
1212 #endif
1214 /* ARGSUSED */
1215 static void
1216 calculate_ins_del_char_costs (frame)
1217 FRAME_PTR frame;
1219 int ins_startup_cost, del_startup_cost;
1220 int ins_cost_per_char, del_cost_per_char;
1221 register int i;
1222 register int *p;
1224 if (TS_ins_multi_chars)
1226 ins_cost_per_char = 0;
1227 ins_startup_cost = string_cost_one_line (TS_ins_multi_chars);
1229 else if (TS_ins_char || TS_pad_inserted_char
1230 || (TS_insert_mode && TS_end_insert_mode))
1232 ins_startup_cost = (30 * (string_cost (TS_insert_mode)
1233 + string_cost (TS_end_insert_mode))) / 100;
1234 ins_cost_per_char = (string_cost_one_line (TS_ins_char)
1235 + string_cost_one_line (TS_pad_inserted_char));
1237 else
1239 ins_startup_cost = 9999;
1240 ins_cost_per_char = 0;
1243 if (TS_del_multi_chars)
1245 del_cost_per_char = 0;
1246 del_startup_cost = string_cost_one_line (TS_del_multi_chars);
1248 else if (TS_del_char)
1250 del_startup_cost = (string_cost (TS_delete_mode)
1251 + string_cost (TS_end_delete_mode));
1252 if (delete_in_insert_mode)
1253 del_startup_cost /= 2;
1254 del_cost_per_char = string_cost_one_line (TS_del_char);
1256 else
1258 del_startup_cost = 9999;
1259 del_cost_per_char = 0;
1262 /* Delete costs are at negative offsets */
1263 p = &char_ins_del_cost (frame)[0];
1264 for (i = FRAME_WIDTH (frame); --i >= 0;)
1265 *--p = (del_startup_cost += del_cost_per_char);
1267 /* Doing nothing is free */
1268 p = &char_ins_del_cost (frame)[0];
1269 *p++ = 0;
1271 /* Insert costs are at positive offsets */
1272 for (i = FRAME_WIDTH (frame); --i >= 0;)
1273 *p++ = (ins_startup_cost += ins_cost_per_char);
1276 void
1277 calculate_costs (frame)
1278 FRAME_PTR frame;
1280 register char *f = (TS_set_scroll_region
1281 ? TS_set_scroll_region
1282 : TS_set_scroll_region_1);
1284 FRAME_COST_BAUD_RATE (frame) = baud_rate;
1286 scroll_region_cost = string_cost (f);
1287 #ifdef HAVE_X_WINDOWS
1288 if (FRAME_X_P (frame))
1290 do_line_insertion_deletion_costs (frame, 0, ".5*", 0, ".5*",
1291 0, 0,
1292 x_screen_planes (frame));
1293 scroll_region_cost = 0;
1294 return;
1296 #endif
1298 /* These variables are only used for terminal stuff. They are allocated
1299 once for the terminal frame of X-windows emacs, but not used afterwards.
1301 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1302 X turns off char_ins_del_ok.
1304 chars_wasted and copybuf are only used here in term.c in cases where
1305 the term hook isn't called. */
1307 max_frame_height = max (max_frame_height, FRAME_HEIGHT (frame));
1308 max_frame_width = max (max_frame_width, FRAME_WIDTH (frame));
1310 if (chars_wasted != 0)
1311 chars_wasted = (char *) xrealloc (chars_wasted, max_frame_height);
1312 else
1313 chars_wasted = (char *) xmalloc (max_frame_height);
1315 if (copybuf != 0)
1316 copybuf = (char *) xrealloc (copybuf, max_frame_height);
1317 else
1318 copybuf = (char *) xmalloc (max_frame_height);
1320 if (char_ins_del_vector != 0)
1321 char_ins_del_vector
1322 = (int *) xrealloc (char_ins_del_vector,
1323 (sizeof (int)
1324 + 2 * max_frame_width * sizeof (int)));
1325 else
1326 char_ins_del_vector
1327 = (int *) xmalloc (sizeof (int)
1328 + 2 * max_frame_width * sizeof (int));
1330 bzero (chars_wasted, max_frame_height);
1331 bzero (copybuf, max_frame_height);
1332 bzero (char_ins_del_vector, (sizeof (int)
1333 + 2 * max_frame_width * sizeof (int)));
1335 if (f && (!TS_ins_line && !TS_del_line))
1336 do_line_insertion_deletion_costs (frame,
1337 TS_rev_scroll, TS_ins_multi_lines,
1338 TS_fwd_scroll, TS_del_multi_lines,
1339 f, f, 1);
1340 else
1341 do_line_insertion_deletion_costs (frame,
1342 TS_ins_line, TS_ins_multi_lines,
1343 TS_del_line, TS_del_multi_lines,
1344 0, 0, 1);
1346 calculate_ins_del_char_costs (frame);
1348 /* Don't use TS_repeat if its padding is worse than sending the chars */
1349 if (TS_repeat && per_line_cost (TS_repeat) * baud_rate < 9000)
1350 RPov = string_cost (TS_repeat);
1351 else
1352 RPov = FRAME_WIDTH (frame) * 2;
1354 cmcostinit (); /* set up cursor motion costs */
1357 struct fkey_table {
1358 char *cap, *name;
1361 /* Termcap capability names that correspond directly to X keysyms.
1362 Some of these (marked "terminfo") aren't supplied by old-style
1363 (Berkeley) termcap entries. They're listed in X keysym order;
1364 except we put the keypad keys first, so that if they clash with
1365 other keys (as on the IBM PC keyboard) they get overridden.
1368 static struct fkey_table keys[] = {
1369 "kh", "home", /* termcap */
1370 "kl", "left", /* termcap */
1371 "ku", "up", /* termcap */
1372 "kr", "right", /* termcap */
1373 "kd", "down", /* termcap */
1374 "%8", "prior", /* terminfo */
1375 "%5", "next", /* terminfo */
1376 "@7", "end", /* terminfo */
1377 "@1", "begin", /* terminfo */
1378 "*6", "select", /* terminfo */
1379 "%9", "print", /* terminfo */
1380 "@4", "execute", /* terminfo --- actually the `command' key */
1382 * "insert" --- see below
1384 "&8", "undo", /* terminfo */
1385 "%0", "redo", /* terminfo */
1386 "%7", "menu", /* terminfo --- actually the `options' key */
1387 "@0", "find", /* terminfo */
1388 "@2", "cancel", /* terminfo */
1389 "%1", "help", /* terminfo */
1391 * "break" goes here, but can't be reliably intercepted with termcap
1393 "&4", "reset", /* terminfo --- actually `restart' */
1395 * "system" and "user" --- no termcaps
1397 "kE", "clearline", /* terminfo */
1398 "kA", "insertline", /* terminfo */
1399 "kL", "deleteline", /* terminfo */
1400 "kI", "insertchar", /* terminfo */
1401 "kD", "deletechar", /* terminfo */
1402 "kB", "backtab", /* terminfo */
1404 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1406 "@8", "kp-enter", /* terminfo */
1408 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1409 * "kp-multiply", "kp-add", "kp-separator",
1410 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1411 * --- no termcaps for any of these.
1413 "K4", "kp-1", /* terminfo */
1415 * "kp-2" --- no termcap
1417 "K5", "kp-3", /* terminfo */
1419 * "kp-4" --- no termcap
1421 "K2", "kp-5", /* terminfo */
1423 * "kp-6" --- no termcap
1425 "K1", "kp-7", /* terminfo */
1427 * "kp-8" --- no termcap
1429 "K3", "kp-9", /* terminfo */
1431 * "kp-equal" --- no termcap
1433 "k1", "f1",
1434 "k2", "f2",
1435 "k3", "f3",
1436 "k4", "f4",
1437 "k5", "f5",
1438 "k6", "f6",
1439 "k7", "f7",
1440 "k8", "f8",
1441 "k9", "f9",
1444 static char **term_get_fkeys_arg;
1445 static Lisp_Object term_get_fkeys_1 ();
1447 /* Find the escape codes sent by the function keys for Vfunction_key_map.
1448 This function scans the termcap function key sequence entries, and
1449 adds entries to Vfunction_key_map for each function key it finds. */
1451 void
1452 term_get_fkeys (address)
1453 char **address;
1455 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1456 errors during the call. The only errors should be from Fdefine_key
1457 when given a key sequence containing an invalid prefix key. If the
1458 termcap defines function keys which use a prefix that is already bound
1459 to a command by the default bindings, we should silently ignore that
1460 function key specification, rather than giving the user an error and
1461 refusing to run at all on such a terminal. */
1463 extern Lisp_Object Fidentity ();
1464 term_get_fkeys_arg = address;
1465 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1468 static Lisp_Object
1469 term_get_fkeys_1 ()
1471 int i;
1473 char **address = term_get_fkeys_arg;
1475 /* This can happen if CANNOT_DUMP or with strange options. */
1476 if (!initialized)
1477 Vfunction_key_map = Fmake_sparse_keymap (Qnil);
1479 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1481 char *sequence = tgetstr (keys[i].cap, address);
1482 if (sequence)
1483 Fdefine_key (Vfunction_key_map, build_string (sequence),
1484 Fmake_vector (make_number (1),
1485 intern (keys[i].name)));
1488 /* The uses of the "k0" capability are inconsistent; sometimes it
1489 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1490 We will attempt to politely accommodate both systems by testing for
1491 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1494 char *k_semi = tgetstr ("k;", address);
1495 char *k0 = tgetstr ("k0", address);
1496 char *k0_name = "f10";
1498 if (k_semi)
1500 Fdefine_key (Vfunction_key_map, build_string (k_semi),
1501 Fmake_vector (make_number (1), intern ("f10")));
1502 k0_name = "f0";
1505 if (k0)
1506 Fdefine_key (Vfunction_key_map, build_string (k0),
1507 Fmake_vector (make_number (1), intern (k0_name)));
1510 /* Set up cookies for numbered function keys above f10. */
1512 char fcap[3], fkey[4];
1514 fcap[0] = 'F'; fcap[2] = '\0';
1515 for (i = 11; i < 64; i++)
1517 if (i <= 19)
1518 fcap[1] = '1' + i - 11;
1519 else if (i <= 45)
1520 fcap[1] = 'A' + i - 20;
1521 else
1522 fcap[1] = 'a' + i - 46;
1525 char *sequence = tgetstr (fcap, address);
1526 if (sequence)
1528 sprintf (fkey, "f%d", i);
1529 Fdefine_key (Vfunction_key_map, build_string (sequence),
1530 Fmake_vector (make_number (1),
1531 intern (fkey)));
1538 * Various mappings to try and get a better fit.
1541 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1542 if (!tgetstr (cap1, address)) \
1544 char *sequence = tgetstr (cap2, address); \
1545 if (sequence) \
1546 Fdefine_key (Vfunction_key_map, build_string (sequence), \
1547 Fmake_vector (make_number (1), \
1548 intern (sym))); \
1551 /* if there's no key_next keycap, map key_npage to `next' keysym */
1552 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1553 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1554 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1555 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1556 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1557 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1558 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1560 /* IBM has their own non-standard dialect of terminfo.
1561 If the standard name isn't found, try the IBM name. */
1562 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1563 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1564 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1565 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1566 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1567 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1568 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1569 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1570 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1571 #undef CONDITIONAL_REASSIGN
1576 void
1577 term_init (terminal_type)
1578 char *terminal_type;
1580 char *area;
1581 char **address = &area;
1582 char buffer[2044];
1583 register char *p;
1584 int status;
1586 #ifdef WINDOWSNT
1587 initialize_w32_display ();
1589 Wcm_clear ();
1591 area = (char *) xmalloc (2044);
1593 if (area == 0)
1594 abort ();
1596 FrameRows = FRAME_HEIGHT (selected_frame);
1597 FrameCols = FRAME_WIDTH (selected_frame);
1598 specified_window = FRAME_HEIGHT (selected_frame);
1600 delete_in_insert_mode = 1;
1602 UseTabs = 0;
1603 scroll_region_ok = 0;
1605 /* Seems to insert lines when it's not supposed to, messing
1606 up the display. In doing a trace, it didn't seem to be
1607 called much, so I don't think we're losing anything by
1608 turning it off. */
1610 line_ins_del_ok = 0;
1611 char_ins_del_ok = 1;
1613 baud_rate = 19200;
1615 FRAME_CAN_HAVE_SCROLL_BARS (selected_frame) = 0;
1616 FRAME_VERTICAL_SCROLL_BAR_TYPE (selected_frame) = vertical_scroll_bar_none;
1618 return;
1619 #else /* not WINDOWSNT */
1621 Wcm_clear ();
1623 status = tgetent (buffer, terminal_type);
1624 if (status < 0)
1626 #ifdef TERMINFO
1627 fatal ("Cannot open terminfo database file");
1628 #else
1629 fatal ("Cannot open termcap database file");
1630 #endif
1632 if (status == 0)
1634 #ifdef TERMINFO
1635 fatal ("Terminal type %s is not defined.\n\
1636 If that is not the actual type of terminal you have,\n\
1637 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
1638 `setenv TERM ...') to specify the correct type. It may be necessary\n\
1639 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
1640 terminal_type);
1641 #else
1642 fatal ("Terminal type %s is not defined.\n\
1643 If that is not the actual type of terminal you have,\n\
1644 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
1645 `setenv TERM ...') to specify the correct type. It may be necessary\n\
1646 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
1647 terminal_type);
1648 #endif
1650 #ifdef TERMINFO
1651 area = (char *) xmalloc (2044);
1652 #else
1653 area = (char *) xmalloc (strlen (buffer));
1654 #endif /* not TERMINFO */
1655 if (area == 0)
1656 abort ();
1658 TS_ins_line = tgetstr ("al", address);
1659 TS_ins_multi_lines = tgetstr ("AL", address);
1660 TS_bell = tgetstr ("bl", address);
1661 BackTab = tgetstr ("bt", address);
1662 TS_clr_to_bottom = tgetstr ("cd", address);
1663 TS_clr_line = tgetstr ("ce", address);
1664 TS_clr_frame = tgetstr ("cl", address);
1665 ColPosition = tgetstr ("ch", address);
1666 AbsPosition = tgetstr ("cm", address);
1667 CR = tgetstr ("cr", address);
1668 TS_set_scroll_region = tgetstr ("cs", address);
1669 TS_set_scroll_region_1 = tgetstr ("cS", address);
1670 RowPosition = tgetstr ("cv", address);
1671 TS_del_char = tgetstr ("dc", address);
1672 TS_del_multi_chars = tgetstr ("DC", address);
1673 TS_del_line = tgetstr ("dl", address);
1674 TS_del_multi_lines = tgetstr ("DL", address);
1675 TS_delete_mode = tgetstr ("dm", address);
1676 TS_end_delete_mode = tgetstr ("ed", address);
1677 TS_end_insert_mode = tgetstr ("ei", address);
1678 Home = tgetstr ("ho", address);
1679 TS_ins_char = tgetstr ("ic", address);
1680 TS_ins_multi_chars = tgetstr ("IC", address);
1681 TS_insert_mode = tgetstr ("im", address);
1682 TS_pad_inserted_char = tgetstr ("ip", address);
1683 TS_end_keypad_mode = tgetstr ("ke", address);
1684 TS_keypad_mode = tgetstr ("ks", address);
1685 LastLine = tgetstr ("ll", address);
1686 Right = tgetstr ("nd", address);
1687 Down = tgetstr ("do", address);
1688 if (!Down)
1689 Down = tgetstr ("nl", address); /* Obsolete name for "do" */
1690 #ifdef VMS
1691 /* VMS puts a carriage return before each linefeed,
1692 so it is not safe to use linefeeds. */
1693 if (Down && Down[0] == '\n' && Down[1] == '\0')
1694 Down = 0;
1695 #endif /* VMS */
1696 if (tgetflag ("bs"))
1697 Left = "\b"; /* can't possibly be longer! */
1698 else /* (Actually, "bs" is obsolete...) */
1699 Left = tgetstr ("le", address);
1700 if (!Left)
1701 Left = tgetstr ("bc", address); /* Obsolete name for "le" */
1702 TS_pad_char = tgetstr ("pc", address);
1703 TS_repeat = tgetstr ("rp", address);
1704 TS_end_standout_mode = tgetstr ("se", address);
1705 TS_fwd_scroll = tgetstr ("sf", address);
1706 TS_standout_mode = tgetstr ("so", address);
1707 TS_rev_scroll = tgetstr ("sr", address);
1708 Wcm.cm_tab = tgetstr ("ta", address);
1709 TS_end_termcap_modes = tgetstr ("te", address);
1710 TS_termcap_modes = tgetstr ("ti", address);
1711 TS_bold_mode = tgetstr ("md", address);
1712 TS_end_bold_mode = tgetstr ("me", address);
1713 TS_underscore_mode = tgetstr ("us", address);
1714 TS_end_underscore_mode = tgetstr ("ue", address);
1715 Up = tgetstr ("up", address);
1716 TS_visible_bell = tgetstr ("vb", address);
1717 TS_end_visual_mode = tgetstr ("ve", address);
1718 TS_visual_mode = tgetstr ("vs", address);
1719 TS_set_window = tgetstr ("wi", address);
1720 MultiUp = tgetstr ("UP", address);
1721 MultiDown = tgetstr ("DO", address);
1722 MultiLeft = tgetstr ("LE", address);
1723 MultiRight = tgetstr ("RI", address);
1725 MagicWrap = tgetflag ("xn");
1726 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
1727 the former flag imply the latter. */
1728 AutoWrap = MagicWrap || tgetflag ("am");
1729 memory_below_frame = tgetflag ("db");
1730 TF_hazeltine = tgetflag ("hz");
1731 must_write_spaces = tgetflag ("in");
1732 meta_key = tgetflag ("km") || tgetflag ("MT");
1733 TF_insmode_motion = tgetflag ("mi");
1734 TF_standout_motion = tgetflag ("ms");
1735 TF_underscore = tgetflag ("ul");
1736 TF_xs = tgetflag ("xs");
1737 TF_teleray = tgetflag ("xt");
1739 term_get_fkeys (address);
1741 /* Get frame size from system, or else from termcap. */
1743 int height, width;
1744 get_frame_size (&width, &height);
1745 FRAME_WIDTH (selected_frame) = width;
1746 FRAME_HEIGHT (selected_frame) = height;
1749 if (FRAME_WIDTH (selected_frame) <= 0)
1750 SET_FRAME_WIDTH (selected_frame, tgetnum ("co"));
1751 else
1752 /* Keep width and external_width consistent */
1753 SET_FRAME_WIDTH (selected_frame, FRAME_WIDTH (selected_frame));
1754 if (FRAME_HEIGHT (selected_frame) <= 0)
1755 FRAME_HEIGHT (selected_frame) = tgetnum ("li");
1757 if (FRAME_HEIGHT (selected_frame) < 3
1758 || FRAME_WIDTH (selected_frame) < 3)
1759 fatal ("Screen size %dx%d is too small",
1760 FRAME_HEIGHT (selected_frame), FRAME_WIDTH (selected_frame));
1762 min_padding_speed = tgetnum ("pb");
1763 TN_standout_width = tgetnum ("sg");
1764 TabWidth = tgetnum ("tw");
1766 #ifdef VMS
1767 /* These capabilities commonly use ^J.
1768 I don't know why, but sending them on VMS does not work;
1769 it causes following spaces to be lost, sometimes.
1770 For now, the simplest fix is to avoid using these capabilities ever. */
1771 if (Down && Down[0] == '\n')
1772 Down = 0;
1773 #endif /* VMS */
1775 if (!TS_bell)
1776 TS_bell = "\07";
1778 if (!TS_fwd_scroll)
1779 TS_fwd_scroll = Down;
1781 PC = TS_pad_char ? *TS_pad_char : 0;
1783 if (TabWidth < 0)
1784 TabWidth = 8;
1786 /* Turned off since /etc/termcap seems to have :ta= for most terminals
1787 and newer termcap doc does not seem to say there is a default.
1788 if (!Wcm.cm_tab)
1789 Wcm.cm_tab = "\t";
1792 if (TS_standout_mode == 0)
1794 TN_standout_width = tgetnum ("ug");
1795 TS_end_standout_mode = tgetstr ("ue", address);
1796 TS_standout_mode = tgetstr ("us", address);
1799 /* If no `se' string, try using a `me' string instead.
1800 If that fails, we can't use standout mode at all. */
1801 if (TS_end_standout_mode == 0)
1803 char *s = tgetstr ("me", address);
1804 if (s != 0)
1805 TS_end_standout_mode = s;
1806 else
1807 TS_standout_mode = 0;
1810 if (TF_teleray)
1812 Wcm.cm_tab = 0;
1813 /* Teleray: most programs want a space in front of TS_standout_mode,
1814 but Emacs can do without it (and give one extra column). */
1815 TS_standout_mode = "\033RD";
1816 TN_standout_width = 1;
1817 /* But that means we cannot rely on ^M to go to column zero! */
1818 CR = 0;
1819 /* LF can't be trusted either -- can alter hpos */
1820 /* if move at column 0 thru a line with TS_standout_mode */
1821 Down = 0;
1824 /* Special handling for certain terminal types known to need it */
1826 if (!strcmp (terminal_type, "supdup"))
1828 memory_below_frame = 1;
1829 Wcm.cm_losewrap = 1;
1831 if (!strncmp (terminal_type, "c10", 3)
1832 || !strcmp (terminal_type, "perq"))
1834 /* Supply a makeshift :wi string.
1835 This string is not valid in general since it works only
1836 for windows starting at the upper left corner;
1837 but that is all Emacs uses.
1839 This string works only if the frame is using
1840 the top of the video memory, because addressing is memory-relative.
1841 So first check the :ti string to see if that is true.
1843 It would be simpler if the :wi string could go in the termcap
1844 entry, but it can't because it is not fully valid.
1845 If it were in the termcap entry, it would confuse other programs. */
1846 if (!TS_set_window)
1848 p = TS_termcap_modes;
1849 while (*p && strcmp (p, "\033v "))
1850 p++;
1851 if (*p)
1852 TS_set_window = "\033v%C %C %C %C ";
1854 /* Termcap entry often fails to have :in: flag */
1855 must_write_spaces = 1;
1856 /* :ti string typically fails to have \E^G! in it */
1857 /* This limits scope of insert-char to one line. */
1858 strcpy (area, TS_termcap_modes);
1859 strcat (area, "\033\007!");
1860 TS_termcap_modes = area;
1861 area += strlen (area) + 1;
1862 p = AbsPosition;
1863 /* Change all %+ parameters to %C, to handle
1864 values above 96 correctly for the C100. */
1865 while (*p)
1867 if (p[0] == '%' && p[1] == '+')
1868 p[1] = 'C';
1869 p++;
1873 FrameRows = FRAME_HEIGHT (selected_frame);
1874 FrameCols = FRAME_WIDTH (selected_frame);
1875 specified_window = FRAME_HEIGHT (selected_frame);
1877 if (Wcm_init () == -1) /* can't do cursor motion */
1878 #ifdef VMS
1879 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
1880 It lacks the ability to position the cursor.\n\
1881 If that is not the actual type of terminal you have, use either the\n\
1882 DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
1883 or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
1884 terminal_type);
1885 #else /* not VMS */
1886 # ifdef TERMINFO
1887 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
1888 It lacks the ability to position the cursor.\n\
1889 If that is not the actual type of terminal you have,\n\
1890 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
1891 `setenv TERM ...') to specify the correct type. It may be necessary\n\
1892 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
1893 terminal_type);
1894 # else /* TERMCAP */
1895 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
1896 It lacks the ability to position the cursor.\n\
1897 If that is not the actual type of terminal you have,\n\
1898 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
1899 `setenv TERM ...') to specify the correct type. It may be necessary\n\
1900 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
1901 terminal_type);
1902 # endif /* TERMINFO */
1903 #endif /*VMS */
1904 if (FRAME_HEIGHT (selected_frame) <= 0
1905 || FRAME_WIDTH (selected_frame) <= 0)
1906 fatal ("The frame size has not been specified");
1908 delete_in_insert_mode
1909 = TS_delete_mode && TS_insert_mode
1910 && !strcmp (TS_delete_mode, TS_insert_mode);
1912 se_is_so = (TS_standout_mode
1913 && TS_end_standout_mode
1914 && !strcmp (TS_standout_mode, TS_end_standout_mode));
1916 /* Remove width of standout marker from usable width of line */
1917 if (TN_standout_width > 0)
1918 SET_FRAME_WIDTH (selected_frame,
1919 FRAME_WIDTH (selected_frame) - TN_standout_width);
1921 UseTabs = tabs_safe_p () && TabWidth == 8;
1923 scroll_region_ok
1924 = (Wcm.cm_abs
1925 && (TS_set_window || TS_set_scroll_region || TS_set_scroll_region_1));
1927 line_ins_del_ok = (((TS_ins_line || TS_ins_multi_lines)
1928 && (TS_del_line || TS_del_multi_lines))
1929 || (scroll_region_ok && TS_fwd_scroll && TS_rev_scroll));
1931 char_ins_del_ok = ((TS_ins_char || TS_insert_mode
1932 || TS_pad_inserted_char || TS_ins_multi_chars)
1933 && (TS_del_char || TS_del_multi_chars));
1935 fast_clear_end_of_line = TS_clr_line != 0;
1937 init_baud_rate ();
1938 if (read_socket_hook) /* Baudrate is somewhat */
1939 /* meaningless in this case */
1940 baud_rate = 9600;
1942 FRAME_CAN_HAVE_SCROLL_BARS (selected_frame) = 0;
1943 FRAME_VERTICAL_SCROLL_BAR_TYPE (selected_frame) = vertical_scroll_bar_none;
1944 #endif /* WINDOWSNT */
1947 /* VARARGS 1 */
1948 void
1949 fatal (str, arg1, arg2)
1950 char *str, *arg1, *arg2;
1952 fprintf (stderr, "emacs: ");
1953 fprintf (stderr, str, arg1, arg2);
1954 fprintf (stderr, "\n");
1955 fflush (stderr);
1956 exit (1);
1959 void
1960 syms_of_term ()
1962 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
1963 "Non-nil means the system uses terminfo rather than termcap.\n\
1964 This variable can be used by terminal emulator packages.");
1965 #ifdef TERMINFO
1966 system_uses_terminfo = 1;
1967 #else
1968 system_uses_terminfo = 0;
1969 #endif
1971 DEFVAR_LISP ("ring-bell-function", &Vring_bell_function,
1972 "Non-nil means call this function to ring the bell.\n\
1973 The function should accept no arguments.");
1974 Vring_bell_function = Qnil;