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