(reassert_line_highlight_hook, change_line_highlight_hook): Variables removed.
[bpt/emacs.git] / src / term.c
1 /* Terminal control module for terminals described by TERMCAP
2 Copyright (C) 1985, 86, 87, 93, 94, 95, 98, 2000, 2001
3 Free Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
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.
11
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.
16
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. */
21
22 /* New redisplay, TTY faces by Gerd Moellmann <gerd@gnu.org>. */
23
24 #include <config.h>
25 #include <stdio.h>
26 #include <ctype.h>
27 #include <string.h>
28
29 #include "termchar.h"
30 #include "termopts.h"
31 #include "lisp.h"
32 #include "charset.h"
33 #include "coding.h"
34 #include "keyboard.h"
35 #include "frame.h"
36 #include "disptab.h"
37 #include "termhooks.h"
38 #include "dispextern.h"
39 #include "window.h"
40 #include "keymap.h"
41
42 /* For now, don't try to include termcap.h. On some systems,
43 configure finds a non-standard termcap.h that the main build
44 won't find. */
45
46 #if defined HAVE_TERMCAP_H && 0
47 #include <termcap.h>
48 #else
49 extern void tputs P_ ((const char *, int, int (*)(int)));
50 extern int tgetent P_ ((char *, const char *));
51 extern int tgetflag P_ ((char *id));
52 extern int tgetnum P_ ((char *id));
53 #endif
54
55 #include "cm.h"
56 #ifdef HAVE_X_WINDOWS
57 #include "xterm.h"
58 #endif
59 #ifdef macintosh
60 #include "macterm.h"
61 #endif
62
63 static void turn_on_face P_ ((struct frame *, int face_id));
64 static void turn_off_face P_ ((struct frame *, int face_id));
65 static void tty_show_cursor P_ ((void));
66 static void tty_hide_cursor P_ ((void));
67
68 #define OUTPUT(a) \
69 tputs (a, (int) (FRAME_HEIGHT (XFRAME (selected_frame)) - curY), cmputc)
70 #define OUTPUT1(a) tputs (a, 1, cmputc)
71 #define OUTPUTL(a, lines) tputs (a, lines, cmputc)
72
73 #define OUTPUT_IF(a) \
74 do { \
75 if (a) \
76 tputs (a, (int) (FRAME_HEIGHT (XFRAME (selected_frame)) \
77 - curY), cmputc); \
78 } while (0)
79
80 #define OUTPUT1_IF(a) do { if (a) tputs (a, 1, cmputc); } while (0)
81
82 /* Function to use to ring the bell. */
83
84 Lisp_Object Vring_bell_function;
85
86 /* Terminal characteristics that higher levels want to look at.
87 These are all extern'd in termchar.h */
88
89 int must_write_spaces; /* Nonzero means spaces in the text
90 must actually be output; can't just skip
91 over some columns to leave them blank. */
92 int min_padding_speed; /* Speed below which no padding necessary */
93
94 int line_ins_del_ok; /* Terminal can insert and delete lines */
95 int char_ins_del_ok; /* Terminal can insert and delete chars */
96 int scroll_region_ok; /* Terminal supports setting the
97 scroll window */
98 int scroll_region_cost; /* Cost of setting a scroll window,
99 measured in characters */
100 int memory_below_frame; /* Terminal remembers lines
101 scrolled off bottom */
102 int fast_clear_end_of_line; /* Terminal has a `ce' string */
103
104 /* Nonzero means no need to redraw the entire frame on resuming
105 a suspended Emacs. This is useful on terminals with multiple pages,
106 where one page is used for Emacs and another for all else. */
107
108 int no_redraw_on_reenter;
109
110 /* Hook functions that you can set to snap out the functions in this file.
111 These are all extern'd in termhooks.h */
112
113 void (*cursor_to_hook) P_ ((int, int));
114 void (*raw_cursor_to_hook) P_ ((int, int));
115 void (*clear_to_end_hook) P_ ((void));
116 void (*clear_frame_hook) P_ ((void));
117 void (*clear_end_of_line_hook) P_ ((int));
118
119 void (*ins_del_lines_hook) P_ ((int, int));
120
121 void (*delete_glyphs_hook) P_ ((int));
122
123 void (*ring_bell_hook) P_ ((void));
124
125 void (*reset_terminal_modes_hook) P_ ((void));
126 void (*set_terminal_modes_hook) P_ ((void));
127 void (*update_begin_hook) P_ ((struct frame *));
128 void (*update_end_hook) P_ ((struct frame *));
129 void (*set_terminal_window_hook) P_ ((int));
130 void (*insert_glyphs_hook) P_ ((struct glyph *, int));
131 void (*write_glyphs_hook) P_ ((struct glyph *, int));
132 void (*delete_glyphs_hook) P_ ((int));
133
134 int (*read_socket_hook) P_ ((int, struct input_event *, int, int));
135
136 void (*frame_up_to_date_hook) P_ ((struct frame *));
137
138 /* Return the current position of the mouse.
139
140 Set *f to the frame the mouse is in, or zero if the mouse is in no
141 Emacs frame. If it is set to zero, all the other arguments are
142 garbage.
143
144 If the motion started in a scroll bar, set *bar_window to the
145 scroll bar's window, *part to the part the mouse is currently over,
146 *x to the position of the mouse along the scroll bar, and *y to the
147 overall length of the scroll bar.
148
149 Otherwise, set *bar_window to Qnil, and *x and *y to the column and
150 row of the character cell the mouse is over.
151
152 Set *time to the time the mouse was at the returned position.
153
154 This should clear mouse_moved until the next motion
155 event arrives. */
156
157 void (*mouse_position_hook) P_ ((FRAME_PTR *f, int insist,
158 Lisp_Object *bar_window,
159 enum scroll_bar_part *part,
160 Lisp_Object *x,
161 Lisp_Object *y,
162 unsigned long *time));
163
164 /* When reading from a minibuffer in a different frame, Emacs wants
165 to shift the highlight from the selected frame to the mini-buffer's
166 frame; under X, this means it lies about where the focus is.
167 This hook tells the window system code to re-decide where to put
168 the highlight. */
169
170 void (*frame_rehighlight_hook) P_ ((FRAME_PTR f));
171
172 /* If we're displaying frames using a window system that can stack
173 frames on top of each other, this hook allows you to bring a frame
174 to the front, or bury it behind all the other windows. If this
175 hook is zero, that means the device we're displaying on doesn't
176 support overlapping frames, so there's no need to raise or lower
177 anything.
178
179 If RAISE is non-zero, F is brought to the front, before all other
180 windows. If RAISE is zero, F is sent to the back, behind all other
181 windows. */
182
183 void (*frame_raise_lower_hook) P_ ((FRAME_PTR f, int raise));
184
185 /* Set the vertical scroll bar for WINDOW to have its upper left corner
186 at (TOP, LEFT), and be LENGTH rows high. Set its handle to
187 indicate that we are displaying PORTION characters out of a total
188 of WHOLE characters, starting at POSITION. If WINDOW doesn't yet
189 have a scroll bar, create one for it. */
190
191 void (*set_vertical_scroll_bar_hook)
192 P_ ((struct window *window,
193 int portion, int whole, int position));
194
195
196 /* The following three hooks are used when we're doing a thorough
197 redisplay of the frame. We don't explicitly know which scroll bars
198 are going to be deleted, because keeping track of when windows go
199 away is a real pain - can you say set-window-configuration?
200 Instead, we just assert at the beginning of redisplay that *all*
201 scroll bars are to be removed, and then save scroll bars from the
202 fiery pit when we actually redisplay their window. */
203
204 /* Arrange for all scroll bars on FRAME to be removed at the next call
205 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
206 `*redeem_scroll_bar_hook' is applied to its window before the judgment.
207
208 This should be applied to each frame each time its window tree is
209 redisplayed, even if it is not displaying scroll bars at the moment;
210 if the HAS_SCROLL_BARS flag has just been turned off, only calling
211 this and the judge_scroll_bars_hook will get rid of them.
212
213 If non-zero, this hook should be safe to apply to any frame,
214 whether or not it can support scroll bars, and whether or not it is
215 currently displaying them. */
216
217 void (*condemn_scroll_bars_hook) P_ ((FRAME_PTR frame));
218
219 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
220 Note that it's okay to redeem a scroll bar that is not condemned. */
221
222 void (*redeem_scroll_bar_hook) P_ ((struct window *window));
223
224 /* Remove all scroll bars on FRAME that haven't been saved since the
225 last call to `*condemn_scroll_bars_hook'.
226
227 This should be applied to each frame after each time its window
228 tree is redisplayed, even if it is not displaying scroll bars at the
229 moment; if the HAS_SCROLL_BARS flag has just been turned off, only
230 calling this and condemn_scroll_bars_hook will get rid of them.
231
232 If non-zero, this hook should be safe to apply to any frame,
233 whether or not it can support scroll bars, and whether or not it is
234 currently displaying them. */
235
236 void (*judge_scroll_bars_hook) P_ ((FRAME_PTR FRAME));
237
238 /* Hook to call in estimate_mode_line_height, if any. */
239
240 int (* estimate_mode_line_height_hook) P_ ((struct frame *f, enum face_id));
241
242
243 /* Strings, numbers and flags taken from the termcap entry. */
244
245 char *TS_ins_line; /* "al" */
246 char *TS_ins_multi_lines; /* "AL" (one parameter, # lines to insert) */
247 char *TS_bell; /* "bl" */
248 char *TS_clr_to_bottom; /* "cd" */
249 char *TS_clr_line; /* "ce", clear to end of line */
250 char *TS_clr_frame; /* "cl" */
251 char *TS_set_scroll_region; /* "cs" (2 params, first line and last line) */
252 char *TS_set_scroll_region_1; /* "cS" (4 params: total lines,
253 lines above scroll region, lines below it,
254 total lines again) */
255 char *TS_del_char; /* "dc" */
256 char *TS_del_multi_chars; /* "DC" (one parameter, # chars to delete) */
257 char *TS_del_line; /* "dl" */
258 char *TS_del_multi_lines; /* "DL" (one parameter, # lines to delete) */
259 char *TS_delete_mode; /* "dm", enter character-delete mode */
260 char *TS_end_delete_mode; /* "ed", leave character-delete mode */
261 char *TS_end_insert_mode; /* "ei", leave character-insert mode */
262 char *TS_ins_char; /* "ic" */
263 char *TS_ins_multi_chars; /* "IC" (one parameter, # chars to insert) */
264 char *TS_insert_mode; /* "im", enter character-insert mode */
265 char *TS_pad_inserted_char; /* "ip". Just padding, no commands. */
266 char *TS_end_keypad_mode; /* "ke" */
267 char *TS_keypad_mode; /* "ks" */
268 char *TS_pad_char; /* "pc", char to use as padding */
269 char *TS_repeat; /* "rp" (2 params, # times to repeat
270 and character to be repeated) */
271 char *TS_end_standout_mode; /* "se" */
272 char *TS_fwd_scroll; /* "sf" */
273 char *TS_standout_mode; /* "so" */
274 char *TS_rev_scroll; /* "sr" */
275 char *TS_end_termcap_modes; /* "te" */
276 char *TS_termcap_modes; /* "ti" */
277 char *TS_visible_bell; /* "vb" */
278 char *TS_cursor_normal; /* "ve" */
279 char *TS_cursor_visible; /* "vs" */
280 char *TS_cursor_invisible; /* "vi" */
281 char *TS_set_window; /* "wi" (4 params, start and end of window,
282 each as vpos and hpos) */
283
284 /* Value of the "NC" (no_color_video) capability, or 0 if not
285 present. */
286
287 static int TN_no_color_video;
288
289 /* Meaning of bits in no_color_video. Each bit set means that the
290 corresponding attribute cannot be combined with colors. */
291
292 enum no_color_bit
293 {
294 NC_STANDOUT = 1 << 0,
295 NC_UNDERLINE = 1 << 1,
296 NC_REVERSE = 1 << 2,
297 NC_BLINK = 1 << 3,
298 NC_DIM = 1 << 4,
299 NC_BOLD = 1 << 5,
300 NC_INVIS = 1 << 6,
301 NC_PROTECT = 1 << 7,
302 NC_ALT_CHARSET = 1 << 8
303 };
304
305 /* "md" -- turn on bold (extra bright mode). */
306
307 char *TS_enter_bold_mode;
308
309 /* "mh" -- turn on half-bright mode. */
310
311 char *TS_enter_dim_mode;
312
313 /* "mb" -- enter blinking mode. */
314
315 char *TS_enter_blink_mode;
316
317 /* "mr" -- enter reverse video mode. */
318
319 char *TS_enter_reverse_mode;
320
321 /* "us"/"ue" -- start/end underlining. */
322
323 char *TS_exit_underline_mode, *TS_enter_underline_mode;
324
325 /* "ug" -- number of blanks left by underline. */
326
327 int TN_magic_cookie_glitch_ul;
328
329 /* "as"/"ae" -- start/end alternate character set. Not really
330 supported, yet. */
331
332 char *TS_enter_alt_charset_mode, *TS_exit_alt_charset_mode;
333
334 /* "me" -- switch appearances off. */
335
336 char *TS_exit_attribute_mode;
337
338 /* "Co" -- number of colors. */
339
340 int TN_max_colors;
341
342 /* "pa" -- max. number of color pairs on screen. Not handled yet.
343 Could be a problem if not equal to TN_max_colors * TN_max_colors. */
344
345 int TN_max_pairs;
346
347 /* "op" -- SVr4 set default pair to its original value. */
348
349 char *TS_orig_pair;
350
351 /* "AF"/"AB" or "Sf"/"Sb"-- set ANSI or SVr4 foreground/background color.
352 1 param, the color index. */
353
354 char *TS_set_foreground, *TS_set_background;
355
356 int TF_hazeltine; /* termcap hz flag. */
357 int TF_insmode_motion; /* termcap mi flag: can move while in insert mode. */
358 int TF_standout_motion; /* termcap mi flag: can move while in standout mode. */
359 int TF_underscore; /* termcap ul flag: _ underlines if over-struck on
360 non-blank position. Must clear before writing _. */
361 int TF_teleray; /* termcap xt flag: many weird consequences.
362 For t1061. */
363
364 int TF_xs; /* Nonzero for "xs". If set together with
365 TN_standout_width == 0, it means don't bother
366 to write any end-standout cookies. */
367
368 int TN_standout_width; /* termcap sg number: width occupied by standout
369 markers */
370
371 static int RPov; /* # chars to start a TS_repeat */
372
373 static int delete_in_insert_mode; /* delete mode == insert mode */
374
375 static int se_is_so; /* 1 if same string both enters and leaves
376 standout mode */
377
378 /* internal state */
379
380 /* The largest frame width in any call to calculate_costs. */
381
382 int max_frame_width;
383
384 /* The largest frame height in any call to calculate_costs. */
385
386 int max_frame_height;
387
388 int costs_set = 0; /* Nonzero if costs have been calculated. */
389
390 int insert_mode; /* Nonzero when in insert mode. */
391 int standout_mode; /* Nonzero when in standout mode. */
392
393 /* Size of window specified by higher levels.
394 This is the number of lines, from the top of frame downwards,
395 which can participate in insert-line/delete-line operations.
396
397 Effectively it excludes the bottom frame_height - specified_window_size
398 lines from those operations. */
399
400 int specified_window;
401
402 /* Frame currently being redisplayed; 0 if not currently redisplaying.
403 (Direct output does not count). */
404
405 FRAME_PTR updating_frame;
406
407 /* Provided for lisp packages. */
408
409 static int system_uses_terminfo;
410
411 /* Flag used in tty_show/hide_cursor. */
412
413 static int tty_cursor_hidden;
414
415 char *tparam ();
416
417 extern char *tgetstr ();
418 \f
419
420 #ifdef WINDOWSNT
421 /* We aren't X windows, but we aren't termcap either. This makes me
422 uncertain as to what value to use for frame.output_method. For
423 this file, we'll define FRAME_TERMCAP_P to be zero so that our
424 output hooks get called instead of the termcap functions. Probably
425 the best long-term solution is to define an output_windows_nt... */
426
427 #undef FRAME_TERMCAP_P
428 #define FRAME_TERMCAP_P(_f_) 0
429 #endif /* WINDOWSNT */
430
431 void
432 ring_bell ()
433 {
434 if (!NILP (Vring_bell_function))
435 {
436 Lisp_Object function;
437
438 /* Temporarily set the global variable to nil
439 so that if we get an error, it stays nil
440 and we don't call it over and over.
441
442 We don't specbind it, because that would carefully
443 restore the bad value if there's an error
444 and make the loop of errors happen anyway. */
445
446 function = Vring_bell_function;
447 Vring_bell_function = Qnil;
448
449 call0 (function);
450
451 Vring_bell_function = function;
452 }
453 else if (!FRAME_TERMCAP_P (XFRAME (selected_frame)))
454 (*ring_bell_hook) ();
455 else
456 OUTPUT (TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell);
457 }
458
459 void
460 set_terminal_modes ()
461 {
462 if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
463 {
464 OUTPUT_IF (TS_termcap_modes);
465 OUTPUT_IF (TS_cursor_visible);
466 OUTPUT_IF (TS_keypad_mode);
467 losecursor ();
468 }
469 else
470 (*set_terminal_modes_hook) ();
471 }
472
473 void
474 reset_terminal_modes ()
475 {
476 if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
477 {
478 if (TN_standout_width < 0)
479 turn_off_highlight ();
480 turn_off_insert ();
481 OUTPUT_IF (TS_end_keypad_mode);
482 OUTPUT_IF (TS_cursor_normal);
483 OUTPUT_IF (TS_end_termcap_modes);
484 OUTPUT_IF (TS_orig_pair);
485 /* Output raw CR so kernel can track the cursor hpos. */
486 /* But on magic-cookie terminals this can erase an end-standout
487 marker and cause the rest of the frame to be in standout, so
488 move down first. */
489 if (TN_standout_width >= 0)
490 cmputc ('\n');
491 cmputc ('\r');
492 }
493 else if (reset_terminal_modes_hook)
494 (*reset_terminal_modes_hook) ();
495 }
496
497 void
498 update_begin (f)
499 struct frame *f;
500 {
501 updating_frame = f;
502 if (!FRAME_TERMCAP_P (f))
503 update_begin_hook (f);
504 }
505
506 void
507 update_end (f)
508 struct frame *f;
509 {
510 if (FRAME_TERMCAP_P (f))
511 {
512 if (!XWINDOW (selected_window)->cursor_off_p)
513 tty_show_cursor ();
514 turn_off_insert ();
515 background_highlight ();
516 }
517 else
518 update_end_hook (f);
519
520 updating_frame = NULL;
521 }
522
523 void
524 set_terminal_window (size)
525 int size;
526 {
527 if (FRAME_TERMCAP_P (updating_frame))
528 {
529 specified_window = size ? size : FRAME_HEIGHT (updating_frame);
530 if (scroll_region_ok)
531 set_scroll_region (0, specified_window);
532 }
533 else
534 set_terminal_window_hook (size);
535 }
536
537 void
538 set_scroll_region (start, stop)
539 int start, stop;
540 {
541 char *buf;
542 struct frame *sf = XFRAME (selected_frame);
543
544 if (TS_set_scroll_region)
545 buf = tparam (TS_set_scroll_region, 0, 0, start, stop - 1);
546 else if (TS_set_scroll_region_1)
547 buf = tparam (TS_set_scroll_region_1, 0, 0,
548 FRAME_HEIGHT (sf), start,
549 FRAME_HEIGHT (sf) - stop,
550 FRAME_HEIGHT (sf));
551 else
552 buf = tparam (TS_set_window, 0, 0, start, 0, stop, FRAME_WIDTH (sf));
553
554 OUTPUT (buf);
555 xfree (buf);
556 losecursor ();
557 }
558
559 \f
560 static void
561 turn_on_insert ()
562 {
563 if (!insert_mode)
564 OUTPUT (TS_insert_mode);
565 insert_mode = 1;
566 }
567
568 void
569 turn_off_insert ()
570 {
571 if (insert_mode)
572 OUTPUT (TS_end_insert_mode);
573 insert_mode = 0;
574 }
575 \f
576 /* Handle highlighting when TN_standout_width (termcap sg) is not specified.
577 In these terminals, output is affected by the value of standout
578 mode when the output is written.
579
580 These functions are called on all terminals, but do nothing
581 on terminals whose standout mode does not work that way. */
582
583 void
584 turn_off_highlight ()
585 {
586 if (TN_standout_width < 0)
587 {
588 if (standout_mode)
589 OUTPUT_IF (TS_end_standout_mode);
590 standout_mode = 0;
591 }
592 }
593
594 static void
595 turn_on_highlight ()
596 {
597 if (TN_standout_width < 0)
598 {
599 if (!standout_mode)
600 OUTPUT_IF (TS_standout_mode);
601 standout_mode = 1;
602 }
603 }
604
605 static void
606 toggle_highlight ()
607 {
608 if (standout_mode)
609 turn_off_highlight ();
610 else
611 turn_on_highlight ();
612 }
613
614
615 /* Make cursor invisible. */
616
617 static void
618 tty_hide_cursor ()
619 {
620 if (tty_cursor_hidden == 0)
621 {
622 tty_cursor_hidden = 1;
623 OUTPUT_IF (TS_cursor_invisible);
624 }
625 }
626
627
628 /* Ensure that cursor is visible. */
629
630 static void
631 tty_show_cursor ()
632 {
633 if (tty_cursor_hidden)
634 {
635 tty_cursor_hidden = 0;
636 OUTPUT_IF (TS_cursor_normal);
637 OUTPUT_IF (TS_cursor_visible);
638 }
639 }
640
641
642 /* Set standout mode to the state it should be in for
643 empty space inside windows. What this is,
644 depends on the user option inverse-video. */
645
646 void
647 background_highlight ()
648 {
649 if (TN_standout_width >= 0)
650 return;
651 if (inverse_video)
652 turn_on_highlight ();
653 else
654 turn_off_highlight ();
655 }
656
657 /* Set standout mode to the mode specified for the text to be output. */
658
659 static void
660 highlight_if_desired ()
661 {
662 if (TN_standout_width >= 0)
663 return;
664 if (inverse_video)
665 turn_on_highlight ();
666 else
667 turn_off_highlight ();
668 }
669 \f
670
671 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
672 frame-relative coordinates. */
673
674 void
675 cursor_to (vpos, hpos)
676 int vpos, hpos;
677 {
678 struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
679
680 if (! FRAME_TERMCAP_P (f) && cursor_to_hook)
681 {
682 (*cursor_to_hook) (vpos, hpos);
683 return;
684 }
685
686 /* Detect the case where we are called from reset_sys_modes
687 and the costs have never been calculated. Do nothing. */
688 if (! costs_set)
689 return;
690
691 if (curY == vpos && curX == hpos)
692 return;
693 if (!TF_standout_motion)
694 background_highlight ();
695 if (!TF_insmode_motion)
696 turn_off_insert ();
697 cmgoto (vpos, hpos);
698 }
699
700 /* Similar but don't take any account of the wasted characters. */
701
702 void
703 raw_cursor_to (row, col)
704 int row, col;
705 {
706 struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
707 if (! FRAME_TERMCAP_P (f))
708 {
709 (*raw_cursor_to_hook) (row, col);
710 return;
711 }
712 if (curY == row && curX == col)
713 return;
714 if (!TF_standout_motion)
715 background_highlight ();
716 if (!TF_insmode_motion)
717 turn_off_insert ();
718 cmgoto (row, col);
719 }
720 \f
721 /* Erase operations */
722
723 /* clear from cursor to end of frame */
724 void
725 clear_to_end ()
726 {
727 register int i;
728
729 if (clear_to_end_hook && ! FRAME_TERMCAP_P (updating_frame))
730 {
731 (*clear_to_end_hook) ();
732 return;
733 }
734 if (TS_clr_to_bottom)
735 {
736 background_highlight ();
737 OUTPUT (TS_clr_to_bottom);
738 }
739 else
740 {
741 for (i = curY; i < FRAME_HEIGHT (XFRAME (selected_frame)); i++)
742 {
743 cursor_to (i, 0);
744 clear_end_of_line (FRAME_WIDTH (XFRAME (selected_frame)));
745 }
746 }
747 }
748
749 /* Clear entire frame */
750
751 void
752 clear_frame ()
753 {
754 struct frame *sf = XFRAME (selected_frame);
755
756 if (clear_frame_hook
757 && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : sf)))
758 {
759 (*clear_frame_hook) ();
760 return;
761 }
762 if (TS_clr_frame)
763 {
764 background_highlight ();
765 OUTPUT (TS_clr_frame);
766 cmat (0, 0);
767 }
768 else
769 {
770 cursor_to (0, 0);
771 clear_to_end ();
772 }
773 }
774
775 /* Clear from cursor to end of line.
776 Assume that the line is already clear starting at column first_unused_hpos.
777
778 Note that the cursor may be moved, on terminals lacking a `ce' string. */
779
780 void
781 clear_end_of_line (first_unused_hpos)
782 int first_unused_hpos;
783 {
784 register int i;
785
786 if (clear_end_of_line_hook
787 && ! FRAME_TERMCAP_P ((updating_frame
788 ? updating_frame
789 : XFRAME (selected_frame))))
790 {
791 (*clear_end_of_line_hook) (first_unused_hpos);
792 return;
793 }
794
795 /* Detect the case where we are called from reset_sys_modes
796 and the costs have never been calculated. Do nothing. */
797 if (! costs_set)
798 return;
799
800 if (curX >= first_unused_hpos)
801 return;
802 background_highlight ();
803 if (TS_clr_line)
804 {
805 OUTPUT1 (TS_clr_line);
806 }
807 else
808 { /* have to do it the hard way */
809 struct frame *sf = XFRAME (selected_frame);
810 turn_off_insert ();
811
812 /* Do not write in last row last col with Auto-wrap on. */
813 if (AutoWrap && curY == FRAME_HEIGHT (sf) - 1
814 && first_unused_hpos == FRAME_WIDTH (sf))
815 first_unused_hpos--;
816
817 for (i = curX; i < first_unused_hpos; i++)
818 {
819 if (termscript)
820 fputc (' ', termscript);
821 putchar (' ');
822 }
823 cmplus (first_unused_hpos - curX);
824 }
825 }
826 \f
827 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes and
828 store them at DST. Do not write more than DST_LEN bytes. That may
829 require stopping before all SRC_LEN input glyphs have been
830 converted.
831
832 We store the number of glyphs actually converted in *CONSUMED. The
833 return value is the number of bytes store in DST. */
834
835 int
836 encode_terminal_code (src, dst, src_len, dst_len, consumed)
837 struct glyph *src;
838 int src_len;
839 unsigned char *dst;
840 int dst_len, *consumed;
841 {
842 struct glyph *src_start = src, *src_end = src + src_len;
843 unsigned char *dst_start = dst, *dst_end = dst + dst_len;
844 register GLYPH g;
845 unsigned char workbuf[MAX_MULTIBYTE_LENGTH], *buf;
846 int len;
847 register int tlen = GLYPH_TABLE_LENGTH;
848 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
849 int result;
850 struct coding_system *coding;
851
852 /* If terminal_coding does any conversion, use it, otherwise use
853 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
854 because it always return 1 if the member src_multibyte is 1. */
855 coding = (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK
856 ? &terminal_coding
857 : &safe_terminal_coding);
858
859 while (src < src_end)
860 {
861 /* We must skip glyphs to be padded for a wide character. */
862 if (! CHAR_GLYPH_PADDING_P (*src))
863 {
864 g = GLYPH_FROM_CHAR_GLYPH (src[0]);
865
866 if (g < 0 || g >= tlen)
867 {
868 /* This glyph doesn't has an entry in Vglyph_table. */
869 if (! CHAR_VALID_P (src->u.ch, 0))
870 {
871 len = 1;
872 buf = " ";
873 coding->src_multibyte = 0;
874 }
875 else
876 {
877 len = CHAR_STRING (src->u.ch, workbuf);
878 buf = workbuf;
879 coding->src_multibyte = 1;
880 }
881 }
882 else
883 {
884 /* This glyph has an entry in Vglyph_table,
885 so process any alias before testing for simpleness. */
886 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
887
888 if (GLYPH_SIMPLE_P (tbase, tlen, g))
889 {
890 /* We set the multi-byte form of a character in G
891 (that should be an ASCII character) at
892 WORKBUF. */
893 workbuf[0] = FAST_GLYPH_CHAR (g);
894 len = 1;
895 buf = workbuf;
896 coding->src_multibyte = 0;
897 }
898 else
899 {
900 /* We have a string in Vglyph_table. */
901 len = GLYPH_LENGTH (tbase, g);
902 buf = GLYPH_STRING (tbase, g);
903 coding->src_multibyte = STRING_MULTIBYTE (tbase[g]);
904 }
905 }
906
907 result = encode_coding (coding, buf, dst, len, dst_end - dst);
908 len -= coding->consumed;
909 dst += coding->produced;
910 if (result == CODING_FINISH_INSUFFICIENT_DST
911 || (result == CODING_FINISH_INSUFFICIENT_SRC
912 && len > dst_end - dst))
913 /* The remaining output buffer is too short. We must
914 break the loop here without increasing SRC so that the
915 next call of this function starts from the same glyph. */
916 break;
917
918 if (len > 0)
919 {
920 /* This is the case that a code of the range 0200..0237
921 exists in buf. We must just write out such a code. */
922 buf += coding->consumed;
923 while (len--)
924 *dst++ = *buf++;
925 }
926 }
927 src++;
928 }
929
930 *consumed = src - src_start;
931 return (dst - dst_start);
932 }
933
934
935 void
936 write_glyphs (string, len)
937 register struct glyph *string;
938 register int len;
939 {
940 int produced, consumed;
941 struct frame *sf = XFRAME (selected_frame);
942 struct frame *f = updating_frame ? updating_frame : sf;
943 unsigned char conversion_buffer[1024];
944 int conversion_buffer_size = sizeof conversion_buffer;
945
946 if (write_glyphs_hook
947 && ! FRAME_TERMCAP_P (f))
948 {
949 (*write_glyphs_hook) (string, len);
950 return;
951 }
952
953 turn_off_insert ();
954 tty_hide_cursor ();
955
956 /* Don't dare write in last column of bottom line, if Auto-Wrap,
957 since that would scroll the whole frame on some terminals. */
958
959 if (AutoWrap
960 && curY + 1 == FRAME_HEIGHT (sf)
961 && (curX + len) == FRAME_WIDTH (sf))
962 len --;
963 if (len <= 0)
964 return;
965
966 cmplus (len);
967
968 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
969 the tail. */
970 terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
971
972 while (len > 0)
973 {
974 /* Identify a run of glyphs with the same face. */
975 int face_id = string->face_id;
976 int n;
977
978 for (n = 1; n < len; ++n)
979 if (string[n].face_id != face_id)
980 break;
981
982 /* Turn appearance modes of the face of the run on. */
983 highlight_if_desired ();
984 turn_on_face (f, face_id);
985
986 while (n > 0)
987 {
988 /* We use a fixed size (1024 bytes) of conversion buffer.
989 Usually it is sufficient, but if not, we just repeat the
990 loop. */
991 produced = encode_terminal_code (string, conversion_buffer,
992 n, conversion_buffer_size,
993 &consumed);
994 if (produced > 0)
995 {
996 fwrite (conversion_buffer, 1, produced, stdout);
997 if (ferror (stdout))
998 clearerr (stdout);
999 if (termscript)
1000 fwrite (conversion_buffer, 1, produced, termscript);
1001 }
1002 len -= consumed;
1003 n -= consumed;
1004 string += consumed;
1005 }
1006
1007 /* Turn appearance modes off. */
1008 turn_off_face (f, face_id);
1009 turn_off_highlight ();
1010 }
1011
1012 /* We may have to output some codes to terminate the writing. */
1013 if (CODING_REQUIRE_FLUSHING (&terminal_coding))
1014 {
1015 terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
1016 encode_coding (&terminal_coding, "", conversion_buffer,
1017 0, conversion_buffer_size);
1018 if (terminal_coding.produced > 0)
1019 {
1020 fwrite (conversion_buffer, 1, terminal_coding.produced, stdout);
1021 if (ferror (stdout))
1022 clearerr (stdout);
1023 if (termscript)
1024 fwrite (conversion_buffer, 1, terminal_coding.produced,
1025 termscript);
1026 }
1027 }
1028
1029 cmcheckmagic ();
1030 }
1031
1032 /* If start is zero, insert blanks instead of a string at start */
1033
1034 void
1035 insert_glyphs (start, len)
1036 register struct glyph *start;
1037 register int len;
1038 {
1039 char *buf;
1040 struct glyph *glyph = NULL;
1041 struct frame *f, *sf;
1042
1043 if (len <= 0)
1044 return;
1045
1046 if (insert_glyphs_hook)
1047 {
1048 (*insert_glyphs_hook) (start, len);
1049 return;
1050 }
1051
1052 sf = XFRAME (selected_frame);
1053 f = updating_frame ? updating_frame : sf;
1054
1055 if (TS_ins_multi_chars)
1056 {
1057 buf = tparam (TS_ins_multi_chars, 0, 0, len);
1058 OUTPUT1 (buf);
1059 xfree (buf);
1060 if (start)
1061 write_glyphs (start, len);
1062 return;
1063 }
1064
1065 turn_on_insert ();
1066 cmplus (len);
1067 /* The bit CODING_MODE_LAST_BLOCK should be set to 1 only at the tail. */
1068 terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
1069 while (len-- > 0)
1070 {
1071 int produced, consumed;
1072 unsigned char conversion_buffer[1024];
1073 int conversion_buffer_size = sizeof conversion_buffer;
1074
1075 OUTPUT1_IF (TS_ins_char);
1076 if (!start)
1077 {
1078 conversion_buffer[0] = SPACEGLYPH;
1079 produced = 1;
1080 }
1081 else
1082 {
1083 highlight_if_desired ();
1084 turn_on_face (f, start->face_id);
1085 glyph = start;
1086 ++start;
1087 /* We must open sufficient space for a character which
1088 occupies more than one column. */
1089 while (len && CHAR_GLYPH_PADDING_P (*start))
1090 {
1091 OUTPUT1_IF (TS_ins_char);
1092 start++, len--;
1093 }
1094
1095 if (len <= 0)
1096 /* This is the last glyph. */
1097 terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
1098
1099 /* The size of conversion buffer (1024 bytes) is surely
1100 sufficient for just one glyph. */
1101 produced = encode_terminal_code (glyph, conversion_buffer, 1,
1102 conversion_buffer_size, &consumed);
1103 }
1104
1105 if (produced > 0)
1106 {
1107 fwrite (conversion_buffer, 1, produced, stdout);
1108 if (ferror (stdout))
1109 clearerr (stdout);
1110 if (termscript)
1111 fwrite (conversion_buffer, 1, produced, termscript);
1112 }
1113
1114 OUTPUT1_IF (TS_pad_inserted_char);
1115 if (start)
1116 {
1117 turn_off_face (f, glyph->face_id);
1118 turn_off_highlight ();
1119 }
1120 }
1121
1122 cmcheckmagic ();
1123 }
1124
1125 void
1126 delete_glyphs (n)
1127 register int n;
1128 {
1129 char *buf;
1130 register int i;
1131
1132 if (delete_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame))
1133 {
1134 (*delete_glyphs_hook) (n);
1135 return;
1136 }
1137
1138 if (delete_in_insert_mode)
1139 {
1140 turn_on_insert ();
1141 }
1142 else
1143 {
1144 turn_off_insert ();
1145 OUTPUT_IF (TS_delete_mode);
1146 }
1147
1148 if (TS_del_multi_chars)
1149 {
1150 buf = tparam (TS_del_multi_chars, 0, 0, n);
1151 OUTPUT1 (buf);
1152 xfree (buf);
1153 }
1154 else
1155 for (i = 0; i < n; i++)
1156 OUTPUT1 (TS_del_char);
1157 if (!delete_in_insert_mode)
1158 OUTPUT_IF (TS_end_delete_mode);
1159 }
1160 \f
1161 /* Insert N lines at vpos VPOS. If N is negative, delete -N lines. */
1162
1163 void
1164 ins_del_lines (vpos, n)
1165 int vpos, n;
1166 {
1167 char *multi = n > 0 ? TS_ins_multi_lines : TS_del_multi_lines;
1168 char *single = n > 0 ? TS_ins_line : TS_del_line;
1169 char *scroll = n > 0 ? TS_rev_scroll : TS_fwd_scroll;
1170 struct frame *sf;
1171
1172 register int i = n > 0 ? n : -n;
1173 register char *buf;
1174
1175 if (ins_del_lines_hook && ! FRAME_TERMCAP_P (updating_frame))
1176 {
1177 (*ins_del_lines_hook) (vpos, n);
1178 return;
1179 }
1180
1181 sf = XFRAME (selected_frame);
1182
1183 /* If the lines below the insertion are being pushed
1184 into the end of the window, this is the same as clearing;
1185 and we know the lines are already clear, since the matching
1186 deletion has already been done. So can ignore this. */
1187 /* If the lines below the deletion are blank lines coming
1188 out of the end of the window, don't bother,
1189 as there will be a matching inslines later that will flush them. */
1190 if (scroll_region_ok && vpos + i >= specified_window)
1191 return;
1192 if (!memory_below_frame && vpos + i >= FRAME_HEIGHT (sf))
1193 return;
1194
1195 if (multi)
1196 {
1197 raw_cursor_to (vpos, 0);
1198 background_highlight ();
1199 buf = tparam (multi, 0, 0, i);
1200 OUTPUT (buf);
1201 xfree (buf);
1202 }
1203 else if (single)
1204 {
1205 raw_cursor_to (vpos, 0);
1206 background_highlight ();
1207 while (--i >= 0)
1208 OUTPUT (single);
1209 if (TF_teleray)
1210 curX = 0;
1211 }
1212 else
1213 {
1214 set_scroll_region (vpos, specified_window);
1215 if (n < 0)
1216 raw_cursor_to (specified_window - 1, 0);
1217 else
1218 raw_cursor_to (vpos, 0);
1219 background_highlight ();
1220 while (--i >= 0)
1221 OUTPUTL (scroll, specified_window - vpos);
1222 set_scroll_region (0, specified_window);
1223 }
1224
1225 if (TN_standout_width >= 0)
1226 {
1227 register int lower_limit
1228 = (scroll_region_ok
1229 ? specified_window
1230 : FRAME_HEIGHT (sf));
1231 }
1232 if (!scroll_region_ok && memory_below_frame && n < 0)
1233 {
1234 cursor_to (FRAME_HEIGHT (sf) + n, 0);
1235 clear_to_end ();
1236 }
1237 }
1238 \f
1239 /* Compute cost of sending "str", in characters,
1240 not counting any line-dependent padding. */
1241
1242 int
1243 string_cost (str)
1244 char *str;
1245 {
1246 cost = 0;
1247 if (str)
1248 tputs (str, 0, evalcost);
1249 return cost;
1250 }
1251
1252 /* Compute cost of sending "str", in characters,
1253 counting any line-dependent padding at one line. */
1254
1255 static int
1256 string_cost_one_line (str)
1257 char *str;
1258 {
1259 cost = 0;
1260 if (str)
1261 tputs (str, 1, evalcost);
1262 return cost;
1263 }
1264
1265 /* Compute per line amount of line-dependent padding,
1266 in tenths of characters. */
1267
1268 int
1269 per_line_cost (str)
1270 register char *str;
1271 {
1272 cost = 0;
1273 if (str)
1274 tputs (str, 0, evalcost);
1275 cost = - cost;
1276 if (str)
1277 tputs (str, 10, evalcost);
1278 return cost;
1279 }
1280
1281 #ifndef old
1282 /* char_ins_del_cost[n] is cost of inserting N characters.
1283 char_ins_del_cost[-n] is cost of deleting N characters.
1284 The length of this vector is based on max_frame_width. */
1285
1286 int *char_ins_del_vector;
1287
1288 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WIDTH ((f))])
1289 #endif
1290
1291 /* ARGSUSED */
1292 static void
1293 calculate_ins_del_char_costs (frame)
1294 FRAME_PTR frame;
1295 {
1296 int ins_startup_cost, del_startup_cost;
1297 int ins_cost_per_char, del_cost_per_char;
1298 register int i;
1299 register int *p;
1300
1301 if (TS_ins_multi_chars)
1302 {
1303 ins_cost_per_char = 0;
1304 ins_startup_cost = string_cost_one_line (TS_ins_multi_chars);
1305 }
1306 else if (TS_ins_char || TS_pad_inserted_char
1307 || (TS_insert_mode && TS_end_insert_mode))
1308 {
1309 ins_startup_cost = (30 * (string_cost (TS_insert_mode)
1310 + string_cost (TS_end_insert_mode))) / 100;
1311 ins_cost_per_char = (string_cost_one_line (TS_ins_char)
1312 + string_cost_one_line (TS_pad_inserted_char));
1313 }
1314 else
1315 {
1316 ins_startup_cost = 9999;
1317 ins_cost_per_char = 0;
1318 }
1319
1320 if (TS_del_multi_chars)
1321 {
1322 del_cost_per_char = 0;
1323 del_startup_cost = string_cost_one_line (TS_del_multi_chars);
1324 }
1325 else if (TS_del_char)
1326 {
1327 del_startup_cost = (string_cost (TS_delete_mode)
1328 + string_cost (TS_end_delete_mode));
1329 if (delete_in_insert_mode)
1330 del_startup_cost /= 2;
1331 del_cost_per_char = string_cost_one_line (TS_del_char);
1332 }
1333 else
1334 {
1335 del_startup_cost = 9999;
1336 del_cost_per_char = 0;
1337 }
1338
1339 /* Delete costs are at negative offsets */
1340 p = &char_ins_del_cost (frame)[0];
1341 for (i = FRAME_WIDTH (frame); --i >= 0;)
1342 *--p = (del_startup_cost += del_cost_per_char);
1343
1344 /* Doing nothing is free */
1345 p = &char_ins_del_cost (frame)[0];
1346 *p++ = 0;
1347
1348 /* Insert costs are at positive offsets */
1349 for (i = FRAME_WIDTH (frame); --i >= 0;)
1350 *p++ = (ins_startup_cost += ins_cost_per_char);
1351 }
1352
1353 void
1354 calculate_costs (frame)
1355 FRAME_PTR frame;
1356 {
1357 register char *f = (TS_set_scroll_region
1358 ? TS_set_scroll_region
1359 : TS_set_scroll_region_1);
1360
1361 FRAME_COST_BAUD_RATE (frame) = baud_rate;
1362
1363 scroll_region_cost = string_cost (f);
1364
1365 /* These variables are only used for terminal stuff. They are allocated
1366 once for the terminal frame of X-windows emacs, but not used afterwards.
1367
1368 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1369 X turns off char_ins_del_ok. */
1370
1371 max_frame_height = max (max_frame_height, FRAME_HEIGHT (frame));
1372 max_frame_width = max (max_frame_width, FRAME_WIDTH (frame));
1373
1374 costs_set = 1;
1375
1376 if (char_ins_del_vector != 0)
1377 char_ins_del_vector
1378 = (int *) xrealloc (char_ins_del_vector,
1379 (sizeof (int)
1380 + 2 * max_frame_width * sizeof (int)));
1381 else
1382 char_ins_del_vector
1383 = (int *) xmalloc (sizeof (int)
1384 + 2 * max_frame_width * sizeof (int));
1385
1386 bzero (char_ins_del_vector, (sizeof (int)
1387 + 2 * max_frame_width * sizeof (int)));
1388
1389 if (f && (!TS_ins_line && !TS_del_line))
1390 do_line_insertion_deletion_costs (frame,
1391 TS_rev_scroll, TS_ins_multi_lines,
1392 TS_fwd_scroll, TS_del_multi_lines,
1393 f, f, 1);
1394 else
1395 do_line_insertion_deletion_costs (frame,
1396 TS_ins_line, TS_ins_multi_lines,
1397 TS_del_line, TS_del_multi_lines,
1398 0, 0, 1);
1399
1400 calculate_ins_del_char_costs (frame);
1401
1402 /* Don't use TS_repeat if its padding is worse than sending the chars */
1403 if (TS_repeat && per_line_cost (TS_repeat) * baud_rate < 9000)
1404 RPov = string_cost (TS_repeat);
1405 else
1406 RPov = FRAME_WIDTH (frame) * 2;
1407
1408 cmcostinit (); /* set up cursor motion costs */
1409 }
1410 \f
1411 struct fkey_table {
1412 char *cap, *name;
1413 };
1414
1415 /* Termcap capability names that correspond directly to X keysyms.
1416 Some of these (marked "terminfo") aren't supplied by old-style
1417 (Berkeley) termcap entries. They're listed in X keysym order;
1418 except we put the keypad keys first, so that if they clash with
1419 other keys (as on the IBM PC keyboard) they get overridden.
1420 */
1421
1422 static struct fkey_table keys[] =
1423 {
1424 "kh", "home", /* termcap */
1425 "kl", "left", /* termcap */
1426 "ku", "up", /* termcap */
1427 "kr", "right", /* termcap */
1428 "kd", "down", /* termcap */
1429 "%8", "prior", /* terminfo */
1430 "%5", "next", /* terminfo */
1431 "@7", "end", /* terminfo */
1432 "@1", "begin", /* terminfo */
1433 "*6", "select", /* terminfo */
1434 "%9", "print", /* terminfo */
1435 "@4", "execute", /* terminfo --- actually the `command' key */
1436 /*
1437 * "insert" --- see below
1438 */
1439 "&8", "undo", /* terminfo */
1440 "%0", "redo", /* terminfo */
1441 "%7", "menu", /* terminfo --- actually the `options' key */
1442 "@0", "find", /* terminfo */
1443 "@2", "cancel", /* terminfo */
1444 "%1", "help", /* terminfo */
1445 /*
1446 * "break" goes here, but can't be reliably intercepted with termcap
1447 */
1448 "&4", "reset", /* terminfo --- actually `restart' */
1449 /*
1450 * "system" and "user" --- no termcaps
1451 */
1452 "kE", "clearline", /* terminfo */
1453 "kA", "insertline", /* terminfo */
1454 "kL", "deleteline", /* terminfo */
1455 "kI", "insertchar", /* terminfo */
1456 "kD", "deletechar", /* terminfo */
1457 "kB", "backtab", /* terminfo */
1458 /*
1459 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1460 */
1461 "@8", "kp-enter", /* terminfo */
1462 /*
1463 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1464 * "kp-multiply", "kp-add", "kp-separator",
1465 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1466 * --- no termcaps for any of these.
1467 */
1468 "K4", "kp-1", /* terminfo */
1469 /*
1470 * "kp-2" --- no termcap
1471 */
1472 "K5", "kp-3", /* terminfo */
1473 /*
1474 * "kp-4" --- no termcap
1475 */
1476 "K2", "kp-5", /* terminfo */
1477 /*
1478 * "kp-6" --- no termcap
1479 */
1480 "K1", "kp-7", /* terminfo */
1481 /*
1482 * "kp-8" --- no termcap
1483 */
1484 "K3", "kp-9", /* terminfo */
1485 /*
1486 * "kp-equal" --- no termcap
1487 */
1488 "k1", "f1",
1489 "k2", "f2",
1490 "k3", "f3",
1491 "k4", "f4",
1492 "k5", "f5",
1493 "k6", "f6",
1494 "k7", "f7",
1495 "k8", "f8",
1496 "k9", "f9",
1497 };
1498
1499 static char **term_get_fkeys_arg;
1500 static Lisp_Object term_get_fkeys_1 ();
1501
1502 /* Find the escape codes sent by the function keys for Vfunction_key_map.
1503 This function scans the termcap function key sequence entries, and
1504 adds entries to Vfunction_key_map for each function key it finds. */
1505
1506 void
1507 term_get_fkeys (address)
1508 char **address;
1509 {
1510 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1511 errors during the call. The only errors should be from Fdefine_key
1512 when given a key sequence containing an invalid prefix key. If the
1513 termcap defines function keys which use a prefix that is already bound
1514 to a command by the default bindings, we should silently ignore that
1515 function key specification, rather than giving the user an error and
1516 refusing to run at all on such a terminal. */
1517
1518 extern Lisp_Object Fidentity ();
1519 term_get_fkeys_arg = address;
1520 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1521 }
1522
1523 static Lisp_Object
1524 term_get_fkeys_1 ()
1525 {
1526 int i;
1527
1528 char **address = term_get_fkeys_arg;
1529
1530 /* This can happen if CANNOT_DUMP or with strange options. */
1531 if (!initialized)
1532 Vfunction_key_map = Fmake_sparse_keymap (Qnil);
1533
1534 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1535 {
1536 char *sequence = tgetstr (keys[i].cap, address);
1537 if (sequence)
1538 Fdefine_key (Vfunction_key_map, build_string (sequence),
1539 Fmake_vector (make_number (1),
1540 intern (keys[i].name)));
1541 }
1542
1543 /* The uses of the "k0" capability are inconsistent; sometimes it
1544 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1545 We will attempt to politely accommodate both systems by testing for
1546 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1547 */
1548 {
1549 char *k_semi = tgetstr ("k;", address);
1550 char *k0 = tgetstr ("k0", address);
1551 char *k0_name = "f10";
1552
1553 if (k_semi)
1554 {
1555 Fdefine_key (Vfunction_key_map, build_string (k_semi),
1556 Fmake_vector (make_number (1), intern ("f10")));
1557 k0_name = "f0";
1558 }
1559
1560 if (k0)
1561 Fdefine_key (Vfunction_key_map, build_string (k0),
1562 Fmake_vector (make_number (1), intern (k0_name)));
1563 }
1564
1565 /* Set up cookies for numbered function keys above f10. */
1566 {
1567 char fcap[3], fkey[4];
1568
1569 fcap[0] = 'F'; fcap[2] = '\0';
1570 for (i = 11; i < 64; i++)
1571 {
1572 if (i <= 19)
1573 fcap[1] = '1' + i - 11;
1574 else if (i <= 45)
1575 fcap[1] = 'A' + i - 20;
1576 else
1577 fcap[1] = 'a' + i - 46;
1578
1579 {
1580 char *sequence = tgetstr (fcap, address);
1581 if (sequence)
1582 {
1583 sprintf (fkey, "f%d", i);
1584 Fdefine_key (Vfunction_key_map, build_string (sequence),
1585 Fmake_vector (make_number (1),
1586 intern (fkey)));
1587 }
1588 }
1589 }
1590 }
1591
1592 /*
1593 * Various mappings to try and get a better fit.
1594 */
1595 {
1596 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1597 if (!tgetstr (cap1, address)) \
1598 { \
1599 char *sequence = tgetstr (cap2, address); \
1600 if (sequence) \
1601 Fdefine_key (Vfunction_key_map, build_string (sequence), \
1602 Fmake_vector (make_number (1), \
1603 intern (sym))); \
1604 }
1605
1606 /* if there's no key_next keycap, map key_npage to `next' keysym */
1607 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1608 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1609 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1610 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1611 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1612 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1613 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1614
1615 /* IBM has their own non-standard dialect of terminfo.
1616 If the standard name isn't found, try the IBM name. */
1617 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1618 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1619 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1620 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1621 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1622 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1623 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1624 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1625 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1626 #undef CONDITIONAL_REASSIGN
1627 }
1628
1629 return Qnil;
1630 }
1631
1632 \f
1633 /***********************************************************************
1634 Character Display Information
1635 ***********************************************************************/
1636
1637 static void append_glyph P_ ((struct it *));
1638
1639
1640 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1641 terminal frames if IT->glyph_row != NULL. IT->c is the character
1642 for which to produce glyphs; IT->face_id contains the character's
1643 face. Padding glyphs are appended if IT->c has a IT->pixel_width >
1644 1. */
1645
1646 static void
1647 append_glyph (it)
1648 struct it *it;
1649 {
1650 struct glyph *glyph, *end;
1651 int i;
1652
1653 xassert (it->glyph_row);
1654 glyph = (it->glyph_row->glyphs[it->area]
1655 + it->glyph_row->used[it->area]);
1656 end = it->glyph_row->glyphs[1 + it->area];
1657
1658 for (i = 0;
1659 i < it->pixel_width && glyph < end;
1660 ++i)
1661 {
1662 glyph->type = CHAR_GLYPH;
1663 glyph->pixel_width = 1;
1664 glyph->u.ch = it->c;
1665 glyph->face_id = it->face_id;
1666 glyph->padding_p = i > 0;
1667 glyph->charpos = CHARPOS (it->position);
1668 glyph->object = it->object;
1669
1670 ++it->glyph_row->used[it->area];
1671 ++glyph;
1672 }
1673 }
1674
1675
1676 /* Produce glyphs for the display element described by IT. The
1677 function fills output fields of IT with pixel information like the
1678 pixel width and height of a character, and maybe produces glyphs at
1679 the same time if IT->glyph_row is non-null. See the explanation of
1680 struct display_iterator in dispextern.h for an overview. */
1681
1682 void
1683 produce_glyphs (it)
1684 struct it *it;
1685 {
1686 /* If a hook is installed, let it do the work. */
1687 xassert (it->what == IT_CHARACTER
1688 || it->what == IT_COMPOSITION
1689 || it->what == IT_IMAGE
1690 || it->what == IT_STRETCH);
1691
1692 /* Nothing but characters are supported on terminal frames. For a
1693 composition sequence, it->c is the first character of the
1694 sequence. */
1695 xassert (it->what == IT_CHARACTER
1696 || it->what == IT_COMPOSITION);
1697
1698 if (it->c >= 040 && it->c < 0177)
1699 {
1700 it->pixel_width = it->nglyphs = 1;
1701 if (it->glyph_row)
1702 append_glyph (it);
1703 }
1704 else if (it->c == '\n')
1705 it->pixel_width = it->nglyphs = 0;
1706 else if (it->c == '\t')
1707 {
1708 int absolute_x = (it->current_x
1709 + it->continuation_lines_width);
1710 int next_tab_x
1711 = (((1 + absolute_x + it->tab_width - 1)
1712 / it->tab_width)
1713 * it->tab_width);
1714 int nspaces;
1715
1716 /* If part of the TAB has been displayed on the previous line
1717 which is continued now, continuation_lines_width will have
1718 been incremented already by the part that fitted on the
1719 continued line. So, we will get the right number of spaces
1720 here. */
1721 nspaces = next_tab_x - absolute_x;
1722
1723 if (it->glyph_row)
1724 {
1725 int n = nspaces;
1726
1727 it->c = ' ';
1728 it->pixel_width = it->len = 1;
1729
1730 while (n--)
1731 append_glyph (it);
1732
1733 it->c = '\t';
1734 }
1735
1736 it->pixel_width = nspaces;
1737 it->nglyphs = nspaces;
1738 }
1739 else if (SINGLE_BYTE_CHAR_P (it->c))
1740 {
1741 /* Coming here means that it->c is from display table, thus we
1742 must send the code as is to the terminal. Although there's
1743 no way to know how many columns it occupies on a screen, it
1744 is a good assumption that a single byte code has 1-column
1745 width. */
1746 it->pixel_width = it->nglyphs = 1;
1747 if (it->glyph_row)
1748 append_glyph (it);
1749 }
1750 else
1751 {
1752 /* A multi-byte character. The display width is fixed for all
1753 characters of the set. Some of the glyphs may have to be
1754 ignored because they are already displayed in a continued
1755 line. */
1756 int charset = CHAR_CHARSET (it->c);
1757
1758 it->pixel_width = CHARSET_WIDTH (charset);
1759 it->nglyphs = it->pixel_width;
1760
1761 if (it->glyph_row)
1762 append_glyph (it);
1763 }
1764
1765 /* Advance current_x by the pixel width as a convenience for
1766 the caller. */
1767 if (it->area == TEXT_AREA)
1768 it->current_x += it->pixel_width;
1769 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1770 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
1771 }
1772
1773
1774 /* Get information about special display element WHAT in an
1775 environment described by IT. WHAT is one of IT_TRUNCATION or
1776 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1777 non-null glyph_row member. This function ensures that fields like
1778 face_id, c, len of IT are left untouched. */
1779
1780 void
1781 produce_special_glyphs (it, what)
1782 struct it *it;
1783 enum display_element_type what;
1784 {
1785 struct it temp_it;
1786
1787 temp_it = *it;
1788 temp_it.dp = NULL;
1789 temp_it.what = IT_CHARACTER;
1790 temp_it.len = 1;
1791 temp_it.object = make_number (0);
1792 bzero (&temp_it.current, sizeof temp_it.current);
1793
1794 if (what == IT_CONTINUATION)
1795 {
1796 /* Continuation glyph. */
1797 if (it->dp
1798 && INTEGERP (DISP_CONTINUE_GLYPH (it->dp))
1799 && GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (it->dp))))
1800 {
1801 temp_it.c = FAST_GLYPH_CHAR (XINT (DISP_CONTINUE_GLYPH (it->dp)));
1802 temp_it.len = CHAR_BYTES (temp_it.c);
1803 }
1804 else
1805 temp_it.c = '\\';
1806
1807 produce_glyphs (&temp_it);
1808 it->pixel_width = temp_it.pixel_width;
1809 it->nglyphs = temp_it.pixel_width;
1810 }
1811 else if (what == IT_TRUNCATION)
1812 {
1813 /* Truncation glyph. */
1814 if (it->dp
1815 && INTEGERP (DISP_TRUNC_GLYPH (it->dp))
1816 && GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (it->dp))))
1817 {
1818 temp_it.c = FAST_GLYPH_CHAR (XINT (DISP_TRUNC_GLYPH (it->dp)));
1819 temp_it.len = CHAR_BYTES (temp_it.c);
1820 }
1821 else
1822 temp_it.c = '$';
1823
1824 produce_glyphs (&temp_it);
1825 it->pixel_width = temp_it.pixel_width;
1826 it->nglyphs = temp_it.pixel_width;
1827 }
1828 else
1829 abort ();
1830 }
1831
1832
1833 /* Return an estimation of the pixel height of mode or top lines on
1834 frame F. FACE_ID specifies what line's height to estimate. */
1835
1836 int
1837 estimate_mode_line_height (f, face_id)
1838 struct frame *f;
1839 enum face_id face_id;
1840 {
1841 if (estimate_mode_line_height_hook)
1842 return estimate_mode_line_height_hook (f, face_id);
1843 else
1844 return 1;
1845 }
1846
1847
1848 \f
1849 /***********************************************************************
1850 Faces
1851 ***********************************************************************/
1852
1853 /* Value is non-zero if attribute ATTR may be used. ATTR should be
1854 one of the enumerators from enum no_color_bit, or a bit set built
1855 from them. Some display attributes may not be used together with
1856 color; the termcap capability `NC' specifies which ones. */
1857
1858 #define MAY_USE_WITH_COLORS_P(ATTR) \
1859 (TN_max_colors > 0 \
1860 ? (TN_no_color_video & (ATTR)) == 0 \
1861 : 1)
1862
1863 /* Turn appearances of face FACE_ID on tty frame F on. */
1864
1865 static void
1866 turn_on_face (f, face_id)
1867 struct frame *f;
1868 int face_id;
1869 {
1870 struct face *face = FACE_FROM_ID (f, face_id);
1871 long fg = face->foreground;
1872 long bg = face->background;
1873
1874 /* Do this first because TS_end_standout_mode may be the same
1875 as TS_exit_attribute_mode, which turns all appearances off. */
1876 if (MAY_USE_WITH_COLORS_P (NC_REVERSE))
1877 {
1878 if (TN_max_colors > 0)
1879 {
1880 if (fg >= 0 && bg >= 0)
1881 {
1882 /* If the terminal supports colors, we can set them
1883 below without using reverse video. The face's fg
1884 and bg colors are set as they should appear on
1885 the screen, i.e. they take the inverse-video'ness
1886 of the face already into account. */
1887 }
1888 else if (inverse_video)
1889 {
1890 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1891 || bg == FACE_TTY_DEFAULT_BG_COLOR)
1892 toggle_highlight ();
1893 }
1894 else
1895 {
1896 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1897 || bg == FACE_TTY_DEFAULT_FG_COLOR)
1898 toggle_highlight ();
1899 }
1900 }
1901 else
1902 {
1903 /* If we can't display colors, use reverse video
1904 if the face specifies that. */
1905 if (inverse_video)
1906 {
1907 if (fg == FACE_TTY_DEFAULT_FG_COLOR
1908 || bg == FACE_TTY_DEFAULT_BG_COLOR)
1909 toggle_highlight ();
1910 }
1911 else
1912 {
1913 if (fg == FACE_TTY_DEFAULT_BG_COLOR
1914 || bg == FACE_TTY_DEFAULT_FG_COLOR)
1915 toggle_highlight ();
1916 }
1917 }
1918 }
1919
1920 if (face->tty_bold_p)
1921 {
1922 if (MAY_USE_WITH_COLORS_P (NC_BOLD))
1923 OUTPUT1_IF (TS_enter_bold_mode);
1924 }
1925 else if (face->tty_dim_p)
1926 if (MAY_USE_WITH_COLORS_P (NC_DIM))
1927 OUTPUT1_IF (TS_enter_dim_mode);
1928
1929 /* Alternate charset and blinking not yet used. */
1930 if (face->tty_alt_charset_p
1931 && MAY_USE_WITH_COLORS_P (NC_ALT_CHARSET))
1932 OUTPUT1_IF (TS_enter_alt_charset_mode);
1933
1934 if (face->tty_blinking_p
1935 && MAY_USE_WITH_COLORS_P (NC_BLINK))
1936 OUTPUT1_IF (TS_enter_blink_mode);
1937
1938 if (face->tty_underline_p
1939 /* Don't underline if that's difficult. */
1940 && TN_magic_cookie_glitch_ul <= 0
1941 && MAY_USE_WITH_COLORS_P (NC_UNDERLINE))
1942 OUTPUT1_IF (TS_enter_underline_mode);
1943
1944 if (TN_max_colors > 0)
1945 {
1946 char *p;
1947
1948 if (fg >= 0 && TS_set_foreground)
1949 {
1950 p = tparam (TS_set_foreground, NULL, 0, (int) fg);
1951 OUTPUT (p);
1952 xfree (p);
1953 }
1954
1955 if (bg >= 0 && TS_set_background)
1956 {
1957 p = tparam (TS_set_background, NULL, 0, (int) bg);
1958 OUTPUT (p);
1959 xfree (p);
1960 }
1961 }
1962 }
1963
1964
1965 /* Turn off appearances of face FACE_ID on tty frame F. */
1966
1967 static void
1968 turn_off_face (f, face_id)
1969 struct frame *f;
1970 int face_id;
1971 {
1972 struct face *face = FACE_FROM_ID (f, face_id);
1973
1974 xassert (face != NULL);
1975
1976 if (TS_exit_attribute_mode)
1977 {
1978 /* Capability "me" will turn off appearance modes double-bright,
1979 half-bright, reverse-video, standout, underline. It may or
1980 may not turn off alt-char-mode. */
1981 if (face->tty_bold_p
1982 || face->tty_dim_p
1983 || face->tty_reverse_p
1984 || face->tty_alt_charset_p
1985 || face->tty_blinking_p
1986 || face->tty_underline_p)
1987 {
1988 OUTPUT1_IF (TS_exit_attribute_mode);
1989 if (strcmp (TS_exit_attribute_mode, TS_end_standout_mode) == 0)
1990 standout_mode = 0;
1991 }
1992
1993 if (face->tty_alt_charset_p)
1994 OUTPUT_IF (TS_exit_alt_charset_mode);
1995 }
1996 else
1997 {
1998 /* If we don't have "me" we can only have those appearances
1999 that have exit sequences defined. */
2000 if (face->tty_alt_charset_p)
2001 OUTPUT_IF (TS_exit_alt_charset_mode);
2002
2003 if (face->tty_underline_p
2004 /* We don't underline if that's difficult. */
2005 && TN_magic_cookie_glitch_ul <= 0)
2006 OUTPUT_IF (TS_exit_underline_mode);
2007 }
2008
2009 /* Switch back to default colors. */
2010 if (TN_max_colors > 0
2011 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
2012 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
2013 || (face->background != FACE_TTY_DEFAULT_COLOR
2014 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
2015 OUTPUT1_IF (TS_orig_pair);
2016 }
2017
2018
2019 /* Return non-zero if the terminal is capable to display colors. */
2020
2021 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
2022 0, 1, 0,
2023 doc: /* Return non-nil if TTY can display colors on FRAME. */)
2024 (frame)
2025 Lisp_Object frame;
2026 {
2027 return TN_max_colors > 0 ? Qt : Qnil;
2028 }
2029
2030
2031
2032 \f
2033 /***********************************************************************
2034 Initialization
2035 ***********************************************************************/
2036
2037 void
2038 term_init (terminal_type)
2039 char *terminal_type;
2040 {
2041 char *area;
2042 char **address = &area;
2043 char buffer[2044];
2044 register char *p;
2045 int status;
2046 struct frame *sf = XFRAME (selected_frame);
2047
2048 #ifdef WINDOWSNT
2049 initialize_w32_display ();
2050
2051 Wcm_clear ();
2052
2053 area = (char *) xmalloc (2044);
2054
2055 if (area == 0)
2056 abort ();
2057
2058 FrameRows = FRAME_HEIGHT (sf);
2059 FrameCols = FRAME_WIDTH (sf);
2060 specified_window = FRAME_HEIGHT (sf);
2061
2062 delete_in_insert_mode = 1;
2063
2064 UseTabs = 0;
2065 scroll_region_ok = 0;
2066
2067 /* Seems to insert lines when it's not supposed to, messing
2068 up the display. In doing a trace, it didn't seem to be
2069 called much, so I don't think we're losing anything by
2070 turning it off. */
2071
2072 line_ins_del_ok = 0;
2073 char_ins_del_ok = 1;
2074
2075 baud_rate = 19200;
2076
2077 FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0;
2078 FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none;
2079 TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
2080
2081 return;
2082 #else /* not WINDOWSNT */
2083
2084 Wcm_clear ();
2085
2086 status = tgetent (buffer, terminal_type);
2087 if (status < 0)
2088 {
2089 #ifdef TERMINFO
2090 fatal ("Cannot open terminfo database file");
2091 #else
2092 fatal ("Cannot open termcap database file");
2093 #endif
2094 }
2095 if (status == 0)
2096 {
2097 #ifdef TERMINFO
2098 fatal ("Terminal type %s is not defined.\n\
2099 If that is not the actual type of terminal you have,\n\
2100 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2101 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2102 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
2103 terminal_type);
2104 #else
2105 fatal ("Terminal type %s is not defined.\n\
2106 If that is not the actual type of terminal you have,\n\
2107 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2108 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2109 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
2110 terminal_type);
2111 #endif
2112 }
2113 #ifdef TERMINFO
2114 area = (char *) xmalloc (2044);
2115 #else
2116 area = (char *) xmalloc (strlen (buffer));
2117 #endif /* not TERMINFO */
2118 if (area == 0)
2119 abort ();
2120
2121 TS_ins_line = tgetstr ("al", address);
2122 TS_ins_multi_lines = tgetstr ("AL", address);
2123 TS_bell = tgetstr ("bl", address);
2124 BackTab = tgetstr ("bt", address);
2125 TS_clr_to_bottom = tgetstr ("cd", address);
2126 TS_clr_line = tgetstr ("ce", address);
2127 TS_clr_frame = tgetstr ("cl", address);
2128 ColPosition = NULL; /* tgetstr ("ch", address); */
2129 AbsPosition = tgetstr ("cm", address);
2130 CR = tgetstr ("cr", address);
2131 TS_set_scroll_region = tgetstr ("cs", address);
2132 TS_set_scroll_region_1 = tgetstr ("cS", address);
2133 RowPosition = tgetstr ("cv", address);
2134 TS_del_char = tgetstr ("dc", address);
2135 TS_del_multi_chars = tgetstr ("DC", address);
2136 TS_del_line = tgetstr ("dl", address);
2137 TS_del_multi_lines = tgetstr ("DL", address);
2138 TS_delete_mode = tgetstr ("dm", address);
2139 TS_end_delete_mode = tgetstr ("ed", address);
2140 TS_end_insert_mode = tgetstr ("ei", address);
2141 Home = tgetstr ("ho", address);
2142 TS_ins_char = tgetstr ("ic", address);
2143 TS_ins_multi_chars = tgetstr ("IC", address);
2144 TS_insert_mode = tgetstr ("im", address);
2145 TS_pad_inserted_char = tgetstr ("ip", address);
2146 TS_end_keypad_mode = tgetstr ("ke", address);
2147 TS_keypad_mode = tgetstr ("ks", address);
2148 LastLine = tgetstr ("ll", address);
2149 Right = tgetstr ("nd", address);
2150 Down = tgetstr ("do", address);
2151 if (!Down)
2152 Down = tgetstr ("nl", address); /* Obsolete name for "do" */
2153 #ifdef VMS
2154 /* VMS puts a carriage return before each linefeed,
2155 so it is not safe to use linefeeds. */
2156 if (Down && Down[0] == '\n' && Down[1] == '\0')
2157 Down = 0;
2158 #endif /* VMS */
2159 if (tgetflag ("bs"))
2160 Left = "\b"; /* can't possibly be longer! */
2161 else /* (Actually, "bs" is obsolete...) */
2162 Left = tgetstr ("le", address);
2163 if (!Left)
2164 Left = tgetstr ("bc", address); /* Obsolete name for "le" */
2165 TS_pad_char = tgetstr ("pc", address);
2166 TS_repeat = tgetstr ("rp", address);
2167 TS_end_standout_mode = tgetstr ("se", address);
2168 TS_fwd_scroll = tgetstr ("sf", address);
2169 TS_standout_mode = tgetstr ("so", address);
2170 TS_rev_scroll = tgetstr ("sr", address);
2171 Wcm.cm_tab = tgetstr ("ta", address);
2172 TS_end_termcap_modes = tgetstr ("te", address);
2173 TS_termcap_modes = tgetstr ("ti", address);
2174 Up = tgetstr ("up", address);
2175 TS_visible_bell = tgetstr ("vb", address);
2176 TS_cursor_normal = tgetstr ("ve", address);
2177 TS_cursor_visible = tgetstr ("vs", address);
2178 TS_cursor_invisible = tgetstr ("vi", address);
2179 TS_set_window = tgetstr ("wi", address);
2180
2181 TS_enter_underline_mode = tgetstr ("us", address);
2182 TS_exit_underline_mode = tgetstr ("ue", address);
2183 TN_magic_cookie_glitch_ul = tgetnum ("ug");
2184 TS_enter_bold_mode = tgetstr ("md", address);
2185 TS_enter_dim_mode = tgetstr ("mh", address);
2186 TS_enter_blink_mode = tgetstr ("mb", address);
2187 TS_enter_reverse_mode = tgetstr ("mr", address);
2188 TS_enter_alt_charset_mode = tgetstr ("as", address);
2189 TS_exit_alt_charset_mode = tgetstr ("ae", address);
2190 TS_exit_attribute_mode = tgetstr ("me", address);
2191
2192 MultiUp = tgetstr ("UP", address);
2193 MultiDown = tgetstr ("DO", address);
2194 MultiLeft = tgetstr ("LE", address);
2195 MultiRight = tgetstr ("RI", address);
2196
2197 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
2198 color because we can't switch back to the default foreground and
2199 background. */
2200 TS_orig_pair = tgetstr ("op", address);
2201 if (TS_orig_pair)
2202 {
2203 TS_set_foreground = tgetstr ("AF", address);
2204 TS_set_background = tgetstr ("AB", address);
2205 if (!TS_set_foreground)
2206 {
2207 /* SVr4. */
2208 TS_set_foreground = tgetstr ("Sf", address);
2209 TS_set_background = tgetstr ("Sb", address);
2210 }
2211
2212 TN_max_colors = tgetnum ("Co");
2213 TN_max_pairs = tgetnum ("pa");
2214
2215 TN_no_color_video = tgetnum ("NC");
2216 if (TN_no_color_video == -1)
2217 TN_no_color_video = 0;
2218 }
2219
2220 MagicWrap = tgetflag ("xn");
2221 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
2222 the former flag imply the latter. */
2223 AutoWrap = MagicWrap || tgetflag ("am");
2224 memory_below_frame = tgetflag ("db");
2225 TF_hazeltine = tgetflag ("hz");
2226 must_write_spaces = tgetflag ("in");
2227 meta_key = tgetflag ("km") || tgetflag ("MT");
2228 TF_insmode_motion = tgetflag ("mi");
2229 TF_standout_motion = tgetflag ("ms");
2230 TF_underscore = tgetflag ("ul");
2231 TF_xs = tgetflag ("xs");
2232 TF_teleray = tgetflag ("xt");
2233
2234 term_get_fkeys (address);
2235
2236 /* Get frame size from system, or else from termcap. */
2237 {
2238 int height, width;
2239 get_frame_size (&width, &height);
2240 FRAME_WIDTH (sf) = width;
2241 FRAME_HEIGHT (sf) = height;
2242 }
2243
2244 if (FRAME_WIDTH (sf) <= 0)
2245 SET_FRAME_WIDTH (sf, tgetnum ("co"));
2246 else
2247 /* Keep width and external_width consistent */
2248 SET_FRAME_WIDTH (sf, FRAME_WIDTH (sf));
2249 if (FRAME_HEIGHT (sf) <= 0)
2250 FRAME_HEIGHT (sf) = tgetnum ("li");
2251
2252 if (FRAME_HEIGHT (sf) < 3 || FRAME_WIDTH (sf) < 3)
2253 fatal ("Screen size %dx%d is too small",
2254 FRAME_HEIGHT (sf), FRAME_WIDTH (sf));
2255
2256 min_padding_speed = tgetnum ("pb");
2257 TN_standout_width = tgetnum ("sg");
2258 TabWidth = tgetnum ("tw");
2259
2260 #ifdef VMS
2261 /* These capabilities commonly use ^J.
2262 I don't know why, but sending them on VMS does not work;
2263 it causes following spaces to be lost, sometimes.
2264 For now, the simplest fix is to avoid using these capabilities ever. */
2265 if (Down && Down[0] == '\n')
2266 Down = 0;
2267 #endif /* VMS */
2268
2269 if (!TS_bell)
2270 TS_bell = "\07";
2271
2272 if (!TS_fwd_scroll)
2273 TS_fwd_scroll = Down;
2274
2275 PC = TS_pad_char ? *TS_pad_char : 0;
2276
2277 if (TabWidth < 0)
2278 TabWidth = 8;
2279
2280 /* Turned off since /etc/termcap seems to have :ta= for most terminals
2281 and newer termcap doc does not seem to say there is a default.
2282 if (!Wcm.cm_tab)
2283 Wcm.cm_tab = "\t";
2284 */
2285
2286 if (TS_standout_mode == 0)
2287 {
2288 TN_standout_width = tgetnum ("ug");
2289 TS_end_standout_mode = tgetstr ("ue", address);
2290 TS_standout_mode = tgetstr ("us", address);
2291 }
2292
2293 /* If no `se' string, try using a `me' string instead.
2294 If that fails, we can't use standout mode at all. */
2295 if (TS_end_standout_mode == 0)
2296 {
2297 char *s = tgetstr ("me", address);
2298 if (s != 0)
2299 TS_end_standout_mode = s;
2300 else
2301 TS_standout_mode = 0;
2302 }
2303
2304 if (TF_teleray)
2305 {
2306 Wcm.cm_tab = 0;
2307 /* Teleray: most programs want a space in front of TS_standout_mode,
2308 but Emacs can do without it (and give one extra column). */
2309 TS_standout_mode = "\033RD";
2310 TN_standout_width = 1;
2311 /* But that means we cannot rely on ^M to go to column zero! */
2312 CR = 0;
2313 /* LF can't be trusted either -- can alter hpos */
2314 /* if move at column 0 thru a line with TS_standout_mode */
2315 Down = 0;
2316 }
2317
2318 /* Special handling for certain terminal types known to need it */
2319
2320 if (!strcmp (terminal_type, "supdup"))
2321 {
2322 memory_below_frame = 1;
2323 Wcm.cm_losewrap = 1;
2324 }
2325 if (!strncmp (terminal_type, "c10", 3)
2326 || !strcmp (terminal_type, "perq"))
2327 {
2328 /* Supply a makeshift :wi string.
2329 This string is not valid in general since it works only
2330 for windows starting at the upper left corner;
2331 but that is all Emacs uses.
2332
2333 This string works only if the frame is using
2334 the top of the video memory, because addressing is memory-relative.
2335 So first check the :ti string to see if that is true.
2336
2337 It would be simpler if the :wi string could go in the termcap
2338 entry, but it can't because it is not fully valid.
2339 If it were in the termcap entry, it would confuse other programs. */
2340 if (!TS_set_window)
2341 {
2342 p = TS_termcap_modes;
2343 while (*p && strcmp (p, "\033v "))
2344 p++;
2345 if (*p)
2346 TS_set_window = "\033v%C %C %C %C ";
2347 }
2348 /* Termcap entry often fails to have :in: flag */
2349 must_write_spaces = 1;
2350 /* :ti string typically fails to have \E^G! in it */
2351 /* This limits scope of insert-char to one line. */
2352 strcpy (area, TS_termcap_modes);
2353 strcat (area, "\033\007!");
2354 TS_termcap_modes = area;
2355 area += strlen (area) + 1;
2356 p = AbsPosition;
2357 /* Change all %+ parameters to %C, to handle
2358 values above 96 correctly for the C100. */
2359 while (*p)
2360 {
2361 if (p[0] == '%' && p[1] == '+')
2362 p[1] = 'C';
2363 p++;
2364 }
2365 }
2366
2367 FrameRows = FRAME_HEIGHT (sf);
2368 FrameCols = FRAME_WIDTH (sf);
2369 specified_window = FRAME_HEIGHT (sf);
2370
2371 if (Wcm_init () == -1) /* can't do cursor motion */
2372 #ifdef VMS
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, use either the\n\
2376 DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
2377 or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
2378 terminal_type);
2379 #else /* not VMS */
2380 # ifdef TERMINFO
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 TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
2387 terminal_type);
2388 # else /* TERMCAP */
2389 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
2390 It lacks the ability to position the cursor.\n\
2391 If that is not the actual type of terminal you have,\n\
2392 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
2393 `setenv TERM ...') to specify the correct type. It may be necessary\n\
2394 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
2395 terminal_type);
2396 # endif /* TERMINFO */
2397 #endif /*VMS */
2398 if (FRAME_HEIGHT (sf) <= 0
2399 || FRAME_WIDTH (sf) <= 0)
2400 fatal ("The frame size has not been specified");
2401
2402 delete_in_insert_mode
2403 = TS_delete_mode && TS_insert_mode
2404 && !strcmp (TS_delete_mode, TS_insert_mode);
2405
2406 se_is_so = (TS_standout_mode
2407 && TS_end_standout_mode
2408 && !strcmp (TS_standout_mode, TS_end_standout_mode));
2409
2410 /* Remove width of standout marker from usable width of line */
2411 if (TN_standout_width > 0)
2412 SET_FRAME_WIDTH (sf, FRAME_WIDTH (sf) - TN_standout_width);
2413
2414 UseTabs = tabs_safe_p () && TabWidth == 8;
2415
2416 scroll_region_ok
2417 = (Wcm.cm_abs
2418 && (TS_set_window || TS_set_scroll_region || TS_set_scroll_region_1));
2419
2420 line_ins_del_ok = (((TS_ins_line || TS_ins_multi_lines)
2421 && (TS_del_line || TS_del_multi_lines))
2422 || (scroll_region_ok && TS_fwd_scroll && TS_rev_scroll));
2423
2424 char_ins_del_ok = ((TS_ins_char || TS_insert_mode
2425 || TS_pad_inserted_char || TS_ins_multi_chars)
2426 && (TS_del_char || TS_del_multi_chars));
2427
2428 fast_clear_end_of_line = TS_clr_line != 0;
2429
2430 init_baud_rate ();
2431 if (read_socket_hook) /* Baudrate is somewhat */
2432 /* meaningless in this case */
2433 baud_rate = 9600;
2434
2435 FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0;
2436 FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none;
2437 #endif /* WINDOWSNT */
2438 }
2439
2440 /* VARARGS 1 */
2441 void
2442 fatal (str, arg1, arg2)
2443 char *str, *arg1, *arg2;
2444 {
2445 fprintf (stderr, "emacs: ");
2446 fprintf (stderr, str, arg1, arg2);
2447 fprintf (stderr, "\n");
2448 fflush (stderr);
2449 exit (1);
2450 }
2451
2452 void
2453 syms_of_term ()
2454 {
2455 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
2456 doc: /* Non-nil means the system uses terminfo rather than termcap.
2457 This variable can be used by terminal emulator packages. */);
2458 #ifdef TERMINFO
2459 system_uses_terminfo = 1;
2460 #else
2461 system_uses_terminfo = 0;
2462 #endif
2463
2464 DEFVAR_LISP ("ring-bell-function", &Vring_bell_function,
2465 doc: /* Non-nil means call this function to ring the bell.
2466 The function should accept no arguments. */);
2467 Vring_bell_function = Qnil;
2468
2469 defsubr (&Stty_display_color_p);
2470 }
2471