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