(fill-individual-paragraphs): Calculate new
[emacs.git] / src / term.c
blob7c05f7cbf10e87113b22291745c557dc222ef5fc
1 /* terminal control module for terminals described by TERMCAP
2 Copyright (C) 1985, 86, 87, 93, 94, 95, 98
3 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* New redisplay, TTY faces by Gerd Moellmann <gerd@acm.org>. */
25 #include <config.h>
26 #include <stdio.h>
27 #include <ctype.h>
28 #include <string.h>
29 #include "termchar.h"
30 #include "termopts.h"
31 #include "lisp.h"
32 #include "charset.h"
33 #include "coding.h"
34 #include "frame.h"
35 #include "disptab.h"
36 #include "termhooks.h"
37 #include "keyboard.h"
38 #include "dispextern.h"
39 #include "window.h"
41 #include "cm.h"
42 #ifdef HAVE_X_WINDOWS
43 #include "xterm.h"
44 #endif
46 static void turn_on_face P_ ((struct frame *, int face_id));
47 static void turn_off_face P_ ((struct frame *, int face_id));
48 static void tty_show_cursor P_ ((void));
49 static void tty_hide_cursor P_ ((void));
51 #define max(a, b) ((a) > (b) ? (a) : (b))
52 #define min(a, b) ((a) < (b) ? (a) : (b))
54 #define OUTPUT(a) tputs (a, (int) (FRAME_HEIGHT (selected_frame) - curY), cmputc)
55 #define OUTPUT1(a) tputs (a, 1, cmputc)
56 #define OUTPUTL(a, lines) tputs (a, lines, cmputc)
58 #define OUTPUT_IF(a) \
59 if (a) \
60 tputs (a, (int) (FRAME_HEIGHT (selected_frame) - curY), cmputc); \
61 else \
62 (void) 0
64 #define OUTPUT1_IF(a) if (a) tputs (a, 1, cmputc); else (void) 0
66 /* Function to use to ring the bell. */
68 Lisp_Object Vring_bell_function;
70 /* Terminal characteristics that higher levels want to look at.
71 These are all extern'd in termchar.h */
73 int must_write_spaces; /* Nonzero means spaces in the text
74 must actually be output; can't just skip
75 over some columns to leave them blank. */
76 int min_padding_speed; /* Speed below which no padding necessary */
78 int line_ins_del_ok; /* Terminal can insert and delete lines */
79 int char_ins_del_ok; /* Terminal can insert and delete chars */
80 int scroll_region_ok; /* Terminal supports setting the
81 scroll window */
82 int scroll_region_cost; /* Cost of setting a scroll window,
83 measured in characters */
84 int memory_below_frame; /* Terminal remembers lines
85 scrolled off bottom */
86 int fast_clear_end_of_line; /* Terminal has a `ce' string */
88 /* Nonzero means no need to redraw the entire frame on resuming
89 a suspended Emacs. This is useful on terminals with multiple pages,
90 where one page is used for Emacs and another for all else. */
92 int no_redraw_on_reenter;
94 /* Hook functions that you can set to snap out the functions in this file.
95 These are all extern'd in termhooks.h */
97 void (*cursor_to_hook) P_ ((int, int));
98 void (*raw_cursor_to_hook) P_ ((int, int));
99 void (*clear_to_end_hook) P_ ((void));
100 void (*clear_frame_hook) P_ ((void));
101 void (*clear_end_of_line_hook) P_ ((int));
103 void (*ins_del_lines_hook) P_ ((int, int));
105 void (*change_line_highlight_hook) P_ ((int, int, int, int));
106 void (*reassert_line_highlight_hook) P_ ((int, int));
108 void (*delete_glyphs_hook) P_ ((int));
110 void (*ring_bell_hook) P_ ((void));
112 void (*reset_terminal_modes_hook) P_ ((void));
113 void (*set_terminal_modes_hook) P_ ((void));
114 void (*update_begin_hook) P_ ((struct frame *));
115 void (*update_end_hook) P_ ((struct frame *));
116 void (*set_terminal_window_hook) P_ ((int));
117 void (*insert_glyphs_hook) P_ ((struct glyph *, int));
118 void (*write_glyphs_hook) P_ ((struct glyph *, int));
119 void (*delete_glyphs_hook) P_ ((int));
121 int (*read_socket_hook) P_ ((int, struct input_event *, int, int));
123 void (*frame_up_to_date_hook) P_ ((struct frame *));
125 /* Return the current position of the mouse.
127 Set *f to the frame the mouse is in, or zero if the mouse is in no
128 Emacs frame. If it is set to zero, all the other arguments are
129 garbage.
131 If the motion started in a scroll bar, set *bar_window to the
132 scroll bar's window, *part to the part the mouse is currently over,
133 *x to the position of the mouse along the scroll bar, and *y to the
134 overall length of the scroll bar.
136 Otherwise, set *bar_window to Qnil, and *x and *y to the column and
137 row of the character cell the mouse is over.
139 Set *time to the time the mouse was at the returned position.
141 This should clear mouse_moved until the next motion
142 event arrives. */
143 void (*mouse_position_hook) P_ ((FRAME_PTR *f, int insist,
144 Lisp_Object *bar_window,
145 enum scroll_bar_part *part,
146 Lisp_Object *x,
147 Lisp_Object *y,
148 unsigned long *time));
150 /* When reading from a minibuffer in a different frame, Emacs wants
151 to shift the highlight from the selected frame to the mini-buffer's
152 frame; under X, this means it lies about where the focus is.
153 This hook tells the window system code to re-decide where to put
154 the highlight. */
155 void (*frame_rehighlight_hook) P_ ((FRAME_PTR f));
157 /* If we're displaying frames using a window system that can stack
158 frames on top of each other, this hook allows you to bring a frame
159 to the front, or bury it behind all the other windows. If this
160 hook is zero, that means the device we're displaying on doesn't
161 support overlapping frames, so there's no need to raise or lower
162 anything.
164 If RAISE is non-zero, F is brought to the front, before all other
165 windows. If RAISE is zero, F is sent to the back, behind all other
166 windows. */
167 void (*frame_raise_lower_hook) P_ ((FRAME_PTR f, int raise));
169 /* Set the vertical scroll bar for WINDOW to have its upper left corner
170 at (TOP, LEFT), and be LENGTH rows high. Set its handle to
171 indicate that we are displaying PORTION characters out of a total
172 of WHOLE characters, starting at POSITION. If WINDOW doesn't yet
173 have a scroll bar, create one for it. */
175 void (*set_vertical_scroll_bar_hook)
176 P_ ((struct window *window,
177 int portion, int whole, int position));
180 /* The following three hooks are used when we're doing a thorough
181 redisplay of the frame. We don't explicitly know which scroll bars
182 are going to be deleted, because keeping track of when windows go
183 away is a real pain - can you say set-window-configuration?
184 Instead, we just assert at the beginning of redisplay that *all*
185 scroll bars are to be removed, and then save scroll bars from the
186 fiery pit when we actually redisplay their window. */
188 /* Arrange for all scroll bars on FRAME to be removed at the next call
189 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
190 `*redeem_scroll_bar_hook' is applied to its window before the judgment.
192 This should be applied to each frame each time its window tree is
193 redisplayed, even if it is not displaying scroll bars at the moment;
194 if the HAS_SCROLL_BARS flag has just been turned off, only calling
195 this and the judge_scroll_bars_hook will get rid of them.
197 If non-zero, this hook should be safe to apply to any frame,
198 whether or not it can support scroll bars, and whether or not it is
199 currently displaying them. */
200 void (*condemn_scroll_bars_hook) P_ ((FRAME_PTR frame));
202 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
203 Note that it's okay to redeem a scroll bar that is not condemned. */
204 void (*redeem_scroll_bar_hook) P_ ((struct window *window));
206 /* Remove all scroll bars on FRAME that haven't been saved since the
207 last call to `*condemn_scroll_bars_hook'.
209 This should be applied to each frame after each time its window
210 tree is redisplayed, even if it is not displaying scroll bars at the
211 moment; if the HAS_SCROLL_BARS flag has just been turned off, only
212 calling this and condemn_scroll_bars_hook will get rid of them.
214 If non-zero, this hook should be safe to apply to any frame,
215 whether or not it can support scroll bars, and whether or not it is
216 currently displaying them. */
217 void (*judge_scroll_bars_hook) P_ ((FRAME_PTR FRAME));
219 /* Hook to call in estimate_mode_line_height, if any. */
221 int (* estimate_mode_line_height_hook) P_ ((struct frame *f, enum face_id));
224 /* Strings, numbers and flags taken from the termcap entry. */
226 char *TS_ins_line; /* "al" */
227 char *TS_ins_multi_lines; /* "AL" (one parameter, # lines to insert) */
228 char *TS_bell; /* "bl" */
229 char *TS_clr_to_bottom; /* "cd" */
230 char *TS_clr_line; /* "ce", clear to end of line */
231 char *TS_clr_frame; /* "cl" */
232 char *TS_set_scroll_region; /* "cs" (2 params, first line and last line) */
233 char *TS_set_scroll_region_1; /* "cS" (4 params: total lines,
234 lines above scroll region, lines below it,
235 total lines again) */
236 char *TS_del_char; /* "dc" */
237 char *TS_del_multi_chars; /* "DC" (one parameter, # chars to delete) */
238 char *TS_del_line; /* "dl" */
239 char *TS_del_multi_lines; /* "DL" (one parameter, # lines to delete) */
240 char *TS_delete_mode; /* "dm", enter character-delete mode */
241 char *TS_end_delete_mode; /* "ed", leave character-delete mode */
242 char *TS_end_insert_mode; /* "ei", leave character-insert mode */
243 char *TS_ins_char; /* "ic" */
244 char *TS_ins_multi_chars; /* "IC" (one parameter, # chars to insert) */
245 char *TS_insert_mode; /* "im", enter character-insert mode */
246 char *TS_pad_inserted_char; /* "ip". Just padding, no commands. */
247 char *TS_end_keypad_mode; /* "ke" */
248 char *TS_keypad_mode; /* "ks" */
249 char *TS_pad_char; /* "pc", char to use as padding */
250 char *TS_repeat; /* "rp" (2 params, # times to repeat
251 and character to be repeated) */
252 char *TS_end_standout_mode; /* "se" */
253 char *TS_fwd_scroll; /* "sf" */
254 char *TS_standout_mode; /* "so" */
255 char *TS_rev_scroll; /* "sr" */
256 char *TS_end_termcap_modes; /* "te" */
257 char *TS_termcap_modes; /* "ti" */
258 char *TS_visible_bell; /* "vb" */
259 char *TS_cursor_normal; /* "ve" */
260 char *TS_cursor_visible; /* "vs" */
261 char *TS_cursor_invisible; /* "vi" */
262 char *TS_set_window; /* "wi" (4 params, start and end of window,
263 each as vpos and hpos) */
265 /* "md" -- turn on bold (extra bright mode). */
267 char *TS_enter_bold_mode;
269 /* "mh" -- turn on half-bright mode. */
271 char *TS_enter_dim_mode;
273 /* "mb" -- enter blinking mode. */
275 char *TS_enter_blink_mode;
277 /* "mr" -- enter reverse video mode. */
279 char *TS_enter_reverse_mode;
281 /* "us"/"ue" -- start/end underlining. */
283 char *TS_exit_underline_mode, *TS_enter_underline_mode;
285 /* "ug" -- number of blanks left by underline. */
287 int TN_magic_cookie_glitch_ul;
289 /* "as"/"ae" -- start/end alternate character set. Not really
290 supported, yet. */
292 char *TS_enter_alt_charset_mode, *TS_exit_alt_charset_mode;
294 /* "me" -- switch appearances off. */
296 char *TS_exit_attribute_mode;
298 /* "Co" -- number of colors. */
300 int TN_max_colors;
302 /* "pa" -- max. number of color pairs on screen. Not handled yet.
303 Could be a problem if not equal to TN_max_colors * TN_max_colors. */
305 int TN_max_pairs;
307 /* "op" -- SVr4 set default pair to its original value. */
309 char *TS_orig_pair;
311 /* "AF"/"AB" or "Sf"/"Sb"-- set ANSI or SVr4 foreground/background color.
312 1 param, the color index. */
314 char *TS_set_foreground, *TS_set_background;
316 int TF_hazeltine; /* termcap hz flag. */
317 int TF_insmode_motion; /* termcap mi flag: can move while in insert mode. */
318 int TF_standout_motion; /* termcap mi flag: can move while in standout mode. */
319 int TF_underscore; /* termcap ul flag: _ underlines if over-struck on
320 non-blank position. Must clear before writing _. */
321 int TF_teleray; /* termcap xt flag: many weird consequences.
322 For t1061. */
324 int TF_xs; /* Nonzero for "xs". If set together with
325 TN_standout_width == 0, it means don't bother
326 to write any end-standout cookies. */
328 int TN_standout_width; /* termcap sg number: width occupied by standout
329 markers */
331 static int RPov; /* # chars to start a TS_repeat */
333 static int delete_in_insert_mode; /* delete mode == insert mode */
335 static int se_is_so; /* 1 if same string both enters and leaves
336 standout mode */
338 /* internal state */
340 /* The largest frame width in any call to calculate_costs. */
342 int max_frame_width;
344 /* The largest frame height in any call to calculate_costs. */
346 int max_frame_height;
348 /* Number of chars of space used for standout marker at beginning of line,
349 or'd with 0100. Zero if no standout marker at all.
350 The length of these vectors is max_frame_height.
352 Used IFF TN_standout_width >= 0. */
354 static char *chars_wasted;
355 static char *copybuf;
357 /* nonzero means supposed to write text in standout mode. */
359 int standout_requested;
361 int insert_mode; /* Nonzero when in insert mode. */
362 int standout_mode; /* Nonzero when in standout mode. */
364 /* Size of window specified by higher levels.
365 This is the number of lines, from the top of frame downwards,
366 which can participate in insert-line/delete-line operations.
368 Effectively it excludes the bottom frame_height - specified_window_size
369 lines from those operations. */
371 int specified_window;
373 /* Frame currently being redisplayed; 0 if not currently redisplaying.
374 (Direct output does not count). */
376 FRAME_PTR updating_frame;
378 /* Provided for lisp packages. */
380 static int system_uses_terminfo;
382 char *tparam ();
384 extern char *tgetstr ();
387 #ifdef WINDOWSNT
389 /* We aren't X windows, but we aren't termcap either. This makes me
390 uncertain as to what value to use for frame.output_method. For
391 this file, we'll define FRAME_TERMCAP_P to be zero so that our
392 output hooks get called instead of the termcap functions. Probably
393 the best long-term solution is to define an output_windows_nt... */
395 #undef FRAME_TERMCAP_P
396 #define FRAME_TERMCAP_P(_f_) 0
397 #endif /* WINDOWSNT */
399 void
400 ring_bell ()
402 if (! NILP (Vring_bell_function))
404 Lisp_Object function;
406 /* Temporarily set the global variable to nil
407 so that if we get an error, it stays nil
408 and we don't call it over and over.
410 We don't specbind it, because that would carefully
411 restore the bad value if there's an error
412 and make the loop of errors happen anyway. */
413 function = Vring_bell_function;
414 Vring_bell_function = Qnil;
416 call0 (function);
418 Vring_bell_function = function;
419 return;
422 if (! FRAME_TERMCAP_P (selected_frame))
424 (*ring_bell_hook) ();
425 return;
427 OUTPUT (TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell);
430 void
431 set_terminal_modes ()
433 if (! FRAME_TERMCAP_P (selected_frame))
435 (*set_terminal_modes_hook) ();
436 return;
438 OUTPUT_IF (TS_termcap_modes);
439 OUTPUT_IF (TS_cursor_visible);
440 OUTPUT_IF (TS_keypad_mode);
441 losecursor ();
444 void
445 reset_terminal_modes ()
447 if (! FRAME_TERMCAP_P (selected_frame))
449 if (reset_terminal_modes_hook)
450 (*reset_terminal_modes_hook) ();
451 return;
453 if (TN_standout_width < 0)
454 turn_off_highlight ();
455 turn_off_insert ();
456 OUTPUT_IF (TS_end_keypad_mode);
457 OUTPUT_IF (TS_cursor_normal);
458 OUTPUT_IF (TS_end_termcap_modes);
459 OUTPUT_IF (TS_orig_pair);
460 /* Output raw CR so kernel can track the cursor hpos. */
461 /* But on magic-cookie terminals this can erase an end-standout marker and
462 cause the rest of the frame to be in standout, so move down first. */
463 if (TN_standout_width >= 0)
464 cmputc ('\n');
465 cmputc ('\r');
468 void
469 update_begin (f)
470 FRAME_PTR f;
472 updating_frame = f;
473 if (! FRAME_TERMCAP_P (updating_frame))
474 (*update_begin_hook) (f);
475 else
476 tty_hide_cursor ();
479 void
480 update_end (f)
481 FRAME_PTR f;
483 if (! FRAME_TERMCAP_P (updating_frame))
485 (*update_end_hook) (f);
486 updating_frame = 0;
487 return;
490 if (!XWINDOW (selected_window)->cursor_off_p)
491 tty_show_cursor ();
493 turn_off_insert ();
494 background_highlight ();
495 standout_requested = 0;
496 updating_frame = 0;
499 void
500 set_terminal_window (size)
501 int size;
503 if (! FRAME_TERMCAP_P (updating_frame))
505 (*set_terminal_window_hook) (size);
506 return;
508 specified_window = size ? size : FRAME_HEIGHT (selected_frame);
509 if (!scroll_region_ok)
510 return;
511 set_scroll_region (0, specified_window);
514 void
515 set_scroll_region (start, stop)
516 int start, stop;
518 char *buf;
519 if (TS_set_scroll_region)
521 buf = tparam (TS_set_scroll_region, 0, 0, start, stop - 1);
523 else if (TS_set_scroll_region_1)
525 buf = tparam (TS_set_scroll_region_1, 0, 0,
526 FRAME_HEIGHT (selected_frame), start,
527 FRAME_HEIGHT (selected_frame) - stop,
528 FRAME_HEIGHT (selected_frame));
530 else
532 buf = tparam (TS_set_window, 0, 0, start, 0, stop, FRAME_WIDTH (selected_frame));
534 OUTPUT (buf);
535 xfree (buf);
536 losecursor ();
539 void
540 turn_on_insert ()
542 if (!insert_mode)
543 OUTPUT (TS_insert_mode);
544 insert_mode = 1;
547 void
548 turn_off_insert ()
550 if (insert_mode)
551 OUTPUT (TS_end_insert_mode);
552 insert_mode = 0;
555 /* Handle highlighting when TN_standout_width (termcap sg) is not specified.
556 In these terminals, output is affected by the value of standout
557 mode when the output is written.
559 These functions are called on all terminals, but do nothing
560 on terminals whose standout mode does not work that way. */
562 void
563 turn_off_highlight ()
565 if (TN_standout_width < 0)
567 if (standout_mode)
568 OUTPUT_IF (TS_end_standout_mode);
569 standout_mode = 0;
573 void
574 turn_on_highlight ()
576 if (TN_standout_width < 0)
578 if (!standout_mode)
579 OUTPUT_IF (TS_standout_mode);
580 standout_mode = 1;
585 /* Make cursor invisible. */
587 static void
588 tty_hide_cursor ()
590 OUTPUT_IF (TS_cursor_invisible);
594 /* Ensure that cursor is visible. */
596 static void
597 tty_show_cursor ()
599 OUTPUT_IF (TS_cursor_normal);
600 OUTPUT_IF (TS_cursor_visible);
604 /* Set standout mode to the state it should be in for
605 empty space inside windows. What this is,
606 depends on the user option inverse-video. */
608 void
609 background_highlight ()
611 if (TN_standout_width >= 0)
612 return;
613 if (inverse_video)
614 turn_on_highlight ();
615 else
616 turn_off_highlight ();
619 /* Set standout mode to the mode specified for the text to be output. */
621 static void
622 highlight_if_desired ()
624 if (TN_standout_width >= 0)
625 return;
626 if (!inverse_video == !standout_requested)
627 turn_off_highlight ();
628 else
629 turn_on_highlight ();
632 /* Handle standout mode for terminals in which TN_standout_width >= 0.
633 On these terminals, standout is controlled by markers that
634 live inside the terminal's memory. TN_standout_width is the width
635 that the marker occupies in memory. Standout runs from the marker
636 to the end of the line on some terminals, or to the next
637 turn-off-standout marker (TS_end_standout_mode) string
638 on other terminals. */
640 /* Write a standout marker or end-standout marker at the front of the line
641 at vertical position vpos. */
643 void
644 write_standout_marker (flag, vpos)
645 int flag, vpos;
647 if (flag || (TS_end_standout_mode && !TF_teleray && !se_is_so
648 && !(TF_xs && TN_standout_width == 0)))
650 cmgoto (vpos, 0);
651 cmplus (TN_standout_width);
652 OUTPUT (flag ? TS_standout_mode : TS_end_standout_mode);
653 chars_wasted[curY] = TN_standout_width | 0100;
657 /* External interface to control of standout mode.
658 Call this when about to modify line at position VPOS
659 and not change whether it is highlighted. */
661 void
662 reassert_line_highlight (highlight, vpos)
663 int highlight;
664 int vpos;
666 if (! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
668 (*reassert_line_highlight_hook) (highlight, vpos);
669 return;
671 if (TN_standout_width < 0)
672 /* Handle terminals where standout takes affect at output time */
673 standout_requested = highlight;
674 else if (chars_wasted && chars_wasted[vpos] == 0)
675 /* For terminals with standout markers, write one on this line
676 if there isn't one already. */
677 write_standout_marker (highlight, vpos);
680 /* Call this when about to modify line at position VPOS
681 and change whether it is highlighted. */
683 void
684 change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
685 int new_highlight, vpos, y, first_unused_hpos;
687 standout_requested = new_highlight;
688 if (! FRAME_TERMCAP_P (updating_frame))
690 (*change_line_highlight_hook) (new_highlight, vpos, y, first_unused_hpos);
691 return;
694 cursor_to (vpos, 0);
696 if (TN_standout_width < 0)
697 background_highlight ();
698 /* If line starts with a marker, delete the marker */
699 else if (TS_clr_line && chars_wasted[curY])
701 turn_off_insert ();
702 /* On Teleray, make sure to erase the SO marker. */
703 if (TF_teleray)
705 cmgoto (curY - 1, FRAME_WIDTH (selected_frame) - 4);
706 OUTPUT ("\033S");
707 curY++; /* ESC S moves to next line where the TS_standout_mode was */
708 curX = 0;
710 else
711 cmgoto (curY, 0); /* reposition to kill standout marker */
713 clear_end_of_line_raw (first_unused_hpos);
714 reassert_line_highlight (new_highlight, curY);
718 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
719 frame-relative coordinates. */
721 void
722 cursor_to (vpos, hpos)
723 int vpos, hpos;
725 if (! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame))
726 && cursor_to_hook)
728 (*cursor_to_hook) (vpos, hpos);
729 return;
732 /* Detect the case where we are called from reset_sys_modes
733 and the costs have never been calculated. Do nothing. */
734 if (chars_wasted == 0)
735 return;
737 hpos += chars_wasted[vpos] & 077;
738 if (curY == vpos && curX == hpos)
739 return;
740 if (!TF_standout_motion)
741 background_highlight ();
742 if (!TF_insmode_motion)
743 turn_off_insert ();
744 cmgoto (vpos, hpos);
747 /* Similar but don't take any account of the wasted characters. */
749 void
750 raw_cursor_to (row, col)
751 int row, col;
753 if (! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
755 (*raw_cursor_to_hook) (row, col);
756 return;
758 if (curY == row && curX == col)
759 return;
760 if (!TF_standout_motion)
761 background_highlight ();
762 if (!TF_insmode_motion)
763 turn_off_insert ();
764 cmgoto (row, col);
767 /* Erase operations */
769 /* clear from cursor to end of frame */
770 void
771 clear_to_end ()
773 register int i;
775 if (clear_to_end_hook && ! FRAME_TERMCAP_P (updating_frame))
777 (*clear_to_end_hook) ();
778 return;
780 if (TS_clr_to_bottom)
782 background_highlight ();
783 OUTPUT (TS_clr_to_bottom);
784 bzero (chars_wasted + curY, FRAME_HEIGHT (selected_frame) - curY);
786 else
788 for (i = curY; i < FRAME_HEIGHT (selected_frame); i++)
790 cursor_to (i, 0);
791 clear_end_of_line_raw (FRAME_WIDTH (selected_frame));
796 /* Clear entire frame */
798 void
799 clear_frame ()
801 if (clear_frame_hook
802 && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
804 (*clear_frame_hook) ();
805 return;
807 if (TS_clr_frame)
809 background_highlight ();
810 OUTPUT (TS_clr_frame);
811 bzero (chars_wasted, FRAME_HEIGHT (selected_frame));
812 cmat (0, 0);
814 else
816 cursor_to (0, 0);
817 clear_to_end ();
821 /* Clear to end of line, but do not clear any standout marker.
822 Assumes that the cursor is positioned at a character of real text,
823 which implies it cannot be before a standout marker
824 unless the marker has zero width.
826 Note that the cursor may be moved. */
828 void
829 clear_end_of_line (first_unused_hpos)
830 int first_unused_hpos;
832 if (FRAME_TERMCAP_P (selected_frame)
833 && chars_wasted != 0
834 && TN_standout_width == 0 && curX == 0 && chars_wasted[curY] != 0)
835 write_glyphs (&space_glyph, 1);
836 clear_end_of_line_raw (first_unused_hpos);
839 /* Clear from cursor to end of line.
840 Assume that the line is already clear starting at column first_unused_hpos.
841 If the cursor is at a standout marker, erase the marker.
843 Note that the cursor may be moved, on terminals lacking a `ce' string. */
845 void
846 clear_end_of_line_raw (first_unused_hpos)
847 int first_unused_hpos;
849 register int i;
851 if (clear_end_of_line_hook
852 && ! FRAME_TERMCAP_P ((updating_frame
853 ? updating_frame
854 : selected_frame)))
856 (*clear_end_of_line_hook) (first_unused_hpos);
857 return;
860 /* Detect the case where we are called from reset_sys_modes
861 and the costs have never been calculated. Do nothing. */
862 if (chars_wasted == 0)
863 return;
865 first_unused_hpos += chars_wasted[curY] & 077;
866 if (curX >= first_unused_hpos)
867 return;
868 /* Notice if we are erasing a magic cookie */
869 if (curX == 0)
870 chars_wasted[curY] = 0;
871 background_highlight ();
872 if (TS_clr_line)
874 OUTPUT1 (TS_clr_line);
876 else
877 { /* have to do it the hard way */
878 turn_off_insert ();
880 /* Do not write in last row last col with Auto-wrap on. */
881 if (AutoWrap && curY == FRAME_HEIGHT (selected_frame) - 1
882 && first_unused_hpos == FRAME_WIDTH (selected_frame))
883 first_unused_hpos--;
885 for (i = curX; i < first_unused_hpos; i++)
887 if (termscript)
888 fputc (' ', termscript);
889 putchar (' ');
891 cmplus (first_unused_hpos - curX);
895 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes and
896 store them at DST. Do not write more than DST_LEN bytes. That may
897 require stopping before all SRC_LEN input glyphs have been
898 converted.
900 We store the number of glyphs actually converted in *CONSUMED. The
901 return value is the number of bytes store in DST. */
904 encode_terminal_code (src, dst, src_len, dst_len, consumed)
905 struct glyph *src;
906 int src_len;
907 unsigned char *dst;
908 int dst_len, *consumed;
910 struct glyph *src_start = src, *src_end = src + src_len;
911 unsigned char *dst_start = dst, *dst_end = dst + dst_len;
912 register GLYPH g;
913 unsigned int c;
914 unsigned char workbuf[4], *buf;
915 int len;
916 register int tlen = GLYPH_TABLE_LENGTH;
917 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
918 int result;
919 struct coding_system *coding;
921 coding = (CODING_REQUIRE_ENCODING (&terminal_coding)
922 ? &terminal_coding
923 : &safe_terminal_coding);
925 while (src < src_end)
927 g = GLYPH_FROM_CHAR_GLYPH (*src);
929 /* We must skip glyphs to be padded for a wide character. */
930 if (! CHAR_GLYPH_PADDING_P (*src))
932 c = src->u.ch.code;
933 if (! GLYPH_CHAR_VALID_P (c))
935 c = ' ';
936 g = MAKE_GLYPH (selected_frame, c,
937 GLYPH_FACE (selected_frame, g));
939 if (COMPOSITE_CHAR_P (c))
941 /* If C is a composite character, we can display
942 only the first component. */
943 g = cmpchar_table[COMPOSITE_CHAR_ID (c)]->glyph[0],
944 c = GLYPH_CHAR (selected_frame, g);
946 if (c < tlen)
948 /* G has an entry in Vglyph_table,
949 so process any alias before testing for simpleness. */
950 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
951 c = GLYPH_CHAR (selected_frame, g);
953 if (GLYPH_SIMPLE_P (tbase, tlen, g))
954 /* We set the multi-byte form of C at BUF. */
955 len = CHAR_STRING (c, workbuf, buf);
956 else
958 /* We have a string in Vglyph_table. */
959 len = GLYPH_LENGTH (tbase, g);
960 buf = GLYPH_STRING (tbase, g);
963 result = encode_coding (coding, buf, dst, len, dst_end - dst);
964 len -= coding->consumed;
965 dst += coding->produced;
966 if (result == CODING_FINISH_INSUFFICIENT_DST
967 || (result == CODING_FINISH_INSUFFICIENT_SRC
968 && len > dst_end - dst))
969 /* The remaining output buffer is too short. We must
970 break the loop here without increasing SRC so that the
971 next call of this function starts from the same glyph. */
972 break;
974 if (len > 0)
976 /* This is the case that a code of the range 0200..0237
977 exists in buf. We must just write out such a code. */
978 buf += coding->consumed;
979 while (len--)
980 *dst++ = *buf++;
983 src++;
986 *consumed = src - src_start;
987 return (dst - dst_start);
991 void
992 write_glyphs (string, len)
993 register struct glyph *string;
994 register int len;
996 int produced, consumed;
997 struct frame *f = updating_frame ? updating_frame : selected_frame;
999 if (write_glyphs_hook
1000 && ! FRAME_TERMCAP_P (f))
1002 (*write_glyphs_hook) (string, len);
1003 return;
1006 highlight_if_desired ();
1007 turn_off_insert ();
1009 /* Don't dare write in last column of bottom line, if Auto-Wrap,
1010 since that would scroll the whole frame on some terminals. */
1012 if (AutoWrap
1013 && curY + 1 == FRAME_HEIGHT (selected_frame)
1014 && (curX + len - (chars_wasted[curY] & 077)
1015 == FRAME_WIDTH (selected_frame)))
1016 len --;
1017 if (len <= 0)
1018 return;
1020 cmplus (len);
1022 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
1023 the tail. */
1024 terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
1026 while (len > 0)
1028 /* Identify a run of glyphs with the same face. */
1029 int face_id = string->u.ch.face_id;
1030 int n;
1032 for (n = 1; n < len; ++n)
1033 if (string[n].u.ch.face_id != face_id)
1034 break;
1036 /* Turn appearance modes of the face of the run on. */
1037 turn_on_face (f, face_id);
1039 while (n > 0)
1041 /* We use a shared conversion buffer of the current size
1042 (1024 bytes at least). Usually it is sufficient, but if
1043 not, we just repeat the loop. */
1044 produced = encode_terminal_code (string, conversion_buffer,
1045 n, conversion_buffer_size,
1046 &consumed);
1047 if (produced > 0)
1049 fwrite (conversion_buffer, 1, produced, stdout);
1050 if (ferror (stdout))
1051 clearerr (stdout);
1052 if (termscript)
1053 fwrite (conversion_buffer, 1, produced, termscript);
1055 len -= consumed;
1056 n -= consumed;
1057 string += consumed;
1060 /* Turn appearance modes off. */
1061 turn_off_face (f, face_id);
1064 /* We may have to output some codes to terminate the writing. */
1065 if (CODING_REQUIRE_FLUSHING (&terminal_coding))
1067 terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
1068 encode_coding (&terminal_coding, "", conversion_buffer,
1069 0, conversion_buffer_size);
1070 if (terminal_coding.produced > 0)
1072 fwrite (conversion_buffer, 1, terminal_coding.produced, stdout);
1073 if (ferror (stdout))
1074 clearerr (stdout);
1075 if (termscript)
1076 fwrite (conversion_buffer, 1, terminal_coding.produced,
1077 termscript);
1081 cmcheckmagic ();
1084 /* If start is zero, insert blanks instead of a string at start */
1086 void
1087 insert_glyphs (start, len)
1088 register struct glyph *start;
1089 register int len;
1091 char *buf;
1092 GLYPH g;
1093 struct frame *f;
1095 if (len <= 0)
1096 return;
1098 if (insert_glyphs_hook)
1100 (*insert_glyphs_hook) (start, len);
1101 return;
1104 f = updating_frame ? updating_frame : selected_frame;
1105 highlight_if_desired ();
1107 if (TS_ins_multi_chars)
1109 buf = tparam (TS_ins_multi_chars, 0, 0, len);
1110 OUTPUT1 (buf);
1111 xfree (buf);
1112 if (start)
1113 write_glyphs (start, len);
1114 return;
1117 turn_on_insert ();
1118 cmplus (len);
1119 /* The bit CODING_MODE_LAST_BLOCK should be set to 1 only at the tail. */
1120 terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
1121 while (len-- > 0)
1123 int produced, consumed;
1124 struct glyph glyph;
1126 OUTPUT1_IF (TS_ins_char);
1127 if (!start)
1128 g = SPACEGLYPH;
1129 else
1131 g = GLYPH_FROM_CHAR_GLYPH (*start);
1132 ++start;
1133 /* We must open sufficient space for a character which
1134 occupies more than one column. */
1135 while (len && CHAR_GLYPH_PADDING_P (*start))
1137 OUTPUT1_IF (TS_ins_char);
1138 start++, len--;
1142 if (len <= 0)
1143 /* This is the last glyph. */
1144 terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
1146 /* We use shared conversion buffer of the current size (1024
1147 bytes at least). It is surely sufficient for just one glyph. */
1148 SET_CHAR_GLYPH_FROM_GLYPH (glyph, g);
1149 turn_on_face (f, glyph.u.ch.face_id);
1150 produced = encode_terminal_code (&glyph, conversion_buffer,
1151 1, conversion_buffer_size, &consumed);
1152 if (produced > 0)
1154 fwrite (conversion_buffer, 1, produced, stdout);
1155 if (ferror (stdout))
1156 clearerr (stdout);
1157 if (termscript)
1158 fwrite (conversion_buffer, 1, produced, termscript);
1161 OUTPUT1_IF (TS_pad_inserted_char);
1162 turn_off_face (f, glyph.u.ch.face_id);
1165 cmcheckmagic ();
1168 void
1169 delete_glyphs (n)
1170 register int n;
1172 char *buf;
1173 register int i;
1175 if (delete_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame))
1177 (*delete_glyphs_hook) (n);
1178 return;
1181 if (delete_in_insert_mode)
1183 turn_on_insert ();
1185 else
1187 turn_off_insert ();
1188 OUTPUT_IF (TS_delete_mode);
1191 if (TS_del_multi_chars)
1193 buf = tparam (TS_del_multi_chars, 0, 0, n);
1194 OUTPUT1 (buf);
1195 xfree (buf);
1197 else
1198 for (i = 0; i < n; i++)
1199 OUTPUT1 (TS_del_char);
1200 if (!delete_in_insert_mode)
1201 OUTPUT_IF (TS_end_delete_mode);
1204 /* Insert N lines at vpos VPOS. If N is negative, delete -N lines. */
1206 void
1207 ins_del_lines (vpos, n)
1208 int vpos, n;
1210 char *multi = n > 0 ? TS_ins_multi_lines : TS_del_multi_lines;
1211 char *single = n > 0 ? TS_ins_line : TS_del_line;
1212 char *scroll = n > 0 ? TS_rev_scroll : TS_fwd_scroll;
1214 register int i = n > 0 ? n : -n;
1215 register char *buf;
1217 if (ins_del_lines_hook && ! FRAME_TERMCAP_P (updating_frame))
1219 (*ins_del_lines_hook) (vpos, n);
1220 return;
1223 /* If the lines below the insertion are being pushed
1224 into the end of the window, this is the same as clearing;
1225 and we know the lines are already clear, since the matching
1226 deletion has already been done. So can ignore this. */
1227 /* If the lines below the deletion are blank lines coming
1228 out of the end of the window, don't bother,
1229 as there will be a matching inslines later that will flush them. */
1230 if (scroll_region_ok && vpos + i >= specified_window)
1231 return;
1232 if (!memory_below_frame && vpos + i >= FRAME_HEIGHT (selected_frame))
1233 return;
1235 if (multi)
1237 raw_cursor_to (vpos, 0);
1238 background_highlight ();
1239 buf = tparam (multi, 0, 0, i);
1240 OUTPUT (buf);
1241 xfree (buf);
1243 else if (single)
1245 raw_cursor_to (vpos, 0);
1246 background_highlight ();
1247 while (--i >= 0)
1248 OUTPUT (single);
1249 if (TF_teleray)
1250 curX = 0;
1252 else
1254 set_scroll_region (vpos, specified_window);
1255 if (n < 0)
1256 raw_cursor_to (specified_window - 1, 0);
1257 else
1258 raw_cursor_to (vpos, 0);
1259 background_highlight ();
1260 while (--i >= 0)
1261 OUTPUTL (scroll, specified_window - vpos);
1262 set_scroll_region (0, specified_window);
1265 if (TN_standout_width >= 0)
1267 register int lower_limit
1268 = (scroll_region_ok
1269 ? specified_window
1270 : FRAME_HEIGHT (selected_frame));
1272 if (n < 0)
1274 bcopy (&chars_wasted[vpos - n], &chars_wasted[vpos],
1275 lower_limit - vpos + n);
1276 bzero (&chars_wasted[lower_limit + n], - n);
1278 else
1280 bcopy (&chars_wasted[vpos], &copybuf[vpos], lower_limit - vpos - n);
1281 bcopy (&copybuf[vpos], &chars_wasted[vpos + n],
1282 lower_limit - vpos - n);
1283 bzero (&chars_wasted[vpos], n);
1286 if (!scroll_region_ok && memory_below_frame && n < 0)
1288 cursor_to (FRAME_HEIGHT (selected_frame) + n, 0);
1289 clear_to_end ();
1293 /* Compute cost of sending "str", in characters,
1294 not counting any line-dependent padding. */
1297 string_cost (str)
1298 char *str;
1300 cost = 0;
1301 if (str)
1302 tputs (str, 0, evalcost);
1303 return cost;
1306 /* Compute cost of sending "str", in characters,
1307 counting any line-dependent padding at one line. */
1309 static int
1310 string_cost_one_line (str)
1311 char *str;
1313 cost = 0;
1314 if (str)
1315 tputs (str, 1, evalcost);
1316 return cost;
1319 /* Compute per line amount of line-dependent padding,
1320 in tenths of characters. */
1323 per_line_cost (str)
1324 register char *str;
1326 cost = 0;
1327 if (str)
1328 tputs (str, 0, evalcost);
1329 cost = - cost;
1330 if (str)
1331 tputs (str, 10, evalcost);
1332 return cost;
1335 #ifndef old
1336 /* char_ins_del_cost[n] is cost of inserting N characters.
1337 char_ins_del_cost[-n] is cost of deleting N characters.
1338 The length of this vector is based on max_frame_width. */
1340 int *char_ins_del_vector;
1342 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WIDTH ((f))])
1343 #endif
1345 /* ARGSUSED */
1346 static void
1347 calculate_ins_del_char_costs (frame)
1348 FRAME_PTR frame;
1350 int ins_startup_cost, del_startup_cost;
1351 int ins_cost_per_char, del_cost_per_char;
1352 register int i;
1353 register int *p;
1355 if (TS_ins_multi_chars)
1357 ins_cost_per_char = 0;
1358 ins_startup_cost = string_cost_one_line (TS_ins_multi_chars);
1360 else if (TS_ins_char || TS_pad_inserted_char
1361 || (TS_insert_mode && TS_end_insert_mode))
1363 ins_startup_cost = (30 * (string_cost (TS_insert_mode)
1364 + string_cost (TS_end_insert_mode))) / 100;
1365 ins_cost_per_char = (string_cost_one_line (TS_ins_char)
1366 + string_cost_one_line (TS_pad_inserted_char));
1368 else
1370 ins_startup_cost = 9999;
1371 ins_cost_per_char = 0;
1374 if (TS_del_multi_chars)
1376 del_cost_per_char = 0;
1377 del_startup_cost = string_cost_one_line (TS_del_multi_chars);
1379 else if (TS_del_char)
1381 del_startup_cost = (string_cost (TS_delete_mode)
1382 + string_cost (TS_end_delete_mode));
1383 if (delete_in_insert_mode)
1384 del_startup_cost /= 2;
1385 del_cost_per_char = string_cost_one_line (TS_del_char);
1387 else
1389 del_startup_cost = 9999;
1390 del_cost_per_char = 0;
1393 /* Delete costs are at negative offsets */
1394 p = &char_ins_del_cost (frame)[0];
1395 for (i = FRAME_WIDTH (frame); --i >= 0;)
1396 *--p = (del_startup_cost += del_cost_per_char);
1398 /* Doing nothing is free */
1399 p = &char_ins_del_cost (frame)[0];
1400 *p++ = 0;
1402 /* Insert costs are at positive offsets */
1403 for (i = FRAME_WIDTH (frame); --i >= 0;)
1404 *p++ = (ins_startup_cost += ins_cost_per_char);
1407 void
1408 calculate_costs (frame)
1409 FRAME_PTR frame;
1411 register char *f = (TS_set_scroll_region
1412 ? TS_set_scroll_region
1413 : TS_set_scroll_region_1);
1415 FRAME_COST_BAUD_RATE (frame) = baud_rate;
1417 scroll_region_cost = string_cost (f);
1418 #ifdef HAVE_X_WINDOWS
1419 if (FRAME_X_P (frame))
1421 do_line_insertion_deletion_costs (frame, 0, ".5*", 0, ".5*",
1422 0, 0,
1423 x_screen_planes (frame));
1424 scroll_region_cost = 0;
1425 return;
1427 #endif
1429 /* These variables are only used for terminal stuff. They are allocated
1430 once for the terminal frame of X-windows emacs, but not used afterwards.
1432 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1433 X turns off char_ins_del_ok.
1435 chars_wasted and copybuf are only used here in term.c in cases where
1436 the term hook isn't called. */
1438 max_frame_height = max (max_frame_height, FRAME_HEIGHT (frame));
1439 max_frame_width = max (max_frame_width, FRAME_WIDTH (frame));
1441 if (chars_wasted != 0)
1442 chars_wasted = (char *) xrealloc (chars_wasted, max_frame_height);
1443 else
1444 chars_wasted = (char *) xmalloc (max_frame_height);
1446 if (copybuf != 0)
1447 copybuf = (char *) xrealloc (copybuf, max_frame_height);
1448 else
1449 copybuf = (char *) xmalloc (max_frame_height);
1451 if (char_ins_del_vector != 0)
1452 char_ins_del_vector
1453 = (int *) xrealloc (char_ins_del_vector,
1454 (sizeof (int)
1455 + 2 * max_frame_width * sizeof (int)));
1456 else
1457 char_ins_del_vector
1458 = (int *) xmalloc (sizeof (int)
1459 + 2 * max_frame_width * sizeof (int));
1461 bzero (chars_wasted, max_frame_height);
1462 bzero (copybuf, max_frame_height);
1463 bzero (char_ins_del_vector, (sizeof (int)
1464 + 2 * max_frame_width * sizeof (int)));
1466 if (f && (!TS_ins_line && !TS_del_line))
1467 do_line_insertion_deletion_costs (frame,
1468 TS_rev_scroll, TS_ins_multi_lines,
1469 TS_fwd_scroll, TS_del_multi_lines,
1470 f, f, 1);
1471 else
1472 do_line_insertion_deletion_costs (frame,
1473 TS_ins_line, TS_ins_multi_lines,
1474 TS_del_line, TS_del_multi_lines,
1475 0, 0, 1);
1477 calculate_ins_del_char_costs (frame);
1479 /* Don't use TS_repeat if its padding is worse than sending the chars */
1480 if (TS_repeat && per_line_cost (TS_repeat) * baud_rate < 9000)
1481 RPov = string_cost (TS_repeat);
1482 else
1483 RPov = FRAME_WIDTH (frame) * 2;
1485 cmcostinit (); /* set up cursor motion costs */
1488 struct fkey_table {
1489 char *cap, *name;
1492 /* Termcap capability names that correspond directly to X keysyms.
1493 Some of these (marked "terminfo") aren't supplied by old-style
1494 (Berkeley) termcap entries. They're listed in X keysym order;
1495 except we put the keypad keys first, so that if they clash with
1496 other keys (as on the IBM PC keyboard) they get overridden.
1499 static struct fkey_table keys[] =
1501 "kh", "home", /* termcap */
1502 "kl", "left", /* termcap */
1503 "ku", "up", /* termcap */
1504 "kr", "right", /* termcap */
1505 "kd", "down", /* termcap */
1506 "%8", "prior", /* terminfo */
1507 "%5", "next", /* terminfo */
1508 "@7", "end", /* terminfo */
1509 "@1", "begin", /* terminfo */
1510 "*6", "select", /* terminfo */
1511 "%9", "print", /* terminfo */
1512 "@4", "execute", /* terminfo --- actually the `command' key */
1514 * "insert" --- see below
1516 "&8", "undo", /* terminfo */
1517 "%0", "redo", /* terminfo */
1518 "%7", "menu", /* terminfo --- actually the `options' key */
1519 "@0", "find", /* terminfo */
1520 "@2", "cancel", /* terminfo */
1521 "%1", "help", /* terminfo */
1523 * "break" goes here, but can't be reliably intercepted with termcap
1525 "&4", "reset", /* terminfo --- actually `restart' */
1527 * "system" and "user" --- no termcaps
1529 "kE", "clearline", /* terminfo */
1530 "kA", "insertline", /* terminfo */
1531 "kL", "deleteline", /* terminfo */
1532 "kI", "insertchar", /* terminfo */
1533 "kD", "deletechar", /* terminfo */
1534 "kB", "backtab", /* terminfo */
1536 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1538 "@8", "kp-enter", /* terminfo */
1540 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1541 * "kp-multiply", "kp-add", "kp-separator",
1542 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1543 * --- no termcaps for any of these.
1545 "K4", "kp-1", /* terminfo */
1547 * "kp-2" --- no termcap
1549 "K5", "kp-3", /* terminfo */
1551 * "kp-4" --- no termcap
1553 "K2", "kp-5", /* terminfo */
1555 * "kp-6" --- no termcap
1557 "K1", "kp-7", /* terminfo */
1559 * "kp-8" --- no termcap
1561 "K3", "kp-9", /* terminfo */
1563 * "kp-equal" --- no termcap
1565 "k1", "f1",
1566 "k2", "f2",
1567 "k3", "f3",
1568 "k4", "f4",
1569 "k5", "f5",
1570 "k6", "f6",
1571 "k7", "f7",
1572 "k8", "f8",
1573 "k9", "f9",
1576 static char **term_get_fkeys_arg;
1577 static Lisp_Object term_get_fkeys_1 ();
1579 /* Find the escape codes sent by the function keys for Vfunction_key_map.
1580 This function scans the termcap function key sequence entries, and
1581 adds entries to Vfunction_key_map for each function key it finds. */
1583 void
1584 term_get_fkeys (address)
1585 char **address;
1587 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1588 errors during the call. The only errors should be from Fdefine_key
1589 when given a key sequence containing an invalid prefix key. If the
1590 termcap defines function keys which use a prefix that is already bound
1591 to a command by the default bindings, we should silently ignore that
1592 function key specification, rather than giving the user an error and
1593 refusing to run at all on such a terminal. */
1595 extern Lisp_Object Fidentity ();
1596 term_get_fkeys_arg = address;
1597 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1600 static Lisp_Object
1601 term_get_fkeys_1 ()
1603 int i;
1605 char **address = term_get_fkeys_arg;
1607 /* This can happen if CANNOT_DUMP or with strange options. */
1608 if (!initialized)
1609 Vfunction_key_map = Fmake_sparse_keymap (Qnil);
1611 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1613 char *sequence = tgetstr (keys[i].cap, address);
1614 if (sequence)
1615 Fdefine_key (Vfunction_key_map, build_string (sequence),
1616 Fmake_vector (make_number (1),
1617 intern (keys[i].name)));
1620 /* The uses of the "k0" capability are inconsistent; sometimes it
1621 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1622 We will attempt to politely accommodate both systems by testing for
1623 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1626 char *k_semi = tgetstr ("k;", address);
1627 char *k0 = tgetstr ("k0", address);
1628 char *k0_name = "f10";
1630 if (k_semi)
1632 Fdefine_key (Vfunction_key_map, build_string (k_semi),
1633 Fmake_vector (make_number (1), intern ("f10")));
1634 k0_name = "f0";
1637 if (k0)
1638 Fdefine_key (Vfunction_key_map, build_string (k0),
1639 Fmake_vector (make_number (1), intern (k0_name)));
1642 /* Set up cookies for numbered function keys above f10. */
1644 char fcap[3], fkey[4];
1646 fcap[0] = 'F'; fcap[2] = '\0';
1647 for (i = 11; i < 64; i++)
1649 if (i <= 19)
1650 fcap[1] = '1' + i - 11;
1651 else if (i <= 45)
1652 fcap[1] = 'A' + i - 20;
1653 else
1654 fcap[1] = 'a' + i - 46;
1657 char *sequence = tgetstr (fcap, address);
1658 if (sequence)
1660 sprintf (fkey, "f%d", i);
1661 Fdefine_key (Vfunction_key_map, build_string (sequence),
1662 Fmake_vector (make_number (1),
1663 intern (fkey)));
1670 * Various mappings to try and get a better fit.
1673 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1674 if (!tgetstr (cap1, address)) \
1676 char *sequence = tgetstr (cap2, address); \
1677 if (sequence) \
1678 Fdefine_key (Vfunction_key_map, build_string (sequence), \
1679 Fmake_vector (make_number (1), \
1680 intern (sym))); \
1683 /* if there's no key_next keycap, map key_npage to `next' keysym */
1684 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1685 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1686 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1687 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1688 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1689 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1690 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1692 /* IBM has their own non-standard dialect of terminfo.
1693 If the standard name isn't found, try the IBM name. */
1694 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1695 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1696 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1697 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1698 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1699 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1700 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1701 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1702 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1703 #undef CONDITIONAL_REASSIGN
1706 return Qnil;
1710 /***********************************************************************
1711 Character Display Information
1712 ***********************************************************************/
1714 static void append_glyph P_ ((struct it *));
1717 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1718 terminal frames if IT->glyph_row != NULL. IT->c is the character
1719 for which to produce glyphs; IT->face_id contains the character's
1720 face. Padding glyphs are appended if IT->c has a IT->pixel_width >
1721 1. */
1723 static void
1724 append_glyph (it)
1725 struct it *it;
1727 struct glyph *glyph, *end;
1728 int i;
1730 xassert (it->glyph_row);
1731 glyph = (it->glyph_row->glyphs[it->area]
1732 + it->glyph_row->used[it->area]);
1733 end = it->glyph_row->glyphs[1 + it->area];
1735 for (i = 0;
1736 i < it->pixel_width && glyph < end;
1737 ++i)
1739 glyph->type = CHAR_GLYPH;
1740 glyph->pixel_width = 1;
1741 glyph->u.ch.code = it->c;
1742 glyph->u.ch.face_id = it->face_id;
1743 glyph->u.ch.padding_p = i > 0;
1744 glyph->charpos = CHARPOS (it->position);
1745 glyph->object = it->object;
1747 ++it->glyph_row->used[it->area];
1748 ++glyph;
1753 /* Produce glyphs for the display element described by IT. The
1754 function fills output fields of IT with pixel information like the
1755 pixel width and height of a character, and maybe produces glyphs at
1756 the same time if IT->glyph_row is non-null. See the explanation of
1757 struct display_iterator in dispextern.h for an overview. */
1759 void
1760 produce_glyphs (it)
1761 struct it *it;
1763 /* If a hook is installed, let it do the work. */
1764 xassert (it->what == IT_CHARACTER
1765 || it->what == IT_IMAGE
1766 || it->what == IT_STRETCH);
1768 /* Nothing but characters are supported on terminal frames. */
1769 xassert (it->what == IT_CHARACTER);
1771 if (it->c >= 040 && it->c < 0177)
1773 it->pixel_width = it->nglyphs = 1;
1774 if (it->glyph_row)
1775 append_glyph (it);
1777 else if (it->c == '\n')
1778 it->pixel_width = it->nglyphs = 0;
1779 else if (it->c == '\t')
1781 int absolute_x = (it->current_x - it->prompt_width
1782 + it->continuation_lines_width);
1783 int next_tab_x
1784 = (((1 + absolute_x + it->tab_width - 1)
1785 / it->tab_width)
1786 * it->tab_width);
1787 int nspaces;
1789 /* If part of the TAB has been displayed on the previous line
1790 which is continued now, continuation_lines_width will have
1791 been incremented already by the part that fitted on the
1792 continued line. So, we will get the right number of spaces
1793 here. */
1794 nspaces = next_tab_x - absolute_x;
1796 if (it->glyph_row)
1798 int n = nspaces;
1800 it->c = ' ';
1801 it->pixel_width = it->len = 1;
1803 while (n--)
1804 append_glyph (it);
1806 it->c = '\t';
1809 it->pixel_width = nspaces;
1810 it->nglyphs = nspaces;
1812 else
1814 /* A multi-byte character. The display width is a per character
1815 value for characters of set CHARSET_COMPOSITION; otherwise
1816 it is fixed for all characters of the set. Some of the
1817 glyphs may have to be ignored because they are already
1818 displayed in a continued line. */
1819 int charset = CHAR_CHARSET (it->c);
1821 if (charset == CHARSET_COMPOSITION)
1822 it->pixel_width = cmpchar_table[COMPOSITE_CHAR_ID (it->c)]->width;
1823 else
1824 it->pixel_width = CHARSET_WIDTH (charset);
1825 it->nglyphs = it->pixel_width;
1827 if (it->glyph_row)
1828 append_glyph (it);
1831 /* Advance current_x by the pixel width as a convenience for
1832 the caller. */
1833 if (it->area == TEXT_AREA)
1834 it->current_x += it->pixel_width;
1835 it->ascent = it->max_ascent = 0;
1836 it->descent = it->max_descent = 1;
1840 /* Get information about special display element WHAT in an
1841 environment described by IT. WHAT is one of IT_TRUNCATION or
1842 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1843 non-null glyph_row member. This function ensures that fields like
1844 face_id, c, len of IT are left untouched. */
1846 void
1847 produce_special_glyphs (it, what)
1848 struct it *it;
1849 enum display_element_type what;
1851 struct it temp_it;
1853 temp_it = *it;
1854 temp_it.dp = NULL;
1855 temp_it.what = IT_CHARACTER;
1856 temp_it.len = 1;
1857 temp_it.object = 0;
1858 bzero (&temp_it.current, sizeof temp_it.current);
1860 if (what == IT_CONTINUATION)
1862 /* Continuation glyph. */
1863 if (it->dp
1864 && INTEGERP (DISP_CONTINUE_GLYPH (it->dp))
1865 && GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (it->dp))))
1867 temp_it.c = FAST_GLYPH_CHAR (XINT (DISP_CONTINUE_GLYPH (it->dp)));
1868 temp_it.len = CHAR_LEN (temp_it.c);
1870 else
1871 temp_it.c = '\\';
1873 produce_glyphs (&temp_it);
1874 it->pixel_width = temp_it.pixel_width;
1875 it->nglyphs = temp_it.pixel_width;
1877 else if (what == IT_TRUNCATION)
1879 /* Truncation glyph. */
1880 if (it->dp
1881 && INTEGERP (DISP_TRUNC_GLYPH (it->dp))
1882 && GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (it->dp))))
1884 temp_it.c = FAST_GLYPH_CHAR (XINT (DISP_TRUNC_GLYPH (it->dp)));
1885 temp_it.len = CHAR_LEN (temp_it.c);
1887 else
1888 temp_it.c = '$';
1890 produce_glyphs (&temp_it);
1891 it->pixel_width = temp_it.pixel_width;
1892 it->nglyphs = temp_it.pixel_width;
1894 else
1895 abort ();
1899 /* Return an estimation of the pixel height of mode or top lines on
1900 frame F. FACE_ID specifies what line's height to estimate. */
1903 estimate_mode_line_height (f, face_id)
1904 struct frame *f;
1905 enum face_id face_id;
1907 if (estimate_mode_line_height_hook)
1908 return estimate_mode_line_height_hook (f, face_id);
1909 else
1910 return 1;
1915 /***********************************************************************
1916 Faces
1917 ***********************************************************************/
1920 /* Turn appearances of face FACE_ID on tty frame F on. */
1922 static void
1923 turn_on_face (f, face_id)
1924 struct frame *f;
1925 int face_id;
1927 struct face *face = FACE_FROM_ID (f, face_id);
1929 xassert (face != NULL);
1931 if (face->tty_bold_p)
1932 OUTPUT1_IF (TS_enter_bold_mode);
1933 else if (face->tty_dim_p)
1934 OUTPUT1_IF (TS_enter_dim_mode);
1936 /* Alternate charset and blinking not yet used. */
1937 if (face->tty_alt_charset_p)
1938 OUTPUT1_IF (TS_enter_alt_charset_mode);
1940 if (face->tty_blinking_p)
1941 OUTPUT1_IF (TS_enter_blink_mode);
1943 if (face->tty_underline_p
1944 /* Don't underline if that's difficult. */
1945 && TN_magic_cookie_glitch_ul <= 0)
1946 OUTPUT1_IF (TS_enter_underline_mode);
1948 if (face->tty_reverse_p)
1949 OUTPUT1_IF (TS_enter_reverse_mode);
1951 if (TN_max_colors > 0)
1953 char *p;
1955 if (face->foreground != FACE_TTY_DEFAULT_COLOR
1956 && TS_set_foreground)
1958 p = tparam (TS_set_foreground, NULL, 0, (int) face->foreground);
1959 OUTPUT (p);
1960 xfree (p);
1963 if (face->background != FACE_TTY_DEFAULT_COLOR
1964 && TS_set_background)
1966 p = tparam (TS_set_background, NULL, 0, (int) face->background);
1967 OUTPUT (p);
1968 xfree (p);
1974 /* Turn off appearances of face FACE_ID on tty frame F. */
1976 static void
1977 turn_off_face (f, face_id)
1978 struct frame *f;
1979 int face_id;
1981 struct face *face = FACE_FROM_ID (f, face_id);
1982 Lisp_Object entry;
1984 xassert (face != NULL);
1986 if (TS_exit_attribute_mode)
1988 /* Capability "me" will turn off appearance modes double-bright,
1989 half-bright, reverse-video, standout, underline. It may or
1990 may not turn off alt-char-mode. */
1991 if (face->tty_bold_p
1992 || face->tty_dim_p
1993 || face->tty_reverse_p
1994 || face->tty_alt_charset_p
1995 || face->tty_blinking_p
1996 || face->tty_underline_p)
1997 OUTPUT1_IF (TS_exit_attribute_mode);
1999 if (face->tty_alt_charset_p)
2000 OUTPUT_IF (TS_exit_alt_charset_mode);
2002 else
2004 /* If we don't have "me" we can only have those appearances
2005 that have exit sequences defined. */
2006 if (face->tty_alt_charset_p)
2007 OUTPUT_IF (TS_exit_alt_charset_mode);
2009 if (face->tty_underline_p
2010 /* We don't underline if that's difficult. */
2011 && TN_magic_cookie_glitch_ul <= 0)
2012 OUTPUT_IF (TS_exit_underline_mode);
2015 /* Switch back to default colors. */
2016 if (TN_max_colors > 0
2017 && (face->foreground != FACE_TTY_DEFAULT_COLOR
2018 || face->background != FACE_TTY_DEFAULT_COLOR))
2019 OUTPUT1_IF (TS_orig_pair);
2023 /* Return non-zero if the terminal is capable to display colors. */
2025 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
2026 0, 0, 0,
2027 "Return non-nil if TTY can display colors.")
2030 return TN_max_colors > 0 ? Qt : Qnil;
2036 /***********************************************************************
2037 Initialization
2038 ***********************************************************************/
2040 void
2041 term_init (terminal_type)
2042 char *terminal_type;
2044 char *area;
2045 char **address = &area;
2046 char buffer[2044];
2047 register char *p;
2048 int status;
2050 #ifdef WINDOWSNT
2051 initialize_w32_display ();
2053 Wcm_clear ();
2055 area = (char *) xmalloc (2044);
2057 if (area == 0)
2058 abort ();
2060 FrameRows = FRAME_HEIGHT (selected_frame);
2061 FrameCols = FRAME_WIDTH (selected_frame);
2062 specified_window = FRAME_HEIGHT (selected_frame);
2064 delete_in_insert_mode = 1;
2066 UseTabs = 0;
2067 scroll_region_ok = 0;
2069 /* Seems to insert lines when it's not supposed to, messing
2070 up the display. In doing a trace, it didn't seem to be
2071 called much, so I don't think we're losing anything by
2072 turning it off. */
2074 line_ins_del_ok = 0;
2075 char_ins_del_ok = 1;
2077 baud_rate = 19200;
2079 FRAME_CAN_HAVE_SCROLL_BARS (selected_frame) = 0;
2080 FRAME_VERTICAL_SCROLL_BAR_TYPE (selected_frame) = vertical_scroll_bar_none;
2082 return;
2083 #else /* not WINDOWSNT */
2085 Wcm_clear ();
2087 status = tgetent (buffer, terminal_type);
2088 if (status < 0)
2090 #ifdef TERMINFO
2091 fatal ("Cannot open terminfo database file");
2092 #else
2093 fatal ("Cannot open termcap database file");
2094 #endif
2096 if (status == 0)
2098 #ifdef TERMINFO
2099 fatal ("Terminal type %s is not defined.\n\
2100 If that is not the actual type of terminal you have,\n\
2101 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2102 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2103 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
2104 terminal_type);
2105 #else
2106 fatal ("Terminal type %s is not defined.\n\
2107 If that is not the actual type of terminal you have,\n\
2108 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2109 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2110 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
2111 terminal_type);
2112 #endif
2114 #ifdef TERMINFO
2115 area = (char *) xmalloc (2044);
2116 #else
2117 area = (char *) xmalloc (strlen (buffer));
2118 #endif /* not TERMINFO */
2119 if (area == 0)
2120 abort ();
2122 TS_ins_line = tgetstr ("al", address);
2123 TS_ins_multi_lines = tgetstr ("AL", address);
2124 TS_bell = tgetstr ("bl", address);
2125 BackTab = tgetstr ("bt", address);
2126 TS_clr_to_bottom = tgetstr ("cd", address);
2127 TS_clr_line = tgetstr ("ce", address);
2128 TS_clr_frame = tgetstr ("cl", address);
2129 ColPosition = tgetstr ("ch", address);
2130 AbsPosition = tgetstr ("cm", address);
2131 CR = tgetstr ("cr", address);
2132 TS_set_scroll_region = tgetstr ("cs", address);
2133 TS_set_scroll_region_1 = tgetstr ("cS", address);
2134 RowPosition = tgetstr ("cv", address);
2135 TS_del_char = tgetstr ("dc", address);
2136 TS_del_multi_chars = tgetstr ("DC", address);
2137 TS_del_line = tgetstr ("dl", address);
2138 TS_del_multi_lines = tgetstr ("DL", address);
2139 TS_delete_mode = tgetstr ("dm", address);
2140 TS_end_delete_mode = tgetstr ("ed", address);
2141 TS_end_insert_mode = tgetstr ("ei", address);
2142 Home = tgetstr ("ho", address);
2143 TS_ins_char = tgetstr ("ic", address);
2144 TS_ins_multi_chars = tgetstr ("IC", address);
2145 TS_insert_mode = tgetstr ("im", address);
2146 TS_pad_inserted_char = tgetstr ("ip", address);
2147 TS_end_keypad_mode = tgetstr ("ke", address);
2148 TS_keypad_mode = tgetstr ("ks", address);
2149 LastLine = tgetstr ("ll", address);
2150 Right = tgetstr ("nd", address);
2151 Down = tgetstr ("do", address);
2152 if (!Down)
2153 Down = tgetstr ("nl", address); /* Obsolete name for "do" */
2154 #ifdef VMS
2155 /* VMS puts a carriage return before each linefeed,
2156 so it is not safe to use linefeeds. */
2157 if (Down && Down[0] == '\n' && Down[1] == '\0')
2158 Down = 0;
2159 #endif /* VMS */
2160 if (tgetflag ("bs"))
2161 Left = "\b"; /* can't possibly be longer! */
2162 else /* (Actually, "bs" is obsolete...) */
2163 Left = tgetstr ("le", address);
2164 if (!Left)
2165 Left = tgetstr ("bc", address); /* Obsolete name for "le" */
2166 TS_pad_char = tgetstr ("pc", address);
2167 TS_repeat = tgetstr ("rp", address);
2168 TS_end_standout_mode = tgetstr ("se", address);
2169 TS_fwd_scroll = tgetstr ("sf", address);
2170 TS_standout_mode = tgetstr ("so", address);
2171 TS_rev_scroll = tgetstr ("sr", address);
2172 Wcm.cm_tab = tgetstr ("ta", address);
2173 TS_end_termcap_modes = tgetstr ("te", address);
2174 TS_termcap_modes = tgetstr ("ti", address);
2175 Up = tgetstr ("up", address);
2176 TS_visible_bell = tgetstr ("vb", address);
2177 TS_cursor_normal = tgetstr ("ve", address);
2178 TS_cursor_visible = tgetstr ("vs", address);
2179 TS_cursor_invisible = tgetstr ("vi", address);
2180 TS_set_window = tgetstr ("wi", address);
2182 TS_enter_underline_mode = tgetstr ("us", address);
2183 TS_exit_underline_mode = tgetstr ("ue", address);
2184 TN_magic_cookie_glitch_ul = tgetnum ("ug");
2185 TS_enter_bold_mode = tgetstr ("md", address);
2186 TS_enter_dim_mode = tgetstr ("mh", address);
2187 TS_enter_blink_mode = tgetstr ("mb", address);
2188 TS_enter_reverse_mode = tgetstr ("mr", address);
2189 TS_enter_alt_charset_mode = tgetstr ("as", address);
2190 TS_exit_alt_charset_mode = tgetstr ("ae", address);
2191 TS_exit_attribute_mode = tgetstr ("me", address);
2193 MultiUp = tgetstr ("UP", address);
2194 MultiDown = tgetstr ("DO", address);
2195 MultiLeft = tgetstr ("LE", address);
2196 MultiRight = tgetstr ("RI", address);
2198 /* SVr4/ANSI color suppert. */
2199 TS_orig_pair = tgetstr ("op", address);
2200 TS_set_foreground = tgetstr ("AF", address);
2201 TS_set_background = tgetstr ("AB", address);
2202 if (!TS_set_foreground)
2204 /* SVr4. */
2205 TS_set_foreground = tgetstr ("Sf", address);
2206 TS_set_background = tgetstr ("Sb", address);
2208 TN_max_colors = tgetnum ("Co");
2209 TN_max_pairs = tgetnum ("pa");
2211 MagicWrap = tgetflag ("xn");
2212 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
2213 the former flag imply the latter. */
2214 AutoWrap = MagicWrap || tgetflag ("am");
2215 memory_below_frame = tgetflag ("db");
2216 TF_hazeltine = tgetflag ("hz");
2217 must_write_spaces = tgetflag ("in");
2218 meta_key = tgetflag ("km") || tgetflag ("MT");
2219 TF_insmode_motion = tgetflag ("mi");
2220 TF_standout_motion = tgetflag ("ms");
2221 TF_underscore = tgetflag ("ul");
2222 TF_xs = tgetflag ("xs");
2223 TF_teleray = tgetflag ("xt");
2225 term_get_fkeys (address);
2227 /* Get frame size from system, or else from termcap. */
2229 int height, width;
2230 get_frame_size (&width, &height);
2231 FRAME_WIDTH (selected_frame) = width;
2232 FRAME_HEIGHT (selected_frame) = height;
2235 if (FRAME_WIDTH (selected_frame) <= 0)
2236 SET_FRAME_WIDTH (selected_frame, tgetnum ("co"));
2237 else
2238 /* Keep width and external_width consistent */
2239 SET_FRAME_WIDTH (selected_frame, FRAME_WIDTH (selected_frame));
2240 if (FRAME_HEIGHT (selected_frame) <= 0)
2241 FRAME_HEIGHT (selected_frame) = tgetnum ("li");
2243 if (FRAME_HEIGHT (selected_frame) < 3
2244 || FRAME_WIDTH (selected_frame) < 3)
2245 fatal ("Screen size %dx%d is too small",
2246 FRAME_HEIGHT (selected_frame), FRAME_WIDTH (selected_frame));
2248 min_padding_speed = tgetnum ("pb");
2249 TN_standout_width = tgetnum ("sg");
2250 TabWidth = tgetnum ("tw");
2252 #ifdef VMS
2253 /* These capabilities commonly use ^J.
2254 I don't know why, but sending them on VMS does not work;
2255 it causes following spaces to be lost, sometimes.
2256 For now, the simplest fix is to avoid using these capabilities ever. */
2257 if (Down && Down[0] == '\n')
2258 Down = 0;
2259 #endif /* VMS */
2261 if (!TS_bell)
2262 TS_bell = "\07";
2264 if (!TS_fwd_scroll)
2265 TS_fwd_scroll = Down;
2267 PC = TS_pad_char ? *TS_pad_char : 0;
2269 if (TabWidth < 0)
2270 TabWidth = 8;
2272 /* Turned off since /etc/termcap seems to have :ta= for most terminals
2273 and newer termcap doc does not seem to say there is a default.
2274 if (!Wcm.cm_tab)
2275 Wcm.cm_tab = "\t";
2278 if (TS_standout_mode == 0)
2280 TN_standout_width = tgetnum ("ug");
2281 TS_end_standout_mode = tgetstr ("ue", address);
2282 TS_standout_mode = tgetstr ("us", address);
2285 /* If no `se' string, try using a `me' string instead.
2286 If that fails, we can't use standout mode at all. */
2287 if (TS_end_standout_mode == 0)
2289 char *s = tgetstr ("me", address);
2290 if (s != 0)
2291 TS_end_standout_mode = s;
2292 else
2293 TS_standout_mode = 0;
2296 if (TF_teleray)
2298 Wcm.cm_tab = 0;
2299 /* Teleray: most programs want a space in front of TS_standout_mode,
2300 but Emacs can do without it (and give one extra column). */
2301 TS_standout_mode = "\033RD";
2302 TN_standout_width = 1;
2303 /* But that means we cannot rely on ^M to go to column zero! */
2304 CR = 0;
2305 /* LF can't be trusted either -- can alter hpos */
2306 /* if move at column 0 thru a line with TS_standout_mode */
2307 Down = 0;
2310 /* Special handling for certain terminal types known to need it */
2312 if (!strcmp (terminal_type, "supdup"))
2314 memory_below_frame = 1;
2315 Wcm.cm_losewrap = 1;
2317 if (!strncmp (terminal_type, "c10", 3)
2318 || !strcmp (terminal_type, "perq"))
2320 /* Supply a makeshift :wi string.
2321 This string is not valid in general since it works only
2322 for windows starting at the upper left corner;
2323 but that is all Emacs uses.
2325 This string works only if the frame is using
2326 the top of the video memory, because addressing is memory-relative.
2327 So first check the :ti string to see if that is true.
2329 It would be simpler if the :wi string could go in the termcap
2330 entry, but it can't because it is not fully valid.
2331 If it were in the termcap entry, it would confuse other programs. */
2332 if (!TS_set_window)
2334 p = TS_termcap_modes;
2335 while (*p && strcmp (p, "\033v "))
2336 p++;
2337 if (*p)
2338 TS_set_window = "\033v%C %C %C %C ";
2340 /* Termcap entry often fails to have :in: flag */
2341 must_write_spaces = 1;
2342 /* :ti string typically fails to have \E^G! in it */
2343 /* This limits scope of insert-char to one line. */
2344 strcpy (area, TS_termcap_modes);
2345 strcat (area, "\033\007!");
2346 TS_termcap_modes = area;
2347 area += strlen (area) + 1;
2348 p = AbsPosition;
2349 /* Change all %+ parameters to %C, to handle
2350 values above 96 correctly for the C100. */
2351 while (*p)
2353 if (p[0] == '%' && p[1] == '+')
2354 p[1] = 'C';
2355 p++;
2359 FrameRows = FRAME_HEIGHT (selected_frame);
2360 FrameCols = FRAME_WIDTH (selected_frame);
2361 specified_window = FRAME_HEIGHT (selected_frame);
2363 if (Wcm_init () == -1) /* can't do cursor motion */
2364 #ifdef VMS
2365 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2366 It lacks the ability to position the cursor.\n\
2367 If that is not the actual type of terminal you have, use either the\n\
2368 DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
2369 or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
2370 terminal_type);
2371 #else /* not VMS */
2372 # ifdef TERMINFO
2373 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2374 It lacks the ability to position the cursor.\n\
2375 If that is not the actual type of terminal you have,\n\
2376 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2377 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2378 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
2379 terminal_type);
2380 # else /* TERMCAP */
2381 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2382 It lacks the ability to position the cursor.\n\
2383 If that is not the actual type of terminal you have,\n\
2384 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2385 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2386 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
2387 terminal_type);
2388 # endif /* TERMINFO */
2389 #endif /*VMS */
2390 if (FRAME_HEIGHT (selected_frame) <= 0
2391 || FRAME_WIDTH (selected_frame) <= 0)
2392 fatal ("The frame size has not been specified");
2394 delete_in_insert_mode
2395 = TS_delete_mode && TS_insert_mode
2396 && !strcmp (TS_delete_mode, TS_insert_mode);
2398 se_is_so = (TS_standout_mode
2399 && TS_end_standout_mode
2400 && !strcmp (TS_standout_mode, TS_end_standout_mode));
2402 /* Remove width of standout marker from usable width of line */
2403 if (TN_standout_width > 0)
2404 SET_FRAME_WIDTH (selected_frame,
2405 FRAME_WIDTH (selected_frame) - TN_standout_width);
2407 UseTabs = tabs_safe_p () && TabWidth == 8;
2409 scroll_region_ok
2410 = (Wcm.cm_abs
2411 && (TS_set_window || TS_set_scroll_region || TS_set_scroll_region_1));
2413 line_ins_del_ok = (((TS_ins_line || TS_ins_multi_lines)
2414 && (TS_del_line || TS_del_multi_lines))
2415 || (scroll_region_ok && TS_fwd_scroll && TS_rev_scroll));
2417 char_ins_del_ok = ((TS_ins_char || TS_insert_mode
2418 || TS_pad_inserted_char || TS_ins_multi_chars)
2419 && (TS_del_char || TS_del_multi_chars));
2421 fast_clear_end_of_line = TS_clr_line != 0;
2423 init_baud_rate ();
2424 if (read_socket_hook) /* Baudrate is somewhat */
2425 /* meaningless in this case */
2426 baud_rate = 9600;
2428 FRAME_CAN_HAVE_SCROLL_BARS (selected_frame) = 0;
2429 FRAME_VERTICAL_SCROLL_BAR_TYPE (selected_frame) = vertical_scroll_bar_none;
2430 #endif /* WINDOWSNT */
2433 /* VARARGS 1 */
2434 void
2435 fatal (str, arg1, arg2)
2436 char *str, *arg1, *arg2;
2438 fprintf (stderr, "emacs: ");
2439 fprintf (stderr, str, arg1, arg2);
2440 fprintf (stderr, "\n");
2441 fflush (stderr);
2442 exit (1);
2445 void
2446 syms_of_term ()
2448 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
2449 "Non-nil means the system uses terminfo rather than termcap.\n\
2450 This variable can be used by terminal emulator packages.");
2451 #ifdef TERMINFO
2452 system_uses_terminfo = 1;
2453 #else
2454 system_uses_terminfo = 0;
2455 #endif
2457 DEFVAR_LISP ("ring-bell-function", &Vring_bell_function,
2458 "Non-nil means call this function to ring the bell.\n\
2459 The function should accept no arguments.");
2460 Vring_bell_function = Qnil;
2462 defsubr (&Stty_display_color_p);