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